From 63dafe5728e7354bc3f15bd49f13f1f9a433e8fb Mon Sep 17 00:00:00 2001 From: Becky Bruce Date: Sat, 14 Jan 2006 16:57:39 -0600 Subject: [PATCH] powerpc: Updated Initial MPC8540 ADS port with OF Flat Dev Updated patch for support for mpc8540_ads in arch/powerpc with a flat OF device tree. This patch does not yet support PCI or I2C. Signed-off-by: Becky Bruce Signed-off-by: Jon Loeliger Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras --- arch/powerpc/Kconfig | 23 +- arch/powerpc/configs/mpc8540_ads_defconfig | 721 +++++++++++++++++++++++++++++ arch/powerpc/kernel/head_booke.h | 363 +++++++++++++++ arch/powerpc/platforms/85xx/Kconfig | 74 +-- arch/powerpc/platforms/85xx/Makefile | 5 +- arch/powerpc/platforms/85xx/mpc8540_ads.h | 60 +++ arch/powerpc/platforms/85xx/mpc85xx.c | 31 ++ arch/powerpc/platforms/85xx/mpc85xx.h | 17 + arch/powerpc/platforms/85xx/mpc85xx_ads.c | 208 +++++++++ arch/powerpc/platforms/Makefile | 2 +- 10 files changed, 1431 insertions(+), 73 deletions(-) create mode 100644 arch/powerpc/configs/mpc8540_ads_defconfig create mode 100644 arch/powerpc/kernel/head_booke.h create mode 100644 arch/powerpc/platforms/85xx/mpc8540_ads.h create mode 100644 arch/powerpc/platforms/85xx/mpc85xx.c create mode 100644 arch/powerpc/platforms/85xx/mpc85xx.h create mode 100644 arch/powerpc/platforms/85xx/mpc85xx_ads.c (limited to 'arch/powerpc') diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index df338c5cc910..8aa39d073dfe 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -121,6 +121,12 @@ config PPC_83xx select 83xx select PPC_FPU +config PPC_85xx + bool "Freescale 85xx" + select E500 + select FSL_SOC + select 85xx + config 40x bool "AMCC 40x" @@ -133,8 +139,6 @@ config 8xx config E200 bool "Freescale e200" -config E500 - bool "Freescale e500" endchoice config POWER4_ONLY @@ -162,6 +166,13 @@ config 6xx config 83xx bool +# this is temp to handle compat with arch=ppc +config 85xx + bool + +config E500 + bool + config PPC_FPU bool default y if PPC64 @@ -211,6 +222,7 @@ config ALTIVEC config SPE bool "SPE Support" depends on E200 || E500 + default y ---help--- This option enables kernel support for the Signal Processing Extensions (SPE) to the PowerPC processor. The kernel currently @@ -728,13 +740,12 @@ config GENERIC_ISA_DMA config PPC_I8259 bool - default y if 85xx default n config PPC_INDIRECT_PCI bool depends on PCI - default y if 40x || 44x || 85xx + default y if 40x || 44x default n config EISA @@ -751,8 +762,8 @@ config MCA bool config PCI - bool "PCI support" if 40x || CPM2 || PPC_83xx || 85xx || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) - default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx && !85xx + bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) + default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx && !PPC_85xx default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS default PCI_QSPAN if !4xx && !CPM2 && 8xx help diff --git a/arch/powerpc/configs/mpc8540_ads_defconfig b/arch/powerpc/configs/mpc8540_ads_defconfig new file mode 100644 index 000000000000..2a8290ee15c6 --- /dev/null +++ b/arch/powerpc/configs/mpc8540_ads_defconfig @@ -0,0 +1,721 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: +# Sat Jan 14 15:57:54 2006 +# +# CONFIG_PPC64 is not set +CONFIG_PPC32=y +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_PPC_UDBG_16550=y +# CONFIG_GENERIC_TBSYNC is not set + +# +# Processor support +# +# CONFIG_CLASSIC32 is not set +# CONFIG_PPC_52xx is not set +# CONFIG_PPC_82xx is not set +# CONFIG_PPC_83xx is not set +CONFIG_PPC_85xx=y +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_8xx is not set +# CONFIG_E200 is not set +CONFIG_85xx=y +CONFIG_E500=y +CONFIG_BOOKE=y +CONFIG_FSL_BOOKE=y +# CONFIG_PHYS_64BIT is not set +CONFIG_SPE=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Block layer +# +# CONFIG_LBD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_MPIC=y +# CONFIG_WANT_EARLY_SERIAL is not set + +# +# Platform support +# +CONFIG_MPC8540_ADS=y +CONFIG_MPC8540=y +CONFIG_PPC_INDIRECT_PCI_BE=y + +# +# Kernel options +# +# CONFIG_HIGHMEM is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_MATH_EMULATION=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set +# CONFIG_PM is not set +# CONFIG_SOFTWARE_SUSPEND is not set +# CONFIG_SECCOMP is not set +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +# CONFIG_PPC_I8259 is not set +CONFIG_PPC_INDIRECT_PCI=y +CONFIG_FSL_SOC=y +# CONFIG_PCI is not set +# CONFIG_PCI_DOMAINS is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PCI Hotplug Support +# + +# +# Advanced setup +# +# CONFIG_ADVANCED_OPTIONS is not set + +# +# Default settings for advanced configuration options are used +# +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE=0x80000000 +CONFIG_BOOT_LOAD=0x00800000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=32768 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Macintosh device drivers +# +# CONFIG_WINDFARM is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# PHY device support +# +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y + +# +# Ethernet (1000 Mbit) +# +CONFIG_GIANFAR=y +CONFIG_GFAR_NAPI=y + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +CONFIG_GEN_RTC=y +# CONFIG_GEN_RTC_X is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia Capabilities Port drivers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# InfiniBand support +# + +# +# SN Devices +# + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_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_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_MSDOS_PARTITION is not set +# CONFIG_LDM_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 + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set + +# +# Instrumentation Support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_DEBUGGER is not set +# CONFIG_BDI_SWITCH is not set +# CONFIG_BOOTX_TEXT is not set +# CONFIG_PPC_EARLY_DEBUG_LPAR is not set +# CONFIG_PPC_EARLY_DEBUG_G5 is not set +# CONFIG_PPC_EARLY_DEBUG_RTAS is not set +# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set +# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Hardware crypto devices +# diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/head_booke.h new file mode 100644 index 000000000000..5827c27e0b59 --- /dev/null +++ b/arch/powerpc/kernel/head_booke.h @@ -0,0 +1,363 @@ +#ifndef __HEAD_BOOKE_H__ +#define __HEAD_BOOKE_H__ + +/* + * Macros used for common Book-e exception handling + */ + +#define SET_IVOR(vector_number, vector_label) \ + li r26,vector_label@l; \ + mtspr SPRN_IVOR##vector_number,r26; \ + sync + +#define NORMAL_EXCEPTION_PROLOG \ + mtspr SPRN_SPRG0,r10; /* save two registers to work with */\ + mtspr SPRN_SPRG1,r11; \ + mtspr SPRN_SPRG4W,r1; \ + mfcr r10; /* save CR in r10 for now */\ + mfspr r11,SPRN_SRR1; /* check whether user or kernel */\ + andi. r11,r11,MSR_PR; \ + beq 1f; \ + mfspr r1,SPRN_SPRG3; /* if from user, start at top of */\ + lwz r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack */\ + addi r1,r1,THREAD_SIZE; \ +1: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\ + mr r11,r1; \ + stw r10,_CCR(r11); /* save various registers */\ + stw r12,GPR12(r11); \ + stw r9,GPR9(r11); \ + mfspr r10,SPRN_SPRG0; \ + stw r10,GPR10(r11); \ + mfspr r12,SPRN_SPRG1; \ + stw r12,GPR11(r11); \ + mflr r10; \ + stw r10,_LINK(r11); \ + mfspr r10,SPRN_SPRG4R; \ + mfspr r12,SPRN_SRR0; \ + stw r10,GPR1(r11); \ + mfspr r9,SPRN_SRR1; \ + stw r10,0(r11); \ + rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\ + stw r0,GPR0(r11); \ + SAVE_4GPRS(3, r11); \ + SAVE_2GPRS(7, r11) + +/* To handle the additional exception priority levels on 40x and Book-E + * processors we allocate a 4k stack per additional priority level. The various + * head_xxx.S files allocate space (exception_stack_top) for each priority's + * stack times the number of CPUs + * + * On 40x critical is the only additional level + * On 44x/e500 we have critical and machine check + * On e200 we have critical and debug (machine check occurs via critical) + * + * Additionally we reserve a SPRG for each priority level so we can free up a + * GPR to use as the base for indirect access to the exception stacks. This + * is necessary since the MMU is always on, for Book-E parts, and the stacks + * are offset from KERNELBASE. + * + */ +#define BOOKE_EXCEPTION_STACK_SIZE (8192) + +/* CRIT_SPRG only used in critical exception handling */ +#define CRIT_SPRG SPRN_SPRG2 +/* MCHECK_SPRG only used in machine check exception handling */ +#define MCHECK_SPRG SPRN_SPRG6W + +#define MCHECK_STACK_TOP (exception_stack_top - 4096) +#define CRIT_STACK_TOP (exception_stack_top) + +/* only on e200 for now */ +#define DEBUG_STACK_TOP (exception_stack_top - 4096) +#define DEBUG_SPRG SPRN_SPRG6W + +#ifdef CONFIG_SMP +#define BOOKE_LOAD_EXC_LEVEL_STACK(level) \ + mfspr r8,SPRN_PIR; \ + mulli r8,r8,BOOKE_EXCEPTION_STACK_SIZE; \ + neg r8,r8; \ + addis r8,r8,level##_STACK_TOP@ha; \ + addi r8,r8,level##_STACK_TOP@l +#else +#define BOOKE_LOAD_EXC_LEVEL_STACK(level) \ + lis r8,level##_STACK_TOP@h; \ + ori r8,r8,level##_STACK_TOP@l +#endif + +/* + * Exception prolog for critical/machine check exceptions. This is a + * little different from the normal exception prolog above since a + * critical/machine check exception can potentially occur at any point + * during normal exception processing. Thus we cannot use the same SPRG + * registers as the normal prolog above. Instead we use a portion of the + * critical/machine check exception stack at low physical addresses. + */ +#define EXC_LEVEL_EXCEPTION_PROLOG(exc_level, exc_level_srr0, exc_level_srr1) \ + mtspr exc_level##_SPRG,r8; \ + BOOKE_LOAD_EXC_LEVEL_STACK(exc_level);/* r8 points to the exc_level stack*/ \ + stw r10,GPR10-INT_FRAME_SIZE(r8); \ + stw r11,GPR11-INT_FRAME_SIZE(r8); \ + mfcr r10; /* save CR in r10 for now */\ + mfspr r11,exc_level_srr1; /* check whether user or kernel */\ + andi. r11,r11,MSR_PR; \ + mr r11,r8; \ + mfspr r8,exc_level##_SPRG; \ + beq 1f; \ + /* COMING FROM USER MODE */ \ + mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\ + lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\ + addi r11,r11,THREAD_SIZE; \ +1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\ + stw r10,_CCR(r11); /* save various registers */\ + stw r12,GPR12(r11); \ + stw r9,GPR9(r11); \ + mflr r10; \ + stw r10,_LINK(r11); \ + mfspr r12,SPRN_DEAR; /* save DEAR and ESR in the frame */\ + stw r12,_DEAR(r11); /* since they may have had stuff */\ + mfspr r9,SPRN_ESR; /* in them at the point where the */\ + stw r9,_ESR(r11); /* exception was taken */\ + mfspr r12,exc_level_srr0; \ + stw r1,GPR1(r11); \ + mfspr r9,exc_level_srr1; \ + stw r1,0(r11); \ + mr r1,r11; \ + rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\ + stw r0,GPR0(r11); \ + SAVE_4GPRS(3, r11); \ + SAVE_2GPRS(7, r11) + +#define CRITICAL_EXCEPTION_PROLOG \ + EXC_LEVEL_EXCEPTION_PROLOG(CRIT, SPRN_CSRR0, SPRN_CSRR1) +#define DEBUG_EXCEPTION_PROLOG \ + EXC_LEVEL_EXCEPTION_PROLOG(DEBUG, SPRN_DSRR0, SPRN_DSRR1) +#define MCHECK_EXCEPTION_PROLOG \ + EXC_LEVEL_EXCEPTION_PROLOG(MCHECK, SPRN_MCSRR0, SPRN_MCSRR1) + +/* + * Exception vectors. + */ +#define START_EXCEPTION(label) \ + .align 5; \ +label: + +#define FINISH_EXCEPTION(func) \ + bl transfer_to_handler_full; \ + .long func; \ + .long ret_from_except_full + +#define EXCEPTION(n, label, hdlr, xfer) \ + START_EXCEPTION(label); \ + NORMAL_EXCEPTION_PROLOG; \ + addi r3,r1,STACK_FRAME_OVERHEAD; \ + xfer(n, hdlr) + +#define CRITICAL_EXCEPTION(n, label, hdlr) \ + START_EXCEPTION(label); \ + CRITICAL_EXCEPTION_PROLOG; \ + addi r3,r1,STACK_FRAME_OVERHEAD; \ + EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \ + NOCOPY, crit_transfer_to_handler, \ + ret_from_crit_exc) + +#define MCHECK_EXCEPTION(n, label, hdlr) \ + START_EXCEPTION(label); \ + MCHECK_EXCEPTION_PROLOG; \ + mfspr r5,SPRN_ESR; \ + stw r5,_ESR(r11); \ + addi r3,r1,STACK_FRAME_OVERHEAD; \ + EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \ + NOCOPY, mcheck_transfer_to_handler, \ + ret_from_mcheck_exc) + +#define EXC_XFER_TEMPLATE(hdlr, trap, msr, copyee, tfer, ret) \ + li r10,trap; \ + stw r10,_TRAP(r11); \ + lis r10,msr@h; \ + ori r10,r10,msr@l; \ + copyee(r10, r9); \ + bl tfer; \ + .long hdlr; \ + .long ret + +#define COPY_EE(d, s) rlwimi d,s,0,16,16 +#define NOCOPY(d, s) + +#define EXC_XFER_STD(n, hdlr) \ + EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, transfer_to_handler_full, \ + ret_from_except_full) + +#define EXC_XFER_LITE(n, hdlr) \ + EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \ + ret_from_except) + +#define EXC_XFER_EE(n, hdlr) \ + EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE, transfer_to_handler_full, \ + ret_from_except_full) + +#define EXC_XFER_EE_LITE(n, hdlr) \ + EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \ + ret_from_except) + +/* Check for a single step debug exception while in an exception + * handler before state has been saved. This is to catch the case + * where an instruction that we are trying to single step causes + * an exception (eg ITLB/DTLB miss) and thus the first instruction of + * the exception handler generates a single step debug exception. + * + * If we get a debug trap on the first instruction of an exception handler, + * we reset the MSR_DE in the _exception handler's_ MSR (the debug trap is + * a critical exception, so we are using SPRN_CSRR1 to manipulate the MSR). + * The exception handler was handling a non-critical interrupt, so it will + * save (and later restore) the MSR via SPRN_CSRR1, which will still have + * the MSR_DE bit set. + */ +#ifdef CONFIG_E200 +#define DEBUG_EXCEPTION \ + START_EXCEPTION(Debug); \ + DEBUG_EXCEPTION_PROLOG; \ + \ + /* \ + * If there is a single step or branch-taken exception in an \ + * exception entry sequence, it was probably meant to apply to \ + * the code where the exception occurred (since exception entry \ + * doesn't turn off DE automatically). We simulate the effect \ + * of turning off DE on entry to an exception handler by turning \ + * off DE in the CSRR1 value and clearing the debug status. \ + */ \ + mfspr r10,SPRN_DBSR; /* check single-step/branch taken */ \ + andis. r10,r10,DBSR_IC@h; \ + beq+ 2f; \ + \ + lis r10,KERNELBASE@h; /* check if exception in vectors */ \ + ori r10,r10,KERNELBASE@l; \ + cmplw r12,r10; \ + blt+ 2f; /* addr below exception vectors */ \ + \ + lis r10,Debug@h; \ + ori r10,r10,Debug@l; \ + cmplw r12,r10; \ + bgt+ 2f; /* addr above exception vectors */ \ + \ + /* here it looks like we got an inappropriate debug exception. */ \ +1: rlwinm r9,r9,0,~MSR_DE; /* clear DE in the CDRR1 value */ \ + lis r10,DBSR_IC@h; /* clear the IC event */ \ + mtspr SPRN_DBSR,r10; \ + /* restore state and get out */ \ + lwz r10,_CCR(r11); \ + lwz r0,GPR0(r11); \ + lwz r1,GPR1(r11); \ + mtcrf 0x80,r10; \ + mtspr SPRN_DSRR0,r12; \ + mtspr SPRN_DSRR1,r9; \ + lwz r9,GPR9(r11); \ + lwz r12,GPR12(r11); \ + mtspr DEBUG_SPRG,r8; \ + BOOKE_LOAD_EXC_LEVEL_STACK(DEBUG); /* r8 points to the debug stack */ \ + lwz r10,GPR10-INT_FRAME_SIZE(r8); \ + lwz r11,GPR11-INT_FRAME_SIZE(r8); \ + mfspr r8,DEBUG_SPRG; \ + \ + RFDI; \ + b .; \ + \ + /* continue normal handling for a critical exception... */ \ +2: mfspr r4,SPRN_DBSR; \ + addi r3,r1,STACK_FRAME_OVERHEAD; \ + EXC_XFER_TEMPLATE(DebugException, 0x2002, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, debug_transfer_to_handler, ret_from_debug_exc) +#else +#define DEBUG_EXCEPTION \ + START_EXCEPTION(Debug); \ + CRITICAL_EXCEPTION_PROLOG; \ + \ + /* \ + * If there is a single step or branch-taken exception in an \ + * exception entry sequence, it was probably meant to apply to \ + * the code where the exception occurred (since exception entry \ + * doesn't turn off DE automatically). We simulate the effect \ + * of turning off DE on entry to an exception handler by turning \ + * off DE in the CSRR1 value and clearing the debug status. \ + */ \ + mfspr r10,SPRN_DBSR; /* check single-step/branch taken */ \ + andis. r10,r10,DBSR_IC@h; \ + beq+ 2f; \ + \ + lis r10,KERNELBASE@h; /* check if exception in vectors */ \ + ori r10,r10,KERNELBASE@l; \ + cmplw r12,r10; \ + blt+ 2f; /* addr below exception vectors */ \ + \ + lis r10,Debug@h; \ + ori r10,r10,Debug@l; \ + cmplw r12,r10; \ + bgt+ 2f; /* addr above exception vectors */ \ + \ + /* here it looks like we got an inappropriate debug exception. */ \ +1: rlwinm r9,r9,0,~MSR_DE; /* clear DE in the CSRR1 value */ \ + lis r10,DBSR_IC@h; /* clear the IC event */ \ + mtspr SPRN_DBSR,r10; \ + /* restore state and get out */ \ + lwz r10,_CCR(r11); \ + lwz r0,GPR0(r11); \ + lwz r1,GPR1(r11); \ + mtcrf 0x80,r10; \ + mtspr SPRN_CSRR0,r12; \ + mtspr SPRN_CSRR1,r9; \ + lwz r9,GPR9(r11); \ + lwz r12,GPR12(r11); \ + mtspr CRIT_SPRG,r8; \ + BOOKE_LOAD_EXC_LEVEL_STACK(CRIT); /* r8 points to the debug stack */ \ + lwz r10,GPR10-INT_FRAME_SIZE(r8); \ + lwz r11,GPR11-INT_FRAME_SIZE(r8); \ + mfspr r8,CRIT_SPRG; \ + \ + rfci; \ + b .; \ + \ + /* continue normal handling for a critical exception... */ \ +2: mfspr r4,SPRN_DBSR; \ + addi r3,r1,STACK_FRAME_OVERHEAD; \ + EXC_XFER_TEMPLATE(DebugException, 0x2002, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, crit_transfer_to_handler, ret_from_crit_exc) +#endif + +#define INSTRUCTION_STORAGE_EXCEPTION \ + START_EXCEPTION(InstructionStorage) \ + NORMAL_EXCEPTION_PROLOG; \ + mfspr r5,SPRN_ESR; /* Grab the ESR and save it */ \ + stw r5,_ESR(r11); \ + mr r4,r12; /* Pass SRR0 as arg2 */ \ + li r5,0; /* Pass zero as arg3 */ \ + EXC_XFER_EE_LITE(0x0400, handle_page_fault) + +#define ALIGNMENT_EXCEPTION \ + START_EXCEPTION(Alignment) \ + NORMAL_EXCEPTION_PROLOG; \ + mfspr r4,SPRN_DEAR; /* Grab the DEAR and save it */ \ + stw r4,_DEAR(r11); \ + addi r3,r1,STACK_FRAME_OVERHEAD; \ + EXC_XFER_EE(0x0600, alignment_exception) + +#define PROGRAM_EXCEPTION \ + START_EXCEPTION(Program) \ + NORMAL_EXCEPTION_PROLOG; \ + mfspr r4,SPRN_ESR; /* Grab the ESR and save it */ \ + stw r4,_ESR(r11); \ + addi r3,r1,STACK_FRAME_OVERHEAD; \ + EXC_XFER_STD(0x0700, program_check_exception) + +#define DECREMENTER_EXCEPTION \ + START_EXCEPTION(Decrementer) \ + NORMAL_EXCEPTION_PROLOG; \ + lis r0,TSR_DIS@h; /* Setup the DEC interrupt mask */ \ + mtspr SPRN_TSR,r0; /* Clear the DEC interrupt */ \ + addi r3,r1,STACK_FRAME_OVERHEAD; \ + EXC_XFER_LITE(0x0900, timer_interrupt) + +#define FP_UNAVAILABLE_EXCEPTION \ + START_EXCEPTION(FloatingPointUnavailable) \ + NORMAL_EXCEPTION_PROLOG; \ + bne load_up_fpu; /* if from user, just load it up */ \ + addi r3,r1,STACK_FRAME_OVERHEAD; \ + EXC_XFER_EE_LITE(0x800, KernelFP) + +#endif /* __HEAD_BOOKE_H__ */ diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index c5bc2821d991..d3d0ff745e84 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig @@ -1,86 +1,30 @@ -config 85xx - bool - depends on E500 - default y - -config PPC_INDIRECT_PCI_BE - bool - depends on 85xx - default y - -menu "Freescale 85xx options" - depends on E500 +menu "Platform support" + depends on PPC_85xx choice prompt "Machine Type" - depends on 85xx default MPC8540_ADS config MPC8540_ADS bool "Freescale MPC8540 ADS" help - This option enables support for the MPC 8540 ADS evaluation board. - -config MPC8548_CDS - bool "Freescale MPC8548 CDS" - help - This option enablese support for the MPC8548 CDS evaluation board. - -config MPC8555_CDS - bool "Freescale MPC8555 CDS" - help - This option enablese support for the MPC8555 CDS evaluation board. - -config MPC8560_ADS - bool "Freescale MPC8560 ADS" - help - This option enables support for the MPC 8560 ADS evaluation board. - -config SBC8560 - bool "WindRiver PowerQUICC III SBC8560" - help - This option enables support for the WindRiver PowerQUICC III - SBC8560 board. - -config STX_GP3 - bool "Silicon Turnkey Express GP3" - help - This option enables support for the Silicon Turnkey Express GP3 - board. + This option enables support for the MPC 8540 ADS board endchoice -# It's often necessary to know the specific 85xx processor type. -# Fortunately, it is implied (so far) from the board type, so we -# don't need to ask more redundant questions. config MPC8540 bool - depends on MPC8540_ADS - default y - -config MPC8548 - bool - depends on MPC8548_CDS - default y + select PPC_UDBG_16550 + select PPC_INDIRECT_PCI + default y if MPC8540_ADS -config MPC8555 - bool - depends on MPC8555_CDS - default y - -config MPC8560 +config PPC_INDIRECT_PCI_BE bool - depends on SBC8560 || MPC8560_ADS || STX_GP3 - default y - -config 85xx_PCI2 - bool "Supprt for 2nd PCI host controller" - depends on MPC8555_CDS + depends on PPC_85xx default y -config PPC_GEN550 +config MPIC bool - depends on MPC8540 || SBC8560 || MPC8555 default y endmenu diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index 6407197ffd89..b443206e61af 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile @@ -1 +1,4 @@ -# empty makefile so make clean works +# +# Makefile for the PowerPC 85xx linux kernel. +# +obj-$(CONFIG_PPC_85xx) += mpc85xx.o mpc85xx_ads.o diff --git a/arch/powerpc/platforms/85xx/mpc8540_ads.h b/arch/powerpc/platforms/85xx/mpc8540_ads.h new file mode 100644 index 000000000000..47609c97e01e --- /dev/null +++ b/arch/powerpc/platforms/85xx/mpc8540_ads.h @@ -0,0 +1,60 @@ +/* + * arch/ppc/platforms/85xx/mpc8540_ads.h + * + * MPC8540ADS board definitions + * + * Maintainer: Kumar Gala + * + * Copyright 2004 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef __MACH_MPC8540ADS_H__ +#define __MACH_MPC8540ADS_H__ + +#include +#include + +#define BOARD_CCSRBAR ((uint)0xe0000000) +#define BCSR_ADDR ((uint)0xf8000000) +#define BCSR_SIZE ((uint)(32 * 1024)) + +/* PCI interrupt controller */ +#define PIRQA MPC85xx_IRQ_EXT1 +#define PIRQB MPC85xx_IRQ_EXT2 +#define PIRQC MPC85xx_IRQ_EXT3 +#define PIRQD MPC85xx_IRQ_EXT4 + +#define MPC85XX_PCI1_LOWER_IO 0x00000000 +#define MPC85XX_PCI1_UPPER_IO 0x00ffffff + +#define MPC85XX_PCI1_LOWER_MEM 0x80000000 +#define MPC85XX_PCI1_UPPER_MEM 0x9fffffff + +#define MPC85XX_PCI1_IO_BASE 0xe2000000 +#define MPC85XX_PCI1_MEM_OFFSET 0x00000000 + +#define MPC85XX_PCI1_IO_SIZE 0x01000000 + +/* PCI config */ +#define PCI1_CFG_ADDR_OFFSET (0x8000) +#define PCI1_CFG_DATA_OFFSET (0x8004) + +#define PCI2_CFG_ADDR_OFFSET (0x9000) +#define PCI2_CFG_DATA_OFFSET (0x9004) + +/* Additional register for PCI-X configuration */ +#define PCIX_NEXT_CAP 0x60 +#define PCIX_CAP_ID 0x61 +#define PCIX_COMMAND 0x62 +#define PCIX_STATUS 0x64 + +/* Offset of CPM register space */ +#define CPM_MAP_ADDR (CCSRBAR + MPC85xx_CPM_OFFSET) + +#endif /* __MACH_MPC8540ADS_H__ */ diff --git a/arch/powerpc/platforms/85xx/mpc85xx.c b/arch/powerpc/platforms/85xx/mpc85xx.c new file mode 100644 index 000000000000..82510385d88a --- /dev/null +++ b/arch/powerpc/platforms/85xx/mpc85xx.c @@ -0,0 +1,31 @@ +/* + * MPC85xx generic code. + * + * Maintained by Kumar Gala (see MAINTAINERS for contact information) + * + * Copyright 2005 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include + +extern void abort(void); + +void +mpc85xx_restart(char *cmd) +{ + local_irq_disable(); + abort(); +} + +/* For now this is a pass through */ +phys_addr_t fixup_bigphys_addr(phys_addr_t addr, phys_addr_t size) +{ + return addr; +}; +EXPORT_SYMBOL(fixup_bigphys_addr); diff --git a/arch/powerpc/platforms/85xx/mpc85xx.h b/arch/powerpc/platforms/85xx/mpc85xx.h new file mode 100644 index 000000000000..be75abb2a283 --- /dev/null +++ b/arch/powerpc/platforms/85xx/mpc85xx.h @@ -0,0 +1,17 @@ +/* + * arch/ppc/platforms/85xx/mpc85xx.h + * + * MPC85xx soc definitions/function decls + * + * Maintainer: Kumar Gala + * + * Copyright 2005 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +extern void mpc85xx_restart(char *); diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c new file mode 100644 index 000000000000..41191e9aa528 --- /dev/null +++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c @@ -0,0 +1,208 @@ +/* + * MPC85xx setup and early boot code plus other random bits. + * + * Maintained by Kumar Gala (see MAINTAINERS for contact information) + * + * Copyright 2005 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for linux/serial_core.h */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "mpc85xx.h" + +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +#endif + + +/* + * Internal interrupts are all Level Sensitive, and Positive Polarity + * + * Note: Likely, this table and the following function should be + * obtained and derived from the OF Device Tree. + */ +static u_char mpc85xx_ads_openpic_initsenses[] __initdata = { + MPC85XX_INTERNAL_IRQ_SENSES, + 0x0, /* External 0: */ +#if defined(CONFIG_PCI) + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 1: PCI slot 0 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 2: PCI slot 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 3: PCI slot 2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 4: PCI slot 3 */ +#else + 0x0, /* External 1: */ + 0x0, /* External 2: */ + 0x0, /* External 3: */ + 0x0, /* External 4: */ +#endif + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 5: PHY */ + 0x0, /* External 6: */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 7: PHY */ + 0x0, /* External 8: */ + 0x0, /* External 9: */ + 0x0, /* External 10: */ + 0x0, /* External 11: */ +}; + + +void __init mpc85xx_ads_pic_init(void) +{ + struct mpic *mpic1; + phys_addr_t OpenPIC_PAddr; + + /* Determine the Physical Address of the OpenPIC regs */ + OpenPIC_PAddr = get_immrbase() + MPC85xx_OPENPIC_OFFSET; + + mpic1 = mpic_alloc(OpenPIC_PAddr, + MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, + 4, MPC85xx_OPENPIC_IRQ_OFFSET, 0, 250, + mpc85xx_ads_openpic_initsenses, + sizeof(mpc85xx_ads_openpic_initsenses), " OpenPIC "); + BUG_ON(mpic1 == NULL); + mpic_assign_isu(mpic1, 0, OpenPIC_PAddr + 0x10200); + mpic_assign_isu(mpic1, 1, OpenPIC_PAddr + 0x10280); + mpic_assign_isu(mpic1, 2, OpenPIC_PAddr + 0x10300); + mpic_assign_isu(mpic1, 3, OpenPIC_PAddr + 0x10380); + mpic_assign_isu(mpic1, 4, OpenPIC_PAddr + 0x10400); + mpic_assign_isu(mpic1, 5, OpenPIC_PAddr + 0x10480); + mpic_assign_isu(mpic1, 6, OpenPIC_PAddr + 0x10500); + mpic_assign_isu(mpic1, 7, OpenPIC_PAddr + 0x10580); + + /* dummy mappings to get to 48 */ + mpic_assign_isu(mpic1, 8, OpenPIC_PAddr + 0x10600); + mpic_assign_isu(mpic1, 9, OpenPIC_PAddr + 0x10680); + mpic_assign_isu(mpic1, 10, OpenPIC_PAddr + 0x10700); + mpic_assign_isu(mpic1, 11, OpenPIC_PAddr + 0x10780); + + /* External ints */ + mpic_assign_isu(mpic1, 12, OpenPIC_PAddr + 0x10000); + mpic_assign_isu(mpic1, 13, OpenPIC_PAddr + 0x10080); + mpic_assign_isu(mpic1, 14, OpenPIC_PAddr + 0x10100); + mpic_init(mpic1); +} + + +/* + * Setup the architecture + */ +static void __init +mpc85xx_ads_setup_arch(void) +{ + struct device_node *cpu; + + if (ppc_md.progress) + ppc_md.progress("mpc85xx_ads_setup_arch()", 0); + + cpu = of_find_node_by_type(NULL, "cpu"); + if (cpu != 0) { + unsigned int *fp; + + fp = (int *)get_property(cpu, "clock-frequency", NULL); + if (fp != 0) + loops_per_jiffy = *fp / HZ; + else + loops_per_jiffy = 50000000 / HZ; + of_node_put(cpu); + } + +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_HDA1; +#endif +} + + +void +mpc85xx_ads_show_cpuinfo(struct seq_file *m) +{ + uint pvid, svid, phid1; + uint memsize = total_memory; + + pvid = mfspr(SPRN_PVR); + svid = mfspr(SPRN_SVR); + + seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); + seq_printf(m, "Machine\t\t: mpc85xx\n"); + seq_printf(m, "PVR\t\t: 0x%x\n", pvid); + seq_printf(m, "SVR\t\t: 0x%x\n", svid); + + /* Display cpu Pll setting */ + phid1 = mfspr(SPRN_HID1); + seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); + + /* Display the amount of memory */ + seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); +} + + +void __init +platform_init(void) +{ + ppc_md.setup_arch = mpc85xx_ads_setup_arch; + ppc_md.show_cpuinfo = mpc85xx_ads_show_cpuinfo; + + ppc_md.init_IRQ = mpc85xx_ads_pic_init; + ppc_md.get_irq = mpic_get_irq; + + ppc_md.restart = mpc85xx_restart; + ppc_md.power_off = NULL; + ppc_md.halt = NULL; + + ppc_md.time_init = NULL; + ppc_md.set_rtc_time = NULL; + ppc_md.get_rtc_time = NULL; + ppc_md.calibrate_decr = generic_calibrate_decr; + + ppc_md.progress = udbg_progress; + + if (ppc_md.progress) + ppc_md.progress("mpc85xx_ads platform_init(): exit", 0); +} + + diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile index 04073fd987ec..c4f6b0d2d140 100644 --- a/arch/powerpc/platforms/Makefile +++ b/arch/powerpc/platforms/Makefile @@ -8,7 +8,7 @@ endif obj-$(CONFIG_PPC_CHRP) += chrp/ obj-$(CONFIG_4xx) += 4xx/ obj-$(CONFIG_PPC_83xx) += 83xx/ -obj-$(CONFIG_85xx) += 85xx/ +obj-$(CONFIG_PPC_85xx) += 85xx/ obj-$(CONFIG_PPC_PSERIES) += pseries/ obj-$(CONFIG_PPC_ISERIES) += iseries/ obj-$(CONFIG_PPC_MAPLE) += maple/ -- cgit v1.2.2 From f4fc4a5b74cff2a487222f05704a2bd01953d250 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Mon, 16 Jan 2006 10:53:22 -0600 Subject: [PATCH] powerpc: Add CONFIG_DEFAULT_UIMAGE to build a uImage by default for a board Embedded boards that u-boot require a kernel image in the uImage format. This allows a given board to specify it wants a uImage built by default. Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras --- arch/powerpc/Kconfig | 6 ++++++ arch/powerpc/Makefile | 1 + 2 files changed, 7 insertions(+) (limited to 'arch/powerpc') diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 8aa39d073dfe..fb0dcb994b84 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -83,6 +83,12 @@ config GENERIC_TBSYNC default y if PPC32 && SMP default n +config DEFAULT_UIMAGE + bool + help + Used to allow a board to specify it wants a uImage built by default + default n + menu "Processor support" choice prompt "Processor Type" diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 44dd82b791d1..15fc3e98ac5c 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -142,6 +142,7 @@ drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/ # Default to zImage, override when needed defaultimage-y := zImage defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux +defaultimage-$(CONFIG_DEFAULT_UIMAGE) := uImage KBUILD_IMAGE := $(defaultimage-y) all: $(KBUILD_IMAGE) -- cgit v1.2.2 From 72646c7f69acad3595cc69f82a6e664a23b05542 Mon Sep 17 00:00:00 2001 From: "Grant C. Likely" Date: Thu, 19 Jan 2006 01:13:20 -0700 Subject: [PATCH] powerpc: Add Virtex-4 FX to cpu table Signed-off-by: Grant C. Likely Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/cputable.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 10696456a4c6..3191be7135fe 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -891,7 +891,7 @@ struct cpu_spec cpu_specs[] = { .platform = "ppc405", }, { /* Xilinx Virtex-II Pro */ - .pvr_mask = 0xffff0000, + .pvr_mask = 0xfffff000, .pvr_value = 0x20010000, .cpu_name = "Virtex-II Pro", .cpu_features = CPU_FTRS_40X, @@ -901,6 +901,16 @@ struct cpu_spec cpu_specs[] = { .dcache_bsize = 32, .platform = "ppc405", }, + { /* Xilinx Virtex-4 FX */ + .pvr_mask = 0xfffff000, + .pvr_value = 0x20011000, + .cpu_name = "Virtex-4 FX", + .cpu_features = CPU_FTRS_40X, + .cpu_user_features = PPC_FEATURE_32 | + PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, + .icache_bsize = 32, + .dcache_bsize = 32, + }, { /* 405EP */ .pvr_mask = 0xffff0000, .pvr_value = 0x51210000, -- cgit v1.2.2 From d2515c806ea2b602e99b9aa19448577c7f0318fb Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Sun, 22 Jan 2006 22:19:02 +0100 Subject: [PATCH] powerpc: cleanup pmac_newworld variable usage remove extern declarations of pmac_newworld move pmac_newworld to bss if there is any "interrupt-controller" device, then it is newworld. Signed-off-by: Olaf Hering Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/ppc_ksyms.c | 1 - arch/powerpc/platforms/powermac/setup.c | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index d9a459c144d8..b212d3e64b8d 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c @@ -57,7 +57,6 @@ extern void machine_check_exception(struct pt_regs *regs); extern void alignment_exception(struct pt_regs *regs); extern void program_check_exception(struct pt_regs *regs); extern void single_step_exception(struct pt_regs *regs); -extern int pmac_newworld; extern int sys_sigreturn(struct pt_regs *regs); EXPORT_SYMBOL(clear_pages); diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 89c4c3636161..616b1e3ebe04 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -88,11 +88,10 @@ int ppc_override_l2cr = 0; int ppc_override_l2cr_value; int has_l2cache = 0; -int pmac_newworld = 1; +int pmac_newworld; static int current_root_goodness = -1; -extern int pmac_newworld; extern struct machdep_calls pmac_md; #define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */ @@ -310,9 +309,10 @@ static void __init pmac_setup_arch(void) for (ic = NULL; (ic = of_find_all_nodes(ic)) != NULL; ) if (get_property(ic, "interrupt-controller", NULL)) break; - pmac_newworld = (ic != NULL); - if (ic) + if (ic) { + pmac_newworld = 1; of_node_put(ic); + } /* Lookup PCI hosts */ pmac_pci_init(); -- cgit v1.2.2 From 2fb07d776b3c4473275eb225b6bf2a83755c9bfe Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Mon, 23 Jan 2006 16:58:04 -0600 Subject: [PATCH] powerpc: cleaned up fsl_soc.c Cleaned up fsl_soc.c based on comments from Olof Johansson. Ran through Lindent, and split gfar_mdio init into its own function. Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras --- arch/powerpc/sysdev/fsl_soc.c | 152 ++++++++++++++++++++++++++---------------- 1 file changed, 94 insertions(+), 58 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index 064c9de47732..e0887d5c3bb1 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c @@ -40,7 +40,7 @@ phys_addr_t get_immrbase(void) return immrbase; soc = of_find_node_by_type(NULL, "soc"); - if (soc != 0) { + if (soc) { unsigned int size; void *prop = get_property(soc, "reg", &size); immrbase = of_translate_address(soc, prop); @@ -49,21 +49,20 @@ phys_addr_t get_immrbase(void) return immrbase; } -EXPORT_SYMBOL(get_immrbase); -static const char * gfar_tx_intr = "tx"; -static const char * gfar_rx_intr = "rx"; -static const char * gfar_err_intr = "error"; +EXPORT_SYMBOL(get_immrbase); -static int __init gfar_of_init(void) +static int __init gfar_mdio_of_init(void) { struct device_node *np; unsigned int i; - struct platform_device *mdio_dev, *gfar_dev; + struct platform_device *mdio_dev; struct resource res; int ret; - for (np = NULL, i = 0; (np = of_find_compatible_node(np, "mdio", "gianfar")) != NULL; i++) { + for (np = NULL, i = 0; + (np = of_find_compatible_node(np, "mdio", "gianfar")) != NULL; + i++) { int k; struct device_node *child = NULL; struct gianfar_mdio_data mdio_data; @@ -73,12 +72,14 @@ static int __init gfar_of_init(void) ret = of_address_to_resource(np, 0, &res); if (ret) - goto mdio_err; + goto err; - mdio_dev = platform_device_register_simple("fsl-gianfar_mdio", res.start, &res, 1); + mdio_dev = + platform_device_register_simple("fsl-gianfar_mdio", + res.start, &res, 1); if (IS_ERR(mdio_dev)) { ret = PTR_ERR(mdio_dev); - goto mdio_err; + goto err; } for (k = 0; k < 32; k++) @@ -86,17 +87,44 @@ static int __init gfar_of_init(void) while ((child = of_get_next_child(np, child)) != NULL) { if (child->n_intrs) { - u32 *id = (u32 *) get_property(child, "reg", NULL); + u32 *id = + (u32 *) get_property(child, "reg", NULL); mdio_data.irq[*id] = child->intrs[0].line; } } - ret = platform_device_add_data(mdio_dev, &mdio_data, sizeof(struct gianfar_mdio_data)); + ret = + platform_device_add_data(mdio_dev, &mdio_data, + sizeof(struct gianfar_mdio_data)); if (ret) - goto mdio_unreg; + goto unreg; } - for (np = NULL, i = 0; (np = of_find_compatible_node(np, "network", "gianfar")) != NULL; i++) { + return 0; + +unreg: + platform_device_unregister(mdio_dev); +err: + return ret; +} + +arch_initcall(gfar_mdio_of_init); + +static const char *gfar_tx_intr = "tx"; +static const char *gfar_rx_intr = "rx"; +static const char *gfar_err_intr = "error"; + +static int __init gfar_of_init(void) +{ + struct device_node *np; + unsigned int i; + struct platform_device *gfar_dev; + struct resource res; + int ret; + + for (np = NULL, i = 0; + (np = of_find_compatible_node(np, "network", "gianfar")) != NULL; + i++) { struct resource r[4]; struct device_node *phy, *mdio; struct gianfar_platform_data gfar_data; @@ -110,7 +138,7 @@ static int __init gfar_of_init(void) ret = of_address_to_resource(np, 0, &r[0]); if (ret) - goto gfar_err; + goto err; r[1].start = np->intrs[0].line; r[1].end = np->intrs[0].line; @@ -133,11 +161,13 @@ static int __init gfar_of_init(void) r[3].flags = IORESOURCE_IRQ; } - gfar_dev = platform_device_register_simple("fsl-gianfar", i, &r[0], np->n_intrs + 1); + gfar_dev = + platform_device_register_simple("fsl-gianfar", i, &r[0], + np->n_intrs + 1); if (IS_ERR(gfar_dev)) { ret = PTR_ERR(gfar_dev); - goto gfar_err; + goto err; } mac_addr = get_property(np, "address", NULL); @@ -145,26 +175,26 @@ static int __init gfar_of_init(void) if (model && !strcasecmp(model, "TSEC")) gfar_data.device_flags = - FSL_GIANFAR_DEV_HAS_GIGABIT | - FSL_GIANFAR_DEV_HAS_COALESCE | - FSL_GIANFAR_DEV_HAS_RMON | - FSL_GIANFAR_DEV_HAS_MULTI_INTR; + FSL_GIANFAR_DEV_HAS_GIGABIT | + FSL_GIANFAR_DEV_HAS_COALESCE | + FSL_GIANFAR_DEV_HAS_RMON | + FSL_GIANFAR_DEV_HAS_MULTI_INTR; if (model && !strcasecmp(model, "eTSEC")) gfar_data.device_flags = - FSL_GIANFAR_DEV_HAS_GIGABIT | - FSL_GIANFAR_DEV_HAS_COALESCE | - FSL_GIANFAR_DEV_HAS_RMON | - FSL_GIANFAR_DEV_HAS_MULTI_INTR | - FSL_GIANFAR_DEV_HAS_CSUM | - FSL_GIANFAR_DEV_HAS_VLAN | - FSL_GIANFAR_DEV_HAS_EXTENDED_HASH; + FSL_GIANFAR_DEV_HAS_GIGABIT | + FSL_GIANFAR_DEV_HAS_COALESCE | + FSL_GIANFAR_DEV_HAS_RMON | + FSL_GIANFAR_DEV_HAS_MULTI_INTR | + FSL_GIANFAR_DEV_HAS_CSUM | + FSL_GIANFAR_DEV_HAS_VLAN | + FSL_GIANFAR_DEV_HAS_EXTENDED_HASH; ph = (phandle *) get_property(np, "phy-handle", NULL); phy = of_find_node_by_phandle(*ph); if (phy == NULL) { ret = -ENODEV; - goto gfar_unreg; + goto unreg; } mdio = of_get_parent(phy); @@ -174,7 +204,7 @@ static int __init gfar_of_init(void) if (ret) { of_node_put(phy); of_node_put(mdio); - goto gfar_unreg; + goto unreg; } gfar_data.phy_id = *id; @@ -183,23 +213,22 @@ static int __init gfar_of_init(void) of_node_put(phy); of_node_put(mdio); - ret = platform_device_add_data(gfar_dev, &gfar_data, sizeof(struct gianfar_platform_data)); + ret = + platform_device_add_data(gfar_dev, &gfar_data, + sizeof(struct + gianfar_platform_data)); if (ret) - goto gfar_unreg; + goto unreg; } return 0; -mdio_unreg: - platform_device_unregister(mdio_dev); -mdio_err: - return ret; - -gfar_unreg: +unreg: platform_device_unregister(gfar_dev); -gfar_err: +err: return ret; } + arch_initcall(gfar_of_init); static int __init fsl_i2c_of_init(void) @@ -209,17 +238,19 @@ static int __init fsl_i2c_of_init(void) struct platform_device *i2c_dev; int ret; - for (np = NULL, i = 0; (np = of_find_compatible_node(np, "i2c", "fsl-i2c")) != NULL; i++) { + for (np = NULL, i = 0; + (np = of_find_compatible_node(np, "i2c", "fsl-i2c")) != NULL; + i++) { struct resource r[2]; struct fsl_i2c_platform_data i2c_data; - unsigned char * flags = NULL; + unsigned char *flags = NULL; memset(&r, 0, sizeof(r)); memset(&i2c_data, 0, sizeof(i2c_data)); ret = of_address_to_resource(np, 0, &r[0]); if (ret) - goto i2c_err; + goto err; r[1].start = np->intrs[0].line; r[1].end = np->intrs[0].line; @@ -228,7 +259,7 @@ static int __init fsl_i2c_of_init(void) i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2); if (IS_ERR(i2c_dev)) { ret = PTR_ERR(i2c_dev); - goto i2c_err; + goto err; } i2c_data.device_flags = 0; @@ -240,18 +271,22 @@ static int __init fsl_i2c_of_init(void) if (flags) i2c_data.device_flags |= FSL_I2C_DEV_CLOCK_5200; - ret = platform_device_add_data(i2c_dev, &i2c_data, sizeof(struct fsl_i2c_platform_data)); + ret = + platform_device_add_data(i2c_dev, &i2c_data, + sizeof(struct + fsl_i2c_platform_data)); if (ret) - goto i2c_unreg; + goto unreg; } return 0; -i2c_unreg: +unreg: platform_device_unregister(i2c_dev); -i2c_err: +err: return ret; } + arch_initcall(fsl_i2c_of_init); #ifdef CONFIG_PPC_83xx @@ -267,51 +302,52 @@ static int __init mpc83xx_wdt_init(void) if (!np) { ret = -ENODEV; - goto mpc83xx_wdt_nodev; + goto nodev; } soc = of_find_node_by_type(NULL, "soc"); if (!soc) { ret = -ENODEV; - goto mpc83xx_wdt_nosoc; + goto nosoc; } freq = (unsigned int *)get_property(soc, "bus-frequency", NULL); if (!freq) { ret = -ENODEV; - goto mpc83xx_wdt_err; + goto err; } memset(&r, 0, sizeof(r)); ret = of_address_to_resource(np, 0, &r); if (ret) - goto mpc83xx_wdt_err; + goto err; dev = platform_device_register_simple("mpc83xx_wdt", 0, &r, 1); if (IS_ERR(dev)) { ret = PTR_ERR(dev); - goto mpc83xx_wdt_err; + goto err; } ret = platform_device_add_data(dev, freq, sizeof(int)); if (ret) - goto mpc83xx_wdt_unreg; + goto unreg; of_node_put(soc); of_node_put(np); return 0; -mpc83xx_wdt_unreg: +unreg: platform_device_unregister(dev); -mpc83xx_wdt_err: +err: of_node_put(soc); -mpc83xx_wdt_nosoc: +nosoc: of_node_put(np); -mpc83xx_wdt_nodev: +nodev: return ret; } + arch_initcall(mpc83xx_wdt_init); #endif -- cgit v1.2.2 From d7a5b2ffa1352f0310630934a56aecbdfb617b72 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 25 Jan 2006 21:31:28 +1300 Subject: [PATCH] powerpc: Always panic if lmb_alloc() fails Currently most callers of lmb_alloc() don't check if it worked or not, if it ever does weird bad things will probably happen. The few callers who do check just panic or BUG_ON. So make lmb_alloc() panic internally, to catch bugs at the source. The few callers who did check the result no longer need to. The only caller that did anything interesting with the return result was careful_allocation(). For it we create __lmb_alloc_base() which _doesn't_ panic automatically, a little messy, but passable. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom.c | 4 ---- arch/powerpc/mm/hash_utils_64.c | 1 - arch/powerpc/mm/lmb.c | 14 ++++++++++++++ arch/powerpc/mm/mem.c | 1 - arch/powerpc/mm/numa.c | 4 ++-- arch/powerpc/mm/stab.c | 4 ---- arch/powerpc/sysdev/dart_iommu.c | 2 -- 7 files changed, 16 insertions(+), 14 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 294832a7e0a6..82d117c60d7f 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -831,10 +831,6 @@ void __init unflatten_device_tree(void) /* Allocate memory for the expanded device tree */ mem = lmb_alloc(size + 4, __alignof__(struct device_node)); - if (!mem) { - DBG("Couldn't allocate memory with lmb_alloc()!\n"); - panic("Couldn't allocate memory with lmb_alloc()!\n"); - } mem = (unsigned long) __va(mem); ((u32 *)mem)[size / 4] = 0xdeadbeef; diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 149351a84b94..95b4cd6b65e0 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -430,7 +430,6 @@ void __init htab_initialize(void) * the absolute address space. */ table = lmb_alloc(htab_size_bytes, htab_size_bytes); - BUG_ON(table == 0); DBG("Hash table allocated at %lx, size: %lx\n", table, htab_size_bytes); diff --git a/arch/powerpc/mm/lmb.c b/arch/powerpc/mm/lmb.c index bbe3eac918e8..d9c76ce5fa8f 100644 --- a/arch/powerpc/mm/lmb.c +++ b/arch/powerpc/mm/lmb.c @@ -225,6 +225,20 @@ unsigned long __init lmb_alloc(unsigned long size, unsigned long align) unsigned long __init lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr) +{ + unsigned long alloc; + + alloc = __lmb_alloc_base(size, align, max_addr); + + if (alloc < 0) + panic("ERROR: Failed to allocate 0x%lx bytes below 0x%lx.\n", + size, max_addr); + + return alloc; +} + +unsigned long __init __lmb_alloc_base(unsigned long size, unsigned long align, + unsigned long max_addr) { long i, j; unsigned long base = 0; diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 550517c2dd42..6809cdba6e94 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -249,7 +249,6 @@ void __init do_init_bootmem(void) bootmap_pages = bootmem_bootmap_pages(total_pages); start = lmb_alloc(bootmap_pages << PAGE_SHIFT, PAGE_SIZE); - BUG_ON(!start); boot_mapsize = init_bootmem(start >> PAGE_SHIFT, total_pages); diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 2863a912bcd0..da5280f8cf42 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -570,11 +570,11 @@ static void __init *careful_allocation(int nid, unsigned long size, unsigned long end_pfn) { int new_nid; - unsigned long ret = lmb_alloc_base(size, align, end_pfn << PAGE_SHIFT); + unsigned long ret = __lmb_alloc_base(size, align, end_pfn << PAGE_SHIFT); /* retry over all memory */ if (!ret) - ret = lmb_alloc_base(size, align, lmb_end_of_DRAM()); + ret = __lmb_alloc_base(size, align, lmb_end_of_DRAM()); if (!ret) panic("numa.c: cannot allocate %lu bytes on node %d", diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c index 82e4951826bc..91d25fb27f89 100644 --- a/arch/powerpc/mm/stab.c +++ b/arch/powerpc/mm/stab.c @@ -247,10 +247,6 @@ void stabs_alloc(void) newstab = lmb_alloc_base(HW_PAGE_SIZE, HW_PAGE_SIZE, 1<> DART_PAGE_SHIFT) & DARTMAP_RPNMASK); -- cgit v1.2.2 From 3b9331dac16555e8788ae21723f2146c3f994ebb Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 25 Jan 2006 21:31:30 +1300 Subject: [PATCH] powerpc: Move LMB_ALLOC_ANYWHERE out of lmb.h LMB_ALLOC_ANYWHERE doesn't need to be part of the API, it's only used in lmb.c - so move it out of the header file. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/mm/lmb.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/powerpc') diff --git a/arch/powerpc/mm/lmb.c b/arch/powerpc/mm/lmb.c index d9c76ce5fa8f..874cd103ce6e 100644 --- a/arch/powerpc/mm/lmb.c +++ b/arch/powerpc/mm/lmb.c @@ -31,6 +31,8 @@ #define DBG(fmt...) #endif +#define LMB_ALLOC_ANYWHERE 0 + struct lmb lmb; void lmb_dump_all(void) -- cgit v1.2.2 From 158daa4cc827bda9f7206279a1dc55de2cb9c902 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Mon, 30 Jan 2006 14:28:03 +0100 Subject: [PATCH] powerpc: remove check for ELF offset in powerpc bootimage Do not check for offset, it is always set. Signed-off-by: Olaf Hering Signed-off-by: Paul Mackerras --- arch/powerpc/boot/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c index 55ec59867250..816446f0e497 100644 --- a/arch/powerpc/boot/main.c +++ b/arch/powerpc/boot/main.c @@ -152,7 +152,7 @@ static int is_elf64(void *hdr) elf64ph = (Elf64_Phdr *)((unsigned long)elf64 + (unsigned long)elf64->e_phoff); for (i = 0; i < (unsigned int)elf64->e_phnum; i++, elf64ph++) - if (elf64ph->p_type == PT_LOAD && elf64ph->p_offset != 0) + if (elf64ph->p_type == PT_LOAD) break; if (i >= (unsigned int)elf64->e_phnum) return 0; @@ -193,7 +193,7 @@ static int is_elf32(void *hdr) elf32 = (Elf32_Ehdr *)elfheader; elf32ph = (Elf32_Phdr *) ((unsigned long)elf32 + elf32->e_phoff); for (i = 0; i < elf32->e_phnum; i++, elf32ph++) - if (elf32ph->p_type == PT_LOAD && elf32ph->p_offset != 0) + if (elf32ph->p_type == PT_LOAD) break; if (i >= elf32->e_phnum) return 0; -- cgit v1.2.2 From 4b10cfd40e3fa1c1663b9c9fa22260d41e669c6f Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Thu, 2 Feb 2006 12:31:00 -0600 Subject: [PATCH] powerpc: Add platform support for MPC834x USB controllers Setup the platform devices needed by the Freescale EHCI USB host controllers based on a flat device tree Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras --- arch/powerpc/sysdev/fsl_soc.c | 140 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) (limited to 'arch/powerpc') diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index e0887d5c3bb1..ceb584682fa3 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c @@ -351,3 +351,143 @@ nodev: arch_initcall(mpc83xx_wdt_init); #endif + +static enum fsl_usb2_phy_modes determine_usb_phy(char * phy_type) +{ + if (!phy_type) + return FSL_USB2_PHY_NONE; + if (!strcasecmp(phy_type, "ulpi")) + return FSL_USB2_PHY_ULPI; + if (!strcasecmp(phy_type, "utmi")) + return FSL_USB2_PHY_UTMI; + if (!strcasecmp(phy_type, "utmi_wide")) + return FSL_USB2_PHY_UTMI_WIDE; + if (!strcasecmp(phy_type, "serial")) + return FSL_USB2_PHY_SERIAL; + + return FSL_USB2_PHY_NONE; +} + +static int __init fsl_usb_of_init(void) +{ + struct device_node *np; + unsigned int i; + struct platform_device *usb_dev; + int ret; + + for (np = NULL, i = 0; + (np = of_find_compatible_node(np, "usb", "fsl-usb2-mph")) != NULL; + i++) { + struct resource r[2]; + struct fsl_usb2_platform_data usb_data; + unsigned char *prop = NULL; + + memset(&r, 0, sizeof(r)); + memset(&usb_data, 0, sizeof(usb_data)); + + ret = of_address_to_resource(np, 0, &r[0]); + if (ret) + goto err; + + r[1].start = np->intrs[0].line; + r[1].end = np->intrs[0].line; + r[1].flags = IORESOURCE_IRQ; + + usb_dev = + platform_device_register_simple("fsl-usb2-mph", i, r, 2); + if (IS_ERR(usb_dev)) { + ret = PTR_ERR(usb_dev); + goto err; + } + + usb_dev->dev.coherent_dma_mask = 0xffffffffUL; + usb_dev->dev.dma_mask = &usb_dev->dev.coherent_dma_mask; + + usb_data.operating_mode = FSL_USB2_MPH_HOST; + + prop = get_property(np, "port0", NULL); + if (prop) + usb_data.port_enables |= FSL_USB2_PORT0_ENABLED; + + prop = get_property(np, "port1", NULL); + if (prop) + usb_data.port_enables |= FSL_USB2_PORT1_ENABLED; + + prop = get_property(np, "phy_type", NULL); + usb_data.phy_mode = determine_usb_phy(prop); + + ret = + platform_device_add_data(usb_dev, &usb_data, + sizeof(struct + fsl_usb2_platform_data)); + if (ret) + goto unreg; + } + + return 0; + +unreg: + platform_device_unregister(usb_dev); +err: + return ret; +} + +arch_initcall(fsl_usb_of_init); + +static int __init fsl_usb_dr_of_init(void) +{ + struct device_node *np; + unsigned int i; + struct platform_device *usb_dev; + int ret; + + for (np = NULL, i = 0; + (np = of_find_compatible_node(np, "usb", "fsl-usb2-dr")) != NULL; + i++) { + struct resource r[2]; + struct fsl_usb2_platform_data usb_data; + unsigned char *prop = NULL; + + memset(&r, 0, sizeof(r)); + memset(&usb_data, 0, sizeof(usb_data)); + + ret = of_address_to_resource(np, 0, &r[0]); + if (ret) + goto err; + + r[1].start = np->intrs[0].line; + r[1].end = np->intrs[0].line; + r[1].flags = IORESOURCE_IRQ; + + usb_dev = + platform_device_register_simple("fsl-usb2-dr", i, r, 2); + if (IS_ERR(usb_dev)) { + ret = PTR_ERR(usb_dev); + goto err; + } + + usb_dev->dev.coherent_dma_mask = 0xffffffffUL; + usb_dev->dev.dma_mask = &usb_dev->dev.coherent_dma_mask; + + usb_data.operating_mode = FSL_USB2_DR_HOST; + + prop = get_property(np, "phy_type", NULL); + usb_data.phy_mode = determine_usb_phy(prop); + + ret = + platform_device_add_data(usb_dev, &usb_data, + sizeof(struct + fsl_usb2_platform_data)); + if (ret) + goto unreg; + } + + return 0; + +unreg: + platform_device_unregister(usb_dev); +err: + return ret; +} + +arch_initcall(fsl_usb_dr_of_init); -- cgit v1.2.2 From 30f5933657d17fbbc743ce9522543ba50ce2e834 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Thu, 2 Feb 2006 13:50:44 -0600 Subject: [PATCH] powerpc: Cleanup MPC83xx platform support Moved some code around so its usable by more systems than just the MPC834x SYS. Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/83xx/Makefile | 4 ++- arch/powerpc/platforms/83xx/misc.c | 55 +++++++++++++++++++++++++++++ arch/powerpc/platforms/83xx/mpc834x_sys.c | 58 ------------------------------- arch/powerpc/platforms/83xx/mpc83xx.h | 3 ++ arch/powerpc/platforms/83xx/pci.c | 13 +++++-- 5 files changed, 71 insertions(+), 62 deletions(-) create mode 100644 arch/powerpc/platforms/83xx/misc.c (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile index 9d8b28ef3343..5c72367441a8 100644 --- a/arch/powerpc/platforms/83xx/Makefile +++ b/arch/powerpc/platforms/83xx/Makefile @@ -1,4 +1,6 @@ # # Makefile for the PowerPC 83xx linux kernel. # -obj-$(CONFIG_MPC834x_SYS) += mpc834x_sys.o pci.o +obj-y := misc.o +obj-$(CONFIG_PCI) += pci.o +obj-$(CONFIG_MPC834x_SYS) += mpc834x_sys.o diff --git a/arch/powerpc/platforms/83xx/misc.c b/arch/powerpc/platforms/83xx/misc.c new file mode 100644 index 000000000000..0eb3d99f1b93 --- /dev/null +++ b/arch/powerpc/platforms/83xx/misc.c @@ -0,0 +1,55 @@ +/* + * misc setup functions for MPC83xx + * + * Maintainer: Kumar Gala + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include + +#include +#include +#include + +#include "mpc83xx.h" + +void mpc83xx_restart(char *cmd) +{ +#define RST_OFFSET 0x00000900 +#define RST_PROT_REG 0x00000018 +#define RST_CTRL_REG 0x0000001c + __be32 __iomem *reg; + + /* map reset register space */ + reg = ioremap(get_immrbase() + 0x900, 0xff); + + local_irq_disable(); + + /* enable software reset "RSTE" */ + out_be32(reg + (RST_PROT_REG >> 2), 0x52535445); + + /* set software hard reset */ + out_be32(reg + (RST_CTRL_REG >> 2), 0x52535445); + for (;;) ; +} + +long __init mpc83xx_time_init(void) +{ +#define SPCR_OFFSET 0x00000110 +#define SPCR_TBEN 0x00400000 + __be32 __iomem *spcr = ioremap(get_immrbase() + SPCR_OFFSET, 4); + __be32 tmp; + + tmp = in_be32(spcr); + out_be32(spcr, tmp | SPCR_TBEN); + + iounmap(spcr); + + return 0; +} diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.c b/arch/powerpc/platforms/83xx/mpc834x_sys.c index 2098dd05a773..7d5a27829bc8 100644 --- a/arch/powerpc/platforms/83xx/mpc834x_sys.c +++ b/arch/powerpc/platforms/83xx/mpc834x_sys.c @@ -24,22 +24,15 @@ #include #include #include -#include -#include #include -#include -#include #include #include #include #include #include #include -#include -#include #include -#include #include #include #include @@ -52,8 +45,6 @@ unsigned long isa_mem_base = 0; #endif #ifdef CONFIG_PCI -extern int mpc83xx_pci2_busno; - static int mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) { @@ -78,17 +69,6 @@ mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) const long min_idsel = 0x11, max_idsel = 0x20, irqs_per_slot = 4; return PCI_IRQ_TABLE_LOOKUP; } - -static int -mpc83xx_exclude_device(u_char bus, u_char devfn) -{ - if (bus == 0 && PCI_SLOT(devfn) == 0) - return PCIBIOS_DEVICE_NOT_FOUND; - if (mpc83xx_pci2_busno) - if (bus == (mpc83xx_pci2_busno) && PCI_SLOT(devfn) == 0) - return PCIBIOS_DEVICE_NOT_FOUND; - return PCIBIOS_SUCCESSFUL; -} #endif /* CONFIG_PCI */ /* ************************************************************************ @@ -180,42 +160,6 @@ mpc834x_rtc_hookup(void) late_initcall(mpc834x_rtc_hookup); #endif -static void -mpc83xx_restart(char *cmd) -{ -#define RST_OFFSET 0x00000900 -#define RST_PROT_REG 0x00000018 -#define RST_CTRL_REG 0x0000001c - __be32 __iomem *reg; - - // map reset register space - reg = ioremap(get_immrbase() + 0x900, 0xff); - - local_irq_disable(); - - /* enable software reset "RSTE" */ - out_be32(reg + (RST_PROT_REG >> 2), 0x52535445); - - /* set software hard reset */ - out_be32(reg + (RST_CTRL_REG >> 2), 0x52535445); - for(;;); -} - -static long __init -mpc83xx_time_init(void) -{ -#define SPCR_OFFSET 0x00000110 -#define SPCR_TBEN 0x00400000 - __be32 __iomem *spcr = ioremap(get_immrbase() + SPCR_OFFSET, 4); - __be32 tmp; - - tmp = in_be32(spcr); - out_be32(spcr, tmp|SPCR_TBEN); - - iounmap(spcr); - - return 0; -} void __init platform_init(void) { @@ -239,5 +183,3 @@ platform_init(void) return; } - - diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h index ce9e66abef24..228d5c463f71 100644 --- a/arch/powerpc/platforms/83xx/mpc83xx.h +++ b/arch/powerpc/platforms/83xx/mpc83xx.h @@ -10,5 +10,8 @@ */ extern int add_bridge(struct device_node *dev); +extern int mpc83xx_exclude_device(u_char bus, u_char devfn); +extern void mpc83xx_restart(char *cmd); +extern long mpc83xx_time_init(void); #endif /* __MPC83XX_H__ */ diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c index 469cdacc5bd4..70e28fcdb38f 100644 --- a/arch/powerpc/platforms/83xx/pci.c +++ b/arch/powerpc/platforms/83xx/pci.c @@ -36,7 +36,16 @@ int mpc83xx_pci2_busno; -#ifdef CONFIG_PCI +int mpc83xx_exclude_device(u_char bus, u_char devfn) +{ + if (bus == 0 && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + if (mpc83xx_pci2_busno) + if (bus == (mpc83xx_pci2_busno) && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + return PCIBIOS_SUCCESSFUL; +} + int __init add_bridge(struct device_node *dev) { int len; @@ -95,5 +104,3 @@ int __init add_bridge(struct device_node *dev) return 0; } - -#endif -- cgit v1.2.2 From e060e084e7d9e1c62d02cb6b8d3fe07db5317eaa Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Thu, 2 Feb 2006 13:51:10 -0600 Subject: [PATCH] powerpc: Lindent platforms/83xx Ran arch/powerpc/platforms/83xx through Lindent Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/83xx/mpc834x_sys.c | 31 ++++++++++++++----------------- arch/powerpc/platforms/83xx/mpc834x_sys.h | 2 +- arch/powerpc/platforms/83xx/mpc83xx.h | 2 +- arch/powerpc/platforms/83xx/pci.c | 8 ++++---- 4 files changed, 20 insertions(+), 23 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.c b/arch/powerpc/platforms/83xx/mpc834x_sys.c index 7d5a27829bc8..7c18b4cd5db4 100644 --- a/arch/powerpc/platforms/83xx/mpc834x_sys.c +++ b/arch/powerpc/platforms/83xx/mpc834x_sys.c @@ -69,15 +69,14 @@ mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) const long min_idsel = 0x11, max_idsel = 0x20, irqs_per_slot = 4; return PCI_IRQ_TABLE_LOOKUP; } -#endif /* CONFIG_PCI */ +#endif /* CONFIG_PCI */ /* ************************************************************************ * * Setup the architecture * */ -static void __init -mpc834x_sys_setup_arch(void) +static void __init mpc834x_sys_setup_arch(void) { struct device_node *np; @@ -86,14 +85,14 @@ mpc834x_sys_setup_arch(void) np = of_find_node_by_type(NULL, "cpu"); if (np != 0) { - unsigned int *fp = (int *) get_property(np, "clock-frequency", NULL); + unsigned int *fp = + (int *)get_property(np, "clock-frequency", NULL); if (fp != 0) loops_per_jiffy = *fp / HZ; else loops_per_jiffy = 50000000 / HZ; of_node_put(np); } - #ifdef CONFIG_PCI for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) add_bridge(np); @@ -104,14 +103,13 @@ mpc834x_sys_setup_arch(void) #endif #ifdef CONFIG_ROOT_NFS - ROOT_DEV = Root_NFS; + ROOT_DEV = Root_NFS; #else - ROOT_DEV = Root_HDA1; + ROOT_DEV = Root_HDA1; #endif } -void __init -mpc834x_sys_init_IRQ(void) +void __init mpc834x_sys_init_IRQ(void) { u8 senses[8] = { 0, /* EXT 0 */ @@ -140,28 +138,27 @@ mpc834x_sys_init_IRQ(void) } #if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374) -extern ulong ds1374_get_rtc_time(void); -extern int ds1374_set_rtc_time(ulong); +extern ulong ds1374_get_rtc_time(void); +extern int ds1374_set_rtc_time(ulong); -static int __init -mpc834x_rtc_hookup(void) +static int __init mpc834x_rtc_hookup(void) { - struct timespec tv; + struct timespec tv; ppc_md.get_rtc_time = ds1374_get_rtc_time; ppc_md.set_rtc_time = ds1374_set_rtc_time; tv.tv_nsec = 0; - tv.tv_sec = (ppc_md.get_rtc_time)(); + tv.tv_sec = (ppc_md.get_rtc_time) (); do_settimeofday(&tv); return 0; } + late_initcall(mpc834x_rtc_hookup); #endif -void __init -platform_init(void) +void __init platform_init(void) { /* setup the PowerPC module struct */ ppc_md.setup_arch = mpc834x_sys_setup_arch; diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.h b/arch/powerpc/platforms/83xx/mpc834x_sys.h index e4ca39f6a862..fedecb73f7ff 100644 --- a/arch/powerpc/platforms/83xx/mpc834x_sys.h +++ b/arch/powerpc/platforms/83xx/mpc834x_sys.h @@ -20,4 +20,4 @@ #define PIRQC MPC83xx_IRQ_EXT6 #define PIRQD MPC83xx_IRQ_EXT7 -#endif /* __MACH_MPC83XX_SYS_H__ */ +#endif /* __MACH_MPC83XX_SYS_H__ */ diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h index 228d5c463f71..01cae106912b 100644 --- a/arch/powerpc/platforms/83xx/mpc83xx.h +++ b/arch/powerpc/platforms/83xx/mpc83xx.h @@ -14,4 +14,4 @@ extern int mpc83xx_exclude_device(u_char bus, u_char devfn); extern void mpc83xx_restart(char *cmd); extern long mpc83xx_time_init(void); -#endif /* __MPC83XX_H__ */ +#endif /* __MPC83XX_H__ */ diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c index 70e28fcdb38f..16f7d3b30e1d 100644 --- a/arch/powerpc/platforms/83xx/pci.c +++ b/arch/powerpc/platforms/83xx/pci.c @@ -61,7 +61,7 @@ int __init add_bridge(struct device_node *dev) has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); /* Get bus range if any */ - bus_range = (int *) get_property(dev, "bus-range", &len); + bus_range = (int *)get_property(dev, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) { printk(KERN_WARNING "Can't get bus-range for %s, assume" " bus 0\n", dev->full_name); @@ -83,7 +83,7 @@ int __init add_bridge(struct device_node *dev) if ((rsrc.start & 0xfffff) == 0x8500) { setup_indirect_pci(hose, immr + 0x8300, immr + 0x8304); } - /* PCI 2*/ + /* PCI 2 */ if ((rsrc.start & 0xfffff) == 0x8600) { setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384); primary = 0; @@ -93,10 +93,10 @@ int __init add_bridge(struct device_node *dev) printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%08lx. " "Firmware bus number: %d->%d\n", - rsrc.start, hose->first_busno, hose->last_busno); + rsrc.start, hose->first_busno, hose->last_busno); DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", - hose, hose->cfg_addr, hose->cfg_data); + hose, hose->cfg_addr, hose->cfg_data); /* Interpret the "ranges" property */ /* This also maps the I/O region and sets isa_io/mem_base */ -- cgit v1.2.2 From 66f2d025e234d44e35ae5bcec328078c35b8a8fb Mon Sep 17 00:00:00 2001 From: Becky Bruce Date: Tue, 31 Jan 2006 17:52:59 -0600 Subject: [PATCH] powerpc: Fix Kernel FP unavail exception for BookE Updated FP unavailable exception to refer to the correct function in traps.c. head_booke.h was using the old name, KernelFP, instead of kernel_fp_unavailable_exception. Signed-off-by: Becky Bruce Acked-by: Kumar Gala Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/head_booke.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/head_booke.h index 5827c27e0b59..8536e7676160 100644 --- a/arch/powerpc/kernel/head_booke.h +++ b/arch/powerpc/kernel/head_booke.h @@ -358,6 +358,6 @@ label: NORMAL_EXCEPTION_PROLOG; \ bne load_up_fpu; /* if from user, just load it up */ \ addi r3,r1,STACK_FRAME_OVERHEAD; \ - EXC_XFER_EE_LITE(0x800, KernelFP) + EXC_XFER_EE_LITE(0x800, kernel_fp_unavailable_exception) #endif /* __HEAD_BOOKE_H__ */ -- cgit v1.2.2 From 46ed55f647371008c33e06e61459192f96cc24ca Mon Sep 17 00:00:00 2001 From: Becky Bruce Date: Tue, 7 Feb 2006 21:22:52 -0600 Subject: [PATCH] powerpc: mpc85xx_ads.c include file cleanup Cut-and-paste from the old platform code in arch/ppc resulted in arch/powerpc/platforms/85xx/mpc85xx_ads.c having way too many header files included. Clean this up. Signed-off-by: Becky Bruce Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/85xx/mpc85xx_ads.c | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c index 41191e9aa528..9e8a91bc8018 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c @@ -14,38 +14,17 @@ #include #include #include -#include -#include -#include #include #include -#include -#include #include -#include #include #include -#include -#include /* for linux/serial_core.h */ -#include -#include -#include -#include -#include -#include #include -#include -#include -#include #include -#include #include -#include #include #include -#include -#include #include #include #include -- cgit v1.2.2 From e19217d42e3d12d74d9eca40827721a3ef1b251c Mon Sep 17 00:00:00 2001 From: Becky Bruce Date: Tue, 7 Feb 2006 21:27:34 -0600 Subject: [PATCH] powerpc: rename mpc85xx.c to misc.c Rename mpc85xx.c to misc.c to match the pattern established by the 8349 port - consistency is a good thing. Also run Lindent on the file to clean it up. Signed-off-by: Becky Bruce Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/85xx/Makefile | 2 +- arch/powerpc/platforms/85xx/misc.c | 31 +++++++++++++++++++++++++++++++ arch/powerpc/platforms/85xx/mpc85xx.c | 31 ------------------------------- 3 files changed, 32 insertions(+), 32 deletions(-) create mode 100644 arch/powerpc/platforms/85xx/misc.c delete mode 100644 arch/powerpc/platforms/85xx/mpc85xx.c (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index b443206e61af..70e1190809f8 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile @@ -1,4 +1,4 @@ # # Makefile for the PowerPC 85xx linux kernel. # -obj-$(CONFIG_PPC_85xx) += mpc85xx.o mpc85xx_ads.o +obj-$(CONFIG_PPC_85xx) += misc.o mpc85xx_ads.o diff --git a/arch/powerpc/platforms/85xx/misc.c b/arch/powerpc/platforms/85xx/misc.c new file mode 100644 index 000000000000..26c5e822c7c8 --- /dev/null +++ b/arch/powerpc/platforms/85xx/misc.c @@ -0,0 +1,31 @@ +/* + * MPC85xx generic code. + * + * Maintained by Kumar Gala (see MAINTAINERS for contact information) + * + * Copyright 2005 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include + +extern void abort(void); + +void mpc85xx_restart(char *cmd) +{ + local_irq_disable(); + abort(); +} + +/* For now this is a pass through */ +phys_addr_t fixup_bigphys_addr(phys_addr_t addr, phys_addr_t size) +{ + return addr; +}; + +EXPORT_SYMBOL(fixup_bigphys_addr); diff --git a/arch/powerpc/platforms/85xx/mpc85xx.c b/arch/powerpc/platforms/85xx/mpc85xx.c deleted file mode 100644 index 82510385d88a..000000000000 --- a/arch/powerpc/platforms/85xx/mpc85xx.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * MPC85xx generic code. - * - * Maintained by Kumar Gala (see MAINTAINERS for contact information) - * - * Copyright 2005 Freescale Semiconductor Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ -#include -#include -#include - -extern void abort(void); - -void -mpc85xx_restart(char *cmd) -{ - local_irq_disable(); - abort(); -} - -/* For now this is a pass through */ -phys_addr_t fixup_bigphys_addr(phys_addr_t addr, phys_addr_t size) -{ - return addr; -}; -EXPORT_SYMBOL(fixup_bigphys_addr); -- cgit v1.2.2 From fbc94e7c3d78d53c7fa671e02e5bb6fbb3254f85 Mon Sep 17 00:00:00 2001 From: Becky Bruce Date: Tue, 7 Feb 2006 21:29:42 -0600 Subject: [PATCH] powerpc: lindent 85xx platform code Ran arch/powerpc/platforms/85xx through Lindent Signed-off-by: Becky Bruce Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/85xx/mpc8540_ads.h | 2 +- arch/powerpc/platforms/85xx/mpc85xx_ads.c | 46 ++++++++++++------------------- 2 files changed, 19 insertions(+), 29 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/85xx/mpc8540_ads.h b/arch/powerpc/platforms/85xx/mpc8540_ads.h index 47609c97e01e..b3ec88caad11 100644 --- a/arch/powerpc/platforms/85xx/mpc8540_ads.h +++ b/arch/powerpc/platforms/85xx/mpc8540_ads.h @@ -57,4 +57,4 @@ /* Offset of CPM register space */ #define CPM_MAP_ADDR (CCSRBAR + MPC85xx_CPM_OFFSET) -#endif /* __MACH_MPC8540ADS_H__ */ +#endif /* __MACH_MPC8540ADS_H__ */ diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c index 9e8a91bc8018..ba6798d47654 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c @@ -38,7 +38,6 @@ unsigned long isa_io_base = 0; unsigned long isa_mem_base = 0; #endif - /* * Internal interrupts are all Level Sensitive, and Positive Polarity * @@ -47,28 +46,27 @@ unsigned long isa_mem_base = 0; */ static u_char mpc85xx_ads_openpic_initsenses[] __initdata = { MPC85XX_INTERNAL_IRQ_SENSES, - 0x0, /* External 0: */ + 0x0, /* External 0: */ #if defined(CONFIG_PCI) (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 1: PCI slot 0 */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 2: PCI slot 1 */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 3: PCI slot 2 */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 4: PCI slot 3 */ #else - 0x0, /* External 1: */ - 0x0, /* External 2: */ - 0x0, /* External 3: */ - 0x0, /* External 4: */ + 0x0, /* External 1: */ + 0x0, /* External 2: */ + 0x0, /* External 3: */ + 0x0, /* External 4: */ #endif (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 5: PHY */ - 0x0, /* External 6: */ + 0x0, /* External 6: */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 7: PHY */ - 0x0, /* External 8: */ - 0x0, /* External 9: */ - 0x0, /* External 10: */ - 0x0, /* External 11: */ + 0x0, /* External 8: */ + 0x0, /* External 9: */ + 0x0, /* External 10: */ + 0x0, /* External 11: */ }; - void __init mpc85xx_ads_pic_init(void) { struct mpic *mpic1; @@ -78,10 +76,11 @@ void __init mpc85xx_ads_pic_init(void) OpenPIC_PAddr = get_immrbase() + MPC85xx_OPENPIC_OFFSET; mpic1 = mpic_alloc(OpenPIC_PAddr, - MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, - 4, MPC85xx_OPENPIC_IRQ_OFFSET, 0, 250, - mpc85xx_ads_openpic_initsenses, - sizeof(mpc85xx_ads_openpic_initsenses), " OpenPIC "); + MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, + 4, MPC85xx_OPENPIC_IRQ_OFFSET, 0, 250, + mpc85xx_ads_openpic_initsenses, + sizeof(mpc85xx_ads_openpic_initsenses), + " OpenPIC "); BUG_ON(mpic1 == NULL); mpic_assign_isu(mpic1, 0, OpenPIC_PAddr + 0x10200); mpic_assign_isu(mpic1, 1, OpenPIC_PAddr + 0x10280); @@ -105,12 +104,10 @@ void __init mpc85xx_ads_pic_init(void) mpic_init(mpic1); } - /* * Setup the architecture */ -static void __init -mpc85xx_ads_setup_arch(void) +static void __init mpc85xx_ads_setup_arch(void) { struct device_node *cpu; @@ -128,7 +125,6 @@ mpc85xx_ads_setup_arch(void) loops_per_jiffy = 50000000 / HZ; of_node_put(cpu); } - #ifdef CONFIG_ROOT_NFS ROOT_DEV = Root_NFS; #else @@ -136,9 +132,7 @@ mpc85xx_ads_setup_arch(void) #endif } - -void -mpc85xx_ads_show_cpuinfo(struct seq_file *m) +void mpc85xx_ads_show_cpuinfo(struct seq_file *m) { uint pvid, svid, phid1; uint memsize = total_memory; @@ -159,9 +153,7 @@ mpc85xx_ads_show_cpuinfo(struct seq_file *m) seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); } - -void __init -platform_init(void) +void __init platform_init(void) { ppc_md.setup_arch = mpc85xx_ads_setup_arch; ppc_md.show_cpuinfo = mpc85xx_ads_show_cpuinfo; @@ -183,5 +175,3 @@ platform_init(void) if (ppc_md.progress) ppc_md.progress("mpc85xx_ads platform_init(): exit", 0); } - - -- cgit v1.2.2 From a7cb03375d794d3494561bbad90aeab13ff7e4d0 Mon Sep 17 00:00:00 2001 From: Becky Bruce Date: Wed, 8 Feb 2006 16:41:26 -0600 Subject: [PATCH] powerpc/ppc: Add missing isyncs in head_fsl_booke.S The e500 core reference manual indicates that isync is required after mtmsr(DE bit) and mtspr DBCR0. Add isyncs to make the code conform to the spec. Signed-off-by: Becky Bruce Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/head_fsl_booke.S | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index 8d60fa99fc4b..0abd05f14f87 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S @@ -316,6 +316,7 @@ skpinv: addi r6,r6,1 /* Increment */ */ lis r2,DBCR0_IDM@h mtspr SPRN_DBCR0,r2 + isync /* clear any residual debug events */ li r2,-1 mtspr SPRN_DBSR,r2 @@ -1002,12 +1003,15 @@ _GLOBAL(giveup_fpu) _GLOBAL(abort) li r13,0 mtspr SPRN_DBCR0,r13 /* disable all debug events */ + isync mfmsr r13 ori r13,r13,MSR_DE@l /* Enable Debug Events */ mtmsr r13 + isync mfspr r13,SPRN_DBCR0 lis r13,(DBCR0_IDM|DBCR0_RST_CHIP)@h mtspr SPRN_DBCR0,r13 + isync _GLOBAL(set_context) -- cgit v1.2.2 From 0941d57aa7034ef7010bd523752c2e3bee569ef1 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Fri, 10 Feb 2006 15:47:32 +1100 Subject: [PATCH] powerpc: Clean up pSeries firmware feature initialisation Clean up fw_feature_init in platforms/pseries/setup.c. Clean up white space and replace the while loop with a for loop - which seems clearer to me. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/setup.c | 48 ++++++++++++++++------------------ 1 file changed, 22 insertions(+), 26 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 9edeca83f434..984241bb776c 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -263,48 +263,44 @@ static int __init pSeries_init_panel(void) arch_initcall(pSeries_init_panel); -/* Build up the ppc64_firmware_features bitmask field - * using contents of device-tree/ibm,hypertas-functions. - * Ultimately this functionality may be moved into prom.c prom_init(). +/* Build up the firmware features bitmask using the contents of + * device-tree/ibm,hypertas-functions. Ultimately this functionality may + * be moved into prom.c prom_init(). */ static void __init fw_feature_init(void) { - struct device_node * dn; - char * hypertas; - unsigned int len; + struct device_node *dn; + char *hypertas, *s; + int len, i; DBG(" -> fw_feature_init()\n"); - ppc64_firmware_features = 0; dn = of_find_node_by_path("/rtas"); if (dn == NULL) { - printk(KERN_ERR "WARNING ! Cannot find RTAS in device-tree !\n"); - goto no_rtas; + printk(KERN_ERR "WARNING! Cannot find RTAS in device-tree!\n"); + goto out; } hypertas = get_property(dn, "ibm,hypertas-functions", &len); - if (hypertas) { - while (len > 0){ - int i, hypertas_len; + if (hypertas == NULL) + goto out; + + for (s = hypertas; s < hypertas + len; s += strlen(s) + 1) { + for (i = 0; i < FIRMWARE_MAX_FEATURES; i++) { /* check value against table of strings */ - for(i=0; i < FIRMWARE_MAX_FEATURES ;i++) { - if ((firmware_features_table[i].name) && - (strcmp(firmware_features_table[i].name,hypertas))==0) { - /* we have a match */ - ppc64_firmware_features |= - (firmware_features_table[i].val); - break; - } - } - hypertas_len = strlen(hypertas); - len -= hypertas_len +1; - hypertas+= hypertas_len +1; + if (!firmware_features_table[i].name || + strcmp(firmware_features_table[i].name, s)) + continue; + + /* we have a match */ + ppc64_firmware_features |= + firmware_features_table[i].val; + break; } } +out: of_node_put(dn); -no_rtas: - DBG(" <- fw_feature_init()\n"); } -- cgit v1.2.2 From 1965746bce49ddf001af52c7985e16343c768021 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Fri, 10 Feb 2006 15:47:36 +1100 Subject: [PATCH] powerpc: Move pSeries firmware feature setup into platforms/pseries Currently we have some stuff in firmware.h and kernel/firmware.c that is #ifdef CONFIG_PPC_PSERIES. Move it all into platforms/pseries. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/firmware.c | 25 -------- arch/powerpc/platforms/pseries/Makefile | 3 +- arch/powerpc/platforms/pseries/firmware.c | 103 ++++++++++++++++++++++++++++++ arch/powerpc/platforms/pseries/firmware.h | 17 +++++ arch/powerpc/platforms/pseries/setup.c | 45 +------------ 5 files changed, 123 insertions(+), 70 deletions(-) create mode 100644 arch/powerpc/platforms/pseries/firmware.c create mode 100644 arch/powerpc/platforms/pseries/firmware.h (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/firmware.c b/arch/powerpc/kernel/firmware.c index 65eae752a527..4d37a3cb80f6 100644 --- a/arch/powerpc/kernel/firmware.c +++ b/arch/powerpc/kernel/firmware.c @@ -18,28 +18,3 @@ #include unsigned long ppc64_firmware_features; - -#ifdef CONFIG_PPC_PSERIES -firmware_feature_t firmware_features_table[FIRMWARE_MAX_FEATURES] = { - {FW_FEATURE_PFT, "hcall-pft"}, - {FW_FEATURE_TCE, "hcall-tce"}, - {FW_FEATURE_SPRG0, "hcall-sprg0"}, - {FW_FEATURE_DABR, "hcall-dabr"}, - {FW_FEATURE_COPY, "hcall-copy"}, - {FW_FEATURE_ASR, "hcall-asr"}, - {FW_FEATURE_DEBUG, "hcall-debug"}, - {FW_FEATURE_PERF, "hcall-perf"}, - {FW_FEATURE_DUMP, "hcall-dump"}, - {FW_FEATURE_INTERRUPT, "hcall-interrupt"}, - {FW_FEATURE_MIGRATE, "hcall-migrate"}, - {FW_FEATURE_PERFMON, "hcall-perfmon"}, - {FW_FEATURE_CRQ, "hcall-crq"}, - {FW_FEATURE_VIO, "hcall-vio"}, - {FW_FEATURE_RDMA, "hcall-rdma"}, - {FW_FEATURE_LLAN, "hcall-lLAN"}, - {FW_FEATURE_BULK, "hcall-bulk"}, - {FW_FEATURE_XDABR, "hcall-xdabr"}, - {FW_FEATURE_MULTITCE, "hcall-multi-tce"}, - {FW_FEATURE_SPLPAR, "hcall-splpar"}, -}; -#endif diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 61616d144072..930898635c9f 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile @@ -1,5 +1,6 @@ obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \ - setup.o iommu.o ras.o rtasd.o pci_dlpar.o + setup.o iommu.o ras.o rtasd.o pci_dlpar.o \ + firmware.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_IBMVIO) += vio.o obj-$(CONFIG_XICS) += xics.o diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c new file mode 100644 index 000000000000..989f4bc136cb --- /dev/null +++ b/arch/powerpc/platforms/pseries/firmware.c @@ -0,0 +1,103 @@ +/* + * pSeries firmware setup code. + * + * Portions from arch/powerpc/platforms/pseries/setup.c: + * Copyright (C) 1995 Linus Torvalds + * Adapted from 'alpha' version by Gary Thomas + * Modified by Cort Dougan (cort@cs.nmt.edu) + * Modified by PPC64 Team, IBM Corp + * + * Portions from arch/powerpc/kernel/firmware.c + * Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org) + * Modifications for ppc64: + * Copyright (C) 2003 Dave Engebretsen + * Copyright (C) 2005 Stephen Rothwell, IBM Corporation + * + * Copyright 2006 IBM Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#undef DEBUG + +#include +#include + +#ifdef DEBUG +#define DBG(fmt...) udbg_printf(fmt) +#else +#define DBG(fmt...) +#endif + +typedef struct { + unsigned long val; + char * name; +} firmware_feature_t; + +static __initdata firmware_feature_t +firmware_features_table[FIRMWARE_MAX_FEATURES] = { + {FW_FEATURE_PFT, "hcall-pft"}, + {FW_FEATURE_TCE, "hcall-tce"}, + {FW_FEATURE_SPRG0, "hcall-sprg0"}, + {FW_FEATURE_DABR, "hcall-dabr"}, + {FW_FEATURE_COPY, "hcall-copy"}, + {FW_FEATURE_ASR, "hcall-asr"}, + {FW_FEATURE_DEBUG, "hcall-debug"}, + {FW_FEATURE_PERF, "hcall-perf"}, + {FW_FEATURE_DUMP, "hcall-dump"}, + {FW_FEATURE_INTERRUPT, "hcall-interrupt"}, + {FW_FEATURE_MIGRATE, "hcall-migrate"}, + {FW_FEATURE_PERFMON, "hcall-perfmon"}, + {FW_FEATURE_CRQ, "hcall-crq"}, + {FW_FEATURE_VIO, "hcall-vio"}, + {FW_FEATURE_RDMA, "hcall-rdma"}, + {FW_FEATURE_LLAN, "hcall-lLAN"}, + {FW_FEATURE_BULK, "hcall-bulk"}, + {FW_FEATURE_XDABR, "hcall-xdabr"}, + {FW_FEATURE_MULTITCE, "hcall-multi-tce"}, + {FW_FEATURE_SPLPAR, "hcall-splpar"}, +}; + +/* Build up the firmware features bitmask using the contents of + * device-tree/ibm,hypertas-functions. Ultimately this functionality may + * be moved into prom.c prom_init(). + */ +void __init fw_feature_init(void) +{ + struct device_node *dn; + char *hypertas, *s; + int len, i; + + DBG(" -> fw_feature_init()\n"); + + dn = of_find_node_by_path("/rtas"); + if (dn == NULL) { + printk(KERN_ERR "WARNING! Cannot find RTAS in device-tree!\n"); + goto out; + } + + hypertas = get_property(dn, "ibm,hypertas-functions", &len); + if (hypertas == NULL) + goto out; + + for (s = hypertas; s < hypertas + len; s += strlen(s) + 1) { + for (i = 0; i < FIRMWARE_MAX_FEATURES; i++) { + /* check value against table of strings */ + if (!firmware_features_table[i].name || + strcmp(firmware_features_table[i].name, s)) + continue; + + /* we have a match */ + ppc64_firmware_features |= + firmware_features_table[i].val; + break; + } + } + +out: + of_node_put(dn); + DBG(" <- fw_feature_init()\n"); +} diff --git a/arch/powerpc/platforms/pseries/firmware.h b/arch/powerpc/platforms/pseries/firmware.h new file mode 100644 index 000000000000..714f56f55362 --- /dev/null +++ b/arch/powerpc/platforms/pseries/firmware.h @@ -0,0 +1,17 @@ +/* + * Copyright 2006 IBM Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _PSERIES_FIRMWARE_H +#define _PSERIES_FIRMWARE_H + +#include + +extern void __init fw_feature_init(void); + +#endif /* _PSERIES_FIRMWARE_H */ diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 984241bb776c..b5996a7060f4 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -60,7 +60,6 @@ #include #include #include "xics.h" -#include #include #include #include @@ -70,6 +69,7 @@ #include "plpar_wrappers.h" #include "ras.h" +#include "firmware.h" #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) @@ -262,49 +262,6 @@ static int __init pSeries_init_panel(void) } arch_initcall(pSeries_init_panel); - -/* Build up the firmware features bitmask using the contents of - * device-tree/ibm,hypertas-functions. Ultimately this functionality may - * be moved into prom.c prom_init(). - */ -static void __init fw_feature_init(void) -{ - struct device_node *dn; - char *hypertas, *s; - int len, i; - - DBG(" -> fw_feature_init()\n"); - - dn = of_find_node_by_path("/rtas"); - if (dn == NULL) { - printk(KERN_ERR "WARNING! Cannot find RTAS in device-tree!\n"); - goto out; - } - - hypertas = get_property(dn, "ibm,hypertas-functions", &len); - if (hypertas == NULL) - goto out; - - for (s = hypertas; s < hypertas + len; s += strlen(s) + 1) { - for (i = 0; i < FIRMWARE_MAX_FEATURES; i++) { - /* check value against table of strings */ - if (!firmware_features_table[i].name || - strcmp(firmware_features_table[i].name, s)) - continue; - - /* we have a match */ - ppc64_firmware_features |= - firmware_features_table[i].val; - break; - } - } - -out: - of_node_put(dn); - DBG(" <- fw_feature_init()\n"); -} - - static void __init pSeries_discover_pic(void) { struct device_node *np; -- cgit v1.2.2 From 2ef9481e666b4654159ac9f847e6963809e3c470 Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Mon, 23 Jan 2006 10:58:20 -0600 Subject: [PATCH] powerpc: trivial: modify comments to refer to new location of files This patch removes all self references and fixes references to files in the now defunct arch/ppc64 tree. I think this accomplises everything wanted, though there might be a few references I missed. Signed-off-by: Jon Mason Signed-off-by: Paul Mackerras --- arch/powerpc/boot/install.sh | 2 -- arch/powerpc/kernel/entry_64.S | 4 +--- arch/powerpc/kernel/head_44x.S | 2 -- arch/powerpc/kernel/head_64.S | 2 -- arch/powerpc/kernel/head_8xx.S | 2 -- arch/powerpc/kernel/head_fsl_booke.S | 2 -- arch/powerpc/kernel/iomap.c | 2 -- arch/powerpc/kernel/iommu.c | 1 - arch/powerpc/kernel/irq.c | 2 -- arch/powerpc/kernel/kprobes.c | 1 - arch/powerpc/kernel/pci_iommu.c | 1 - arch/powerpc/kernel/process.c | 2 -- arch/powerpc/kernel/ptrace-common.h | 2 -- arch/powerpc/kernel/rtas-proc.c | 1 - arch/powerpc/kernel/rtas_pci.c | 2 -- arch/powerpc/kernel/signal_64.c | 2 -- arch/powerpc/kernel/vdso.c | 2 -- arch/powerpc/lib/copypage_64.S | 2 -- arch/powerpc/lib/copyuser_64.S | 2 -- arch/powerpc/lib/e2a.c | 4 +--- arch/powerpc/lib/memcpy_64.S | 2 -- arch/powerpc/lib/rheap.c | 2 -- arch/powerpc/mm/fault.c | 2 -- arch/powerpc/mm/hash_low_32.S | 2 -- arch/powerpc/mm/mmap.c | 2 -- arch/powerpc/mm/slb_low.S | 2 -- arch/powerpc/mm/tlb_64.c | 2 +- arch/powerpc/platforms/chrp/pegasos_eth.c | 2 -- arch/powerpc/platforms/chrp/setup.c | 2 -- arch/powerpc/platforms/chrp/time.c | 2 -- arch/powerpc/platforms/maple/time.c | 2 -- arch/powerpc/platforms/powermac/cpufreq_32.c | 2 -- arch/powerpc/platforms/powermac/feature.c | 2 -- arch/powerpc/platforms/powermac/nvram.c | 2 -- arch/powerpc/platforms/pseries/hvCall.S | 2 -- arch/powerpc/platforms/pseries/iommu.c | 2 -- arch/powerpc/platforms/pseries/pci.c | 2 -- arch/powerpc/sysdev/dcr.S | 2 -- arch/powerpc/sysdev/ipic.h | 2 -- 39 files changed, 3 insertions(+), 75 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/boot/install.sh b/arch/powerpc/boot/install.sh index eacce9590816..b002bfd56786 100644 --- a/arch/powerpc/boot/install.sh +++ b/arch/powerpc/boot/install.sh @@ -1,7 +1,5 @@ #!/bin/sh # -# arch/ppc64/boot/install.sh -# # This file is subject to the terms and conditions of the GNU General Public # License. See the file "COPYING" in the main directory of this archive # for more details. diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 388f861b8ed1..79a0c910f0d8 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -1,6 +1,4 @@ /* - * arch/ppc64/kernel/entry.S - * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP @@ -374,7 +372,7 @@ _GLOBAL(ret_from_fork) * the fork code also. * * The code which creates the new task context is in 'copy_thread' - * in arch/ppc64/kernel/process.c + * in arch/powerpc/kernel/process.c */ .align 7 _GLOBAL(_switch) diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S index 8b49679fad54..47c7fa148c9a 100644 --- a/arch/powerpc/kernel/head_44x.S +++ b/arch/powerpc/kernel/head_44x.S @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/head_44x.S - * * Kernel execution entry point code. * * Copyright (c) 1995-1996 Gary Thomas diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 415659629394..7ebb73665e9d 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -1,6 +1,4 @@ /* - * arch/ppc64/kernel/head.S - * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index bc6d1ac55235..28941f5ce673 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/except_8xx.S - * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index 0abd05f14f87..dd86bbed7627 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/head_fsl_booke.S - * * Kernel execution entry point code. * * Copyright (c) 1995-1996 Gary Thomas diff --git a/arch/powerpc/kernel/iomap.c b/arch/powerpc/kernel/iomap.c index 6160c8dbb7c5..fd8214caedee 100644 --- a/arch/powerpc/kernel/iomap.c +++ b/arch/powerpc/kernel/iomap.c @@ -1,6 +1,4 @@ /* - * arch/ppc64/kernel/iomap.c - * * ppc64 "iomap" interface implementation. * * (C) Copyright 2004 Linus Torvalds diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 946f3219fd29..d9a7fdef59b9 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -1,5 +1,4 @@ /* - * arch/ppc64/kernel/iommu.c * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation * * Rewrite, cleanup, new allocation schemes, virtual merging: diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index d1fffce86df9..edb2b00edbd2 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/irq.c - * * Derived from arch/i386/kernel/irq.c * Copyright (C) 1992 Linus Torvalds * Adapted from arch/i386 by Gary Thomas diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index cfab48566db1..258039fb3016 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c @@ -1,6 +1,5 @@ /* * Kernel Probes (KProbes) - * arch/ppc64/kernel/kprobes.c * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/powerpc/kernel/pci_iommu.c b/arch/powerpc/kernel/pci_iommu.c index bdf15dbbf4f0..c336f3e31cff 100644 --- a/arch/powerpc/kernel/pci_iommu.c +++ b/arch/powerpc/kernel/pci_iommu.c @@ -1,5 +1,4 @@ /* - * arch/ppc64/kernel/pci_iommu.c * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation * * Rewrite, cleanup, new allocation schemes: diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 57703994a063..1201880cab40 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/process.c - * * Derived from "arch/i386/kernel/process.c" * Copyright (C) 1995 Linus Torvalds * diff --git a/arch/powerpc/kernel/ptrace-common.h b/arch/powerpc/kernel/ptrace-common.h index 5ccbdbe0d5c9..c42a860c8d25 100644 --- a/arch/powerpc/kernel/ptrace-common.h +++ b/arch/powerpc/kernel/ptrace-common.h @@ -1,6 +1,4 @@ /* - * linux/arch/ppc64/kernel/ptrace-common.h - * * Copyright (c) 2002 Stephen Rothwell, IBM Coproration * Extracted from ptrace.c and ptrace32.c * diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c index 7a95b8a28354..1f03fb28cc0a 100644 --- a/arch/powerpc/kernel/rtas-proc.c +++ b/arch/powerpc/kernel/rtas-proc.c @@ -1,5 +1,4 @@ /* - * arch/ppc64/kernel/rtas-proc.c * Copyright (C) 2000 Tilmann Bitterberg * (tilmann@bitterberg.de) * diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index 5579f6559912..03afb79e27e5 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c @@ -1,6 +1,4 @@ /* - * arch/ppc64/kernel/rtas_pci.c - * * Copyright (C) 2001 Dave Engebretsen, IBM Corporation * Copyright (C) 2003 Anton Blanchard , IBM * diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 497a5d3df359..59b9c9cdd6a9 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -1,6 +1,4 @@ /* - * linux/arch/ppc64/kernel/signal.c - * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index f0c47dab0903..b316fda58b89 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c @@ -1,6 +1,4 @@ /* - * linux/arch/ppc64/kernel/vdso.c - * * Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp. * * diff --git a/arch/powerpc/lib/copypage_64.S b/arch/powerpc/lib/copypage_64.S index 40523b140109..f9837f44ac0b 100644 --- a/arch/powerpc/lib/copypage_64.S +++ b/arch/powerpc/lib/copypage_64.S @@ -1,6 +1,4 @@ /* - * arch/ppc64/lib/copypage.S - * * Copyright (C) 2002 Paul Mackerras, IBM Corp. * * This program is free software; you can redistribute it and/or diff --git a/arch/powerpc/lib/copyuser_64.S b/arch/powerpc/lib/copyuser_64.S index 6d69ef39b7df..a6b54cb97c49 100644 --- a/arch/powerpc/lib/copyuser_64.S +++ b/arch/powerpc/lib/copyuser_64.S @@ -1,6 +1,4 @@ /* - * arch/ppc64/lib/copyuser.S - * * Copyright (C) 2002 Paul Mackerras, IBM Corp. * * This program is free software; you can redistribute it and/or diff --git a/arch/powerpc/lib/e2a.c b/arch/powerpc/lib/e2a.c index d2b834887920..4f88f4cc21e8 100644 --- a/arch/powerpc/lib/e2a.c +++ b/arch/powerpc/lib/e2a.c @@ -1,9 +1,7 @@ /* - * arch/ppc64/lib/e2a.c - * * EBCDIC to ASCII conversion * - * This function moved here from arch/ppc64/kernel/viopath.c + * This function moved here from arch/powerpc/platforms/iseries/viopath.c * * (C) Copyright 2000-2004 IBM Corporation * diff --git a/arch/powerpc/lib/memcpy_64.S b/arch/powerpc/lib/memcpy_64.S index 9ccacdf5bcb9..fd66acfd3e3e 100644 --- a/arch/powerpc/lib/memcpy_64.S +++ b/arch/powerpc/lib/memcpy_64.S @@ -1,6 +1,4 @@ /* - * arch/ppc64/lib/memcpy.S - * * Copyright (C) 2002 Paul Mackerras, IBM Corp. * * This program is free software; you can redistribute it and/or diff --git a/arch/powerpc/lib/rheap.c b/arch/powerpc/lib/rheap.c index 42c5de2c898f..31e511856dc5 100644 --- a/arch/powerpc/lib/rheap.c +++ b/arch/powerpc/lib/rheap.c @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/rheap.c - * * A Remote Heap. Remote means that we don't touch the memory that the * heap points to. Normal heap implementations use the memory they manage * to place their list. We cannot do that because the memory we manage may diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index a4815d316722..ec4adcb4bc28 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -1,6 +1,4 @@ /* - * arch/ppc/mm/fault.c - * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * diff --git a/arch/powerpc/mm/hash_low_32.S b/arch/powerpc/mm/hash_low_32.S index 12ccd7155bac..ea469eefa146 100644 --- a/arch/powerpc/mm/hash_low_32.S +++ b/arch/powerpc/mm/hash_low_32.S @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/hashtable.S - * * $Id: hashtable.S,v 1.6 1999/10/08 01:56:15 paulus Exp $ * * PowerPC version diff --git a/arch/powerpc/mm/mmap.c b/arch/powerpc/mm/mmap.c index fe65f522aff3..972a8e884b9a 100644 --- a/arch/powerpc/mm/mmap.c +++ b/arch/powerpc/mm/mmap.c @@ -1,6 +1,4 @@ /* - * linux/arch/ppc64/mm/mmap.c - * * flexible mmap layout support * * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S index d1acee38f163..abfaabf667bf 100644 --- a/arch/powerpc/mm/slb_low.S +++ b/arch/powerpc/mm/slb_low.S @@ -1,6 +1,4 @@ /* - * arch/ppc64/mm/slb_low.S - * * Low-level SLB routines * * Copyright (C) 2004 David Gibson , IBM diff --git a/arch/powerpc/mm/tlb_64.c b/arch/powerpc/mm/tlb_64.c index bb3afb6e6317..f734b11566c2 100644 --- a/arch/powerpc/mm/tlb_64.c +++ b/arch/powerpc/mm/tlb_64.c @@ -36,7 +36,7 @@ DEFINE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch); /* This is declared as we are using the more or less generic - * include/asm-ppc64/tlb.h file -- tgall + * include/asm-powerpc/tlb.h file -- tgall */ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur); diff --git a/arch/powerpc/platforms/chrp/pegasos_eth.c b/arch/powerpc/platforms/chrp/pegasos_eth.c index 29c86781c493..6ad4b1a72c96 100644 --- a/arch/powerpc/platforms/chrp/pegasos_eth.c +++ b/arch/powerpc/platforms/chrp/pegasos_eth.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/chrp_pegasos_eth.c - * * Copyright (C) 2005 Sven Luther * Thanks to : * Dale Farnsworth diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index e1fadbf49150..8bf4307e323d 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/setup.c - * * Copyright (C) 1995 Linus Torvalds * Adapted from 'alpha' version by Gary Thomas * Modified by Cort Dougan (cort@cs.nmt.edu) diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c index 78df2e7ca88a..12c6f689b1aa 100644 --- a/arch/powerpc/platforms/chrp/time.c +++ b/arch/powerpc/platforms/chrp/time.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/chrp_time.c - * * Copyright (C) 1991, 1992, 1995 Linus Torvalds * * Adapted for PowerPC (PReP) by Gary Thomas diff --git a/arch/powerpc/platforms/maple/time.c b/arch/powerpc/platforms/maple/time.c index 50bc4eb85353..5e6981d17379 100644 --- a/arch/powerpc/platforms/maple/time.c +++ b/arch/powerpc/platforms/maple/time.c @@ -1,6 +1,4 @@ /* - * arch/ppc64/kernel/maple_time.c - * * (c) Copyright 2004 Benjamin Herrenschmidt (benh@kernel.crashing.org), * IBM Corp. * diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c index 56fd4e05fede..cfd6527a0d7e 100644 --- a/arch/powerpc/platforms/powermac/cpufreq_32.c +++ b/arch/powerpc/platforms/powermac/cpufreq_32.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/pmac_cpufreq.c - * * Copyright (C) 2002 - 2005 Benjamin Herrenschmidt * Copyright (C) 2004 John Steele Scott * diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index 558dd0692092..50ed8890dd33 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/pmac_feature.c - * * Copyright (C) 1996-2001 Paul Mackerras (paulus@cs.anu.edu.au) * Ben. Herrenschmidt (benh@kernel.crashing.org) * diff --git a/arch/powerpc/platforms/powermac/nvram.c b/arch/powerpc/platforms/powermac/nvram.c index 3ebd045a3350..5fd28995c74c 100644 --- a/arch/powerpc/platforms/powermac/nvram.c +++ b/arch/powerpc/platforms/powermac/nvram.c @@ -1,6 +1,4 @@ /* - * arch/ppc/platforms/pmac_nvram.c - * * Copyright (C) 2002 Benjamin Herrenschmidt (benh@kernel.crashing.org) * * This program is free software; you can redistribute it and/or diff --git a/arch/powerpc/platforms/pseries/hvCall.S b/arch/powerpc/platforms/pseries/hvCall.S index 176e8da76466..db7c19fe9297 100644 --- a/arch/powerpc/platforms/pseries/hvCall.S +++ b/arch/powerpc/platforms/pseries/hvCall.S @@ -1,6 +1,4 @@ /* - * arch/ppc64/kernel/pSeries_hvCall.S - * * This file contains the generic code to perform a call to the * pSeries LPAR hypervisor. * NOTE: this file will go away when we move to inline this work. diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 48cfbfc43f99..57930e23cc74 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -1,6 +1,4 @@ /* - * arch/ppc64/kernel/pSeries_iommu.c - * * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation * * Rewrite, cleanup: diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c index 999a9620b5ce..946ad59e3352 100644 --- a/arch/powerpc/platforms/pseries/pci.c +++ b/arch/powerpc/platforms/pseries/pci.c @@ -1,6 +1,4 @@ /* - * arch/ppc64/kernel/pSeries_pci.c - * * Copyright (C) 2001 Dave Engebretsen, IBM Corporation * Copyright (C) 2003 Anton Blanchard , IBM * diff --git a/arch/powerpc/sysdev/dcr.S b/arch/powerpc/sysdev/dcr.S index 895f10243a43..2078f39e2f17 100644 --- a/arch/powerpc/sysdev/dcr.S +++ b/arch/powerpc/sysdev/dcr.S @@ -1,6 +1,4 @@ /* - * arch/ppc/syslib/dcr.S - * * "Indirect" DCR access * * Copyright (c) 2004 Eugene Surovegin diff --git a/arch/powerpc/sysdev/ipic.h b/arch/powerpc/sysdev/ipic.h index a7ce7da8785c..a60c9d18bb7f 100644 --- a/arch/powerpc/sysdev/ipic.h +++ b/arch/powerpc/sysdev/ipic.h @@ -1,6 +1,4 @@ /* - * arch/ppc/kernel/ipic.h - * * IPIC private definitions and structure. * * Maintainer: Kumar Gala -- cgit v1.2.2 From 774fee58c465ea1c7e9775e347ec307bcf2deeb3 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Thu, 2 Feb 2006 15:41:48 -0800 Subject: [PATCH] powerpc: Add missing vmlinux.bin target With this patch 'make vmlinux.bin' works. This is needed by some embedded platforms. Kumar already added the routines to actually build the image in arch/powerpc/boot/Makefile. Signed-off-by: Geoff Levand Signed-off-by: Paul Mackerras --- arch/powerpc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 15fc3e98ac5c..81d3b3ddc206 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -148,7 +148,7 @@ all: $(KBUILD_IMAGE) CPPFLAGS_vmlinux.lds := -Upowerpc -BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm uImage +BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm uImage vmlinux.bin .PHONY: $(BOOT_TARGETS) -- cgit v1.2.2 From 8b0d5514a96daab7825f481d8cd5e88a0376d659 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Thu, 16 Feb 2006 14:32:08 -0600 Subject: powerpc: Fix mpc83xx restart bug We need to write the correct value to the RCR to get a HW reset. Signed-off-by: Kumar Gala --- arch/powerpc/platforms/83xx/misc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/83xx/misc.c b/arch/powerpc/platforms/83xx/misc.c index 0eb3d99f1b93..1455bcef4892 100644 --- a/arch/powerpc/platforms/83xx/misc.c +++ b/arch/powerpc/platforms/83xx/misc.c @@ -35,7 +35,7 @@ void mpc83xx_restart(char *cmd) out_be32(reg + (RST_PROT_REG >> 2), 0x52535445); /* set software hard reset */ - out_be32(reg + (RST_CTRL_REG >> 2), 0x52535445); + out_be32(reg + (RST_CTRL_REG >> 2), 0x2); for (;;) ; } -- cgit v1.2.2 From 8080d5497146d5d27d9e8e78229d1adc7fe280cf Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Fri, 10 Feb 2006 17:01:06 -0600 Subject: powerpc: Add PCI support for 8540 ADS to powerpc tree Add PCI support for setting PCI from flat device tree on 85xx specifically for MPC8540 ADS. Signed-off-by: Andy Fleming Signed-off-by: Kumar Gala --- arch/powerpc/platforms/85xx/Makefile | 3 +- arch/powerpc/platforms/85xx/mpc8540_ads.h | 24 -------- arch/powerpc/platforms/85xx/mpc85xx.h | 1 + arch/powerpc/platforms/85xx/mpc85xx_ads.c | 67 +++++++++++++++++++++ arch/powerpc/platforms/85xx/pci.c | 96 +++++++++++++++++++++++++++++++ 5 files changed, 166 insertions(+), 25 deletions(-) create mode 100644 arch/powerpc/platforms/85xx/pci.c (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index 70e1190809f8..ffc4139cb214 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile @@ -1,4 +1,5 @@ # # Makefile for the PowerPC 85xx linux kernel. # -obj-$(CONFIG_PPC_85xx) += misc.o mpc85xx_ads.o +obj-$(CONFIG_PPC_85xx) += misc.o pci.o +obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o diff --git a/arch/powerpc/platforms/85xx/mpc8540_ads.h b/arch/powerpc/platforms/85xx/mpc8540_ads.h index b3ec88caad11..f770cadb2080 100644 --- a/arch/powerpc/platforms/85xx/mpc8540_ads.h +++ b/arch/powerpc/platforms/85xx/mpc8540_ads.h @@ -30,30 +30,6 @@ #define PIRQC MPC85xx_IRQ_EXT3 #define PIRQD MPC85xx_IRQ_EXT4 -#define MPC85XX_PCI1_LOWER_IO 0x00000000 -#define MPC85XX_PCI1_UPPER_IO 0x00ffffff - -#define MPC85XX_PCI1_LOWER_MEM 0x80000000 -#define MPC85XX_PCI1_UPPER_MEM 0x9fffffff - -#define MPC85XX_PCI1_IO_BASE 0xe2000000 -#define MPC85XX_PCI1_MEM_OFFSET 0x00000000 - -#define MPC85XX_PCI1_IO_SIZE 0x01000000 - -/* PCI config */ -#define PCI1_CFG_ADDR_OFFSET (0x8000) -#define PCI1_CFG_DATA_OFFSET (0x8004) - -#define PCI2_CFG_ADDR_OFFSET (0x9000) -#define PCI2_CFG_DATA_OFFSET (0x9004) - -/* Additional register for PCI-X configuration */ -#define PCIX_NEXT_CAP 0x60 -#define PCIX_CAP_ID 0x61 -#define PCIX_COMMAND 0x62 -#define PCIX_STATUS 0x64 - /* Offset of CPM register space */ #define CPM_MAP_ADDR (CCSRBAR + MPC85xx_CPM_OFFSET) diff --git a/arch/powerpc/platforms/85xx/mpc85xx.h b/arch/powerpc/platforms/85xx/mpc85xx.h index be75abb2a283..b44db6268f3d 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx.h +++ b/arch/powerpc/platforms/85xx/mpc85xx.h @@ -15,3 +15,4 @@ */ extern void mpc85xx_restart(char *); +extern int add_bridge(struct device_node *dev); diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c index ba6798d47654..b7821dbae00d 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c @@ -67,6 +67,62 @@ static u_char mpc85xx_ads_openpic_initsenses[] __initdata = { 0x0, /* External 11: */ }; +#ifdef CONFIG_PCI +/* + * interrupt routing + */ + +int +mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) +{ + static char pci_irq_table[][4] = + /* + * This is little evil, but works around the fact + * that revA boards have IDSEL starting at 18 + * and others boards (older) start at 12 + * + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + {PIRQA, PIRQB, PIRQC, PIRQD}, /* IDSEL 2 */ + {PIRQD, PIRQA, PIRQB, PIRQC}, + {PIRQC, PIRQD, PIRQA, PIRQB}, + {PIRQB, PIRQC, PIRQD, PIRQA}, /* IDSEL 5 */ + {0, 0, 0, 0}, /* -- */ + {0, 0, 0, 0}, /* -- */ + {0, 0, 0, 0}, /* -- */ + {0, 0, 0, 0}, /* -- */ + {0, 0, 0, 0}, /* -- */ + {0, 0, 0, 0}, /* -- */ + {PIRQA, PIRQB, PIRQC, PIRQD}, /* IDSEL 12 */ + {PIRQD, PIRQA, PIRQB, PIRQC}, + {PIRQC, PIRQD, PIRQA, PIRQB}, + {PIRQB, PIRQC, PIRQD, PIRQA}, /* IDSEL 15 */ + {0, 0, 0, 0}, /* -- */ + {0, 0, 0, 0}, /* -- */ + {PIRQA, PIRQB, PIRQC, PIRQD}, /* IDSEL 18 */ + {PIRQD, PIRQA, PIRQB, PIRQC}, + {PIRQC, PIRQD, PIRQA, PIRQB}, + {PIRQB, PIRQC, PIRQD, PIRQA}, /* IDSEL 21 */ + }; + + const long min_idsel = 2, max_idsel = 21, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP; +} + +int +mpc85xx_exclude_device(u_char bus, u_char devfn) +{ + if (bus == 0 && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + else + return PCIBIOS_SUCCESSFUL; +} + +#endif /* CONFIG_PCI */ + + void __init mpc85xx_ads_pic_init(void) { struct mpic *mpic1; @@ -110,6 +166,7 @@ void __init mpc85xx_ads_pic_init(void) static void __init mpc85xx_ads_setup_arch(void) { struct device_node *cpu; + struct device_node *np; if (ppc_md.progress) ppc_md.progress("mpc85xx_ads_setup_arch()", 0); @@ -125,6 +182,16 @@ static void __init mpc85xx_ads_setup_arch(void) loops_per_jiffy = 50000000 / HZ; of_node_put(cpu); } + +#ifdef CONFIG_PCI + for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) + add_bridge(np); + + ppc_md.pci_swizzle = common_swizzle; + ppc_md.pci_map_irq = mpc85xx_map_irq; + ppc_md.pci_exclude_device = mpc85xx_exclude_device; +#endif + #ifdef CONFIG_ROOT_NFS ROOT_DEV = Root_NFS; #else diff --git a/arch/powerpc/platforms/85xx/pci.c b/arch/powerpc/platforms/85xx/pci.c new file mode 100644 index 000000000000..bad290110ed1 --- /dev/null +++ b/arch/powerpc/platforms/85xx/pci.c @@ -0,0 +1,96 @@ +/* + * FSL SoC setup code + * + * Maintained by Kumar Gala (see MAINTAINERS for contact information) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#undef DEBUG + +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +int mpc85xx_pci2_busno = 0; + +#ifdef CONFIG_PCI +int __init add_bridge(struct device_node *dev) +{ + int len; + struct pci_controller *hose; + struct resource rsrc; + int *bus_range; + int primary = 1, has_address = 0; + phys_addr_t immr = get_immrbase(); + + DBG("Adding PCI host bridge %s\n", dev->full_name); + + /* Fetch host bridge registers address */ + has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); + + /* Get bus range if any */ + bus_range = (int *) get_property(dev, "bus-range", &len); + if (bus_range == NULL || len < 2 * sizeof(int)) { + printk(KERN_WARNING "Can't get bus-range for %s, assume" + " bus 0\n", dev->full_name); + } + + hose = pcibios_alloc_controller(); + if (!hose) + return -ENOMEM; + hose->arch_data = dev; + hose->set_cfg_type = 1; + + hose->first_busno = bus_range ? bus_range[0] : 0; + hose->last_busno = bus_range ? bus_range[1] : 0xff; + + /* PCI 1 */ + if ((rsrc.start & 0xfffff) == 0x8000) { + setup_indirect_pci(hose, immr + 0x8000, immr + 0x8004); + } + /* PCI 2 */ + if ((rsrc.start & 0xfffff) == 0x9000) { + setup_indirect_pci(hose, immr + 0x9000, immr + 0x9004); + primary = 0; + hose->bus_offset = hose->first_busno; + mpc85xx_pci2_busno = hose->first_busno; + } + + printk(KERN_INFO "Found MPC85xx PCI host bridge at 0x%08lx. " + "Firmware bus number: %d->%d\n", + rsrc.start, hose->first_busno, hose->last_busno); + + DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", + hose, hose->cfg_addr, hose->cfg_data); + + /* Interpret the "ranges" property */ + /* This also maps the I/O region and sets isa_io/mem_base */ + pci_process_bridge_OF_ranges(hose, dev, primary); + + return 0; +} + +#endif -- cgit v1.2.2 From c6622f63db86fcbd41bf6fe05ddf2e00c1e51ced Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 24 Feb 2006 10:06:59 +1100 Subject: powerpc: Implement accurate task and CPU time accounting This implements accurate task and cpu time accounting for 64-bit powerpc kernels. Instead of accounting a whole jiffy of time to a task on a timer interrupt because that task happened to be running at the time, we now account time in units of timebase ticks according to the actual time spent by the task in user mode and kernel mode. We also count the time spent processing hardware and software interrupts accurately. This is conditional on CONFIG_VIRT_CPU_ACCOUNTING. If that is not set, we do tick-based approximate accounting as before. To get this accurate information, we read either the PURR (processor utilization of resources register) on POWER5 machines, or the timebase on other machines on * each entry to the kernel from usermode * each exit to usermode * transitions between process context, hard irq context and soft irq context in kernel mode * context switches. On POWER5 systems with shared-processor logical partitioning we also read both the PURR and the timebase at each timer interrupt and context switch in order to determine how much time has been taken by the hypervisor to run other partitions ("steal" time). Unfortunately, since we need values of the PURR on both threads at the same time to accurately calculate the steal time, and since we can only calculate steal time on a per-core basis, the apportioning of the steal time between idle time (time which we ceded to the hypervisor in the idle loop) and actual stolen time is somewhat approximate at the moment. This is all based quite heavily on what s390 does, and it uses the generic interfaces that were added by the s390 developers, i.e. account_system_time(), account_user_time(), etc. This patch doesn't add any new interfaces between the kernel and userspace, and doesn't change the units in which time is reported to userspace by things such as /proc/stat, /proc//stat, getrusage(), times(), etc. Internally the various task and cpu times are stored in timebase units, but they are converted to USER_HZ units (1/100th of a second) when reported to userspace. Some precision is therefore lost but there should not be any accumulating error, since the internal accumulation is at full precision. Signed-off-by: Paul Mackerras --- arch/powerpc/Kconfig | 15 +++ arch/powerpc/kernel/asm-offsets.c | 3 + arch/powerpc/kernel/entry_64.S | 7 +- arch/powerpc/kernel/head_64.S | 9 ++ arch/powerpc/kernel/irq.c | 30 +++-- arch/powerpc/kernel/process.c | 7 +- arch/powerpc/kernel/smp.c | 4 +- arch/powerpc/kernel/time.c | 236 +++++++++++++++++++++++++++++++++++++- 8 files changed, 297 insertions(+), 14 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index fb0dcb994b84..d112aed2999b 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -250,6 +250,21 @@ config PPC_STD_MMU_32 def_bool y depends on PPC_STD_MMU && PPC32 +config VIRT_CPU_ACCOUNTING + bool "Deterministic task and CPU time accounting" + depends on PPC64 + default y + help + Select this option to enable more accurate task and CPU time + accounting. This is done by reading a CPU counter on each + kernel entry and exit and on transitions within the kernel + between system, softirq and hardirq state, so there is a + small performance impact. This also enables accounting of + stolen time on logically-partitioned systems running on + IBM POWER5-based machines. + + If in doubt, say Y here. + config SMP depends on PPC_STD_MMU bool "Symmetric multi-processing support" diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 840aad43a98b..18810ac55bcc 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -137,6 +137,9 @@ int main(void) DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp)); DEFINE(PACALPPACAPTR, offsetof(struct paca_struct, lppaca_ptr)); DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); + DEFINE(PACA_STARTPURR, offsetof(struct paca_struct, startpurr)); + DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time)); + DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time)); DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0)); DEFINE(LPPACASRR1, offsetof(struct lppaca, saved_srr1)); diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 79a0c910f0d8..8f606c1889fa 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -61,6 +61,7 @@ system_call_common: std r12,_MSR(r1) std r0,GPR0(r1) std r10,GPR1(r1) + ACCOUNT_CPU_USER_ENTRY(r10, r11) std r2,GPR2(r1) std r3,GPR3(r1) std r4,GPR4(r1) @@ -168,8 +169,9 @@ syscall_error_cont: stdcx. r0,0,r1 /* to clear the reservation */ andi. r6,r8,MSR_PR ld r4,_LINK(r1) - beq- 1f /* only restore r13 if */ - ld r13,GPR13(r1) /* returning to usermode */ + beq- 1f + ACCOUNT_CPU_USER_EXIT(r11, r12) + ld r13,GPR13(r1) /* only restore r13 if returning to usermode */ 1: ld r2,GPR2(r1) li r12,MSR_RI andc r11,r10,r12 @@ -536,6 +538,7 @@ restore: * userspace */ beq 1f + ACCOUNT_CPU_USER_EXIT(r3, r4) REST_GPR(13, r1) 1: ld r3,_CTR(r1) diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 2b21ec499285..be3ae7733577 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -277,6 +277,7 @@ exception_marker: std r10,0(r1); /* make stack chain pointer */ \ std r0,GPR0(r1); /* save r0 in stackframe */ \ std r10,GPR1(r1); /* save r1 in stackframe */ \ + ACCOUNT_CPU_USER_ENTRY(r9, r10); \ std r2,GPR2(r1); /* save r2 in stackframe */ \ SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \ SAVE_2GPRS(7, r1); /* save r7, r8 in stackframe */ \ @@ -844,6 +845,14 @@ fast_exception_return: ld r11,_NIP(r1) andi. r3,r12,MSR_RI /* check if RI is set */ beq- unrecov_fer + +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + andi. r3,r12,MSR_PR + beq 2f + ACCOUNT_CPU_USER_EXIT(r3, r4) +2: +#endif + ld r3,_CCR(r1) ld r4,_LINK(r1) ld r5,_CTR(r1) diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index edb2b00edbd2..24dc8117b822 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -369,6 +369,7 @@ unsigned int real_irq_to_virt_slowpath(unsigned int real_irq) return NO_IRQ; } +#endif /* CONFIG_PPC64 */ #ifdef CONFIG_IRQSTACKS struct thread_info *softirq_ctx[NR_CPUS]; @@ -392,10 +393,24 @@ void irq_ctx_init(void) } } +static inline void do_softirq_onstack(void) +{ + struct thread_info *curtp, *irqtp; + + curtp = current_thread_info(); + irqtp = softirq_ctx[smp_processor_id()]; + irqtp->task = curtp->task; + call_do_softirq(irqtp); + irqtp->task = NULL; +} + +#else +#define do_softirq_onstack() __do_softirq() +#endif /* CONFIG_IRQSTACKS */ + void do_softirq(void) { unsigned long flags; - struct thread_info *curtp, *irqtp; if (in_interrupt()) return; @@ -403,19 +418,18 @@ void do_softirq(void) local_irq_save(flags); if (local_softirq_pending()) { - curtp = current_thread_info(); - irqtp = softirq_ctx[smp_processor_id()]; - irqtp->task = curtp->task; - call_do_softirq(irqtp); - irqtp->task = NULL; + account_system_vtime(current); + local_bh_disable(); + do_softirq_onstack(); + account_system_vtime(current); + __local_bh_enable(); } local_irq_restore(flags); } EXPORT_SYMBOL(do_softirq); -#endif /* CONFIG_IRQSTACKS */ - +#ifdef CONFIG_PPC64 static int __init setup_noirqdistrib(char *str) { distribute_irqs = 0; diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index dd774c3c9302..1770a066c217 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -45,9 +45,9 @@ #include #include #include +#include #ifdef CONFIG_PPC64 #include -#include #endif extern unsigned long _get_SP(void); @@ -328,6 +328,11 @@ struct task_struct *__switch_to(struct task_struct *prev, #endif local_irq_save(flags); + + account_system_vtime(current); + account_process_vtime(current); + calculate_steal_time(); + last = _switch(old_thread, new_thread); local_irq_restore(flags); diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 13595a64f013..805eaedbc308 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -541,7 +541,7 @@ int __devinit start_secondary(void *unused) smp_ops->take_timebase(); if (system_state > SYSTEM_BOOTING) - per_cpu(last_jiffy, cpu) = get_tb(); + snapshot_timebase(); spin_lock(&call_lock); cpu_set(cpu, cpu_online_map); @@ -573,6 +573,8 @@ void __init smp_cpus_done(unsigned int max_cpus) set_cpus_allowed(current, old_mask); + snapshot_timebases(); + dump_numa_cpu_topology(); } diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 2a7ddc579379..0b34db28916f 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -135,6 +136,220 @@ unsigned long tb_last_stamp; */ DEFINE_PER_CPU(unsigned long, last_jiffy); +#ifdef CONFIG_VIRT_CPU_ACCOUNTING +/* + * Factors for converting from cputime_t (timebase ticks) to + * jiffies, milliseconds, seconds, and clock_t (1/USER_HZ seconds). + * These are all stored as 0.64 fixed-point binary fractions. + */ +u64 __cputime_jiffies_factor; +u64 __cputime_msec_factor; +u64 __cputime_sec_factor; +u64 __cputime_clockt_factor; + +static void calc_cputime_factors(void) +{ + struct div_result res; + + div128_by_32(HZ, 0, tb_ticks_per_sec, &res); + __cputime_jiffies_factor = res.result_low; + div128_by_32(1000, 0, tb_ticks_per_sec, &res); + __cputime_msec_factor = res.result_low; + div128_by_32(1, 0, tb_ticks_per_sec, &res); + __cputime_sec_factor = res.result_low; + div128_by_32(USER_HZ, 0, tb_ticks_per_sec, &res); + __cputime_clockt_factor = res.result_low; +} + +/* + * Read the PURR on systems that have it, otherwise the timebase. + */ +static u64 read_purr(void) +{ + if (cpu_has_feature(CPU_FTR_PURR)) + return mfspr(SPRN_PURR); + return mftb(); +} + +/* + * Account time for a transition between system, hard irq + * or soft irq state. + */ +void account_system_vtime(struct task_struct *tsk) +{ + u64 now, delta; + unsigned long flags; + + local_irq_save(flags); + now = read_purr(); + delta = now - get_paca()->startpurr; + get_paca()->startpurr = now; + if (!in_interrupt()) { + delta += get_paca()->system_time; + get_paca()->system_time = 0; + } + account_system_time(tsk, 0, delta); + local_irq_restore(flags); +} + +/* + * Transfer the user and system times accumulated in the paca + * by the exception entry and exit code to the generic process + * user and system time records. + * Must be called with interrupts disabled. + */ +void account_process_vtime(struct task_struct *tsk) +{ + cputime_t utime; + + utime = get_paca()->user_time; + get_paca()->user_time = 0; + account_user_time(tsk, utime); +} + +static void account_process_time(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + account_process_vtime(current); + run_local_timers(); + if (rcu_pending(cpu)) + rcu_check_callbacks(cpu, user_mode(regs)); + scheduler_tick(); + run_posix_cpu_timers(current); +} + +#ifdef CONFIG_PPC_SPLPAR +/* + * Stuff for accounting stolen time. + */ +struct cpu_purr_data { + int initialized; /* thread is running */ + u64 tb0; /* timebase at origin time */ + u64 purr0; /* PURR at origin time */ + u64 tb; /* last TB value read */ + u64 purr; /* last PURR value read */ + u64 stolen; /* stolen time so far */ + spinlock_t lock; +}; + +static DEFINE_PER_CPU(struct cpu_purr_data, cpu_purr_data); + +static void snapshot_tb_and_purr(void *data) +{ + struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data); + + p->tb0 = mftb(); + p->purr0 = mfspr(SPRN_PURR); + p->tb = p->tb0; + p->purr = 0; + wmb(); + p->initialized = 1; +} + +/* + * Called during boot when all cpus have come up. + */ +void snapshot_timebases(void) +{ + int cpu; + + if (!cpu_has_feature(CPU_FTR_PURR)) + return; + for_each_cpu(cpu) + spin_lock_init(&per_cpu(cpu_purr_data, cpu).lock); + on_each_cpu(snapshot_tb_and_purr, NULL, 0, 1); +} + +void calculate_steal_time(void) +{ + u64 tb, purr, t0; + s64 stolen; + struct cpu_purr_data *p0, *pme, *phim; + int cpu; + + if (!cpu_has_feature(CPU_FTR_PURR)) + return; + cpu = smp_processor_id(); + pme = &per_cpu(cpu_purr_data, cpu); + if (!pme->initialized) + return; /* this can happen in early boot */ + p0 = &per_cpu(cpu_purr_data, cpu & ~1); + phim = &per_cpu(cpu_purr_data, cpu ^ 1); + spin_lock(&p0->lock); + tb = mftb(); + purr = mfspr(SPRN_PURR) - pme->purr0; + if (!phim->initialized || !cpu_online(cpu ^ 1)) { + stolen = (tb - pme->tb) - (purr - pme->purr); + } else { + t0 = pme->tb0; + if (phim->tb0 < t0) + t0 = phim->tb0; + stolen = phim->tb - t0 - phim->purr - purr - p0->stolen; + } + if (stolen > 0) { + account_steal_time(current, stolen); + p0->stolen += stolen; + } + pme->tb = tb; + pme->purr = purr; + spin_unlock(&p0->lock); +} + +/* + * Must be called before the cpu is added to the online map when + * a cpu is being brought up at runtime. + */ +static void snapshot_purr(void) +{ + int cpu; + u64 purr; + struct cpu_purr_data *p0, *pme, *phim; + unsigned long flags; + + if (!cpu_has_feature(CPU_FTR_PURR)) + return; + cpu = smp_processor_id(); + pme = &per_cpu(cpu_purr_data, cpu); + p0 = &per_cpu(cpu_purr_data, cpu & ~1); + phim = &per_cpu(cpu_purr_data, cpu ^ 1); + spin_lock_irqsave(&p0->lock, flags); + pme->tb = pme->tb0 = mftb(); + purr = mfspr(SPRN_PURR); + if (!phim->initialized) { + pme->purr = 0; + pme->purr0 = purr; + } else { + /* set p->purr and p->purr0 for no change in p0->stolen */ + pme->purr = phim->tb - phim->tb0 - phim->purr - p0->stolen; + pme->purr0 = purr - pme->purr; + } + pme->initialized = 1; + spin_unlock_irqrestore(&p0->lock, flags); +} + +#endif /* CONFIG_PPC_SPLPAR */ + +#else /* ! CONFIG_VIRT_CPU_ACCOUNTING */ +#define calc_cputime_factors() +#define account_process_time(regs) update_process_times(user_mode(regs)) +#define calculate_steal_time() do { } while (0) +#endif + +#if !(defined(CONFIG_VIRT_CPU_ACCOUNTING) && defined(CONFIG_PPC_SPLPAR)) +#define snapshot_purr() do { } while (0) +#endif + +/* + * Called when a cpu comes up after the system has finished booting, + * i.e. as a result of a hotplug cpu action. + */ +void snapshot_timebase(void) +{ + __get_cpu_var(last_jiffy) = get_tb(); + snapshot_purr(); +} + void __delay(unsigned long loops) { unsigned long start; @@ -382,6 +597,7 @@ static void iSeries_tb_recal(void) new_tb_ticks_per_jiffy, sign, tick_diff ); tb_ticks_per_jiffy = new_tb_ticks_per_jiffy; tb_ticks_per_sec = new_tb_ticks_per_sec; + calc_cputime_factors(); div128_by_32( XSEC_PER_SEC, 0, tb_ticks_per_sec, &divres ); do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; tb_to_xs = divres.result_low; @@ -430,6 +646,7 @@ void timer_interrupt(struct pt_regs * regs) irq_enter(); profile_tick(CPU_PROFILING, regs); + calculate_steal_time(); #ifdef CONFIG_PPC_ISERIES get_lppaca()->int_dword.fields.decr_int = 0; @@ -451,7 +668,7 @@ void timer_interrupt(struct pt_regs * regs) * is the case. */ if (!cpu_is_offline(cpu)) - update_process_times(user_mode(regs)); + account_process_time(regs); /* * No need to check whether cpu is offline here; boot_cpuid @@ -508,13 +725,27 @@ void wakeup_decrementer(void) void __init smp_space_timers(unsigned int max_cpus) { int i; + unsigned long half = tb_ticks_per_jiffy / 2; unsigned long offset = tb_ticks_per_jiffy / max_cpus; unsigned long previous_tb = per_cpu(last_jiffy, boot_cpuid); /* make sure tb > per_cpu(last_jiffy, cpu) for all cpus always */ previous_tb -= tb_ticks_per_jiffy; + /* + * The stolen time calculation for POWER5 shared-processor LPAR + * systems works better if the two threads' timebase interrupts + * are staggered by half a jiffy with respect to each other. + */ for_each_cpu(i) { - if (i != boot_cpuid) { + if (i == boot_cpuid) + continue; + if (i == (boot_cpuid ^ 1)) + per_cpu(last_jiffy, i) = + per_cpu(last_jiffy, boot_cpuid) - half; + else if (i & 1) + per_cpu(last_jiffy, i) = + per_cpu(last_jiffy, i ^ 1) + half; + else { previous_tb += offset; per_cpu(last_jiffy, i) = previous_tb; } @@ -706,6 +937,7 @@ void __init time_init(void) tb_ticks_per_sec = ppc_tb_freq; tb_ticks_per_usec = ppc_tb_freq / 1000000; tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000); + calc_cputime_factors(); /* * Calculate the length of each tick in ns. It will not be -- cgit v1.2.2 From 2cf82c0256b198ae28c465f2c4d7c12c836ea5ea Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Mon, 27 Feb 2006 15:41:47 +1100 Subject: powerpc: Export variables used in conversions to/from cputime_t The inline cputime_to_foo and foo_to_cputime conversion functions in include/asm-powerpc/cputime.h refer to 5 variables, which need to be exported if those functions are to be usable from modules. Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/time.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 0b34db28916f..4f20a5f15d49 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -99,6 +99,7 @@ unsigned long tb_ticks_per_jiffy; unsigned long tb_ticks_per_usec = 100; /* sane default */ EXPORT_SYMBOL(tb_ticks_per_usec); unsigned long tb_ticks_per_sec; +EXPORT_SYMBOL(tb_ticks_per_sec); /* for cputime_t conversions */ u64 tb_to_xs; unsigned tb_to_us; @@ -143,9 +144,13 @@ DEFINE_PER_CPU(unsigned long, last_jiffy); * These are all stored as 0.64 fixed-point binary fractions. */ u64 __cputime_jiffies_factor; +EXPORT_SYMBOL(__cputime_jiffies_factor); u64 __cputime_msec_factor; +EXPORT_SYMBOL(__cputime_msec_factor); u64 __cputime_sec_factor; +EXPORT_SYMBOL(__cputime_sec_factor); u64 __cputime_clockt_factor; +EXPORT_SYMBOL(__cputime_clockt_factor); static void calc_cputime_factors(void) { -- cgit v1.2.2 From 4f1933620f57145212cdbb1ac6ce099eeeb21c5a Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Sun, 5 Mar 2006 17:14:10 -0500 Subject: kbuild: change kbuild to not rely on incorrect GNU make behavior The kbuild system takes advantage of an incorrect behavior in GNU make. Once this behavior is fixed, all files in the kernel rebuild every time, even if nothing has changed. This patch ensures kbuild works with both the incorrect and correct behaviors of GNU make. For more details on the incorrect behavior, see: http://lists.gnu.org/archive/html/bug-make/2006-03/msg00003.html Changes in this patch: - Keep all targets that are to be marked .PHONY in a variable, PHONY. - Add .PHONY: $(PHONY) to mark them properly. - Remove any $(PHONY) files from the $? list when determining whether targets are up-to-date or not. Signed-off-by: Paul Smith Signed-off-by: Sam Ravnborg --- arch/powerpc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 5500ab55d042..5787d55a20b6 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -150,7 +150,7 @@ CPPFLAGS_vmlinux.lds := -Upowerpc BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm uImage -.PHONY: $(BOOT_TARGETS) +PHONY += $(BOOT_TARGETS) boot := arch/$(ARCH)/boot -- cgit v1.2.2 From 82dfdcae0d57c842e02f037758687eef42fb7af6 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 14 Mar 2006 11:35:37 +1100 Subject: powerpc: Disallow lparcfg being a module The lparcfg code needs several things which are pretty arcane internal details and which we don't want to export, which means that lparcfg doesn't work when built as a module. This makes it a bool instead of a tristate in the Kconfig so that users can't try to build it as a module. Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index 4e5c8f8d869d..a57032cf6f1b 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig @@ -19,7 +19,7 @@ config SCANLOG depends on RTAS_PROC && PPC_PSERIES config LPARCFG - tristate "LPAR Configuration Data" + bool "LPAR Configuration Data" depends on PPC_PSERIES || PPC_ISERIES help Provide system capacity information via human readable -- cgit v1.2.2 From 0a45d4491d0f172e02126370f312405c5d473363 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 15 Mar 2006 13:47:15 +1100 Subject: powerpc: Fix problem with time going backwards The recent changes to keep gettimeofday in sync with xtime had the side effect that it was occasionally possible for the time reported by gettimeofday to go back by a microsecond. There were two reasons: (1) when we recalculated the offsets used by gettimeofday every 2^31 timebase ticks, we lost an accumulated fractional microsecond, and (2) because the update is done some time after the notional start of jiffy, if ntp is slowing the clock, it is possible to see time go backwards when the timebase factor gets reduced. This fixes it by (a) slowing the gettimeofday clock by about 1us in 2^31 timebase ticks (a factor of less than 1 in 3.7 million), and (b) adjusting the timebase offsets in the rare case that the gettimeofday result could possibly go backwards (i.e. when ntp is slowing the clock and the timer interrupt is late). In this case the adjustment will reduce to zero eventually because of (a). Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/time.c | 48 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 14 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 2a7ddc579379..86f7e3d154d8 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -283,9 +283,9 @@ static inline void update_gtod(u64 new_tb_stamp, u64 new_stamp_xsec, * the two values of tb_update_count match and are even then the * tb_to_xs and stamp_xsec values are consistent. If not, then it * loops back and reads them again until this criteria is met. + * We expect the caller to have done the first increment of + * vdso_data->tb_update_count already. */ - ++(vdso_data->tb_update_count); - smp_wmb(); vdso_data->tb_orig_stamp = new_tb_stamp; vdso_data->stamp_xsec = new_stamp_xsec; vdso_data->tb_to_xs = new_tb_to_xs; @@ -310,20 +310,15 @@ static __inline__ void timer_recalc_offset(u64 cur_tb) unsigned long offset; u64 new_stamp_xsec; u64 tlen, t2x; + u64 tb, xsec_old, xsec_new; + struct gettimeofday_vars *varp; if (__USE_RTC()) return; tlen = current_tick_length(); offset = cur_tb - do_gtod.varp->tb_orig_stamp; - if (tlen == last_tick_len && offset < 0x80000000u) { - /* check that we're still in sync; if not, resync */ - struct timeval tv; - __do_gettimeofday(&tv, cur_tb); - if (tv.tv_sec <= xtime.tv_sec && - (tv.tv_sec < xtime.tv_sec || - tv.tv_usec * 1000 <= xtime.tv_nsec)) - return; - } + if (tlen == last_tick_len && offset < 0x80000000u) + return; if (tlen != last_tick_len) { t2x = mulhdu(tlen << TICKLEN_SHIFT, ticklen_to_xs); last_tick_len = tlen; @@ -332,6 +327,21 @@ static __inline__ void timer_recalc_offset(u64 cur_tb) new_stamp_xsec = (u64) xtime.tv_nsec * XSEC_PER_SEC; do_div(new_stamp_xsec, 1000000000); new_stamp_xsec += (u64) xtime.tv_sec * XSEC_PER_SEC; + + ++vdso_data->tb_update_count; + smp_mb(); + + /* + * Make sure time doesn't go backwards for userspace gettimeofday. + */ + tb = get_tb(); + varp = do_gtod.varp; + xsec_old = mulhdu(tb - varp->tb_orig_stamp, varp->tb_to_xs) + + varp->stamp_xsec; + xsec_new = mulhdu(tb - cur_tb, t2x) + new_stamp_xsec; + if (xsec_new < xsec_old) + new_stamp_xsec += xsec_old - xsec_new; + update_gtod(cur_tb, new_stamp_xsec, t2x); } @@ -564,6 +574,10 @@ int do_settimeofday(struct timespec *tv) } #endif + /* Make userspace gettimeofday spin until we're done. */ + ++vdso_data->tb_update_count; + smp_mb(); + /* * Subtract off the number of nanoseconds since the * beginning of the last tick. @@ -724,10 +738,16 @@ void __init time_init(void) * It is computed as: * ticklen_to_xs = 2^N / (tb_ticks_per_jiffy * 1e9) * where N = 64 + 20 - TICKLEN_SCALE - TICKLEN_SHIFT - * so as to give the result as a 0.64 fixed-point fraction. + * which turns out to be N = 51 - SHIFT_HZ. + * This gives the result as a 0.64 fixed-point fraction. + * That value is reduced by an offset amounting to 1 xsec per + * 2^31 timebase ticks to avoid problems with time going backwards + * by 1 xsec when we do timer_recalc_offset due to losing the + * fractional xsec. That offset is equal to ppc_tb_freq/2^51 + * since there are 2^20 xsec in a second. */ - div128_by_32(1ULL << (64 + 20 - TICKLEN_SCALE - TICKLEN_SHIFT), 0, - tb_ticks_per_jiffy, &res); + div128_by_32((1ULL << 51) - ppc_tb_freq, 0, + tb_ticks_per_jiffy << SHIFT_HZ, &res); div128_by_32(res.result_high, res.result_low, NSEC_PER_SEC, &res); ticklen_to_xs = res.result_low; -- cgit v1.2.2 From eacb1962d4594b9d382b40acd73a9c9492718f74 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Sat, 4 Mar 2006 13:15:40 +0100 Subject: [PATCH] powerpc: correct cacheflush loop in zImage Correct the loop for cacheflush. No idea where I copied the code from, but the original does not work correct. Maybe the flush is not needed. Signed-off-by: Olaf Hering Signed-off-by: Paul Mackerras --- arch/powerpc/boot/crt0.S | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/boot/crt0.S b/arch/powerpc/boot/crt0.S index e0192c26037b..70e65b13e033 100644 --- a/arch/powerpc/boot/crt0.S +++ b/arch/powerpc/boot/crt0.S @@ -45,7 +45,8 @@ _zimage_start: bdnz 2b /* Do a cache flush for our text, in case OF didn't */ -3: lis r9,_start@h +3: lis r9,_start@ha + addi r9,r9,_start@l add r9,r0,r9 lis r8,_etext@ha addi r8,r8,_etext@l @@ -53,7 +54,7 @@ _zimage_start: 4: dcbf r0,r9 icbi r0,r9 addi r9,r9,0x20 - cmplwi 0,r9,8 + cmplw cr0,r9,r8 blt 4b sync isync -- cgit v1.2.2 From e2c552cc89287e31b0b2472866a69a44b150acd2 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Mon, 6 Mar 2006 16:39:25 +0100 Subject: [PATCH] powerpc/64: enable CONFIG_BLK_DEV_SL82C105 Enable the onboard IDE driver for p610, p615 and p630. They have the CD connected to this card. All other RS/6000 systems with this controller have no connectors and dont need this option. Signed-off-by: Olaf Hering Signed-off-by: Paul Mackerras --- arch/powerpc/configs/ppc64_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index 0362a70aa97c..395e49847788 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig @@ -407,7 +407,7 @@ CONFIG_IDEPCI_SHARE_IRQ=y # CONFIG_BLK_DEV_OFFBOARD is not set CONFIG_BLK_DEV_GENERIC=y # CONFIG_BLK_DEV_OPTI621 is not set -# CONFIG_BLK_DEV_SL82C105 is not set +CONFIG_BLK_DEV_SL82C105=y CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_IDEDMA_FORCED is not set CONFIG_IDEDMA_PCI_AUTO=y -- cgit v1.2.2 From cd9c99d7e5f75e137c2ea0cf693773d63c8d945c Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Fri, 10 Mar 2006 15:01:08 +1100 Subject: [PATCH] powerpc: Clarify wording for CRASH_DUMP Kconfig option The wording of the CRASH_DUMP Kconfig option is not very clear. It gives you a kernel that can be used _as_ the kdump kernel, not a kernel that can boot into a kdump kernel. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index a834f9e0bbb3..dfba81719dec 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -580,7 +580,7 @@ config KEXEC strongly in flux, so no good recommendation can be made. config CRASH_DUMP - bool "kernel crash dumps (EXPERIMENTAL)" + bool "Build a kdump crash kernel (EXPERIMENTAL)" depends on PPC_MULTIPLATFORM && PPC64 && EXPERIMENTAL help Build a kernel suitable for use as a kdump capture kernel. -- cgit v1.2.2 From c6cb3b5f368bae67c0b258cfebc0b9dbd8e1d929 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sun, 12 Mar 2006 10:55:01 +1100 Subject: [PATCH] powerpc: enable NAP only on cpus who support it to avoid memory corruption This patch fixes incorrect setting of powersave_nap to 1 on all PowerMacs, potentially causing memory corruption on some models. This bug was introuced by me during the 32/64 bits merge. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/powermac/feature.c | 9 ++++----- arch/powerpc/platforms/powermac/setup.c | 4 ---- 2 files changed, 4 insertions(+), 9 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index 34714d3ea69a..bbe794891a20 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c @@ -2491,9 +2491,7 @@ found: pmac_mb.model_id = PMAC_TYPE_COMET; iounmap(mach_id_ptr); } -#endif /* CONFIG_POWER4 */ -#ifdef CONFIG_6xx /* Set default value of powersave_nap on machines that support it. * It appears that uninorth rev 3 has a problem with it, we don't * enable it on those. In theory, the flush-on-lock property is @@ -2522,10 +2520,11 @@ found: * NAP mode */ powersave_lowspeed = 1; -#endif /* CONFIG_6xx */ -#ifdef CONFIG_POWER4 + +#else /* CONFIG_POWER4 */ powersave_nap = 1; -#endif +#endif /* CONFIG_POWER4 */ + /* Check for "mobile" machine */ if (model && (strncmp(model, "PowerBook", 9) == 0 || strncmp(model, "iBook", 5) == 0)) diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 1955462f4082..29c2946f1c77 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -621,10 +621,6 @@ static void __init pmac_init_early(void) /* Probe motherboard chipset */ pmac_feature_init(); - /* We can NAP */ - powersave_nap = 1; - printk(KERN_INFO "Using native/NAP idle loop\n"); - /* Initialize debug stuff */ udbg_scc_init(!!strstr(cmd_line, "sccdbg")); udbg_adb_init(!!strstr(cmd_line, "btextdbg")); -- cgit v1.2.2 From 0e8ed479125a6d246e17cfe6c24e140bfeb01972 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Tue, 14 Mar 2006 17:11:51 +1100 Subject: [PATCH] powerpc: RTC memory corruption We should be memset'ing the data we are pointing to, not the pointer itself. This is in an error path so we probably don't hit it much. Signed-off-by: Michael Neuling Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/rtas-rtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/rtas-rtc.c b/arch/powerpc/kernel/rtas-rtc.c index 635d3b9a8811..34d073fb6091 100644 --- a/arch/powerpc/kernel/rtas-rtc.c +++ b/arch/powerpc/kernel/rtas-rtc.c @@ -52,7 +52,7 @@ void rtas_get_rtc_time(struct rtc_time *rtc_tm) error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { if (in_interrupt() && printk_ratelimit()) { - memset(&rtc_tm, 0, sizeof(struct rtc_time)); + memset(rtc_tm, 0, sizeof(struct rtc_time)); printk(KERN_WARNING "error: reading clock" " would delay interrupt\n"); return; /* delay not allowed */ -- cgit v1.2.2 From 920573bd03bf690135967b5022362d34ede589c3 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Tue, 14 Mar 2006 21:21:11 +0100 Subject: [PATCH] powerpc: remove duplicate EXPORT_SYMBOLS remove warnings when building a 64bit kernel. smp_call_function triggers also with 32bit kernel. WARNING: vmlinux: duplicate symbol 'smp_call_function' previous definition was in vmlinux arch/powerpc/kernel/ppc_ksyms.c:164:EXPORT_SYMBOL(smp_call_function); arch/powerpc/kernel/smp.c:300:EXPORT_SYMBOL(smp_call_function); WARNING: vmlinux: duplicate symbol 'ioremap' previous definition was in vmlinux arch/powerpc/kernel/ppc_ksyms.c:113:EXPORT_SYMBOL(ioremap); arch/powerpc/mm/pgtable_64.c:321:EXPORT_SYMBOL(ioremap); WARNING: vmlinux: duplicate symbol '__ioremap' previous definition was in vmlinux arch/powerpc/kernel/ppc_ksyms.c:117:EXPORT_SYMBOL(__ioremap); arch/powerpc/mm/pgtable_64.c:322:EXPORT_SYMBOL(__ioremap); WARNING: vmlinux: duplicate symbol 'iounmap' previous definition was in vmlinux arch/powerpc/kernel/ppc_ksyms.c:118:EXPORT_SYMBOL(iounmap); arch/powerpc/mm/pgtable_64.c:323:EXPORT_SYMBOL(iounmap); Signed-off-by: Olaf Hering Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/ppc_ksyms.c | 10 ---------- arch/powerpc/mm/pgtable_32.c | 5 +++++ 2 files changed, 5 insertions(+), 10 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index 8a731ea877b7..63ecbec05202 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c @@ -110,15 +110,6 @@ EXPORT_SYMBOL(_insw_ns); EXPORT_SYMBOL(_outsw_ns); EXPORT_SYMBOL(_insl_ns); EXPORT_SYMBOL(_outsl_ns); -EXPORT_SYMBOL(ioremap); -#ifdef CONFIG_44x -EXPORT_SYMBOL(ioremap64); -#endif -EXPORT_SYMBOL(__ioremap); -EXPORT_SYMBOL(iounmap); -#ifdef CONFIG_PPC32 -EXPORT_SYMBOL(ioremap_bot); /* aka VMALLOC_END */ -#endif #if defined(CONFIG_PPC32) && (defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)) EXPORT_SYMBOL(ppc_ide_md); @@ -161,7 +152,6 @@ EXPORT_SYMBOL(__flush_icache_range); EXPORT_SYMBOL(flush_dcache_range); #ifdef CONFIG_SMP -EXPORT_SYMBOL(smp_call_function); #ifdef CONFIG_PPC32 EXPORT_SYMBOL(smp_hw_index); #endif diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index f4e5ac122615..d296eb6b4545 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c @@ -37,6 +37,7 @@ unsigned long ioremap_base; unsigned long ioremap_bot; +EXPORT_SYMBOL(ioremap_bot); /* aka VMALLOC_END */ int io_bat_index; #if defined(CONFIG_6xx) || defined(CONFIG_POWER3) @@ -153,6 +154,7 @@ ioremap64(unsigned long long addr, unsigned long size) { return __ioremap(addr, size, _PAGE_NO_CACHE); } +EXPORT_SYMBOL(ioremap64); void __iomem * ioremap(phys_addr_t addr, unsigned long size) @@ -162,6 +164,7 @@ ioremap(phys_addr_t addr, unsigned long size) return ioremap64(addr64, size); } #endif /* CONFIG_PHYS_64BIT */ +EXPORT_SYMBOL(ioremap); void __iomem * __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags) @@ -247,6 +250,7 @@ __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags) out: return (void __iomem *) (v + ((unsigned long)addr & ~PAGE_MASK)); } +EXPORT_SYMBOL(__ioremap); void iounmap(volatile void __iomem *addr) { @@ -259,6 +263,7 @@ void iounmap(volatile void __iomem *addr) if (addr > high_memory && (unsigned long) addr < ioremap_bot) vunmap((void *) (PAGE_MASK & (unsigned long)addr)); } +EXPORT_SYMBOL(iounmap); void __iomem *ioport_map(unsigned long port, unsigned int len) { -- cgit v1.2.2 From 92eb4602eb5c37db86cd9d2b1f4c8ca304fbc49f Mon Sep 17 00:00:00 2001 From: John Rose Date: Tue, 14 Mar 2006 17:46:45 -0600 Subject: [PATCH] powerpc: properly configure DDR/P5IOC children devs The dynamic add path for PCI Host Bridges can fail to configure children adapters under P5IOC controllers. It fails to properly fixup bus/device resources, and it fails to properly enable EEH. Both of these steps need to occur before any children devices are enabled in pci_bus_add_devices(). Signed-off-by: John Rose Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_64.c | 5 +++-- arch/powerpc/kernel/rtas_pci.c | 24 +----------------------- arch/powerpc/platforms/pseries/pci_dlpar.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 25 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index c367520bc1c3..ba92bab7cc2c 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -589,7 +589,6 @@ void __devinit scan_phb(struct pci_controller *hose) #endif /* CONFIG_PPC_MULTIPLATFORM */ if (mode == PCI_PROBE_NORMAL) hose->last_busno = bus->subordinate = pci_scan_child_bus(bus); - pci_bus_add_devices(bus); } static int __init pcibios_init(void) @@ -608,8 +607,10 @@ static int __init pcibios_init(void) printk("PCI: Probing PCI hardware\n"); /* Scan all of the recorded PCI controllers. */ - list_for_each_entry_safe(hose, tmp, &hose_list, list_node) + list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { scan_phb(hose); + pci_bus_add_devices(hose->bus); + } #ifndef CONFIG_PPC_ISERIES if (pci_probe_only) diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index 5579f6559912..7442775ef2a1 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c @@ -280,8 +280,7 @@ static int phb_set_bus_ranges(struct device_node *dev, return 0; } -static int __devinit setup_phb(struct device_node *dev, - struct pci_controller *phb) +int __devinit setup_phb(struct device_node *dev, struct pci_controller *phb) { if (is_python(dev)) python_countermeasures(dev); @@ -359,27 +358,6 @@ unsigned long __init find_and_init_phbs(void) return 0; } -struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn) -{ - struct pci_controller *phb; - int primary; - - primary = list_empty(&hose_list); - phb = pcibios_alloc_controller(dn); - if (!phb) - return NULL; - setup_phb(dn, phb); - pci_process_bridge_OF_ranges(phb, dn, primary); - - pci_setup_phb_io_dynamic(phb, primary); - - pci_devs_phb_init_dynamic(phb); - scan_phb(phb); - - return phb; -} -EXPORT_SYMBOL(init_phb_dynamic); - /* RPA-specific bits for removing PHBs */ int pcibios_remove_root_bus(struct pci_controller *phb) { diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index f3bad900bbcf..44abdeb9ca03 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c @@ -27,6 +27,7 @@ #include #include +#include static struct pci_bus * find_bus_among_children(struct pci_bus *bus, @@ -179,3 +180,30 @@ pcibios_add_pci_devices(struct pci_bus * bus) } } EXPORT_SYMBOL_GPL(pcibios_add_pci_devices); + +struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn) +{ + struct pci_controller *phb; + int primary; + + primary = list_empty(&hose_list); + phb = pcibios_alloc_controller(dn); + if (!phb) + return NULL; + setup_phb(dn, phb); + pci_process_bridge_OF_ranges(phb, dn, 0); + + pci_setup_phb_io_dynamic(phb, primary); + + pci_devs_phb_init_dynamic(phb); + + if (dn->child) + eeh_add_device_tree_early(dn); + + scan_phb(phb); + pcibios_fixup_new_pci_devices(phb->bus, 0); + pci_bus_add_devices(phb->bus); + + return phb; +} +EXPORT_SYMBOL_GPL(init_phb_dynamic); -- cgit v1.2.2 From 1ae5db3742a0cfaf347231ff0bf181132c64e883 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 15 Mar 2006 16:22:54 +1100 Subject: powerpc: update defconfigs Signed-off-by: Paul Mackerras --- arch/powerpc/configs/cell_defconfig | 94 ++++++++++++++++++++--------- arch/powerpc/configs/iseries_defconfig | 96 ++++++++++++++++++------------ arch/powerpc/configs/maple_defconfig | 50 +++++++++++++--- arch/powerpc/configs/mpc834x_sys_defconfig | 32 +++++----- arch/powerpc/configs/pmac32_defconfig | 77 +++++++++++++++--------- 5 files changed, 232 insertions(+), 117 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig index 063b84f2cbea..3c2acab63736 100644 --- a/arch/powerpc/configs/cell_defconfig +++ b/arch/powerpc/configs/cell_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.15-rc5 -# Tue Dec 20 15:59:26 2005 +# Linux kernel version: 2.6.16-rc6 +# Wed Mar 15 16:19:48 2006 # CONFIG_PPC64=y CONFIG_64BIT=y @@ -16,6 +16,10 @@ CONFIG_COMPAT=y CONFIG_SYSVIPC_COMPAT=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_PPC_UDBG_16550=y +# CONFIG_GENERIC_TBSYNC is not set +# CONFIG_DEFAULT_UIMAGE is not set # # Processor support @@ -33,7 +37,6 @@ CONFIG_NR_CPUS=4 # Code maturity level options # CONFIG_EXPERIMENTAL=y -CONFIG_CLEAN_COMPILE=y CONFIG_LOCK_KERNEL=y CONFIG_INIT_ENV_ARG_LIMIT=32 @@ -48,8 +51,6 @@ CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set -CONFIG_HOTPLUG=y -CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set # CONFIG_CPUSETS is not set CONFIG_INITRAMFS_SOURCE="" @@ -58,8 +59,10 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y +CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -68,8 +71,10 @@ CONFIG_CC_ALIGN_FUNCTIONS=0 CONFIG_CC_ALIGN_LABELS=0 CONFIG_CC_ALIGN_LOOPS=0 CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_SLAB=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set # # Loadable module support @@ -111,7 +116,6 @@ CONFIG_PPC_MULTIPLATFORM=y # CONFIG_PPC_PMAC is not set # CONFIG_PPC_MAPLE is not set CONFIG_PPC_CELL=y -CONFIG_PPC_OF=y # CONFIG_U3_DART is not set CONFIG_PPC_RTAS=y # CONFIG_RTAS_ERROR_LOGGING is not set @@ -120,10 +124,14 @@ CONFIG_RTAS_FLASH=y CONFIG_MMIO_NVRAM=y CONFIG_CELL_IIC=y # CONFIG_PPC_MPC106 is not set -# CONFIG_GENERIC_TBSYNC is not set # CONFIG_CPU_FREQ is not set # CONFIG_WANT_EARLY_SERIAL is not set +# +# Cell Broadband Engine options +# +CONFIG_SPU_FS=y + # # Kernel options # @@ -140,6 +148,7 @@ CONFIG_BINFMT_ELF=y CONFIG_FORCE_MAX_ZONEORDER=13 # CONFIG_IOMMU_VMERGE is not set CONFIG_KEXEC=y +# CONFIG_CRASH_DUMP is not set CONFIG_IRQ_ALL_CPUS=y # CONFIG_NUMA is not set CONFIG_ARCH_SELECT_MEMORY_MODEL=y @@ -191,6 +200,7 @@ CONFIG_NET=y # # Networking options # +# CONFIG_NETDEBUG is not set CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y @@ -234,6 +244,25 @@ CONFIG_NETFILTER=y # Core Netfilter Configuration # # CONFIG_NETFILTER_NETLINK is not set +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m # # IP: Netfilter Configuration @@ -251,37 +280,23 @@ CONFIG_IP_NF_AMANDA=m # CONFIG_IP_NF_PPTP is not set CONFIG_IP_NF_QUEUE=m CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m CONFIG_IP_NF_MATCH_IPRANGE=m -CONFIG_IP_NF_MATCH_MAC=m -CONFIG_IP_NF_MATCH_PKTTYPE=m -CONFIG_IP_NF_MATCH_MARK=m CONFIG_IP_NF_MATCH_MULTIPORT=m CONFIG_IP_NF_MATCH_TOS=m CONFIG_IP_NF_MATCH_RECENT=m CONFIG_IP_NF_MATCH_ECN=m CONFIG_IP_NF_MATCH_DSCP=m CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -CONFIG_IP_NF_MATCH_HELPER=m -CONFIG_IP_NF_MATCH_STATE=m -CONFIG_IP_NF_MATCH_CONNTRACK=m CONFIG_IP_NF_MATCH_OWNER=m CONFIG_IP_NF_MATCH_ADDRTYPE=m -CONFIG_IP_NF_MATCH_REALM=m -CONFIG_IP_NF_MATCH_SCTP=m -# CONFIG_IP_NF_MATCH_DCCP is not set -CONFIG_IP_NF_MATCH_COMMENT=m CONFIG_IP_NF_MATCH_HASHLIMIT=m -CONFIG_IP_NF_MATCH_STRING=m +CONFIG_IP_NF_MATCH_POLICY=m CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_TARGET_REJECT=m CONFIG_IP_NF_TARGET_LOG=m CONFIG_IP_NF_TARGET_ULOG=m CONFIG_IP_NF_TARGET_TCPMSS=m -CONFIG_IP_NF_TARGET_NFQUEUE=m CONFIG_IP_NF_NAT=m CONFIG_IP_NF_NAT_NEEDED=y CONFIG_IP_NF_TARGET_MASQUERADE=m @@ -297,11 +312,8 @@ CONFIG_IP_NF_MANGLE=m CONFIG_IP_NF_TARGET_TOS=m CONFIG_IP_NF_TARGET_ECN=m CONFIG_IP_NF_TARGET_DSCP=m -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_CLASSIFY=m CONFIG_IP_NF_TARGET_TTL=m CONFIG_IP_NF_RAW=m -CONFIG_IP_NF_TARGET_NOTRACK=m CONFIG_IP_NF_ARPTABLES=m CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m @@ -311,7 +323,6 @@ CONFIG_IP_NF_ARP_MANGLE=m # # CONFIG_IP6_NF_QUEUE is not set # CONFIG_IP6_NF_IPTABLES is not set -# CONFIG_IP6_NF_TARGET_NFQUEUE is not set # # DCCP Configuration (EXPERIMENTAL) @@ -322,6 +333,11 @@ CONFIG_IP_NF_ARP_MANGLE=m # SCTP Configuration (EXPERIMENTAL) # # CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set @@ -540,9 +556,11 @@ CONFIG_E1000=m # CONFIG_R8169 is not set # CONFIG_SIS190 is not set CONFIG_SKGE=m +# CONFIG_SKY2 is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set # CONFIG_BNX2 is not set +CONFIG_SPIDER_NET=y # CONFIG_MV643XX_ETH is not set # @@ -628,13 +646,16 @@ CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set # CONFIG_ROCKETPORT is not set # CONFIG_CYCLADES is not set # CONFIG_DIGIEPCA is not set +# CONFIG_MOXA_INTELLIO is not set # CONFIG_MOXA_SMARTIO is not set # CONFIG_ISI is not set # CONFIG_SYNCLINK is not set # CONFIG_SYNCLINKMP is not set +# CONFIG_SYNCLINK_GT is not set # CONFIG_N_HDLC is not set # CONFIG_SPECIALIX is not set # CONFIG_SX is not set @@ -646,6 +667,7 @@ CONFIG_SERIAL_NONSTANDARD=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 # CONFIG_SERIAL_8250_EXTENDED is not set # @@ -755,6 +777,12 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_I2C_DEBUG_CHIP is not set +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + # # Dallas's 1-wire bus # @@ -827,7 +855,7 @@ CONFIG_USB_ARCH_HAS_OHCI=y # CONFIG_INFINIBAND is not set # -# SN Devices +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) # # @@ -847,6 +875,7 @@ CONFIG_FS_MBCACHE=y # CONFIG_JFS_FS is not set CONFIG_FS_POSIX_ACL=y # CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y @@ -886,6 +915,7 @@ CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y CONFIG_RAMFS=y # CONFIG_RELAYFS_FS is not set +# CONFIG_CONFIGFS_FS is not set # # Miscellaneous filesystems @@ -951,6 +981,7 @@ CONFIG_MSDOS_PARTITION=y # CONFIG_SGI_PARTITION is not set # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set CONFIG_EFI_PARTITION=y # @@ -1021,18 +1052,20 @@ CONFIG_TEXTSEARCH_FSM=m # Kernel hacking # # CONFIG_PRINTK_TIME is not set -CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=15 CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_MUTEXES is not set # CONFIG_DEBUG_SPINLOCK is not set CONFIG_DEBUG_SPINLOCK_SLEEP=y # CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_INFO is not set CONFIG_DEBUG_FS=y # CONFIG_DEBUG_VM is not set +# CONFIG_FORCED_INLINING is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_DEBUG_STACKOVERFLOW is not set # CONFIG_DEBUG_STACK_USAGE is not set @@ -1040,6 +1073,11 @@ CONFIG_DEBUGGER=y # CONFIG_XMON is not set CONFIG_IRQSTACKS=y # CONFIG_BOOTX_TEXT is not set +# CONFIG_PPC_EARLY_DEBUG_LPAR is not set +# CONFIG_PPC_EARLY_DEBUG_G5 is not set +# CONFIG_PPC_EARLY_DEBUG_RTAS is not set +# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set +# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set # # Security options diff --git a/arch/powerpc/configs/iseries_defconfig b/arch/powerpc/configs/iseries_defconfig index c775027947f9..1816a46742f6 100644 --- a/arch/powerpc/configs/iseries_defconfig +++ b/arch/powerpc/configs/iseries_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.15-rc5 -# Tue Dec 20 15:59:32 2005 +# Linux kernel version: 2.6.16-rc6 +# Wed Mar 15 16:19:52 2006 # CONFIG_PPC64=y CONFIG_64BIT=y @@ -16,6 +16,10 @@ CONFIG_COMPAT=y CONFIG_SYSVIPC_COMPAT=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +# CONFIG_PPC_UDBG_16550 is not set +# CONFIG_GENERIC_TBSYNC is not set +# CONFIG_DEFAULT_UIMAGE is not set # # Processor support @@ -33,7 +37,6 @@ CONFIG_NR_CPUS=32 # Code maturity level options # CONFIG_EXPERIMENTAL=y -CONFIG_CLEAN_COMPILE=y CONFIG_LOCK_KERNEL=y CONFIG_INIT_ENV_ARG_LIMIT=32 @@ -49,8 +52,6 @@ CONFIG_POSIX_MQUEUE=y CONFIG_SYSCTL=y CONFIG_AUDIT=y CONFIG_AUDITSYSCALL=y -CONFIG_HOTPLUG=y -CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_CPUSETS is not set @@ -60,8 +61,10 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y +CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -70,8 +73,10 @@ CONFIG_CC_ALIGN_FUNCTIONS=0 CONFIG_CC_ALIGN_LABELS=0 CONFIG_CC_ALIGN_LOOPS=0 CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_SLAB=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set # # Loadable module support @@ -113,7 +118,6 @@ CONFIG_PPC_ISERIES=y # CONFIG_MMIO_NVRAM is not set CONFIG_IBMVIO=y # CONFIG_PPC_MPC106 is not set -# CONFIG_GENERIC_TBSYNC is not set # CONFIG_CPU_FREQ is not set # CONFIG_WANT_EARLY_SERIAL is not set @@ -183,6 +187,7 @@ CONFIG_NET=y # # Networking options # +# CONFIG_NETDEBUG is not set CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y @@ -220,6 +225,28 @@ CONFIG_NETFILTER=y # Core Netfilter Configuration # # CONFIG_NETFILTER_NETLINK is not set +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m # # IP: Netfilter Configuration @@ -237,39 +264,23 @@ CONFIG_IP_NF_AMANDA=m # CONFIG_IP_NF_PPTP is not set CONFIG_IP_NF_QUEUE=m CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m CONFIG_IP_NF_MATCH_IPRANGE=m -CONFIG_IP_NF_MATCH_MAC=m -CONFIG_IP_NF_MATCH_PKTTYPE=m -CONFIG_IP_NF_MATCH_MARK=m CONFIG_IP_NF_MATCH_MULTIPORT=m CONFIG_IP_NF_MATCH_TOS=m CONFIG_IP_NF_MATCH_RECENT=m CONFIG_IP_NF_MATCH_ECN=m CONFIG_IP_NF_MATCH_DSCP=m CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -CONFIG_IP_NF_MATCH_HELPER=m -CONFIG_IP_NF_MATCH_STATE=m -CONFIG_IP_NF_MATCH_CONNTRACK=m CONFIG_IP_NF_MATCH_OWNER=m CONFIG_IP_NF_MATCH_ADDRTYPE=m -CONFIG_IP_NF_MATCH_REALM=m -CONFIG_IP_NF_MATCH_SCTP=m -# CONFIG_IP_NF_MATCH_DCCP is not set -CONFIG_IP_NF_MATCH_COMMENT=m -CONFIG_IP_NF_MATCH_CONNMARK=m -CONFIG_IP_NF_MATCH_CONNBYTES=m CONFIG_IP_NF_MATCH_HASHLIMIT=m -CONFIG_IP_NF_MATCH_STRING=m +CONFIG_IP_NF_MATCH_POLICY=m CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_TARGET_REJECT=m CONFIG_IP_NF_TARGET_LOG=m CONFIG_IP_NF_TARGET_ULOG=m CONFIG_IP_NF_TARGET_TCPMSS=m -CONFIG_IP_NF_TARGET_NFQUEUE=m CONFIG_IP_NF_NAT=m CONFIG_IP_NF_NAT_NEEDED=y CONFIG_IP_NF_TARGET_MASQUERADE=m @@ -285,13 +296,9 @@ CONFIG_IP_NF_MANGLE=m CONFIG_IP_NF_TARGET_TOS=m CONFIG_IP_NF_TARGET_ECN=m CONFIG_IP_NF_TARGET_DSCP=m -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_CLASSIFY=m CONFIG_IP_NF_TARGET_TTL=m -CONFIG_IP_NF_TARGET_CONNMARK=m CONFIG_IP_NF_TARGET_CLUSTERIP=m CONFIG_IP_NF_RAW=m -CONFIG_IP_NF_TARGET_NOTRACK=m CONFIG_IP_NF_ARPTABLES=m CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m @@ -305,6 +312,11 @@ CONFIG_IP_NF_ARP_MANGLE=m # SCTP Configuration (EXPERIMENTAL) # # CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set @@ -451,13 +463,7 @@ CONFIG_SCSI_IBMVSCSI=m # CONFIG_SCSI_IPR is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set -CONFIG_SCSI_QLA2XXX=y -# CONFIG_SCSI_QLA21XX is not set -# CONFIG_SCSI_QLA22XX is not set -# CONFIG_SCSI_QLA2300 is not set -# CONFIG_SCSI_QLA2322 is not set -# CONFIG_SCSI_QLA6312 is not set -# CONFIG_SCSI_QLA24XX is not set +# CONFIG_SCSI_QLA_FC is not set # CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set @@ -574,6 +580,7 @@ CONFIG_E1000=m # CONFIG_R8169 is not set # CONFIG_SIS190 is not set # CONFIG_SKGE is not set +# CONFIG_SKY2 is not set # CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set # CONFIG_TIGON3 is not set @@ -722,6 +729,12 @@ CONFIG_MAX_RAW_DEVS=256 # # CONFIG_I2C is not set +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + # # Dallas's 1-wire bus # @@ -788,7 +801,7 @@ CONFIG_USB_ARCH_HAS_OHCI=y # CONFIG_INFINIBAND is not set # -# SN Devices +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) # # @@ -825,6 +838,7 @@ CONFIG_XFS_EXPORT=y CONFIG_XFS_SECURITY=y CONFIG_XFS_POSIX_ACL=y # CONFIG_XFS_RT is not set +# CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y @@ -865,6 +879,7 @@ CONFIG_TMPFS=y # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y # CONFIG_RELAYFS_FS is not set +# CONFIG_CONFIGFS_FS is not set # # Miscellaneous filesystems @@ -993,31 +1008,36 @@ CONFIG_TEXTSEARCH_FSM=m # # Instrumentation Support # -CONFIG_PROFILING=y -CONFIG_OPROFILE=y # CONFIG_KPROBES is not set # # Kernel hacking # # CONFIG_PRINTK_TIME is not set -CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=17 CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_MUTEXES is not set # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_INFO is not set CONFIG_DEBUG_FS=y # CONFIG_DEBUG_VM is not set +# CONFIG_FORCED_INLINING is not set # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_STACKOVERFLOW=y CONFIG_DEBUG_STACK_USAGE=y # CONFIG_DEBUGGER is not set CONFIG_IRQSTACKS=y +# CONFIG_PPC_EARLY_DEBUG_LPAR is not set +# CONFIG_PPC_EARLY_DEBUG_G5 is not set +# CONFIG_PPC_EARLY_DEBUG_RTAS is not set +# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set +# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set # # Security options diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig index 68194c03f6d1..80a0db43aeb7 100644 --- a/arch/powerpc/configs/maple_defconfig +++ b/arch/powerpc/configs/maple_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.15-rc5 -# Tue Dec 20 15:59:36 2005 +# Linux kernel version: 2.6.16-rc6 +# Wed Mar 15 16:19:54 2006 # CONFIG_PPC64=y CONFIG_64BIT=y @@ -16,6 +16,10 @@ CONFIG_COMPAT=y CONFIG_SYSVIPC_COMPAT=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_PPC_UDBG_16550=y +CONFIG_GENERIC_TBSYNC=y +# CONFIG_DEFAULT_UIMAGE is not set # # Processor support @@ -32,7 +36,6 @@ CONFIG_NR_CPUS=2 # Code maturity level options # CONFIG_EXPERIMENTAL=y -CONFIG_CLEAN_COMPILE=y CONFIG_LOCK_KERNEL=y CONFIG_INIT_ENV_ARG_LIMIT=32 @@ -47,8 +50,6 @@ CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set -# CONFIG_HOTPLUG is not set -CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_CPUSETS is not set @@ -58,8 +59,10 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y # CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y +CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -68,8 +71,10 @@ CONFIG_CC_ALIGN_FUNCTIONS=0 CONFIG_CC_ALIGN_LABELS=0 CONFIG_CC_ALIGN_LOOPS=0 CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_SLAB=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set # # Loadable module support @@ -111,14 +116,12 @@ CONFIG_PPC_MULTIPLATFORM=y # CONFIG_PPC_PMAC is not set CONFIG_PPC_MAPLE=y # CONFIG_PPC_CELL is not set -CONFIG_PPC_OF=y CONFIG_U3_DART=y CONFIG_MPIC=y # CONFIG_PPC_RTAS is not set # CONFIG_MMIO_NVRAM is not set CONFIG_MPIC_BROKEN_U3=y # CONFIG_PPC_MPC106 is not set -CONFIG_GENERIC_TBSYNC=y # CONFIG_CPU_FREQ is not set # CONFIG_WANT_EARLY_SERIAL is not set @@ -138,6 +141,7 @@ CONFIG_BINFMT_ELF=y CONFIG_FORCE_MAX_ZONEORDER=13 CONFIG_IOMMU_VMERGE=y CONFIG_KEXEC=y +# CONFIG_CRASH_DUMP is not set CONFIG_IRQ_ALL_CPUS=y # CONFIG_NUMA is not set CONFIG_ARCH_SELECT_MEMORY_MODEL=y @@ -189,6 +193,7 @@ CONFIG_NET=y # # Networking options # +# CONFIG_NETDEBUG is not set CONFIG_PACKET=y CONFIG_PACKET_MMAP=y CONFIG_UNIX=y @@ -226,6 +231,11 @@ CONFIG_TCP_CONG_BIC=y # SCTP Configuration (EXPERIMENTAL) # # CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set @@ -461,6 +471,7 @@ CONFIG_E1000=y # CONFIG_R8169 is not set # CONFIG_SIS190 is not set # CONFIG_SKGE is not set +# CONFIG_SKY2 is not set # CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set # CONFIG_TIGON3 is not set @@ -553,6 +564,7 @@ CONFIG_HW_CONSOLE=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 # CONFIG_SERIAL_8250_EXTENDED is not set # @@ -650,6 +662,12 @@ CONFIG_I2C_AMD8111=y # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_I2C_DEBUG_CHIP is not set +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + # # Dallas's 1-wire bus # @@ -738,12 +756,14 @@ CONFIG_USB_UHCI_HCD=y # may also be needed; see USB_STORAGE Help for more information # # CONFIG_USB_STORAGE is not set +# CONFIG_USB_LIBUSUAL is not set # # USB Input Devices # CONFIG_USB_HID=y CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set # CONFIG_HID_FF is not set # CONFIG_USB_HIDDEV is not set # CONFIG_USB_AIPTEK is not set @@ -757,6 +777,7 @@ CONFIG_USB_HIDINPUT=y # CONFIG_USB_YEALINK is not set # CONFIG_USB_XPAD is not set # CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_ATI_REMOTE2 is not set # CONFIG_USB_KEYSPAN_REMOTE is not set # CONFIG_USB_APPLETOUCH is not set @@ -797,6 +818,7 @@ CONFIG_USB_SERIAL_GENERIC=y # CONFIG_USB_SERIAL_AIRPRIME is not set # CONFIG_USB_SERIAL_ANYDATA is not set # CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set # CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set # CONFIG_USB_SERIAL_CP2101 is not set CONFIG_USB_SERIAL_CYPRESS_M8=m @@ -873,7 +895,7 @@ CONFIG_USB_EZUSB=y # CONFIG_INFINIBAND is not set # -# SN Devices +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) # # @@ -891,6 +913,7 @@ CONFIG_JBD=y # CONFIG_JFS_FS is not set CONFIG_FS_POSIX_ACL=y # CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y @@ -927,6 +950,7 @@ CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y CONFIG_RAMFS=y # CONFIG_RELAYFS_FS is not set +# CONFIG_CONFIGFS_FS is not set # # Miscellaneous filesystems @@ -988,6 +1012,7 @@ CONFIG_MSDOS_PARTITION=y # CONFIG_SGI_PARTITION is not set # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set # CONFIG_EFI_PARTITION is not set # @@ -1053,18 +1078,20 @@ CONFIG_ZLIB_INFLATE=y # Kernel hacking # # CONFIG_PRINTK_TIME is not set -CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=17 CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set CONFIG_DEBUG_SLAB=y +# CONFIG_DEBUG_MUTEXES is not set # CONFIG_DEBUG_SPINLOCK is not set CONFIG_DEBUG_SPINLOCK_SLEEP=y # CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_INFO is not set CONFIG_DEBUG_FS=y # CONFIG_DEBUG_VM is not set +# CONFIG_FORCED_INLINING is not set # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_STACKOVERFLOW=y CONFIG_DEBUG_STACK_USAGE=y @@ -1073,6 +1100,11 @@ CONFIG_XMON=y CONFIG_XMON_DEFAULT=y # CONFIG_IRQSTACKS is not set CONFIG_BOOTX_TEXT=y +# CONFIG_PPC_EARLY_DEBUG_LPAR is not set +# CONFIG_PPC_EARLY_DEBUG_G5 is not set +# CONFIG_PPC_EARLY_DEBUG_RTAS is not set +# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set +# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set # # Security options diff --git a/arch/powerpc/configs/mpc834x_sys_defconfig b/arch/powerpc/configs/mpc834x_sys_defconfig index 3bff761965c2..5078b0441d61 100644 --- a/arch/powerpc/configs/mpc834x_sys_defconfig +++ b/arch/powerpc/configs/mpc834x_sys_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.15-g461d4edf-dirty -# Fri Jan 13 11:01:47 2006 +# Linux kernel version: 2.6.16-rc6 +# Wed Mar 15 16:19:56 2006 # # CONFIG_PPC64 is not set CONFIG_PPC32=y @@ -43,7 +43,6 @@ CONFIG_PPC_STD_MMU_32=y # Code maturity level options # CONFIG_EXPERIMENTAL=y -CONFIG_CLEAN_COMPILE=y CONFIG_BROKEN_ON_SMP=y CONFIG_INIT_ENV_ARG_LIMIT=32 @@ -189,6 +188,7 @@ CONFIG_NET=y # # Networking options # +# CONFIG_NETDEBUG is not set CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y @@ -226,6 +226,11 @@ CONFIG_TCP_CONG_BIC=y # SCTP Configuration (EXPERIMENTAL) # # CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set @@ -511,6 +516,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4 # CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -614,6 +620,12 @@ CONFIG_I2C_MPC=y # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_I2C_DEBUG_CHIP is not set +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + # # Dallas's 1-wire bus # @@ -632,6 +644,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_ASB100 is not set # CONFIG_SENSORS_ATXP1 is not set # CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set # CONFIG_SENSORS_FSCHER is not set # CONFIG_SENSORS_FSCPOS is not set # CONFIG_SENSORS_GL518SM is not set @@ -716,7 +729,7 @@ CONFIG_USB_ARCH_HAS_OHCI=y # CONFIG_INFINIBAND is not set # -# SN Devices +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) # # @@ -826,6 +839,7 @@ CONFIG_PARTITION_ADVANCED=y # CONFIG_SGI_PARTITION is not set # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set # CONFIG_EFI_PARTITION is not set # @@ -899,13 +913,3 @@ CONFIG_CRYPTO_DES=y # # Hardware crypto devices # - -# -# SEC2.x Options -# -CONFIG_MPC8349E_SEC2x=y - -# -# SEC2.x Test Options -# -CONFIG_MPC8349E_SEC2xTEST=y diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig index 2ace57d1e333..57a027971d67 100644 --- a/arch/powerpc/configs/pmac32_defconfig +++ b/arch/powerpc/configs/pmac32_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.15 -# Sat Jan 14 16:26:08 2006 +# Linux kernel version: 2.6.16-rc6 +# Wed Mar 15 16:21:32 2006 # # CONFIG_PPC64 is not set CONFIG_PPC32=y @@ -17,8 +17,8 @@ CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_PPC_OF=y # CONFIG_PPC_UDBG_16550 is not set -# CONFIG_CRASH_DUMP is not set # CONFIG_GENERIC_TBSYNC is not set +# CONFIG_DEFAULT_UIMAGE is not set # # Processor support @@ -43,7 +43,6 @@ CONFIG_PPC_STD_MMU_32=y # Code maturity level options # CONFIG_EXPERIMENTAL=y -CONFIG_CLEAN_COMPILE=y CONFIG_BROKEN_ON_SMP=y CONFIG_INIT_ENV_ARG_LIMIT=32 @@ -236,6 +235,7 @@ CONFIG_NET=y # # Networking options # +# CONFIG_NETDEBUG is not set CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y @@ -271,6 +271,25 @@ CONFIG_NETFILTER=y # Core Netfilter Configuration # # CONFIG_NETFILTER_NETLINK is not set +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m # # IP: Netfilter Configuration @@ -288,37 +307,22 @@ CONFIG_IP_NF_AMANDA=m CONFIG_IP_NF_PPTP=m # CONFIG_IP_NF_QUEUE is not set CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m CONFIG_IP_NF_MATCH_IPRANGE=m -CONFIG_IP_NF_MATCH_MAC=m -CONFIG_IP_NF_MATCH_PKTTYPE=m -CONFIG_IP_NF_MATCH_MARK=m CONFIG_IP_NF_MATCH_MULTIPORT=m CONFIG_IP_NF_MATCH_TOS=m CONFIG_IP_NF_MATCH_RECENT=m CONFIG_IP_NF_MATCH_ECN=m CONFIG_IP_NF_MATCH_DSCP=m CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -CONFIG_IP_NF_MATCH_HELPER=m -CONFIG_IP_NF_MATCH_STATE=m -CONFIG_IP_NF_MATCH_CONNTRACK=m CONFIG_IP_NF_MATCH_OWNER=m -# CONFIG_IP_NF_MATCH_ADDRTYPE is not set -# CONFIG_IP_NF_MATCH_REALM is not set -# CONFIG_IP_NF_MATCH_SCTP is not set -CONFIG_IP_NF_MATCH_DCCP=m -# CONFIG_IP_NF_MATCH_COMMENT is not set -# CONFIG_IP_NF_MATCH_HASHLIMIT is not set -CONFIG_IP_NF_MATCH_STRING=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_TARGET_REJECT=m -# CONFIG_IP_NF_TARGET_LOG is not set +CONFIG_IP_NF_TARGET_LOG=m CONFIG_IP_NF_TARGET_ULOG=m CONFIG_IP_NF_TARGET_TCPMSS=m -# CONFIG_IP_NF_TARGET_NFQUEUE is not set CONFIG_IP_NF_NAT=m CONFIG_IP_NF_NAT_NEEDED=y CONFIG_IP_NF_TARGET_MASQUERADE=m @@ -331,9 +335,12 @@ CONFIG_IP_NF_NAT_FTP=m CONFIG_IP_NF_NAT_TFTP=m CONFIG_IP_NF_NAT_AMANDA=m CONFIG_IP_NF_NAT_PPTP=m -# CONFIG_IP_NF_MANGLE is not set +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_TOS=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_DSCP=m +CONFIG_IP_NF_TARGET_TTL=m CONFIG_IP_NF_RAW=m -CONFIG_IP_NF_TARGET_NOTRACK=m CONFIG_IP_NF_ARPTABLES=m CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m @@ -360,6 +367,11 @@ CONFIG_IP_DCCP_TFRC_LIB=m # SCTP Configuration (EXPERIMENTAL) # # CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set @@ -377,6 +389,7 @@ CONFIG_IP_DCCP_TFRC_LIB=m # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set +CONFIG_NET_CLS_ROUTE=y # # Network testing @@ -568,7 +581,6 @@ CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_BLK_DEV_NS87415 is not set # CONFIG_BLK_DEV_PDC202XX_OLD is not set CONFIG_BLK_DEV_PDC202XX_NEW=y -# CONFIG_PDC202XX_FORCE is not set # CONFIG_BLK_DEV_SVWKS is not set # CONFIG_BLK_DEV_SIIMAGE is not set # CONFIG_BLK_DEV_SLC90E66 is not set @@ -654,8 +666,7 @@ CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 # CONFIG_SCSI_IPR is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set -CONFIG_SCSI_QLA2XXX=y -# CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE is not set +# CONFIG_SCSI_QLA_FC is not set # CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set @@ -991,6 +1002,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4 # CONFIG_SERIAL_CORE=m CONFIG_SERIAL_PMACZILOG=m +# CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -1097,6 +1109,12 @@ CONFIG_I2C_POWERMAC=y # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_I2C_DEBUG_CHIP is not set +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + # # Dallas's 1-wire bus # @@ -1348,6 +1366,7 @@ CONFIG_USB_PRINTER=m # CONFIG_USB_HID=y CONFIG_USB_HIDINPUT=y +CONFIG_USB_HIDINPUT_POWERBOOK=y # CONFIG_HID_FF is not set # CONFIG_USB_HIDDEV is not set # CONFIG_USB_AIPTEK is not set @@ -1488,7 +1507,7 @@ CONFIG_USB_EZUSB=y # CONFIG_INFINIBAND is not set # -# SN Devices +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) # # @@ -1609,6 +1628,7 @@ CONFIG_MSDOS_PARTITION=y # CONFIG_SGI_PARTITION is not set # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set # CONFIG_EFI_PARTITION is not set # @@ -1692,6 +1712,7 @@ CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_FS is not set # CONFIG_DEBUG_VM is not set +# CONFIG_FORCED_INLINING is not set # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUGGER=y CONFIG_XMON=y -- cgit v1.2.2 From 7e5b59384eebe35bff8429243f089931ce1cdf38 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Wed, 8 Mar 2006 20:40:28 +0100 Subject: [PATCH] powerpc: add a raw dump command to xmon Dump a stream of rawbytes with a new 'dr' command. Produces less output and it is simpler to feed the output to scripts. Also, dr has no dumpsize limits. Signed-off-by: Olaf Hering Signed-off-by: Paul Mackerras --- arch/powerpc/xmon/xmon.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'arch/powerpc') diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 7d02fa2a8990..4735b41c113c 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -191,6 +191,7 @@ Commands:\n\ di dump instructions\n\ df dump float values\n\ dd dump double values\n\ + dr dump stream of raw bytes\n\ e print exception information\n\ f flush cache\n\ la lookup symbol+offset of specified address\n\ @@ -1938,6 +1939,28 @@ bsesc(void) return c; } +static void xmon_rawdump (unsigned long adrs, long ndump) +{ + long n, m, r, nr; + unsigned char temp[16]; + + for (n = ndump; n > 0;) { + r = n < 16? n: 16; + nr = mread(adrs, temp, r); + adrs += nr; + for (m = 0; m < r; ++m) { + if (m < nr) + printf("%.2x", temp[m]); + else + printf("%s", fault_chars[fault_type]); + } + n -= r; + if (nr < r) + break; + } + printf("\n"); +} + #define isxdigit(c) (('0' <= (c) && (c) <= '9') \ || ('a' <= (c) && (c) <= 'f') \ || ('A' <= (c) && (c) <= 'F')) @@ -1960,6 +1983,13 @@ dump(void) nidump = MAX_DUMP; adrs += ppc_inst_dump(adrs, nidump, 1); last_cmd = "di\n"; + } else if (c == 'r') { + scanhex(&ndump); + if (ndump == 0) + ndump = 64; + xmon_rawdump(adrs, ndump); + adrs += ndump; + last_cmd = "dr\n"; } else { scanhex(&ndump); if (ndump == 0) -- cgit v1.2.2 From 2c276603c3e5ebf38155a9d1fbbda656d52d138e Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 16 Mar 2006 14:47:20 +1100 Subject: [PATCH] powerpc: Fix bug in bug fix for bug in lmb_alloc() My patch (d7a5b2ffa1352f0310630934a56aecbdfb617b72) to always panic if lmb_alloc() fails is broken because it checks alloc < 0, but should be checking alloc == 0. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/mm/lmb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/mm/lmb.c b/arch/powerpc/mm/lmb.c index 874cd103ce6e..417d58518558 100644 --- a/arch/powerpc/mm/lmb.c +++ b/arch/powerpc/mm/lmb.c @@ -232,7 +232,7 @@ unsigned long __init lmb_alloc_base(unsigned long size, unsigned long align, alloc = __lmb_alloc_base(size, align, max_addr); - if (alloc < 0) + if (alloc == 0) panic("ERROR: Failed to allocate 0x%lx bytes below 0x%lx.\n", size, max_addr); -- cgit v1.2.2 From c08888cf3c80fe07bfd176113c390ca31d3ba5c2 Mon Sep 17 00:00:00 2001 From: Nathan Lynch Date: Mon, 20 Mar 2006 18:34:15 -0600 Subject: [PATCH] powerpc numa: fix boot_cpuid always assigned to node 0 At boot, the numa code is assigning boot_cpuid to node 0 unconditionally. Basically, numa_setup_cpu is being stupid about it, but this is the minimal fix -- just call numa_setup_cpu(boot_cpuid) later, after all nodes have been set online. Signed-off-by: Nathan Lynch Signed-off-by: Paul Mackerras --- arch/powerpc/mm/numa.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index da5280f8cf42..dc6392ce2530 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -375,7 +375,7 @@ static int __init parse_numa_properties(void) { struct device_node *cpu = NULL; struct device_node *memory = NULL; - int max_domain; + int max_domain = 0; unsigned long i; if (numa_enabled == 0) { @@ -389,8 +389,6 @@ static int __init parse_numa_properties(void) if (min_common_depth < 0) return min_common_depth; - max_domain = numa_setup_cpu(boot_cpuid); - /* * Even though we connect cpus to numa domains later in SMP init, * we need to know the maximum node id now. This is because each @@ -469,6 +467,8 @@ new_range: for (i = 0; i <= max_domain; i++) node_set_online(i); + max_domain = numa_setup_cpu(boot_cpuid); + return 0; } -- cgit v1.2.2 From bf4b85b0e4bab42b3e8d8b0acc6851bb85e2050b Mon Sep 17 00:00:00 2001 From: Nathan Lynch Date: Mon, 20 Mar 2006 18:34:45 -0600 Subject: [PATCH] powerpc numa: Minor debugging code changes Add debug statement for map_cpu_to_node; it's useful for cpu hotplug. Clarify debug statement about not finding the numa reference points property. Don't print a meaningless associativity depth (-1) on non-numa systems. Signed-off-by: Nathan Lynch Signed-off-by: Paul Mackerras --- arch/powerpc/mm/numa.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index dc6392ce2530..2ae491d9404f 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -133,6 +133,8 @@ static inline void map_cpu_to_node(int cpu, int node) { numa_cpu_lookup_table[cpu] = node; + dbg("adding cpu %d to node %d\n", cpu, node); + if (!(cpu_isset(cpu, numa_cpumask_lookup_table[node]))) cpu_set(cpu, numa_cpumask_lookup_table[node]); } @@ -246,8 +248,7 @@ static int __init find_min_common_depth(void) if ((len >= 1) && ref_points) { depth = ref_points[1]; } else { - dbg("WARNING: could not find NUMA " - "associativity reference point\n"); + dbg("NUMA: ibm,associativity-reference-points not found.\n"); depth = -1; } of_node_put(rtas_root); @@ -385,10 +386,11 @@ static int __init parse_numa_properties(void) min_common_depth = find_min_common_depth(); - dbg("NUMA associativity depth for CPU/Memory: %d\n", min_common_depth); if (min_common_depth < 0) return min_common_depth; + dbg("NUMA associativity depth for CPU/Memory: %d\n", min_common_depth); + /* * Even though we connect cpus to numa domains later in SMP init, * we need to know the maximum node id now. This is because each -- cgit v1.2.2 From 2e5ce39d6703836b583c43131c365201a76285a5 Mon Sep 17 00:00:00 2001 From: Nathan Lynch Date: Mon, 20 Mar 2006 18:35:15 -0600 Subject: [PATCH] powerpc numa: Minor cpu hotplug-related cleanups map_cpu_to_node does not need to be inline, it is never called in a hot path. map_cpu_to_node, numa_setup_cpu, and find_cpu_node can be marked __cpuinit, as they are never used after boot if CONFIG_HOTPLUG_CPU=n. Signed-off-by: Nathan Lynch Signed-off-by: Paul Mackerras --- arch/powerpc/mm/numa.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 2ae491d9404f..1fb11bbe1ace 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -129,7 +129,7 @@ void __init get_region(unsigned int nid, unsigned long *start_pfn, *start_pfn = 0; } -static inline void map_cpu_to_node(int cpu, int node) +static void __cpuinit map_cpu_to_node(int cpu, int node) { numa_cpu_lookup_table[cpu] = node; @@ -155,7 +155,7 @@ static void unmap_cpu_from_node(unsigned long cpu) } #endif /* CONFIG_HOTPLUG_CPU */ -static struct device_node *find_cpu_node(unsigned int cpu) +static struct device_node * __cpuinit find_cpu_node(unsigned int cpu) { unsigned int hw_cpuid = get_hard_smp_processor_id(cpu); struct device_node *cpu_node = NULL; @@ -284,7 +284,7 @@ static unsigned long __devinit read_n_cells(int n, unsigned int **buf) * Figure out to which domain a cpu belongs and stick it there. * Return the id of the domain used. */ -static int numa_setup_cpu(unsigned long lcpu) +static int __cpuinit numa_setup_cpu(unsigned long lcpu) { int numa_domain = 0; struct device_node *cpu = find_cpu_node(lcpu); -- cgit v1.2.2 From cf950b7af0e51935e559c54262214423e2b6c88a Mon Sep 17 00:00:00 2001 From: Nathan Lynch Date: Mon, 20 Mar 2006 18:35:45 -0600 Subject: [PATCH] powerpc numa: Get rid of "numa domain" terminology Since we effectively treat the domain ids given to us by firmare as logical node ids, make this explicit (basically s/numa_domain/nid/). No functional changes, only variable and function names are modified. Signed-off-by: Nathan Lynch Signed-off-by: Paul Mackerras --- arch/powerpc/mm/numa.c | 78 +++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 39 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 1fb11bbe1ace..a5286a68760a 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -191,9 +191,9 @@ static int *of_get_associativity(struct device_node *dev) return (unsigned int *)get_property(dev, "ibm,associativity", NULL); } -static int of_node_numa_domain(struct device_node *device) +static int of_node_to_nid(struct device_node *device) { - int numa_domain; + int nid; unsigned int *tmp; if (min_common_depth == -1) @@ -201,13 +201,13 @@ static int of_node_numa_domain(struct device_node *device) tmp = of_get_associativity(device); if (tmp && (tmp[0] >= min_common_depth)) { - numa_domain = tmp[min_common_depth]; + nid = tmp[min_common_depth]; } else { dbg("WARNING: no NUMA information for %s\n", device->full_name); - numa_domain = 0; + nid = 0; } - return numa_domain; + return nid; } /* @@ -286,7 +286,7 @@ static unsigned long __devinit read_n_cells(int n, unsigned int **buf) */ static int __cpuinit numa_setup_cpu(unsigned long lcpu) { - int numa_domain = 0; + int nid = 0; struct device_node *cpu = find_cpu_node(lcpu); if (!cpu) { @@ -294,27 +294,27 @@ static int __cpuinit numa_setup_cpu(unsigned long lcpu) goto out; } - numa_domain = of_node_numa_domain(cpu); + nid = of_node_to_nid(cpu); - if (numa_domain >= num_online_nodes()) { + if (nid >= num_online_nodes()) { /* * POWER4 LPAR uses 0xffff as invalid node, * dont warn in this case. */ - if (numa_domain != 0xffff) + if (nid != 0xffff) printk(KERN_ERR "WARNING: cpu %ld " "maps to invalid NUMA node %d\n", - lcpu, numa_domain); - numa_domain = 0; + lcpu, nid); + nid = 0; } out: - node_set_online(numa_domain); + node_set_online(nid); - map_cpu_to_node(lcpu, numa_domain); + map_cpu_to_node(lcpu, nid); of_node_put(cpu); - return numa_domain; + return nid; } static int cpu_numa_callback(struct notifier_block *nfb, @@ -399,17 +399,17 @@ static int __init parse_numa_properties(void) * with larger node ids. In that case we force the cpu into node 0. */ for_each_cpu(i) { - int numa_domain; + int nid; cpu = find_cpu_node(i); if (cpu) { - numa_domain = of_node_numa_domain(cpu); + nid = of_node_to_nid(cpu); of_node_put(cpu); - if (numa_domain < MAX_NUMNODES && - max_domain < numa_domain) - max_domain = numa_domain; + if (nid < MAX_NUMNODES && + max_domain < nid) + max_domain = nid; } } @@ -418,7 +418,7 @@ static int __init parse_numa_properties(void) while ((memory = of_find_node_by_type(memory, "memory")) != NULL) { unsigned long start; unsigned long size; - int numa_domain; + int nid; int ranges; unsigned int *memcell_buf; unsigned int len; @@ -439,18 +439,18 @@ new_range: start = read_n_cells(n_mem_addr_cells, &memcell_buf); size = read_n_cells(n_mem_size_cells, &memcell_buf); - numa_domain = of_node_numa_domain(memory); + nid = of_node_to_nid(memory); - if (numa_domain >= MAX_NUMNODES) { - if (numa_domain != 0xffff) + if (nid >= MAX_NUMNODES) { + if (nid != 0xffff) printk(KERN_ERR "WARNING: memory at %lx maps " "to invalid NUMA node %d\n", start, - numa_domain); - numa_domain = 0; + nid); + nid = 0; } - if (max_domain < numa_domain) - max_domain = numa_domain; + if (max_domain < nid) + max_domain = nid; if (!(size = numa_enforce_memory_limit(start, size))) { if (--ranges) @@ -459,7 +459,7 @@ new_range: continue; } - add_region(numa_domain, start >> PAGE_SHIFT, + add_region(nid, start >> PAGE_SHIFT, size >> PAGE_SHIFT); if (--ranges) @@ -769,10 +769,10 @@ int hot_add_scn_to_nid(unsigned long scn_addr) { struct device_node *memory = NULL; nodemask_t nodes; - int numa_domain = 0; + int nid = 0; if (!numa_enabled || (min_common_depth < 0)) - return numa_domain; + return nid; while ((memory = of_find_node_by_type(memory, "memory")) != NULL) { unsigned long start, size; @@ -789,15 +789,15 @@ int hot_add_scn_to_nid(unsigned long scn_addr) ha_new_range: start = read_n_cells(n_mem_addr_cells, &memcell_buf); size = read_n_cells(n_mem_size_cells, &memcell_buf); - numa_domain = of_node_numa_domain(memory); + nid = of_node_to_nid(memory); /* Domains not present at boot default to 0 */ - if (!node_online(numa_domain)) - numa_domain = any_online_node(NODE_MASK_ALL); + if (!node_online(nid)) + nid = any_online_node(NODE_MASK_ALL); if ((scn_addr >= start) && (scn_addr < (start + size))) { of_node_put(memory); - goto got_numa_domain; + goto got_nid; } if (--ranges) /* process all ranges in cell */ @@ -806,12 +806,12 @@ ha_new_range: BUG(); /* section address should be found above */ /* Temporary code to ensure that returned node is not empty */ -got_numa_domain: +got_nid: nodes_setall(nodes); - while (NODE_DATA(numa_domain)->node_spanned_pages == 0) { - node_clear(numa_domain, nodes); - numa_domain = any_online_node(nodes); + while (NODE_DATA(nid)->node_spanned_pages == 0) { + node_clear(nid, nodes); + nid = any_online_node(nodes); } - return numa_domain; + return nid; } #endif /* CONFIG_MEMORY_HOTPLUG */ -- cgit v1.2.2 From bc16a75926941094db6b42d76014abb5e8d3a910 Mon Sep 17 00:00:00 2001 From: Nathan Lynch Date: Mon, 20 Mar 2006 18:36:15 -0600 Subject: [PATCH] powerpc numa: Consolidate handling of Power4 special case Code to handle Power4's invalid node id (0xffff) is duplicated for cpu and memory. Better to handle this case in one place -- of_node_to_nid. Overall behavior should be unchanged. Signed-off-by: Nathan Lynch Signed-off-by: Paul Mackerras --- arch/powerpc/mm/numa.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index a5286a68760a..dd611ef8df7a 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -207,6 +207,11 @@ static int of_node_to_nid(struct device_node *device) device->full_name); nid = 0; } + + /* POWER4 LPAR uses 0xffff as invalid node */ + if (nid == 0xffff) + nid = 0; + return nid; } @@ -297,14 +302,9 @@ static int __cpuinit numa_setup_cpu(unsigned long lcpu) nid = of_node_to_nid(cpu); if (nid >= num_online_nodes()) { - /* - * POWER4 LPAR uses 0xffff as invalid node, - * dont warn in this case. - */ - if (nid != 0xffff) - printk(KERN_ERR "WARNING: cpu %ld " - "maps to invalid NUMA node %d\n", - lcpu, nid); + printk(KERN_ERR "WARNING: cpu %ld " + "maps to invalid NUMA node %d\n", + lcpu, nid); nid = 0; } out: @@ -442,10 +442,9 @@ new_range: nid = of_node_to_nid(memory); if (nid >= MAX_NUMNODES) { - if (nid != 0xffff) - printk(KERN_ERR "WARNING: memory at %lx maps " - "to invalid NUMA node %d\n", start, - nid); + printk(KERN_ERR "WARNING: memory at %lx maps " + "to invalid NUMA node %d\n", start, + nid); nid = 0; } -- cgit v1.2.2 From 482ec7c403d239bb4f1732faf9a14988094ce08b Mon Sep 17 00:00:00 2001 From: Nathan Lynch Date: Mon, 20 Mar 2006 18:36:45 -0600 Subject: [PATCH] powerpc numa: Support sparse online node map The powerpc numa code unconditionally onlines all nodes from 0 to the highest node id found, regardless of whether cpus or memory are present in the nodes. This wastes 8K per node and complicates some cpu and memory hotplug situations, such as adding a resource that doesn't map to one of the nodes discovered at boot. Set nodes online as resources are scanned. Fall back to node 0 only when we're sure this isn't a NUMA machine. Instead of defaulting to node 0 for cases of hot-adding a resource which doesn't belong to any initialized node, assign it to the first online node. Signed-off-by: Nathan Lynch Signed-off-by: Paul Mackerras --- arch/powerpc/mm/numa.c | 95 +++++++++++++++++++++++--------------------------- 1 file changed, 43 insertions(+), 52 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index dd611ef8df7a..7d6ebe3c3b9b 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -191,27 +191,28 @@ static int *of_get_associativity(struct device_node *dev) return (unsigned int *)get_property(dev, "ibm,associativity", NULL); } +/* Returns nid in the range [0..MAX_NUMNODES-1], or -1 if no useful numa + * info is found. + */ static int of_node_to_nid(struct device_node *device) { - int nid; + int nid = -1; unsigned int *tmp; if (min_common_depth == -1) - return 0; + goto out; tmp = of_get_associativity(device); - if (tmp && (tmp[0] >= min_common_depth)) { + if (!tmp) + goto out; + + if (tmp[0] >= min_common_depth) nid = tmp[min_common_depth]; - } else { - dbg("WARNING: no NUMA information for %s\n", - device->full_name); - nid = 0; - } /* POWER4 LPAR uses 0xffff as invalid node */ - if (nid == 0xffff) - nid = 0; - + if (nid == 0xffff || nid >= MAX_NUMNODES) + nid = -1; +out: return nid; } @@ -301,15 +302,9 @@ static int __cpuinit numa_setup_cpu(unsigned long lcpu) nid = of_node_to_nid(cpu); - if (nid >= num_online_nodes()) { - printk(KERN_ERR "WARNING: cpu %ld " - "maps to invalid NUMA node %d\n", - lcpu, nid); - nid = 0; - } + if (nid < 0 || !node_online(nid)) + nid = any_online_node(NODE_MASK_ALL); out: - node_set_online(nid); - map_cpu_to_node(lcpu, nid); of_node_put(cpu); @@ -376,7 +371,7 @@ static int __init parse_numa_properties(void) { struct device_node *cpu = NULL; struct device_node *memory = NULL; - int max_domain = 0; + int default_nid = 0; unsigned long i; if (numa_enabled == 0) { @@ -392,25 +387,26 @@ static int __init parse_numa_properties(void) dbg("NUMA associativity depth for CPU/Memory: %d\n", min_common_depth); /* - * Even though we connect cpus to numa domains later in SMP init, - * we need to know the maximum node id now. This is because each - * node id must have NODE_DATA etc backing it. - * As a result of hotplug we could still have cpus appear later on - * with larger node ids. In that case we force the cpu into node 0. + * Even though we connect cpus to numa domains later in SMP + * init, we need to know the node ids now. This is because + * each node to be onlined must have NODE_DATA etc backing it. */ - for_each_cpu(i) { + for_each_present_cpu(i) { int nid; cpu = find_cpu_node(i); + BUG_ON(!cpu); + nid = of_node_to_nid(cpu); + of_node_put(cpu); - if (cpu) { - nid = of_node_to_nid(cpu); - of_node_put(cpu); - - if (nid < MAX_NUMNODES && - max_domain < nid) - max_domain = nid; - } + /* + * Don't fall back to default_nid yet -- we will plug + * cpus into nodes once the memory scan has discovered + * the topology. + */ + if (nid < 0) + continue; + node_set_online(nid); } get_n_mem_cells(&n_mem_addr_cells, &n_mem_size_cells); @@ -439,17 +435,15 @@ new_range: start = read_n_cells(n_mem_addr_cells, &memcell_buf); size = read_n_cells(n_mem_size_cells, &memcell_buf); + /* + * Assumption: either all memory nodes or none will + * have associativity properties. If none, then + * everything goes to default_nid. + */ nid = of_node_to_nid(memory); - - if (nid >= MAX_NUMNODES) { - printk(KERN_ERR "WARNING: memory at %lx maps " - "to invalid NUMA node %d\n", start, - nid); - nid = 0; - } - - if (max_domain < nid) - max_domain = nid; + if (nid < 0) + nid = default_nid; + node_set_online(nid); if (!(size = numa_enforce_memory_limit(start, size))) { if (--ranges) @@ -465,10 +459,7 @@ new_range: goto new_range; } - for (i = 0; i <= max_domain; i++) - node_set_online(i); - - max_domain = numa_setup_cpu(boot_cpuid); + numa_setup_cpu(boot_cpuid); return 0; } @@ -768,10 +759,10 @@ int hot_add_scn_to_nid(unsigned long scn_addr) { struct device_node *memory = NULL; nodemask_t nodes; - int nid = 0; + int default_nid = any_online_node(NODE_MASK_ALL); if (!numa_enabled || (min_common_depth < 0)) - return nid; + return default_nid; while ((memory = of_find_node_by_type(memory, "memory")) != NULL) { unsigned long start, size; @@ -791,8 +782,8 @@ ha_new_range: nid = of_node_to_nid(memory); /* Domains not present at boot default to 0 */ - if (!node_online(nid)) - nid = any_online_node(NODE_MASK_ALL); + if (nid < 0 || !node_online(nid)) + nid = default_nid; if ((scn_addr >= start) && (scn_addr < (start + size))) { of_node_put(memory); -- cgit v1.2.2 From 2b2612272c77288b2bd53d5831df737cd669cd93 Mon Sep 17 00:00:00 2001 From: Nathan Lynch Date: Mon, 20 Mar 2006 18:37:15 -0600 Subject: [PATCH] powerpc numa: Consolidate assignment of cpus to nodes We can plug the boot cpu into its node independently of whether numa topology is detected. And numa_setup_cpu does the right thing for all cases now, so remove special-casing for non-numa from the cpu hotplug callback. Signed-off-by: Nathan Lynch Signed-off-by: Paul Mackerras --- arch/powerpc/mm/numa.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 7d6ebe3c3b9b..e89b22aa539e 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -321,10 +321,7 @@ static int cpu_numa_callback(struct notifier_block *nfb, switch (action) { case CPU_UP_PREPARE: - if (min_common_depth == -1 || !numa_enabled) - map_cpu_to_node(lcpu, 0); - else - numa_setup_cpu(lcpu); + numa_setup_cpu(lcpu); ret = NOTIFY_OK; break; #ifdef CONFIG_HOTPLUG_CPU @@ -459,8 +456,6 @@ new_range: goto new_range; } - numa_setup_cpu(boot_cpuid); - return 0; } @@ -475,7 +470,6 @@ static void __init setup_nonnuma(void) printk(KERN_INFO "Memory hole size: %ldMB\n", (top_of_ram - total_ram) >> 20); - map_cpu_to_node(boot_cpuid, 0); for (i = 0; i < lmb.memory.cnt; ++i) add_region(0, lmb.memory.region[i].base >> PAGE_SHIFT, lmb_size_pages(&lmb.memory, i)); @@ -612,6 +606,8 @@ void __init do_init_bootmem(void) dump_numa_memory_topology(); register_cpu_notifier(&ppc64_numa_nb); + cpu_numa_callback(&ppc64_numa_nb, CPU_UP_PREPARE, + (void *)(unsigned long)boot_cpuid); for_each_online_node(nid) { unsigned long start_pfn, end_pfn, pages_present; -- cgit v1.2.2 From caf80e579b5fc0048681a47c5a55487116e56a88 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 21 Mar 2006 20:45:51 +1100 Subject: [PATCH] powerpc: Unconfuse htab_bolt_mapping() callers htab_bolt_mapping() takes a vstart and pstart parameter, but all but one of its callers actually pass it vstart and vstart. Luckily before it passes paddr (calculated from paddr) to the hpte_insert routines it calls virt_to_abs() (aka. __pa()) on the address, so there isn't actually a bug. map_io_page() however does pass pstart properly, so currently it's broken AFAICT because we're calling __pa(paddr) which will get us something very large. Presumably no one's calling map_io_page() in the right context. Anyway, change htab_bolt_mapping() callers to properly pass pstart, and then use it properly in htab_bolt_mapping(), ie. don't call __pa() on it again. Booted on p5 LPAR, iSeries and Power3. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/mm/hash_utils_64.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 7d9ce9a48219..7b4eccffd002 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -169,7 +169,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, #ifdef CONFIG_PPC_ISERIES if (_machine == PLATFORM_ISERIES_LPAR) ret = iSeries_hpte_insert(hpteg, va, - __pa(vaddr), + paddr, tmp_mode, HPTE_V_BOLTED, psize); @@ -178,7 +178,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, #ifdef CONFIG_PPC_PSERIES if (_machine & PLATFORM_LPAR) ret = pSeries_lpar_hpte_insert(hpteg, va, - virt_to_abs(paddr), + paddr, tmp_mode, HPTE_V_BOLTED, psize); @@ -186,7 +186,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, #endif #ifdef CONFIG_PPC_MULTIPLATFORM ret = native_hpte_insert(hpteg, va, - virt_to_abs(paddr), + paddr, tmp_mode, HPTE_V_BOLTED, psize); #endif @@ -392,7 +392,7 @@ static unsigned long __init htab_get_table_size(void) #ifdef CONFIG_MEMORY_HOTPLUG void create_section_mapping(unsigned long start, unsigned long end) { - BUG_ON(htab_bolt_mapping(start, end, start, + BUG_ON(htab_bolt_mapping(start, end, __pa(start), _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX, mmu_linear_psize)); } @@ -473,21 +473,22 @@ void __init htab_initialize(void) if (dart_tablebase != 0 && dart_tablebase >= base && dart_tablebase < (base + size)) { + unsigned long dart_table_end = dart_tablebase + 16 * MB; if (base != dart_tablebase) BUG_ON(htab_bolt_mapping(base, dart_tablebase, - base, mode_rw, - mmu_linear_psize)); - if ((base + size) > (dart_tablebase + 16*MB)) + __pa(base), mode_rw, + mmu_linear_psize)); + if ((base + size) > dart_table_end) BUG_ON(htab_bolt_mapping(dart_tablebase+16*MB, - base + size, - dart_tablebase+16*MB, + base + size, + __pa(dart_table_end), mode_rw, mmu_linear_psize)); continue; } #endif /* CONFIG_U3_DART */ - BUG_ON(htab_bolt_mapping(base, base + size, base, - mode_rw, mmu_linear_psize)); + BUG_ON(htab_bolt_mapping(base, base + size, __pa(base), + mode_rw, mmu_linear_psize)); } /* @@ -504,8 +505,8 @@ void __init htab_initialize(void) if (base + size >= tce_alloc_start) tce_alloc_start = base + size + 1; - BUG_ON(htab_bolt_mapping(tce_alloc_start, tce_alloc_end, - tce_alloc_start, mode_rw, + BUG_ON(htab_bolt_mapping(tce_alloc_start, tce_alloc_end, + __pa(tce_alloc_start), mode_rw, mmu_linear_psize)); } -- cgit v1.2.2 From 415202447d31d0f458cca256ad7e0ed777d993d9 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 21 Mar 2006 20:45:58 +1100 Subject: [PATCH] powerpc: Remove unused iommu_off logic from pSeries_init_early() When iommu_init_early_pSeries() was added, ages ago, we forgot to remove the code that checks /chosen/linux,iommu-off in pSeries_init_early(). We do it now in iommu_init_early_pSeries(). Signed-off-by: Michael Ellerman Acked-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/setup.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index b5996a7060f4..149751a3742a 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -320,19 +320,14 @@ static int pseries_set_xdabr(unsigned long dabr) */ static void __init pSeries_init_early(void) { - int iommu_off = 0; - DBG(" -> pSeries_init_early()\n"); fw_feature_init(); if (platform_is_lpar()) hpte_init_lpar(); - else { + else hpte_init_native(); - iommu_off = (of_chosen && - get_property(of_chosen, "linux,iommu-off", NULL)); - } if (platform_is_lpar()) find_udbg_vterm(); -- cgit v1.2.2 From 57cfb814f698d30894bc28e22125550193ebe549 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 21 Mar 2006 20:45:59 +1100 Subject: [PATCH] powerpc: Replace platform_is_lpar() with a firmware feature It has been decreed that platform numbers are evil, so as a step in that direction, replace platform_is_lpar() with a FW_FEATURE_LPAR bit. Currently FW_FEATURE_LPAR really means i/pSeries LPAR, in the future we might have to clean that up if we need to be more specific about what LPAR actually means. But that's another patch ... Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/mm/hash_utils_64.c | 4 ++-- arch/powerpc/oprofile/op_model_power4.c | 3 ++- arch/powerpc/platforms/iseries/setup.c | 10 +++++++--- arch/powerpc/platforms/pseries/iommu.c | 2 +- arch/powerpc/platforms/pseries/setup.c | 11 +++++++---- arch/powerpc/platforms/pseries/smp.c | 2 +- arch/powerpc/platforms/pseries/xics.c | 3 ++- 7 files changed, 22 insertions(+), 13 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 7b4eccffd002..89b35c181314 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -422,7 +422,7 @@ void __init htab_initialize(void) htab_hash_mask = pteg_count - 1; - if (platform_is_lpar()) { + if (firmware_has_feature(FW_FEATURE_LPAR)) { /* Using a hypervisor which owns the htab */ htab_address = NULL; _SDR1 = 0; @@ -517,7 +517,7 @@ void __init htab_initialize(void) void htab_initialize_secondary(void) { - if (!platform_is_lpar()) + if (!firmware_has_feature(FW_FEATURE_LPAR)) mtspr(SPRN_SDR1, _SDR1); } diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c index 659a021da0c7..4b06e53eb9b4 100644 --- a/arch/powerpc/oprofile/op_model_power4.c +++ b/arch/powerpc/oprofile/op_model_power4.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -232,7 +233,7 @@ static unsigned long get_pc(struct pt_regs *regs) mmcra = mfspr(SPRN_MMCRA); /* Were we in the hypervisor? */ - if (platform_is_lpar() && (mmcra & MMCRA_SIHV)) + if (firmware_has_feature(FW_FEATURE_LPAR) && (mmcra & MMCRA_SIHV)) /* function descriptor madness */ return *((unsigned long *)hypervisor_bucket); diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 3ecc4a652d82..b08c3686f903 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -303,8 +303,6 @@ static void __init iSeries_init_early(void) { DBG(" -> iSeries_init_early()\n"); - ppc64_firmware_features = FW_FEATURE_ISERIES; - ppc64_interrupt_controller = IC_ISERIES; #if defined(CONFIG_BLK_DEV_INITRD) @@ -711,7 +709,13 @@ void __init iSeries_init_IRQ(void) { } static int __init iseries_probe(int platform) { - return PLATFORM_ISERIES_LPAR == platform; + if (PLATFORM_ISERIES_LPAR != platform) + return 0; + + ppc64_firmware_features |= FW_FEATURE_ISERIES; + ppc64_firmware_features |= FW_FEATURE_LPAR; + + return 1; } struct machdep_calls __initdata iseries_md = { diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 57930e23cc74..2643078433f0 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -580,7 +580,7 @@ void iommu_init_early_pSeries(void) return; } - if (platform_is_lpar()) { + if (firmware_has_feature(FW_FEATURE_LPAR)) { if (firmware_has_feature(FW_FEATURE_MULTITCE)) { ppc_md.tce_build = tce_buildmulti_pSeriesLP; ppc_md.tce_free = tce_freemulti_pSeriesLP; diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 149751a3742a..44d5c7fdcd97 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -246,7 +246,7 @@ static void __init pSeries_setup_arch(void) ppc_md.idle_loop = default_idle; } - if (platform_is_lpar()) + if (firmware_has_feature(FW_FEATURE_LPAR)) ppc_md.enable_pmcs = pseries_lpar_enable_pmcs; else ppc_md.enable_pmcs = power4_enable_pmcs; @@ -324,12 +324,12 @@ static void __init pSeries_init_early(void) fw_feature_init(); - if (platform_is_lpar()) + if (firmware_has_feature(FW_FEATURE_LPAR)) hpte_init_lpar(); else hpte_init_native(); - if (platform_is_lpar()) + if (firmware_has_feature(FW_FEATURE_LPAR)) find_udbg_vterm(); if (firmware_has_feature(FW_FEATURE_DABR)) @@ -385,6 +385,9 @@ static int __init pSeries_probe(int platform) * it here ... */ + if (platform == PLATFORM_PSERIES_LPAR) + ppc64_firmware_features |= FW_FEATURE_LPAR; + return 1; } @@ -524,7 +527,7 @@ static void pseries_shared_idle(void) static int pSeries_pci_probe_mode(struct pci_bus *bus) { - if (platform_is_lpar()) + if (firmware_has_feature(FW_FEATURE_LPAR)) return PCI_PROBE_DEVTREE; return PCI_PROBE_NORMAL; } diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index 8d710af50756..3cf78a6cd27c 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c @@ -443,7 +443,7 @@ void __init smp_init_pSeries(void) smp_ops->cpu_die = pSeries_cpu_die; /* Processors can be added/removed only on LPAR */ - if (platform_is_lpar()) + if (firmware_has_feature(FW_FEATURE_LPAR)) pSeries_reconfig_notifier_register(&pSeries_smp_nb); #endif diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index fd823c7c9ac8..eb86cdb9b802 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -536,7 +537,7 @@ nextnode: of_node_put(np); } - if (platform_is_lpar()) + if (firmware_has_feature(FW_FEATURE_LPAR)) ops = &pSeriesLP_ops; else { #ifdef CONFIG_SMP -- cgit v1.2.2 From 260de22faac4d336ca122ebd0f1e59279d0b1dfd Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 21 Mar 2006 20:46:02 +1100 Subject: [PATCH] powerpc: iseries: mf related cleanups Some cleanups in the iSeries code. - Make mf_display_progress() check mf_initialized rather than the caller. - Set mf_initialized in mf_init() rather than in setup.c - Then move mf_initialized into mf.c, the only place it's used. - Move the mf related logic from iSeries_progress() to mf_display_progress() - Use a #define to size the pending_event_prealloc array - Use that define in the initialsation loop rather than sizeof jiggery pokery - Remove stupid comment(s) - Mark stuff static and/or __init Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/mf.c | 32 +++++++++++++++++++++++--------- arch/powerpc/platforms/iseries/setup.c | 11 +---------- 2 files changed, 24 insertions(+), 19 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index a41d8b78c0cd..97a26137cf40 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c @@ -46,6 +46,7 @@ #include "setup.h" extern int piranha_simulator; +static int mf_initialized; /* * This is the structure layout for the Machine Facilites LPAR event @@ -143,7 +144,8 @@ static spinlock_t pending_event_spinlock; static struct pending_event *pending_event_head; static struct pending_event *pending_event_tail; static struct pending_event *pending_event_avail; -static struct pending_event pending_event_prealloc[16]; +#define PENDING_EVENT_PREALLOC_LEN 16 +static struct pending_event pending_event_prealloc[PENDING_EVENT_PREALLOC_LEN]; /* * Put a pending event onto the available queue, so it can get reused. @@ -625,7 +627,7 @@ void mf_display_src(u32 word) /* * Display a single word SRC of the form "PROGXXXX" on the VSP control panel. */ -void mf_display_progress(u16 value) +static __init void mf_display_progress_src(u16 value) { u8 ce[12]; u8 src[72]; @@ -649,30 +651,42 @@ void mf_display_progress(u16 value) * Clear the VSP control panel. Used to "erase" an SRC that was * previously displayed. */ -void mf_clear_src(void) +static void mf_clear_src(void) { signal_ce_msg_simple(0x4b, NULL); } +void __init mf_display_progress(u16 value) +{ + if (piranha_simulator || !mf_initialized) + return; + + if (0xFFFF == value) + mf_clear_src(); + else + mf_display_progress_src(value); +} + /* * Initialization code here. */ -void mf_init(void) +void __init mf_init(void) { int i; - /* initialize */ spin_lock_init(&pending_event_spinlock); - for (i = 0; - i < sizeof(pending_event_prealloc) / sizeof(*pending_event_prealloc); - ++i) + + for (i = 0; i < PENDING_EVENT_PREALLOC_LEN; i++) free_pending_event(&pending_event_prealloc[i]); + HvLpEvent_registerHandler(HvLpEvent_Type_MachineFac, &hv_handler); /* virtual continue ack */ signal_ce_msg_simple(0x57, NULL); - /* initialization complete */ + mf_initialized = 1; + mb(); + printk(KERN_NOTICE "mf.c: iSeries Linux LPAR Machine Facilities " "initialized\n"); } diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index b08c3686f903..190891ce9cb4 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -89,8 +89,6 @@ extern unsigned long embedded_sysmap_end; extern unsigned long iSeries_recal_tb; extern unsigned long iSeries_recal_titan; -static int mf_initialized; - static unsigned long cmd_mem_limit; struct MemoryBlock { @@ -347,8 +345,6 @@ static void __init iSeries_init_early(void) HvCallEvent_setLpEventQueueInterruptProc(0, 0); mf_init(); - mf_initialized = 1; - mb(); /* If we were passed an initrd, set the ROOT_DEV properly if the values * look sensible. If not, clear initrd reference. @@ -585,12 +581,7 @@ static void iSeries_halt(void) static void __init iSeries_progress(char * st, unsigned short code) { printk("Progress: [%04x] - %s\n", (unsigned)code, st); - if (!piranha_simulator && mf_initialized) { - if (code != 0xffff) - mf_display_progress(code); - else - mf_clear_src(); - } + mf_display_progress(code); } static void __init iSeries_fixup_klimit(void) -- cgit v1.2.2 From a9ea2101aaa7fe73cb352cea4145853efdabaa0d Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 21 Mar 2006 20:46:04 +1100 Subject: [PATCH] powerpc: iseries: Remove pointless iSeries_(restart|power_off|halt) These routines just call through to the mf routines, so point ppc_md straight at the mf routines. We need to pass the cmd through to mf_reboot to make it work, but that seems reasonable. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/mf.c | 2 +- arch/powerpc/platforms/iseries/setup.c | 30 +++--------------------------- 2 files changed, 4 insertions(+), 28 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index 97a26137cf40..18054e922bd1 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c @@ -599,7 +599,7 @@ void mf_power_off(void) * Global kernel interface to tell the VSP object in the primary * partition to reboot this partition. */ -void mf_reboot(void) +void mf_reboot(char *cmd) { printk(KERN_INFO "mf.c: Preparing to bounce...\n"); signal_ce_msg_simple(0x4e, NULL); diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 190891ce9cb4..127af3b0ba82 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -554,30 +554,6 @@ static void iSeries_show_cpuinfo(struct seq_file *m) seq_printf(m, "machine\t\t: 64-bit iSeries Logical Partition\n"); } -/* - * Document me. - */ -static void iSeries_restart(char *cmd) -{ - mf_reboot(); -} - -/* - * Document me. - */ -static void iSeries_power_off(void) -{ - mf_power_off(); -} - -/* - * Document me. - */ -static void iSeries_halt(void) -{ - mf_power_off(); -} - static void __init iSeries_progress(char * st, unsigned short code) { printk("Progress: [%04x] - %s\n", (unsigned)code, st); @@ -716,9 +692,9 @@ struct machdep_calls __initdata iseries_md = { .get_irq = iSeries_get_irq, .init_early = iSeries_init_early, .pcibios_fixup = iSeries_pci_final_fixup, - .restart = iSeries_restart, - .power_off = iSeries_power_off, - .halt = iSeries_halt, + .restart = mf_reboot, + .power_off = mf_power_off, + .halt = mf_power_off, .get_boot_time = iSeries_get_boot_time, .set_rtc_time = iSeries_set_rtc_time, .get_rtc_time = iSeries_get_rtc_time, -- cgit v1.2.2 From 00611c5cfc8dea0914c65134f62948a484780a30 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 21 Mar 2006 20:46:05 +1100 Subject: [PATCH] powerpc: iseries: Make more stuff static in platforms/iseries/mf.c Make mf_get_rtc(), mf_get_boot_rtc() and mf_set_rtc() static, cause they can be. We need to move mf_set_rtc() to avoid a forward declaration. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/mf.c | 78 ++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 39 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index 18054e922bd1..d771b8ee857d 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c @@ -706,6 +706,43 @@ static void get_rtc_time_complete(void *token, struct ce_msg_data *ce_msg) complete(&rtc->com); } +static int mf_set_rtc(struct rtc_time *tm) +{ + char ce_time[12]; + u8 day, mon, hour, min, sec, y1, y2; + unsigned year; + + year = 1900 + tm->tm_year; + y1 = year / 100; + y2 = year % 100; + + sec = tm->tm_sec; + min = tm->tm_min; + hour = tm->tm_hour; + day = tm->tm_mday; + mon = tm->tm_mon + 1; + + BIN_TO_BCD(sec); + BIN_TO_BCD(min); + BIN_TO_BCD(hour); + BIN_TO_BCD(mon); + BIN_TO_BCD(day); + BIN_TO_BCD(y1); + BIN_TO_BCD(y2); + + memset(ce_time, 0, sizeof(ce_time)); + ce_time[3] = 0x41; + ce_time[4] = y1; + ce_time[5] = y2; + ce_time[6] = sec; + ce_time[7] = min; + ce_time[8] = hour; + ce_time[10] = day; + ce_time[11] = mon; + + return signal_ce_msg(ce_time, NULL); +} + static int rtc_set_tm(int rc, u8 *ce_msg, struct rtc_time *tm) { tm->tm_wday = 0; @@ -761,7 +798,7 @@ static int rtc_set_tm(int rc, u8 *ce_msg, struct rtc_time *tm) return 0; } -int mf_get_rtc(struct rtc_time *tm) +static int mf_get_rtc(struct rtc_time *tm) { struct ce_msg_comp_data ce_complete; struct rtc_time_data rtc_data; @@ -794,7 +831,7 @@ static void get_boot_rtc_time_complete(void *token, struct ce_msg_data *ce_msg) rtc->busy = 0; } -int mf_get_boot_rtc(struct rtc_time *tm) +static int mf_get_boot_rtc(struct rtc_time *tm) { struct ce_msg_comp_data ce_complete; struct boot_rtc_time_data rtc_data; @@ -816,43 +853,6 @@ int mf_get_boot_rtc(struct rtc_time *tm) return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm); } -int mf_set_rtc(struct rtc_time *tm) -{ - char ce_time[12]; - u8 day, mon, hour, min, sec, y1, y2; - unsigned year; - - year = 1900 + tm->tm_year; - y1 = year / 100; - y2 = year % 100; - - sec = tm->tm_sec; - min = tm->tm_min; - hour = tm->tm_hour; - day = tm->tm_mday; - mon = tm->tm_mon + 1; - - BIN_TO_BCD(sec); - BIN_TO_BCD(min); - BIN_TO_BCD(hour); - BIN_TO_BCD(mon); - BIN_TO_BCD(day); - BIN_TO_BCD(y1); - BIN_TO_BCD(y2); - - memset(ce_time, 0, sizeof(ce_time)); - ce_time[3] = 0x41; - ce_time[4] = y1; - ce_time[5] = y2; - ce_time[6] = sec; - ce_time[7] = min; - ce_time[8] = hour; - ce_time[10] = day; - ce_time[11] = mon; - - return signal_ce_msg(ce_time, NULL); -} - #ifdef CONFIG_PROC_FS static int proc_mf_dump_cmdline(char *page, char **start, off_t off, -- cgit v1.2.2 From 584fc6d111c34a9a2512f6c7652dff29232bf70d Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 21 Mar 2006 20:46:08 +1100 Subject: [PATCH] powerpc: Add strne2a() to convert a string from EBCDIC to ASCII Add strne2a() which converts a string from EBCDIC to ASCII. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/lib/e2a.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'arch/powerpc') diff --git a/arch/powerpc/lib/e2a.c b/arch/powerpc/lib/e2a.c index 4f88f4cc21e8..4b72ed8fd50e 100644 --- a/arch/powerpc/lib/e2a.c +++ b/arch/powerpc/lib/e2a.c @@ -103,4 +103,14 @@ unsigned char e2a(unsigned char x) } EXPORT_SYMBOL(e2a); +unsigned char* strne2a(unsigned char *dest, const unsigned char *src, size_t n) +{ + int i; + + n = strnlen(src, n); + for (i = 0; i < n; i++) + dest[i] = e2a(src[i]); + + return dest; +} -- cgit v1.2.2 From 289f1c74a9b527a816f63092e79a5412cc0352a2 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 21 Mar 2006 20:46:09 +1100 Subject: [PATCH] powerpc: iseries: Add /system-id, /model and /compatible Add /system-id, /model and /compatible to the iSeries device tree. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/setup.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 127af3b0ba82..8fe7237bc46f 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -888,6 +889,24 @@ void dt_cpus(struct iseries_flat_dt *dt) dt_end_node(dt); } +void dt_model(struct iseries_flat_dt *dt) +{ + char buf[16] = "IBM,"; + + /* "IBM," + mfgId[2:3] + systemSerial[1:5] */ + strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2); + strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5); + buf[11] = '\0'; + dt_prop_str(dt, "system-id", buf); + + /* "IBM," + machineType[0:4] */ + strne2a(buf + 4, xItExtVpdPanel.machineType, 4); + buf[8] = '\0'; + dt_prop_str(dt, "model", buf); + + dt_prop_str(dt, "compatible", "IBM,iSeries"); +} + void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) { u64 tmp[2]; @@ -898,6 +917,7 @@ void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) dt_prop_u32(dt, "#address-cells", 2); dt_prop_u32(dt, "#size-cells", 2); + dt_model(dt); /* /memory */ dt_start_node(dt, "memory@0"); -- cgit v1.2.2 From 6c600ad8da189aebe65b765fd0349ef6c9dd8c1f Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 21 Mar 2006 20:46:10 +1100 Subject: [PATCH] powerpc: iseries: Add bootargs to /chosen Add the command line args to the device tree as /chosen/bootargs. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/setup.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 8fe7237bc46f..fa4550611c11 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -931,6 +931,7 @@ void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) /* /chosen */ dt_start_node(dt, "chosen"); dt_prop_u32(dt, "linux,platform", PLATFORM_ISERIES_LPAR); + dt_prop_str(dt, "bootargs", cmd_line); if (cmd_mem_limit) dt_prop_u64(dt, "linux,memory-limit", cmd_mem_limit); dt_end_node(dt); -- cgit v1.2.2 From f8642ebee8e46d054d83828a4048fba4ebcd8f68 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 21 Mar 2006 20:46:11 +1100 Subject: [PATCH] powerpc: Remove calculation of io hole In mm_init_ppc64() we calculate the location of the "IO hole", but then no one ever looks at the value. So don't bother. That's actually all mm_init_ppc64() does, so get rid of it too. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/setup_64.c | 2 -- arch/powerpc/mm/init_64.c | 48 ------------------------------------------ 2 files changed, 50 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index f96c49b03ba0..2f3fdad35594 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -497,8 +497,6 @@ void __init setup_system(void) #endif printk("-----------------------------------------------------\n"); - mm_init_ppc64(); - DBG(" <- setup_system()\n"); } diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 81cfb0c2ec58..5d4733d61805 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -84,54 +84,6 @@ /* max amount of RAM to use */ unsigned long __max_memory; -/* info on what we think the IO hole is */ -unsigned long io_hole_start; -unsigned long io_hole_size; - -/* - * Do very early mm setup. - */ -void __init mm_init_ppc64(void) -{ -#ifndef CONFIG_PPC_ISERIES - unsigned long i; -#endif - - ppc64_boot_msg(0x100, "MM Init"); - - /* This is the story of the IO hole... please, keep seated, - * unfortunately, we are out of oxygen masks at the moment. - * So we need some rough way to tell where your big IO hole - * is. On pmac, it's between 2G and 4G, on POWER3, it's around - * that area as well, on POWER4 we don't have one, etc... - * We need that as a "hint" when sizing the TCE table on POWER3 - * So far, the simplest way that seem work well enough for us it - * to just assume that the first discontinuity in our physical - * RAM layout is the IO hole. That may not be correct in the future - * (and isn't on iSeries but then we don't care ;) - */ - -#ifndef CONFIG_PPC_ISERIES - for (i = 1; i < lmb.memory.cnt; i++) { - unsigned long base, prevbase, prevsize; - - prevbase = lmb.memory.region[i-1].base; - prevsize = lmb.memory.region[i-1].size; - base = lmb.memory.region[i].base; - if (base > (prevbase + prevsize)) { - io_hole_start = prevbase + prevsize; - io_hole_size = base - (prevbase + prevsize); - break; - } - } -#endif /* CONFIG_PPC_ISERIES */ - if (io_hole_start) - printk("IO Hole assumed to be %lx -> %lx\n", - io_hole_start, io_hole_start + io_hole_size - 1); - - ppc64_boot_msg(0x100, "MM Init Done"); -} - void free_initmem(void) { unsigned long addr; -- cgit v1.2.2 From 70dc991d66cac40fdb07346dba2b5d862d732c34 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 22 Mar 2006 00:08:35 -0800 Subject: [PATCH] remove set_page_count(page, 0) users (outside mm) A couple of places set_page_count(page, 1) that don't need to. Signed-off-by: Nick Piggin Cc: Paul Mackerras Cc: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/mm/mem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 550517c2dd42..6ae5c130d0db 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -108,8 +108,8 @@ EXPORT_SYMBOL(phys_mem_access_prot); void online_page(struct page *page) { ClearPageReserved(page); - set_page_count(page, 0); - free_cold_page(page); + set_page_count(page, 1); + __free_page(page); totalram_pages++; num_physpages++; } -- cgit v1.2.2 From 7835e98b2e3c66dba79cb0ff8ebb90a2fe030c29 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 22 Mar 2006 00:08:40 -0800 Subject: [PATCH] remove set_page_count() outside mm/ set_page_count usage outside mm/ is limited to setting the refcount to 1. Remove set_page_count from outside mm/, and replace those users with init_page_count() and set_page_refcounted(). This allows more debug checking, and tighter control on how code is allowed to play around with page->_count. Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/mm/init_32.c | 4 ++-- arch/powerpc/mm/init_64.c | 4 ++-- arch/powerpc/mm/mem.c | 4 ++-- arch/powerpc/platforms/cell/setup.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c index 7d0d75c11848..b57fb3a2b7bb 100644 --- a/arch/powerpc/mm/init_32.c +++ b/arch/powerpc/mm/init_32.c @@ -216,7 +216,7 @@ static void free_sec(unsigned long start, unsigned long end, const char *name) while (start < end) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); cnt++; start += PAGE_SIZE; @@ -248,7 +248,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); totalram_pages++; } diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 81cfb0c2ec58..bacb71c89811 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -140,7 +140,7 @@ void free_initmem(void) for (; addr < (unsigned long)__init_end; addr += PAGE_SIZE) { memset((void *)addr, 0xcc, PAGE_SIZE); ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); + init_page_count(virt_to_page(addr)); free_page(addr); totalram_pages++; } @@ -155,7 +155,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); + init_page_count(virt_to_page(start)); free_page(start); totalram_pages++; } diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 6ae5c130d0db..454cac01d8cc 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -108,7 +108,7 @@ EXPORT_SYMBOL(phys_mem_access_prot); void online_page(struct page *page) { ClearPageReserved(page); - set_page_count(page, 1); + init_page_count(page); __free_page(page); totalram_pages++; num_physpages++; @@ -376,7 +376,7 @@ void __init mem_init(void) struct page *page = pfn_to_page(pfn); ClearPageReserved(page); - set_page_count(page, 1); + init_page_count(page); __free_page(page); totalhigh_pages++; } diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index b33a4443f5a9..fec8e65b36ea 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -115,7 +115,7 @@ static void __init cell_spuprop_present(struct device_node *spe, for (pfn = start_pfn; pfn < end_pfn; pfn++) { struct page *page = pfn_to_page(pfn); set_page_links(page, ZONE_DMA, node_id, pfn); - set_page_count(page, 1); + init_page_count(page); reset_page_mapcount(page); SetPageReserved(page); INIT_LIST_HEAD(&page->lru); -- cgit v1.2.2 From 42b88befd6e0dae1a5fe04c03925037fa890e1f3 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 22 Mar 2006 00:09:01 -0800 Subject: [PATCH] hugepage: is_aligned_hugepage_range() cleanup Quite a long time back, prepare_hugepage_range() replaced is_aligned_hugepage_range() as the callback from mm/mmap.c to arch code to verify if an address range is suitable for a hugepage mapping. is_aligned_hugepage_range() stuck around, but only to implement prepare_hugepage_range() on archs which didn't implement their own. Most archs (everything except ia64 and powerpc) used the same implementation of is_aligned_hugepage_range(). On powerpc, which implements its own prepare_hugepage_range(), the custom version was never used. In addition, "is_aligned_hugepage_range()" was a bad name, because it suggests it returns true iff the given range is a good hugepage range, whereas in fact it returns 0-or-error (so the sense is reversed). This patch cleans up by abolishing is_aligned_hugepage_range(). Instead prepare_hugepage_range() is defined directly. Most archs use the default version, which simply checks the given region is aligned to the size of a hugepage. ia64 and powerpc define custom versions. The ia64 one simply checks that the range is in the correct address space region in addition to being suitably aligned. The powerpc version (just as previously) checks for suitable addresses, and if necessary performs low-level MMU frobbing to set up new areas for use by hugepages. No libhugetlbfs testsuite regressions on ppc64 (POWER5 LPAR). Signed-off-by: David Gibson Signed-off-by: Zhang Yanmin Cc: "David S. Miller" Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: William Lee Irwin III Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/mm/hugetlbpage.c | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index b51bb28c054b..7370f9f33e29 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c @@ -133,21 +133,6 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, return __pte(old); } -/* - * This function checks for proper alignment of input addr and len parameters. - */ -int is_aligned_hugepage_range(unsigned long addr, unsigned long len) -{ - if (len & ~HPAGE_MASK) - return -EINVAL; - if (addr & ~HPAGE_MASK) - return -EINVAL; - if (! (within_hugepage_low_range(addr, len) - || within_hugepage_high_range(addr, len)) ) - return -EINVAL; - return 0; -} - struct slb_flush_info { struct mm_struct *mm; u16 newareas; -- cgit v1.2.2 From 2d0eee14b23f20c501a6c2536edf68f93c56edcd Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 21 Mar 2006 23:00:05 -0800 Subject: [PATCH] powerpc: Fix warning in add_memory arch/powerpc/mm/mem.c: In function `add_memory': arch/powerpc/mm/mem.c:128: warning: assignment makes integer from pointer without a cast Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras --- arch/powerpc/mm/mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 6809cdba6e94..80550b284505 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -125,7 +125,7 @@ int __devinit add_memory(u64 start, u64 size) nid = hot_add_scn_to_nid(start); pgdata = NODE_DATA(nid); - start = __va(start); + start = (unsigned long)__va(start); create_section_mapping(start, start + size); /* this should work for most non-highmem platforms */ -- cgit v1.2.2 From 6ea671a12f66b9d4d0f35fce957a71a6849295f2 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 21 Mar 2006 23:20:27 -0800 Subject: [PATCH] powerpc: tidy-up of_register_driver()/driver_register() return values Remove the assumption that driver_register() returns the number of devices bound to the driver. In fact, it returns zero for success or a negative error value. Nobody uses the return value of of_register_driver() anyway. Signed-off-by: Bjorn Helgaas Acked-by: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/of_device.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c index 22d83d4d1af5..9feeeef5a875 100644 --- a/arch/powerpc/kernel/of_device.c +++ b/arch/powerpc/kernel/of_device.c @@ -147,15 +147,12 @@ postcore_initcall(of_bus_driver_init); int of_register_driver(struct of_platform_driver *drv) { - int count = 0; - /* initialize common driver fields */ drv->driver.name = drv->name; drv->driver.bus = &of_platform_bus_type; /* register with core */ - count = driver_register(&drv->driver); - return count ? count : 1; + return driver_register(&drv->driver); } void of_unregister_driver(struct of_platform_driver *drv) -- cgit v1.2.2 From 7a7d1cf95408863a657035701606b13644c9f55e Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 23 Mar 2006 03:00:35 -0800 Subject: [PATCH] sem2mutex: kprobes Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Ingo Molnar Acked-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/kernel/kprobes.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index 258039fb3016..cb1fe5878e8b 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c @@ -81,9 +81,9 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p) void __kprobes arch_remove_kprobe(struct kprobe *p) { - down(&kprobe_mutex); + mutex_lock(&kprobe_mutex); free_insn_slot(p->ainsn.insn); - up(&kprobe_mutex); + mutex_unlock(&kprobe_mutex); } static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) -- cgit v1.2.2 From 394e3902c55e667945f6f1c2bdbc59842cce70f7 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 23 Mar 2006 03:01:05 -0800 Subject: [PATCH] more for_each_cpu() conversions When we stop allocating percpu memory for not-possible CPUs we must not touch the percpu data for not-possible CPUs at all. The correct way of doing this is to test cpu_possible() or to use for_each_cpu(). This patch is a kernel-wide sweep of all instances of NR_CPUS. I found very few instances of this bug, if any. But the patch converts lots of open-coded test to use the preferred helper macros. Cc: Mikael Starvik Cc: David Howells Acked-by: Kyle McMartin Cc: Anton Blanchard Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Martin Schwidefsky Cc: Heiko Carstens Cc: Paul Mundt Cc: "David S. Miller" Cc: William Lee Irwin III Cc: Andi Kleen Cc: Christian Zankel Cc: Philippe Elie Cc: Nathan Scott Cc: Jens Axboe Cc: Eric Dumazet Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/kernel/irq.c | 5 ++--- arch/powerpc/kernel/setup-common.c | 5 ++--- arch/powerpc/kernel/setup_32.c | 5 ++--- arch/powerpc/platforms/powermac/smp.c | 4 +--- 4 files changed, 7 insertions(+), 12 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 24dc8117b822..771a59cbd213 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -135,9 +135,8 @@ skip: #ifdef CONFIG_TAU_INT if (tau_initialized){ seq_puts(p, "TAU: "); - for (j = 0; j < NR_CPUS; j++) - if (cpu_online(j)) - seq_printf(p, "%10u ", tau_interrupts(j)); + for_each_online_cpu(j) + seq_printf(p, "%10u ", tau_interrupts(j)); seq_puts(p, " PowerPC Thermal Assist (cpu temp)\n"); } #endif diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index be12041c0fc5..c1d62bf11f29 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -162,9 +162,8 @@ static int show_cpuinfo(struct seq_file *m, void *v) #if defined(CONFIG_SMP) && defined(CONFIG_PPC32) unsigned long bogosum = 0; int i; - for (i = 0; i < NR_CPUS; ++i) - if (cpu_online(i)) - bogosum += loops_per_jiffy; + for_each_online_cpu(i) + bogosum += loops_per_jiffy; seq_printf(m, "total bogomips\t: %lu.%02lu\n", bogosum/(500000/HZ), bogosum/(5000/HZ) % 100); #endif /* CONFIG_SMP && CONFIG_PPC32 */ diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index db72a92943bf..dc2770df25b3 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -272,9 +272,8 @@ int __init ppc_init(void) if ( ppc_md.progress ) ppc_md.progress(" ", 0xffff); /* register CPU devices */ - for (i = 0; i < NR_CPUS; i++) - if (cpu_possible(i)) - register_cpu(&cpu_devices[i], i, NULL); + for_each_cpu(i) + register_cpu(&cpu_devices[i], i, NULL); /* call platform init */ if (ppc_md.init != NULL) { diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index 6d64a9bf3474..1065d87fc279 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c @@ -191,9 +191,7 @@ static void smp_psurge_message_pass(int target, int msg) if (num_online_cpus() < 2) return; - for (i = 0; i < NR_CPUS; i++) { - if (!cpu_online(i)) - continue; + for_each_online_cpu(i) { if (target == MSG_ALL || (target == MSG_ALL_BUT_SELF && i != smp_processor_id()) || target == i) { -- cgit v1.2.2 From 3cbb90a9cb7854b1110663919d5bc3da3f46d5e3 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 25 Mar 2006 09:41:40 -0800 Subject: powerpc: fix strncasecmp prototype It takes a size_t, not an int, as its third argument. Signed-off-by: Linus Torvalds --- arch/powerpc/lib/strcase.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/lib/strcase.c b/arch/powerpc/lib/strcase.c index 36b521091bbc..f8ec1eba3fdd 100644 --- a/arch/powerpc/lib/strcase.c +++ b/arch/powerpc/lib/strcase.c @@ -1,4 +1,6 @@ +#include #include +#include int strcasecmp(const char *s1, const char *s2) { @@ -11,7 +13,7 @@ int strcasecmp(const char *s1, const char *s2) return c1 - c2; } -int strncasecmp(const char *s1, const char *s2, int n) +int strncasecmp(const char *s1, const char *s2, size_t n) { int c1, c2; -- cgit v1.2.2 From 14cc3e2b633bb64063698980974df4535368e98f Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 26 Mar 2006 01:37:14 -0800 Subject: [PATCH] sem2mutex: misc static one-file mutexes Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Ingo Molnar Cc: Dave Jones Cc: Paul Mackerras Cc: Ralf Baechle Cc: Jens Axboe Cc: Neil Brown Acked-by: Alasdair G Kergon Cc: Greg KH Cc: Dominik Brodowski Cc: Adam Belay Cc: Martin Schwidefsky Cc: "David S. Miller" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/mm/imalloc.c | 18 +++++++++--------- arch/powerpc/platforms/cell/spu_base.c | 22 +++++++++++----------- arch/powerpc/platforms/powermac/cpufreq_64.c | 7 ++++--- 3 files changed, 24 insertions(+), 23 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/mm/imalloc.c b/arch/powerpc/mm/imalloc.c index 8b0c132bc163..add8c1a9af68 100644 --- a/arch/powerpc/mm/imalloc.c +++ b/arch/powerpc/mm/imalloc.c @@ -13,12 +13,12 @@ #include #include #include -#include +#include #include #include "mmu_decl.h" -static DECLARE_MUTEX(imlist_sem); +static DEFINE_MUTEX(imlist_mutex); struct vm_struct * imlist = NULL; static int get_free_im_addr(unsigned long size, unsigned long *im_addr) @@ -257,7 +257,7 @@ struct vm_struct * im_get_free_area(unsigned long size) struct vm_struct *area; unsigned long addr; - down(&imlist_sem); + mutex_lock(&imlist_mutex); if (get_free_im_addr(size, &addr)) { printk(KERN_ERR "%s() cannot obtain addr for size 0x%lx\n", __FUNCTION__, size); @@ -272,7 +272,7 @@ struct vm_struct * im_get_free_area(unsigned long size) __FUNCTION__, addr, size); } next_im_done: - up(&imlist_sem); + mutex_unlock(&imlist_mutex); return area; } @@ -281,9 +281,9 @@ struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size, { struct vm_struct *area; - down(&imlist_sem); + mutex_lock(&imlist_mutex); area = __im_get_area(v_addr, size, criteria); - up(&imlist_sem); + mutex_unlock(&imlist_mutex); return area; } @@ -297,17 +297,17 @@ void im_free(void * addr) printk(KERN_ERR "Trying to %s bad address (%p)\n", __FUNCTION__, addr); return; } - down(&imlist_sem); + mutex_lock(&imlist_mutex); for (p = &imlist ; (tmp = *p) ; p = &tmp->next) { if (tmp->addr == addr) { *p = tmp->next; unmap_vm_area(tmp); kfree(tmp); - up(&imlist_sem); + mutex_unlock(&imlist_mutex); return; } } - up(&imlist_sem); + mutex_unlock(&imlist_mutex); printk(KERN_ERR "Trying to %s nonexistent area (%p)\n", __FUNCTION__, addr); } diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index d75ae03df686..a8fa1eeeb174 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -32,7 +32,7 @@ #include #include -#include +#include #include #include @@ -342,7 +342,7 @@ spu_free_irqs(struct spu *spu) } static LIST_HEAD(spu_list); -static DECLARE_MUTEX(spu_mutex); +static DEFINE_MUTEX(spu_mutex); static void spu_init_channels(struct spu *spu) { @@ -382,7 +382,7 @@ struct spu *spu_alloc(void) { struct spu *spu; - down(&spu_mutex); + mutex_lock(&spu_mutex); if (!list_empty(&spu_list)) { spu = list_entry(spu_list.next, struct spu, list); list_del_init(&spu->list); @@ -391,7 +391,7 @@ struct spu *spu_alloc(void) pr_debug("No SPU left\n"); spu = NULL; } - up(&spu_mutex); + mutex_unlock(&spu_mutex); if (spu) spu_init_channels(spu); @@ -402,9 +402,9 @@ EXPORT_SYMBOL_GPL(spu_alloc); void spu_free(struct spu *spu) { - down(&spu_mutex); + mutex_lock(&spu_mutex); list_add_tail(&spu->list, &spu_list); - up(&spu_mutex); + mutex_unlock(&spu_mutex); } EXPORT_SYMBOL_GPL(spu_free); @@ -633,14 +633,14 @@ static int __init create_spu(struct device_node *spe) spu->wbox_callback = NULL; spu->stop_callback = NULL; - down(&spu_mutex); + mutex_lock(&spu_mutex); spu->number = number++; ret = spu_request_irqs(spu); if (ret) goto out_unmap; list_add(&spu->list, &spu_list); - up(&spu_mutex); + mutex_unlock(&spu_mutex); pr_debug(KERN_DEBUG "Using SPE %s %02x %p %p %p %p %d\n", spu->name, spu->isrc, spu->local_store, @@ -648,7 +648,7 @@ static int __init create_spu(struct device_node *spe) goto out; out_unmap: - up(&spu_mutex); + mutex_unlock(&spu_mutex); spu_unmap(spu); out_free: kfree(spu); @@ -668,10 +668,10 @@ static void destroy_spu(struct spu *spu) static void cleanup_spu_base(void) { struct spu *spu, *tmp; - down(&spu_mutex); + mutex_lock(&spu_mutex); list_for_each_entry_safe(spu, tmp, &spu_list, list) destroy_spu(spu); - up(&spu_mutex); + mutex_unlock(&spu_mutex); } module_exit(cleanup_spu_base); diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c index a415e8d2f7af..b57e465a1b71 100644 --- a/arch/powerpc/platforms/powermac/cpufreq_64.c +++ b/arch/powerpc/platforms/powermac/cpufreq_64.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -90,7 +91,7 @@ static void (*g5_switch_volt)(int speed_mode); static int (*g5_switch_freq)(int speed_mode); static int (*g5_query_freq)(void); -static DECLARE_MUTEX(g5_switch_mutex); +static DEFINE_MUTEX(g5_switch_mutex); static struct smu_sdbp_fvt *g5_fvt_table; /* table of op. points */ @@ -327,7 +328,7 @@ static int g5_cpufreq_target(struct cpufreq_policy *policy, if (g5_pmode_cur == newstate) return 0; - down(&g5_switch_mutex); + mutex_lock(&g5_switch_mutex); freqs.old = g5_cpu_freqs[g5_pmode_cur].frequency; freqs.new = g5_cpu_freqs[newstate].frequency; @@ -337,7 +338,7 @@ static int g5_cpufreq_target(struct cpufreq_policy *policy, rc = g5_switch_freq(newstate); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - up(&g5_switch_mutex); + mutex_unlock(&g5_switch_mutex); return rc; } -- cgit v1.2.2 From 88959ea968709c35e8b979ac9f5a398fa748091a Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Sun, 26 Mar 2006 01:37:27 -0800 Subject: [PATCH] create struct compat_timex and use it everywhere We had a copy of the compatibility version of struct timex in each 64 bit architecture. This patch just creates a global one and replaces all the usages of the old ones. Signed-off-by: Stephen Rothwell Cc: Arnd Bergmann Acked-by: Kyle McMartin Acked-by: Tony Luck Acked-by: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/kernel/sys_ppc32.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c index cd75ab2908fa..d9867f583c68 100644 --- a/arch/powerpc/kernel/sys_ppc32.c +++ b/arch/powerpc/kernel/sys_ppc32.c @@ -162,22 +162,9 @@ asmlinkage long compat_sys_sysfs(u32 option, u32 arg1, u32 arg2) } /* Handle adjtimex compatibility. */ -struct timex32 { - u32 modes; - s32 offset, freq, maxerror, esterror; - s32 status, constant, precision, tolerance; - struct compat_timeval time; - s32 tick; - s32 ppsfreq, jitter, shift, stabil; - s32 jitcnt, calcnt, errcnt, stbcnt; - s32 :32; s32 :32; s32 :32; s32 :32; - s32 :32; s32 :32; s32 :32; s32 :32; - s32 :32; s32 :32; s32 :32; s32 :32; -}; - extern int do_adjtimex(struct timex *); -asmlinkage long compat_sys_adjtimex(struct timex32 __user *utp) +asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp) { struct timex txc; int ret; -- cgit v1.2.2 From 3158e9411a66fb98d495ac441c242264f31aaf3e Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Sun, 26 Mar 2006 01:37:29 -0800 Subject: [PATCH] consolidate sys32/compat_adjtimex Create compat_sys_adjtimex and use it an all appropriate places. Signed-off-by: Stephen Rothwell Cc: Arnd Bergmann Acked-by: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/kernel/sys_ppc32.c | 60 ----------------------------------------- 1 file changed, 60 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c index d9867f583c68..ec274e688816 100644 --- a/arch/powerpc/kernel/sys_ppc32.c +++ b/arch/powerpc/kernel/sys_ppc32.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -161,65 +160,6 @@ asmlinkage long compat_sys_sysfs(u32 option, u32 arg1, u32 arg2) return sys_sysfs((int)option, arg1, arg2); } -/* Handle adjtimex compatibility. */ -extern int do_adjtimex(struct timex *); - -asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp) -{ - struct timex txc; - int ret; - - memset(&txc, 0, sizeof(struct timex)); - - if(get_user(txc.modes, &utp->modes) || - __get_user(txc.offset, &utp->offset) || - __get_user(txc.freq, &utp->freq) || - __get_user(txc.maxerror, &utp->maxerror) || - __get_user(txc.esterror, &utp->esterror) || - __get_user(txc.status, &utp->status) || - __get_user(txc.constant, &utp->constant) || - __get_user(txc.precision, &utp->precision) || - __get_user(txc.tolerance, &utp->tolerance) || - __get_user(txc.time.tv_sec, &utp->time.tv_sec) || - __get_user(txc.time.tv_usec, &utp->time.tv_usec) || - __get_user(txc.tick, &utp->tick) || - __get_user(txc.ppsfreq, &utp->ppsfreq) || - __get_user(txc.jitter, &utp->jitter) || - __get_user(txc.shift, &utp->shift) || - __get_user(txc.stabil, &utp->stabil) || - __get_user(txc.jitcnt, &utp->jitcnt) || - __get_user(txc.calcnt, &utp->calcnt) || - __get_user(txc.errcnt, &utp->errcnt) || - __get_user(txc.stbcnt, &utp->stbcnt)) - return -EFAULT; - - ret = do_adjtimex(&txc); - - if(put_user(txc.modes, &utp->modes) || - __put_user(txc.offset, &utp->offset) || - __put_user(txc.freq, &utp->freq) || - __put_user(txc.maxerror, &utp->maxerror) || - __put_user(txc.esterror, &utp->esterror) || - __put_user(txc.status, &utp->status) || - __put_user(txc.constant, &utp->constant) || - __put_user(txc.precision, &utp->precision) || - __put_user(txc.tolerance, &utp->tolerance) || - __put_user(txc.time.tv_sec, &utp->time.tv_sec) || - __put_user(txc.time.tv_usec, &utp->time.tv_usec) || - __put_user(txc.tick, &utp->tick) || - __put_user(txc.ppsfreq, &utp->ppsfreq) || - __put_user(txc.jitter, &utp->jitter) || - __put_user(txc.shift, &utp->shift) || - __put_user(txc.stabil, &utp->stabil) || - __put_user(txc.jitcnt, &utp->jitcnt) || - __put_user(txc.calcnt, &utp->calcnt) || - __put_user(txc.errcnt, &utp->errcnt) || - __put_user(txc.stbcnt, &utp->stbcnt)) - ret = -EFAULT; - - return ret; -} - asmlinkage long compat_sys_pause(void) { current->state = TASK_INTERRUPTIBLE; -- cgit v1.2.2 From c6fd91f0bdcd294a0ae0ba2b2a7f7456ef4b7144 Mon Sep 17 00:00:00 2001 From: bibo mao Date: Sun, 26 Mar 2006 01:38:20 -0800 Subject: [PATCH] kretprobe instance recycled by parent process When kretprobe probes the schedule() function, if the probed process exits then schedule() will never return, so some kretprobe instances will never be recycled. In this patch the parent process will recycle retprobe instances of the probed function and there will be no memory leak of kretprobe instances. Signed-off-by: bibo mao Cc: Masami Hiramatsu Cc: Prasanna S Panchamukhi Cc: Ananth N Mavinakayanahalli Cc: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/kernel/process.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 1770a066c217..f698aa77127e 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include @@ -460,7 +459,6 @@ void show_regs(struct pt_regs * regs) void exit_thread(void) { - kprobe_flush_task(current); discard_lazy_cpu_state(); } -- cgit v1.2.2 From 2326c77017c79fd6d55c69d8a49a57a252921bcd Mon Sep 17 00:00:00 2001 From: "bibo,mao" Date: Sun, 26 Mar 2006 01:38:21 -0800 Subject: [PATCH] kprobe handler: discard user space trap Currently kprobe handler traps only happen in kernel space, so function kprobe_exceptions_notify should skip traps which happen in user space. This patch modifies this, and it is based on 2.6.16-rc4. Signed-off-by: bibo mao Cc: Ananth N Mavinakayanahalli Cc: "Keshavamurthy, Anil S" Cc: Signed-off-by: Prasanna S Panchamukhi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/kernel/kprobes.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index cb1fe5878e8b..aea25dd18dae 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c @@ -396,6 +396,9 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE; + if (args->regs && user_mode(args->regs)) + return ret; + switch (val) { case DIE_BPT: if (kprobe_handler(args->regs)) -- cgit v1.2.2 From 50e21f2b2861711b6df0b72ffef4a70d1532b023 Mon Sep 17 00:00:00 2001 From: Prasanna S Panchamukhi Date: Sun, 26 Mar 2006 01:38:24 -0800 Subject: [PATCH] kprobes: fix broken fault handling for powerpc64 Provide proper kprobes fault handling, if a user-specified pre/post handlers tries to access user address space, through copy_from_user(), get_user() etc. The user-specified fault handler gets called only if the fault occurs while executing user-specified handlers. In such a case user-specified handler is allowed to fix it first, later if the user-specifed fault handler does not fix it, we try to fix it by calling fix_exception(). The user-specified handler will not be called if the fault happens when single stepping the original instruction, instead we reset the current probe and allow the system page fault handler to fix it up. Signed-off-by: Prasanna S Panchamukhi Cc: Paul Mackerras Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/kernel/kprobes.c | 63 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 8 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index aea25dd18dae..ad7a90212204 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c @@ -30,9 +30,11 @@ #include #include #include +#include #include #include #include +#include DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); @@ -372,17 +374,62 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) { struct kprobe *cur = kprobe_running(); struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - - if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) - return 1; - - if (kcb->kprobe_status & KPROBE_HIT_SS) { - resume_execution(cur, regs); + const struct exception_table_entry *entry; + + switch(kcb->kprobe_status) { + case KPROBE_HIT_SS: + case KPROBE_REENTER: + /* + * We are here because the instruction being single + * stepped caused a page fault. We reset the current + * kprobe and the nip points back to the probe address + * and allow the page fault handler to continue as a + * normal page fault. + */ + regs->nip = (unsigned long)cur->addr; regs->msr &= ~MSR_SE; regs->msr |= kcb->kprobe_saved_msr; - - reset_current_kprobe(); + if (kcb->kprobe_status == KPROBE_REENTER) + restore_previous_kprobe(kcb); + else + reset_current_kprobe(); preempt_enable_no_resched(); + break; + case KPROBE_HIT_ACTIVE: + case KPROBE_HIT_SSDONE: + /* + * We increment the nmissed count for accounting, + * we can also use npre/npostfault count for accouting + * these specific fault cases. + */ + kprobes_inc_nmissed_count(cur); + + /* + * We come here because instructions in the pre/post + * handler caused the page_fault, this could happen + * if handler tries to access user space by + * copy_from_user(), get_user() etc. Let the + * user-specified handler try to fix it first. + */ + if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) + return 1; + + /* + * In case the user-specified fault handler returned + * zero, try to fix up. + */ + if ((entry = search_exception_tables(regs->nip)) != NULL) { + regs->nip = entry->fixup; + return 1; + } + + /* + * fixup_exception() could not handle it, + * Let do_page_fault() fix it. + */ + break; + default: + break; } return 0; } -- cgit v1.2.2 From e779b2f95f3786cd9cfc804cd6f04f7267d75541 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sun, 26 Mar 2006 01:39:33 -0800 Subject: [PATCH] bitops: powerpc: use generic bitops - remove __{,test_and_}{set,clear,change}_bit() and test_bit() - remove generic_fls64() - remove generic_hweight{64,32,16,8}() - remove sched_find_first_bit() Signed-off-by: Akinobu Mita Cc: Paul Mackerras Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch/powerpc') diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index fae42da7468d..a433b7126d33 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -37,6 +37,10 @@ config RWSEM_XCHGADD_ALGORITHM bool default y +config GENERIC_HWEIGHT + bool + default y + config GENERIC_CALIBRATE_DELAY bool default y -- cgit v1.2.2 From af308377e204e25f1f58627d05fe0f483703b514 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 23 Mar 2006 17:38:10 +1100 Subject: [PATCH] powerpc: fix various sparse warnings Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/legacy_serial.c | 4 ++-- arch/powerpc/kernel/nvram_64.c | 3 ++- arch/powerpc/kernel/process.c | 6 +++++- arch/powerpc/kernel/setup_32.c | 2 +- arch/powerpc/lib/sstep.c | 2 +- arch/powerpc/platforms/powermac/bootx_init.c | 2 +- arch/powerpc/platforms/powermac/nvram.c | 12 ++++++------ arch/powerpc/platforms/powermac/udbg_scc.c | 2 +- 8 files changed, 19 insertions(+), 14 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c index c7a799a09516..09d9c825fa9c 100644 --- a/arch/powerpc/kernel/legacy_serial.c +++ b/arch/powerpc/kernel/legacy_serial.c @@ -37,7 +37,7 @@ static int legacy_serial_console = -1; static int __init add_legacy_port(struct device_node *np, int want_index, int iotype, phys_addr_t base, phys_addr_t taddr, unsigned long irq, - unsigned int flags) + upf_t flags) { u32 *clk, *spd, clock = BASE_BAUD * 16; int index; @@ -113,7 +113,7 @@ static int __init add_legacy_soc_port(struct device_node *np, { phys_addr_t addr; u32 *addrp; - unsigned int flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ; + upf_t flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ; /* We only support ports that have a clock frequency properly * encoded in the device-tree. diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c index fd7db8d542db..6c3989f6247d 100644 --- a/arch/powerpc/kernel/nvram_64.c +++ b/arch/powerpc/kernel/nvram_64.c @@ -174,8 +174,9 @@ static int dev_nvram_ioctl(struct inode *inode, struct file *file, return 0; } #endif /* CONFIG_PPC_PMAC */ + default: + return -EINVAL; } - return -EINVAL; } struct file_operations nvram_fops = { diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index f698aa77127e..995b14688d3a 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -362,7 +362,11 @@ static void show_instructions(struct pt_regs *regs) if (!(i % 8)) printk("\n"); - if (BAD_PC(pc) || __get_user(instr, (unsigned int *)pc)) { + /* We use __get_user here *only* to avoid an OOPS on a + * bad address because the pc *should* only be a + * kernel address. + */ + if (BAD_PC(pc) || __get_user(instr, (unsigned int __user *)pc)) { printk("XXXXXXXX "); } else { if (regs->nip == pc) diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index dc2770df25b3..676f894c3380 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -111,7 +111,7 @@ unsigned long __init early_init(unsigned long dt_ptr) /* First zero the BSS -- use memset_io, some platforms don't have * caches on yet */ - memset_io(PTRRELOC(&__bss_start), 0, _end - __bss_start); + memset_io((void __iomem *)PTRRELOC(&__bss_start), 0, _end - __bss_start); /* * Identify the CPU type and fix up code sections diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index 666c2aa55016..c251d9936612 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c @@ -18,7 +18,7 @@ extern char system_call_common[]; #ifdef CONFIG_PPC64 /* Bits in SRR1 that are copied from MSR */ -#define MSR_MASK 0xffffffff87c0ffff +#define MSR_MASK 0xffffffff87c0ffffUL #else #define MSR_MASK 0x87c0ffff #endif diff --git a/arch/powerpc/platforms/powermac/bootx_init.c b/arch/powerpc/platforms/powermac/bootx_init.c index fa8b4d7b5ded..a94571be65ca 100644 --- a/arch/powerpc/platforms/powermac/bootx_init.c +++ b/arch/powerpc/platforms/powermac/bootx_init.c @@ -493,7 +493,7 @@ void __init bootx_init(unsigned long r3, unsigned long r4) && (strcmp(model, "iMac,1") == 0 || strcmp(model, "PowerMac1,1") == 0)) { bootx_printf("iMac,1 detected, shutting down USB \n"); - out_le32((unsigned *)0x80880008, 1); /* XXX */ + out_le32((unsigned __iomem *)0x80880008, 1); /* XXX */ } } diff --git a/arch/powerpc/platforms/powermac/nvram.c b/arch/powerpc/platforms/powermac/nvram.c index 5fd28995c74c..3aa3477b86f7 100644 --- a/arch/powerpc/platforms/powermac/nvram.c +++ b/arch/powerpc/platforms/powermac/nvram.c @@ -74,7 +74,7 @@ struct core99_header { * Read and write the non-volatile RAM on PowerMacs and CHRP machines. */ static int nvram_naddrs; -static volatile unsigned char *nvram_data; +static volatile unsigned char __iomem *nvram_data; static int is_core_99; static int core99_bank = 0; static int nvram_partitions[3]; @@ -148,7 +148,7 @@ static ssize_t core99_nvram_size(void) } #ifdef CONFIG_PPC32 -static volatile unsigned char *nvram_addr; +static volatile unsigned char __iomem *nvram_addr; static int nvram_mult; static unsigned char direct_nvram_read_byte(int addr) @@ -285,7 +285,7 @@ static int sm_erase_bank(int bank) int stat, i; unsigned long timeout; - u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE; + u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE; DBG("nvram: Sharp/Micron Erasing bank %d...\n", bank); @@ -317,7 +317,7 @@ static int sm_write_bank(int bank, u8* datas) int i, stat = 0; unsigned long timeout; - u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE; + u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE; DBG("nvram: Sharp/Micron Writing bank %d...\n", bank); @@ -352,7 +352,7 @@ static int amd_erase_bank(int bank) int i, stat = 0; unsigned long timeout; - u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE; + u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE; DBG("nvram: AMD Erasing bank %d...\n", bank); @@ -399,7 +399,7 @@ static int amd_write_bank(int bank, u8* datas) int i, stat = 0; unsigned long timeout; - u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE; + u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE; DBG("nvram: AMD Writing bank %d...\n", bank); diff --git a/arch/powerpc/platforms/powermac/udbg_scc.c b/arch/powerpc/platforms/powermac/udbg_scc.c index c4352a8db644..b4fa9f03b461 100644 --- a/arch/powerpc/platforms/powermac/udbg_scc.c +++ b/arch/powerpc/platforms/powermac/udbg_scc.c @@ -116,7 +116,7 @@ void udbg_scc_init(int force_scc) /* Setup for 57600 8N1 */ if (ch == ch_a) addr += 0x20; - sccc = (volatile u8 * __iomem) ioremap(addr & PAGE_MASK, PAGE_SIZE) ; + sccc = ioremap(addr & PAGE_MASK, PAGE_SIZE) ; sccc += addr & ~PAGE_MASK; sccd = sccc + 0x10; -- cgit v1.2.2 From 5fa500bfc60f36c54bb20338795cc2facc0425f6 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 23 Mar 2006 00:00:04 +0100 Subject: [PATCH] powerpc: fix cell iommu setup A small bug crept in the iommu driver when we made it more generic. This patch is needed for boards that have a dma window that does not start at bus address zero. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/iommu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index 46e7cb9c3e64..c8a98be8b6a1 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c @@ -289,7 +289,7 @@ static void cell_do_map_iommu(struct cell_iommu *iommu, ioc_base = iommu->mapped_base; ioc_mmio_base = iommu->mapped_mmio_base; - for (real_address = 0, io_address = 0; + for (real_address = 0, io_address = map_start; io_address <= map_start + map_size; real_address += io_page_size, io_address += io_page_size) { ioste = get_iost_entry(fake_iopt, io_address, io_page_size); @@ -302,7 +302,7 @@ static void cell_do_map_iommu(struct cell_iommu *iommu, set_iopt_cache(ioc_mmio_base, get_ioc_hash_1way(ioste, io_address), get_ioc_tag(ioste, io_address), - get_iopt_entry(real_address-map_start, ioid, IOPT_PROT_RW)); + get_iopt_entry(real_address, ioid, IOPT_PROT_RW)); } } -- cgit v1.2.2 From 1a19f85584414ae0a9f94406ffd628096127583e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 23 Mar 2006 00:00:05 +0100 Subject: [PATCH] powerpc: update cell defconfig The default configuration in mainline got a little out of sync with what we use internally. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/configs/cell_defconfig | 133 ++++++++++++++---------------------- 1 file changed, 52 insertions(+), 81 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig index 3c2acab63736..fe22e54ab2b0 100644 --- a/arch/powerpc/configs/cell_defconfig +++ b/arch/powerpc/configs/cell_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16-rc6 -# Wed Mar 15 16:19:48 2006 +# Linux kernel version: 2.6.16 +# Thu Mar 23 20:48:09 2006 # CONFIG_PPC64=y CONFIG_64BIT=y @@ -30,6 +30,7 @@ CONFIG_POWER4=y CONFIG_PPC_FPU=y CONFIG_ALTIVEC=y CONFIG_PPC_STD_MMU=y +CONFIG_VIRT_CPU_ACCOUNTING=y CONFIG_SMP=y CONFIG_NR_CPUS=4 @@ -51,7 +52,8 @@ CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set -# CONFIG_IKCONFIG is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y # CONFIG_CPUSETS is not set CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y @@ -85,7 +87,7 @@ CONFIG_MODULE_UNLOAD=y CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set -# CONFIG_KMOD is not set +CONFIG_KMOD=y CONFIG_STOP_MACHINE=y # @@ -130,7 +132,8 @@ CONFIG_CELL_IIC=y # # Cell Broadband Engine options # -CONFIG_SPU_FS=y +CONFIG_SPU_FS=m +CONFIG_SPUFS_MMAP=y # # Kernel options @@ -144,7 +147,7 @@ CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT is not set CONFIG_PREEMPT_BKL=y CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set +CONFIG_BINFMT_MISC=m CONFIG_FORCE_MAX_ZONEORDER=13 # CONFIG_IOMMU_VMERGE is not set CONFIG_KEXEC=y @@ -155,13 +158,16 @@ CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_FLATMEM_MANUAL=y +# CONFIG_FLATMEM_MANUAL is not set # CONFIG_DISCONTIGMEM_MANUAL is not set -# CONFIG_SPARSEMEM_MANUAL is not set -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM=y +CONFIG_HAVE_MEMORY_PRESENT=y # CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPARSEMEM_EXTREME=y +# CONFIG_MEMORY_HOTPLUG is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_MIGRATION=y # CONFIG_PPC_64K_PAGES is not set CONFIG_SCHED_SMT=y CONFIG_PROC_DEVICETREE=y @@ -232,6 +238,7 @@ CONFIG_TCP_CONG_BIC=y # CONFIG_IP_VS is not set CONFIG_IPV6=y # CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set CONFIG_INET6_AH=m CONFIG_INET6_ESP=m CONFIG_INET6_IPCOMP=m @@ -244,25 +251,7 @@ CONFIG_NETFILTER=y # Core Netfilter Configuration # # CONFIG_NETFILTER_NETLINK is not set -CONFIG_NETFILTER_XTABLES=m -CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m -CONFIG_NETFILTER_XT_TARGET_MARK=m -CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -CONFIG_NETFILTER_XT_TARGET_NOTRACK=m -CONFIG_NETFILTER_XT_MATCH_COMMENT=m -CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m -# CONFIG_NETFILTER_XT_MATCH_DCCP is not set -CONFIG_NETFILTER_XT_MATCH_HELPER=m -CONFIG_NETFILTER_XT_MATCH_LENGTH=m -CONFIG_NETFILTER_XT_MATCH_LIMIT=m -CONFIG_NETFILTER_XT_MATCH_MAC=m -CONFIG_NETFILTER_XT_MATCH_MARK=m -CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m -CONFIG_NETFILTER_XT_MATCH_REALM=m -CONFIG_NETFILTER_XT_MATCH_SCTP=m -CONFIG_NETFILTER_XT_MATCH_STATE=m -CONFIG_NETFILTER_XT_MATCH_STRING=m -CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +# CONFIG_NETFILTER_XTABLES is not set # # IP: Netfilter Configuration @@ -278,51 +267,13 @@ CONFIG_IP_NF_IRC=m CONFIG_IP_NF_TFTP=m CONFIG_IP_NF_AMANDA=m # CONFIG_IP_NF_PPTP is not set +# CONFIG_IP_NF_H323 is not set CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_IPRANGE=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -CONFIG_IP_NF_MATCH_RECENT=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_DSCP=m -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_OWNER=m -CONFIG_IP_NF_MATCH_ADDRTYPE=m -CONFIG_IP_NF_MATCH_HASHLIMIT=m -CONFIG_IP_NF_MATCH_POLICY=m -CONFIG_IP_NF_FILTER=m -CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_TARGET_NETMAP=m -CONFIG_IP_NF_TARGET_SAME=m -CONFIG_IP_NF_NAT_SNMP_BASIC=m -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_NAT_TFTP=m -CONFIG_IP_NF_NAT_AMANDA=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_DSCP=m -CONFIG_IP_NF_TARGET_TTL=m -CONFIG_IP_NF_RAW=m -CONFIG_IP_NF_ARPTABLES=m -CONFIG_IP_NF_ARPFILTER=m -CONFIG_IP_NF_ARP_MANGLE=m # # IPv6: Netfilter Configuration (EXPERIMENTAL) # # CONFIG_IP6_NF_QUEUE is not set -# CONFIG_IP6_NF_IPTABLES is not set # # DCCP Configuration (EXPERIMENTAL) @@ -355,7 +306,6 @@ CONFIG_IP_NF_ARP_MANGLE=m # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set -CONFIG_NET_CLS_ROUTE=y # # Network testing @@ -408,7 +358,7 @@ CONFIG_FW_LOADER=y # CONFIG_BLK_DEV_COW_COMMON is not set CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_CRYPTOLOOP is not set -CONFIG_BLK_DEV_NBD=y +# CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 @@ -484,7 +434,23 @@ CONFIG_IDEDMA_AUTO=y # # Multi-device support (RAID and LVM) # -# CONFIG_MD is not set +CONFIG_MD=y +CONFIG_BLK_DEV_MD=m +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +# CONFIG_MD_RAID10 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_MD_RAID6 is not set +# CONFIG_MD_MULTIPATH is not set +# CONFIG_MD_FAULTY is not set +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +# CONFIG_DM_MULTIPATH_EMC is not set # # Fusion MPT device support @@ -548,7 +514,7 @@ CONFIG_MII=y # CONFIG_ACENIC is not set # CONFIG_DL2K is not set CONFIG_E1000=m -# CONFIG_E1000_NAPI is not set +CONFIG_E1000_NAPI=y # CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set @@ -560,7 +526,7 @@ CONFIG_SKGE=m # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set # CONFIG_BNX2 is not set -CONFIG_SPIDER_NET=y +CONFIG_SPIDER_NET=m # CONFIG_MV643XX_ETH is not set # @@ -678,6 +644,8 @@ CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y # CONFIG_LEGACY_PTYS is not set +CONFIG_HVC_DRIVER=y +CONFIG_HVC_RTAS=y # # IPMI @@ -694,14 +662,13 @@ CONFIG_WATCHDOG=y # Watchdog Device Drivers # # CONFIG_SOFT_WATCHDOG is not set -# CONFIG_WATCHDOG_RTAS is not set +CONFIG_WATCHDOG_RTAS=y # # PCI-based Watchdog Cards # # CONFIG_PCIPCWATCHDOG is not set # CONFIG_WDTPCI is not set -# CONFIG_RTC is not set CONFIG_GEN_RTC=y # CONFIG_GEN_RTC_X is not set # CONFIG_DTLK is not set @@ -833,6 +800,7 @@ CONFIG_DUMMY_CONSOLE=y # CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y # CONFIG_USB is not set # @@ -852,7 +820,14 @@ CONFIG_USB_ARCH_HAS_OHCI=y # # InfiniBand support # -# CONFIG_INFINIBAND is not set +CONFIG_INFINIBAND=y +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_MTHCA=m +CONFIG_INFINIBAND_MTHCA_DEBUG=y +CONFIG_INFINIBAND_IPOIB=m +CONFIG_INFINIBAND_IPOIB_DEBUG=y +CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y # # EDAC - error detection and reporting (RAS) (EXPERIMENTAL) @@ -1037,10 +1012,6 @@ CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=m CONFIG_ZLIB_DEFLATE=m -CONFIG_TEXTSEARCH=y -CONFIG_TEXTSEARCH_KMP=m -CONFIG_TEXTSEARCH_BM=m -CONFIG_TEXTSEARCH_FSM=m # # Instrumentation Support @@ -1058,7 +1029,7 @@ CONFIG_LOG_BUF_SHIFT=15 CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_MUTEXES is not set +CONFIG_DEBUG_MUTEXES=y # CONFIG_DEBUG_SPINLOCK is not set CONFIG_DEBUG_SPINLOCK_SLEEP=y # CONFIG_DEBUG_KOBJECT is not set -- cgit v1.2.2 From d0e57c68373f8ded8c50245fd082e606f9f63221 Mon Sep 17 00:00:00 2001 From: Jens Osterkamp Date: Thu, 23 Mar 2006 00:00:06 +0100 Subject: [PATCH] powerpc: cell interrupt controller updates The current interrupt controller setup on Cell is done in a rather ad-hoc way with device tree properties that are not standardized at all. In an attempt to do something that follows the OF standard (or at least the IBM extensions to it) more closely, we have now come up with this patch. It still provides a fallback to the old behaviour when we find older firmware, that hack can not be removed until the existing customer installations have upgraded. Cc: hpenner@de.ibm.com Cc: stk@de.ibm.com Cc: Segher Boessenkool Cc: Milton Miller Cc: benh@kernel.crashing.org Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/interrupt.c | 116 ++++++++++++++++++++++++------- arch/powerpc/platforms/cell/interrupt.h | 2 +- arch/powerpc/platforms/cell/spider-pic.c | 106 ++++++++++++++++++++-------- 3 files changed, 169 insertions(+), 55 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 63aa52acf441..9d41e07b0c95 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -123,7 +123,7 @@ static int iic_external_get_irq(struct iic_pending_bits pending) pending.class != 2) break; irq = IIC_EXT_OFFSET - + spider_get_irq(pending.prio + node * IIC_NODE_STRIDE) + + spider_get_irq(node) + node * IIC_NODE_STRIDE; break; case 0x01 ... 0x04: @@ -174,38 +174,102 @@ int iic_get_irq(struct pt_regs *regs) return irq; } -static int setup_iic(int cpu, struct iic *iic) +/* hardcoded part to be compatible with older firmware */ + +static int setup_iic_hardcoded(void) { struct device_node *np; - int nodeid = cpu / 2; + int nodeid, cpu; unsigned long regs; + struct iic *iic; - for (np = of_find_node_by_type(NULL, "cpu"); - np; - np = of_find_node_by_type(np, "cpu")) { - if (nodeid == *(int *)get_property(np, "node-id", NULL)) - break; + for_each_cpu(cpu) { + iic = &per_cpu(iic, cpu); + nodeid = cpu/2; + + for (np = of_find_node_by_type(NULL, "cpu"); + np; + np = of_find_node_by_type(np, "cpu")) { + if (nodeid == *(int *)get_property(np, "node-id", NULL)) + break; + } + + if (!np) { + printk(KERN_WARNING "IIC: CPU %d not found\n", cpu); + iic->regs = NULL; + iic->target_id = 0xff; + return -ENODEV; + } + + regs = *(long *)get_property(np, "iic", NULL); + + /* hack until we have decided on the devtree info */ + regs += 0x400; + if (cpu & 1) + regs += 0x20; + + printk(KERN_INFO "IIC for CPU %d at %lx\n", cpu, regs); + iic->regs = __ioremap(regs, sizeof(struct iic_regs), + _PAGE_NO_CACHE); + + iic->target_id = (nodeid << 4) + ((cpu & 1) ? 0xf : 0xe); } - if (!np) { - printk(KERN_WARNING "IIC: CPU %d not found\n", cpu); - iic->regs = NULL; - iic->target_id = 0xff; - return -ENODEV; - } + return 0; +} - regs = *(long *)get_property(np, "iic", NULL); +static int setup_iic(void) +{ + struct device_node *dn; + unsigned long *regs; + char *compatible; + unsigned *np, found = 0; + struct iic *iic = NULL; + + for (dn = NULL; (dn = of_find_node_by_name(dn, "interrupt-controller"));) { + compatible = (char *)get_property(dn, "compatible", NULL); + + if (!compatible) { + printk(KERN_WARNING "no compatible property found !\n"); + continue; + } - /* hack until we have decided on the devtree info */ - regs += 0x400; - if (cpu & 1) - regs += 0x20; + if (strstr(compatible, "IBM,CBEA-Internal-Interrupt-Controller")) + regs = (unsigned long *)get_property(dn,"reg", NULL); + else + continue; - printk(KERN_DEBUG "IIC for CPU %d at %lx\n", cpu, regs); - iic->regs = __ioremap(regs, sizeof(struct iic_regs), - _PAGE_NO_CACHE); - iic->target_id = (nodeid << 4) + ((cpu & 1) ? 0xf : 0xe); - return 0; + if (!regs) + printk(KERN_WARNING "IIC: no reg property\n"); + + np = (unsigned int *)get_property(dn, "ibm,interrupt-server-ranges", NULL); + + if (!np) { + printk(KERN_WARNING "IIC: CPU association not found\n"); + iic->regs = NULL; + iic->target_id = 0xff; + return -ENODEV; + } + + iic = &per_cpu(iic, np[0]); + iic->regs = __ioremap(regs[0], sizeof(struct iic_regs), + _PAGE_NO_CACHE); + iic->target_id = ((np[0] & 2) << 3) + ((np[0] & 1) ? 0xf : 0xe); + printk("IIC for CPU %d at %lx mapped to %p\n", np[0], regs[0], iic->regs); + + iic = &per_cpu(iic, np[1]); + iic->regs = __ioremap(regs[2], sizeof(struct iic_regs), + _PAGE_NO_CACHE); + iic->target_id = ((np[1] & 2) << 3) + ((np[1] & 1) ? 0xf : 0xe); + printk("IIC for CPU %d at %lx mapped to %p\n", np[1], regs[2], iic->regs); + + found++; + } + + if (found) + return 0; + else + return -ENODEV; } #ifdef CONFIG_SMP @@ -283,10 +347,12 @@ void iic_init_IRQ(void) int cpu, irq_offset; struct iic *iic; + if (setup_iic() < 0) + setup_iic_hardcoded(); + irq_offset = 0; for_each_cpu(cpu) { iic = &per_cpu(iic, cpu); - setup_iic(cpu, iic); if (iic->regs) out_be64(&iic->regs->prio, 0xff); } diff --git a/arch/powerpc/platforms/cell/interrupt.h b/arch/powerpc/platforms/cell/interrupt.h index a14bd38791c0..799f77d98f96 100644 --- a/arch/powerpc/platforms/cell/interrupt.h +++ b/arch/powerpc/platforms/cell/interrupt.h @@ -57,7 +57,7 @@ extern void iic_local_disable(void); extern u8 iic_get_target_id(int cpu); extern void spider_init_IRQ(void); -extern int spider_get_irq(unsigned long int_pending); +extern int spider_get_irq(int node); #endif #endif /* ASM_CELL_PIC_H */ diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c index e74132188bdf..0e9bb0b72c50 100644 --- a/arch/powerpc/platforms/cell/spider-pic.c +++ b/arch/powerpc/platforms/cell/spider-pic.c @@ -84,10 +84,11 @@ static void __iomem *spider_get_irq_config(int irq) static void spider_enable_irq(unsigned int irq) { + int nodeid = (irq / IIC_NODE_STRIDE) * 0x10; void __iomem *cfg = spider_get_irq_config(irq); irq = spider_get_nr(irq); - out_be32(cfg, in_be32(cfg) | 0x3107000eu); + out_be32(cfg, in_be32(cfg) | 0x3107000eu | nodeid); out_be32(cfg + 4, in_be32(cfg + 4) | 0x00020000u | irq); } @@ -131,61 +132,108 @@ static struct hw_interrupt_type spider_pic = { .end = spider_end_irq, }; - -int spider_get_irq(unsigned long int_pending) +int spider_get_irq(int node) { - void __iomem *regs = spider_get_pic(int_pending); unsigned long cs; - int irq; - - cs = in_be32(regs + TIR_CS); + void __iomem *regs = spider_pics[node]; - irq = cs >> 24; - if (irq != 63) - return irq; + cs = in_be32(regs + TIR_CS) >> 24; - return -1; + if (cs == 63) + return -1; + else + return cs; } - -void spider_init_IRQ(void) + +/* hardcoded part to be compatible with older firmware */ + +void spider_init_IRQ_hardcoded(void) { int node; - struct device_node *dn; - unsigned int *property; long spiderpic; + long pics[] = { 0x24000008000, 0x34000008000 }; int n; -/* FIXME: detect multiple PICs as soon as the device tree has them */ - for (node = 0; node < 1; node++) { - dn = of_find_node_by_path("/"); - n = prom_n_addr_cells(dn); - property = (unsigned int *) get_property(dn, - "platform-spider-pic", NULL); + pr_debug("%s(%d): Using hardcoded defaults\n", __FUNCTION__, __LINE__); - if (!property) - continue; - for (spiderpic = 0; n > 0; --n) - spiderpic = (spiderpic << 32) + *property++; + for (node = 0; node < num_present_cpus()/2; node++) { + spiderpic = pics[node]; printk(KERN_DEBUG "SPIDER addr: %lx\n", spiderpic); spider_pics[node] = __ioremap(spiderpic, 0x800, _PAGE_NO_CACHE); for (n = 0; n < IIC_NUM_EXT; n++) { int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE; get_irq_desc(irq)->handler = &spider_pic; + } /* do not mask any interrupts because of level */ out_be32(spider_pics[node] + TIR_MSK, 0x0); - + /* disable edge detection clear */ /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */ - + /* enable interrupt packets to be output */ out_be32(spider_pics[node] + TIR_PIEN, in_be32(spider_pics[node] + TIR_PIEN) | 0x1); - + /* Enable the interrupt detection enable bit. Do this last! */ out_be32(spider_pics[node] + TIR_DEN, - in_be32(spider_pics[node] +TIR_DEN) | 0x1); + in_be32(spider_pics[node] + TIR_DEN) | 0x1); + } +} + +void spider_init_IRQ(void) +{ + long spider_reg; + struct device_node *dn; + char *compatible; + int n, node = 0; + + for (dn = NULL; (dn = of_find_node_by_name(dn, "interrupt-controller"));) { + compatible = (char *)get_property(dn, "compatible", NULL); + if (!compatible) + continue; + + if (strstr(compatible, "CBEA,platform-spider-pic")) + spider_reg = *(long *)get_property(dn,"reg", NULL); + else if (strstr(compatible, "sti,platform-spider-pic")) { + spider_init_IRQ_hardcoded(); + return; + } else + continue; + + if (!spider_reg) + printk("interrupt controller does not have reg property !\n"); + + n = prom_n_addr_cells(dn); + + if ( n != 2) + printk("reg property with invalid number of elements \n"); + + spider_pics[node] = __ioremap(spider_reg, 0x800, _PAGE_NO_CACHE); + + printk("SPIDER addr: %lx with %i addr_cells mapped to %p\n", + spider_reg, n, spider_pics[node]); + + for (n = 0; n < IIC_NUM_EXT; n++) { + int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE; + get_irq_desc(irq)->handler = &spider_pic; } + + /* do not mask any interrupts because of level */ + out_be32(spider_pics[node] + TIR_MSK, 0x0); + + /* disable edge detection clear */ + /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */ + + /* enable interrupt packets to be output */ + out_be32(spider_pics[node] + TIR_PIEN, + in_be32(spider_pics[node] + TIR_PIEN) | 0x1); + + /* Enable the interrupt detection enable bit. Do this last! */ + out_be32(spider_pics[node] + TIR_DEN, + in_be32(spider_pics[node] + TIR_DEN) | 0x1); + + node++; } } -- cgit v1.2.2 From 5536408c21cdde38bfdbb59a6fd4fcbf1232699f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 23 Mar 2006 00:00:07 +0100 Subject: [PATCH] powerpc: work around a cell interrupt HW bug Apparently we have found a bug in the CPU that causes external interrupts to sometimes get disabled indefinitely. This adds a workaround for the problem. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/interrupt.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 9d41e07b0c95..e3fffdfcc674 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -63,7 +63,24 @@ static DEFINE_PER_CPU(struct iic, iic); void iic_local_enable(void) { - out_be64(&__get_cpu_var(iic).regs->prio, 0xff); + struct iic *iic = &__get_cpu_var(iic); + u64 tmp; + + /* + * There seems to be a bug that is present in DD2.x CPUs + * and still only partially fixed in DD3.1. + * This bug causes a value written to the priority register + * not to make it there, resulting in a system hang unless we + * write it again. + * Masking with 0xf0 is done because the Cell BE does not + * implement the lower four bits of the interrupt priority, + * they always read back as zeroes, although future CPUs + * might implement different bits. + */ + do { + out_be64(&iic->regs->prio, 0xff); + tmp = in_be64(&iic->regs->prio); + } while ((tmp & 0xf0) != 0xf0); } void iic_local_disable(void) -- cgit v1.2.2 From a7f31841a40776605c834053ad1eb82d539bd79f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 23 Mar 2006 00:00:08 +0100 Subject: [PATCH] powerpc: declare arch syscalls in powerpc currently declares some of its own system calls in , but not all of them. That place also contains remainders of the now almost unused kernel syscall hack. - Add a new with clean declarations - Include that file from every source that implements one of these - Get rid of old declarations in This patch is required as a base for implementing system calls from an SPU, but also makes sense as a general cleanup. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/process.c | 1 + arch/powerpc/kernel/rtas.c | 1 + arch/powerpc/kernel/signal_32.c | 1 + arch/powerpc/kernel/signal_64.c | 1 + arch/powerpc/kernel/syscalls.c | 1 + 5 files changed, 5 insertions(+) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 995b14688d3a..c6e81bbd615c 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -45,6 +45,7 @@ #include #include #include +#include #ifdef CONFIG_PPC64 #include #endif diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index b5b2add7ad1e..142d818a31a6 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -32,6 +32,7 @@ #include #include #include +#include struct rtas_t rtas = { .lock = SPIN_LOCK_UNLOCKED diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index d7a4e814974d..01e3c08cb550 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -42,6 +42,7 @@ #include #include +#include #include #include #ifdef CONFIG_PPC64 diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 47f910380a6a..82ec2f3f6713 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #define DEBUG_SIG 0 diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c index ad895c99813b..9b69d99a9103 100644 --- a/arch/powerpc/kernel/syscalls.c +++ b/arch/powerpc/kernel/syscalls.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include -- cgit v1.2.2 From 2dd14934c9138c562d93c501e88c6d6f061eb8ba Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 23 Mar 2006 00:00:09 +0100 Subject: [PATCH] spufs: allow SPU code to do syscalls An SPU does not have a way to implement system calls itself, but it can create intercepts to the kernel. This patch uses the method defined by the JSRE interface for C99 host library calls from an SPU to implement Linux system calls. It uses the reserved SPU stop code 0x2104 for this, using the structure layout and syscall numbers for ppc64-linux. I'm still undecided wether it is better to have a list of allowed syscalls or a list of forbidden syscalls, since we can't allow an SPU to call all syscalls that are defined for ppc64-linux. This patch implements the easier choice of them, with a blacklist that only prevents an SPU from calling anything that interacts with its own execution, e.g fork, execve, clone, vfork, exit, spu_run and spu_create and everything that deals with signals. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/Makefile | 10 +- arch/powerpc/platforms/cell/spu_callbacks.c | 345 ++++++++++++++++++++++++++++ arch/powerpc/platforms/cell/spufs/run.c | 91 ++++++++ 3 files changed, 444 insertions(+), 2 deletions(-) create mode 100644 arch/powerpc/platforms/cell/spu_callbacks.c (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile index 3b998a393e3f..e570bad06394 100644 --- a/arch/powerpc/platforms/cell/Makefile +++ b/arch/powerpc/platforms/cell/Makefile @@ -6,5 +6,11 @@ obj-$(CONFIG_SPU_FS) += spu-base.o spufs/ spu-base-y += spu_base.o spu_priv1.o -builtin-spufs-$(CONFIG_SPU_FS) += spu_syscalls.o -obj-y += $(builtin-spufs-m) +# needed only when building loadable spufs.ko +spufs-modular-$(CONFIG_SPU_FS) += spu_syscalls.o +obj-y += $(spufs-modular-m) + +# always needed in kernel +spufs-builtin-$(CONFIG_SPU_FS) += spu_callbacks.o +obj-y += $(spufs-builtin-y) $(spufs-builtin-m) + diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c new file mode 100644 index 000000000000..3a4245c926ad --- /dev/null +++ b/arch/powerpc/platforms/cell/spu_callbacks.c @@ -0,0 +1,345 @@ +/* + * System call callback functions for SPUs + */ + +#define DEBUG + +#include +#include +#include + +#include +#include +#include + +/* + * This table defines the system calls that an SPU can call. + * It is currently a subset of the 64 bit powerpc system calls, + * with the exact semantics. + * + * The reasons for disabling some of the system calls are: + * 1. They interact with the way SPU syscalls are handled + * and we can't let them execute ever: + * restart_syscall, exit, for, execve, ptrace, ... + * 2. They are deprecated and replaced by other means: + * uselib, pciconfig_*, sysfs, ... + * 3. They are somewhat interacting with the system in a way + * we don't want an SPU to: + * reboot, init_module, mount, kexec_load + * 4. They are optional and we can't rely on them being + * linked into the kernel. Unfortunately, the cond_syscall + * helper does not work here as it does not add the necessary + * opd symbols: + * mbind, mq_open, ipc, ... + */ + +void *spu_syscall_table[] = { + [__NR_restart_syscall] sys_ni_syscall, /* sys_restart_syscall */ + [__NR_exit] sys_ni_syscall, /* sys_exit */ + [__NR_fork] sys_ni_syscall, /* ppc_fork */ + [__NR_read] sys_read, + [__NR_write] sys_write, + [__NR_open] sys_open, + [__NR_close] sys_close, + [__NR_waitpid] sys_waitpid, + [__NR_creat] sys_creat, + [__NR_link] sys_link, + [__NR_unlink] sys_unlink, + [__NR_execve] sys_ni_syscall, /* sys_execve */ + [__NR_chdir] sys_chdir, + [__NR_time] sys_time, + [__NR_mknod] sys_mknod, + [__NR_chmod] sys_chmod, + [__NR_lchown] sys_lchown, + [__NR_break] sys_ni_syscall, + [__NR_oldstat] sys_ni_syscall, + [__NR_lseek] sys_lseek, + [__NR_getpid] sys_getpid, + [__NR_mount] sys_ni_syscall, /* sys_mount */ + [__NR_umount] sys_ni_syscall, + [__NR_setuid] sys_setuid, + [__NR_getuid] sys_getuid, + [__NR_stime] sys_stime, + [__NR_ptrace] sys_ni_syscall, /* sys_ptrace */ + [__NR_alarm] sys_alarm, + [__NR_oldfstat] sys_ni_syscall, + [__NR_pause] sys_ni_syscall, /* sys_pause */ + [__NR_utime] sys_ni_syscall, /* sys_utime */ + [__NR_stty] sys_ni_syscall, + [__NR_gtty] sys_ni_syscall, + [__NR_access] sys_access, + [__NR_nice] sys_nice, + [__NR_ftime] sys_ni_syscall, + [__NR_sync] sys_sync, + [__NR_kill] sys_kill, + [__NR_rename] sys_rename, + [__NR_mkdir] sys_mkdir, + [__NR_rmdir] sys_rmdir, + [__NR_dup] sys_dup, + [__NR_pipe] sys_pipe, + [__NR_times] sys_times, + [__NR_prof] sys_ni_syscall, + [__NR_brk] sys_brk, + [__NR_setgid] sys_setgid, + [__NR_getgid] sys_getgid, + [__NR_signal] sys_ni_syscall, /* sys_signal */ + [__NR_geteuid] sys_geteuid, + [__NR_getegid] sys_getegid, + [__NR_acct] sys_ni_syscall, /* sys_acct */ + [__NR_umount2] sys_ni_syscall, /* sys_umount */ + [__NR_lock] sys_ni_syscall, + [__NR_ioctl] sys_ioctl, + [__NR_fcntl] sys_fcntl, + [__NR_mpx] sys_ni_syscall, + [__NR_setpgid] sys_setpgid, + [__NR_ulimit] sys_ni_syscall, + [__NR_oldolduname] sys_ni_syscall, + [__NR_umask] sys_umask, + [__NR_chroot] sys_chroot, + [__NR_ustat] sys_ni_syscall, /* sys_ustat */ + [__NR_dup2] sys_dup2, + [__NR_getppid] sys_getppid, + [__NR_getpgrp] sys_getpgrp, + [__NR_setsid] sys_setsid, + [__NR_sigaction] sys_ni_syscall, + [__NR_sgetmask] sys_sgetmask, + [__NR_ssetmask] sys_ssetmask, + [__NR_setreuid] sys_setreuid, + [__NR_setregid] sys_setregid, + [__NR_sigsuspend] sys_ni_syscall, + [__NR_sigpending] sys_ni_syscall, + [__NR_sethostname] sys_sethostname, + [__NR_setrlimit] sys_setrlimit, + [__NR_getrlimit] sys_ni_syscall, + [__NR_getrusage] sys_getrusage, + [__NR_gettimeofday] sys_gettimeofday, + [__NR_settimeofday] sys_settimeofday, + [__NR_getgroups] sys_getgroups, + [__NR_setgroups] sys_setgroups, + [__NR_select] sys_ni_syscall, + [__NR_symlink] sys_symlink, + [__NR_oldlstat] sys_ni_syscall, + [__NR_readlink] sys_readlink, + [__NR_uselib] sys_ni_syscall, /* sys_uselib */ + [__NR_swapon] sys_ni_syscall, /* sys_swapon */ + [__NR_reboot] sys_ni_syscall, /* sys_reboot */ + [__NR_readdir] sys_ni_syscall, + [__NR_mmap] sys_mmap, + [__NR_munmap] sys_munmap, + [__NR_truncate] sys_truncate, + [__NR_ftruncate] sys_ftruncate, + [__NR_fchmod] sys_fchmod, + [__NR_fchown] sys_fchown, + [__NR_getpriority] sys_getpriority, + [__NR_setpriority] sys_setpriority, + [__NR_profil] sys_ni_syscall, + [__NR_statfs] sys_ni_syscall, /* sys_statfs */ + [__NR_fstatfs] sys_ni_syscall, /* sys_fstatfs */ + [__NR_ioperm] sys_ni_syscall, + [__NR_socketcall] sys_socketcall, + [__NR_syslog] sys_syslog, + [__NR_setitimer] sys_setitimer, + [__NR_getitimer] sys_getitimer, + [__NR_stat] sys_newstat, + [__NR_lstat] sys_newlstat, + [__NR_fstat] sys_newfstat, + [__NR_olduname] sys_ni_syscall, + [__NR_iopl] sys_ni_syscall, + [__NR_vhangup] sys_vhangup, + [__NR_idle] sys_ni_syscall, + [__NR_vm86] sys_ni_syscall, + [__NR_wait4] sys_wait4, + [__NR_swapoff] sys_ni_syscall, /* sys_swapoff */ + [__NR_sysinfo] sys_sysinfo, + [__NR_ipc] sys_ni_syscall, /* sys_ipc */ + [__NR_fsync] sys_fsync, + [__NR_sigreturn] sys_ni_syscall, + [__NR_clone] sys_ni_syscall, /* ppc_clone */ + [__NR_setdomainname] sys_setdomainname, + [__NR_uname] ppc_newuname, + [__NR_modify_ldt] sys_ni_syscall, + [__NR_adjtimex] sys_adjtimex, + [__NR_mprotect] sys_mprotect, + [__NR_sigprocmask] sys_ni_syscall, + [__NR_create_module] sys_ni_syscall, + [__NR_init_module] sys_ni_syscall, /* sys_init_module */ + [__NR_delete_module] sys_ni_syscall, /* sys_delete_module */ + [__NR_get_kernel_syms] sys_ni_syscall, + [__NR_quotactl] sys_ni_syscall, /* sys_quotactl */ + [__NR_getpgid] sys_getpgid, + [__NR_fchdir] sys_fchdir, + [__NR_bdflush] sys_bdflush, + [__NR_sysfs] sys_ni_syscall, /* sys_sysfs */ + [__NR_personality] ppc64_personality, + [__NR_afs_syscall] sys_ni_syscall, + [__NR_setfsuid] sys_setfsuid, + [__NR_setfsgid] sys_setfsgid, + [__NR__llseek] sys_llseek, + [__NR_getdents] sys_getdents, + [__NR__newselect] sys_select, + [__NR_flock] sys_flock, + [__NR_msync] sys_msync, + [__NR_readv] sys_readv, + [__NR_writev] sys_writev, + [__NR_getsid] sys_getsid, + [__NR_fdatasync] sys_fdatasync, + [__NR__sysctl] sys_ni_syscall, /* sys_sysctl */ + [__NR_mlock] sys_mlock, + [__NR_munlock] sys_munlock, + [__NR_mlockall] sys_mlockall, + [__NR_munlockall] sys_munlockall, + [__NR_sched_setparam] sys_sched_setparam, + [__NR_sched_getparam] sys_sched_getparam, + [__NR_sched_setscheduler] sys_sched_setscheduler, + [__NR_sched_getscheduler] sys_sched_getscheduler, + [__NR_sched_yield] sys_sched_yield, + [__NR_sched_get_priority_max] sys_sched_get_priority_max, + [__NR_sched_get_priority_min] sys_sched_get_priority_min, + [__NR_sched_rr_get_interval] sys_sched_rr_get_interval, + [__NR_nanosleep] sys_nanosleep, + [__NR_mremap] sys_mremap, + [__NR_setresuid] sys_setresuid, + [__NR_getresuid] sys_getresuid, + [__NR_query_module] sys_ni_syscall, + [__NR_poll] sys_poll, + [__NR_nfsservctl] sys_ni_syscall, /* sys_nfsservctl */ + [__NR_setresgid] sys_setresgid, + [__NR_getresgid] sys_getresgid, + [__NR_prctl] sys_prctl, + [__NR_rt_sigreturn] sys_ni_syscall, /* ppc64_rt_sigreturn */ + [__NR_rt_sigaction] sys_ni_syscall, /* sys_rt_sigaction */ + [__NR_rt_sigprocmask] sys_ni_syscall, /* sys_rt_sigprocmask */ + [__NR_rt_sigpending] sys_ni_syscall, /* sys_rt_sigpending */ + [__NR_rt_sigtimedwait] sys_ni_syscall, /* sys_rt_sigtimedwait */ + [__NR_rt_sigqueueinfo] sys_ni_syscall, /* sys_rt_sigqueueinfo */ + [__NR_rt_sigsuspend] sys_ni_syscall, /* sys_rt_sigsuspend */ + [__NR_pread64] sys_pread64, + [__NR_pwrite64] sys_pwrite64, + [__NR_chown] sys_chown, + [__NR_getcwd] sys_getcwd, + [__NR_capget] sys_capget, + [__NR_capset] sys_capset, + [__NR_sigaltstack] sys_ni_syscall, /* sys_sigaltstack */ + [__NR_sendfile] sys_sendfile64, + [__NR_getpmsg] sys_ni_syscall, + [__NR_putpmsg] sys_ni_syscall, + [__NR_vfork] sys_ni_syscall, /* ppc_vfork */ + [__NR_ugetrlimit] sys_getrlimit, + [__NR_readahead] sys_readahead, + [192] sys_ni_syscall, + [193] sys_ni_syscall, + [194] sys_ni_syscall, + [195] sys_ni_syscall, + [196] sys_ni_syscall, + [197] sys_ni_syscall, + [__NR_pciconfig_read] sys_ni_syscall, /* sys_pciconfig_read */ + [__NR_pciconfig_write] sys_ni_syscall, /* sys_pciconfig_write */ + [__NR_pciconfig_iobase] sys_ni_syscall, /* sys_pciconfig_iobase */ + [__NR_multiplexer] sys_ni_syscall, + [__NR_getdents64] sys_getdents64, + [__NR_pivot_root] sys_pivot_root, + [204] sys_ni_syscall, + [__NR_madvise] sys_madvise, + [__NR_mincore] sys_mincore, + [__NR_gettid] sys_gettid, + [__NR_tkill] sys_tkill, + [__NR_setxattr] sys_setxattr, + [__NR_lsetxattr] sys_lsetxattr, + [__NR_fsetxattr] sys_fsetxattr, + [__NR_getxattr] sys_getxattr, + [__NR_lgetxattr] sys_lgetxattr, + [__NR_fgetxattr] sys_fgetxattr, + [__NR_listxattr] sys_listxattr, + [__NR_llistxattr] sys_llistxattr, + [__NR_flistxattr] sys_flistxattr, + [__NR_removexattr] sys_removexattr, + [__NR_lremovexattr] sys_lremovexattr, + [__NR_fremovexattr] sys_fremovexattr, + [__NR_futex] sys_futex, + [__NR_sched_setaffinity] sys_sched_setaffinity, + [__NR_sched_getaffinity] sys_sched_getaffinity, + [__NR_tuxcall] sys_ni_syscall, + [226] sys_ni_syscall, + [__NR_io_setup] sys_io_setup, + [__NR_io_destroy] sys_io_destroy, + [__NR_io_getevents] sys_io_getevents, + [__NR_io_submit] sys_io_submit, + [__NR_io_cancel] sys_io_cancel, + [__NR_set_tid_address] sys_ni_syscall, /* sys_set_tid_address */ + [__NR_fadvise64] sys_fadvise64, + [__NR_exit_group] sys_ni_syscall, /* sys_exit_group */ + [__NR_lookup_dcookie] sys_ni_syscall, /* sys_lookup_dcookie */ + [__NR_epoll_create] sys_epoll_create, + [__NR_epoll_ctl] sys_epoll_ctl, + [__NR_epoll_wait] sys_epoll_wait, + [__NR_remap_file_pages] sys_remap_file_pages, + [__NR_timer_create] sys_timer_create, + [__NR_timer_settime] sys_timer_settime, + [__NR_timer_gettime] sys_timer_gettime, + [__NR_timer_getoverrun] sys_timer_getoverrun, + [__NR_timer_delete] sys_timer_delete, + [__NR_clock_settime] sys_clock_settime, + [__NR_clock_gettime] sys_clock_gettime, + [__NR_clock_getres] sys_clock_getres, + [__NR_clock_nanosleep] sys_clock_nanosleep, + [__NR_swapcontext] sys_ni_syscall, /* ppc64_swapcontext */ + [__NR_tgkill] sys_tgkill, + [__NR_utimes] sys_utimes, + [__NR_statfs64] sys_statfs64, + [__NR_fstatfs64] sys_fstatfs64, + [254] sys_ni_syscall, + [__NR_rtas] ppc_rtas, + [256] sys_ni_syscall, + [257] sys_ni_syscall, + [258] sys_ni_syscall, + [__NR_mbind] sys_ni_syscall, /* sys_mbind */ + [__NR_get_mempolicy] sys_ni_syscall, /* sys_get_mempolicy */ + [__NR_set_mempolicy] sys_ni_syscall, /* sys_set_mempolicy */ + [__NR_mq_open] sys_ni_syscall, /* sys_mq_open */ + [__NR_mq_unlink] sys_ni_syscall, /* sys_mq_unlink */ + [__NR_mq_timedsend] sys_ni_syscall, /* sys_mq_timedsend */ + [__NR_mq_timedreceive] sys_ni_syscall, /* sys_mq_timedreceive */ + [__NR_mq_notify] sys_ni_syscall, /* sys_mq_notify */ + [__NR_mq_getsetattr] sys_ni_syscall, /* sys_mq_getsetattr */ + [__NR_kexec_load] sys_ni_syscall, /* sys_kexec_load */ + [__NR_add_key] sys_ni_syscall, /* sys_add_key */ + [__NR_request_key] sys_ni_syscall, /* sys_request_key */ + [__NR_keyctl] sys_ni_syscall, /* sys_keyctl */ + [__NR_waitid] sys_ni_syscall, /* sys_waitid */ + [__NR_ioprio_set] sys_ni_syscall, /* sys_ioprio_set */ + [__NR_ioprio_get] sys_ni_syscall, /* sys_ioprio_get */ + [__NR_inotify_init] sys_ni_syscall, /* sys_inotify_init */ + [__NR_inotify_add_watch] sys_ni_syscall, /* sys_inotify_add_watch */ + [__NR_inotify_rm_watch] sys_ni_syscall, /* sys_inotify_rm_watch */ + [__NR_spu_run] sys_ni_syscall, /* sys_spu_run */ + [__NR_spu_create] sys_ni_syscall, /* sys_spu_create */ + [__NR_pselect6] sys_ni_syscall, /* sys_pselect */ + [__NR_ppoll] sys_ni_syscall, /* sys_ppoll */ + [__NR_unshare] sys_unshare, +}; + +long spu_sys_callback(struct spu_syscall_block *s) +{ + long (*syscall)(u64 a1, u64 a2, u64 a3, u64 a4, u64 a5, u64 a6); + + BUILD_BUG_ON(ARRAY_SIZE(spu_syscall_table) != __NR_syscalls); + + syscall = spu_syscall_table[s->nr_ret]; + + if (s->nr_ret >= __NR_syscalls) { + pr_debug("%s: invalid syscall #%ld", __FUNCTION__, s->nr_ret); + return -ENOSYS; + } + +#ifdef DEBUG + print_symbol(KERN_DEBUG "SPU-syscall %s:", (unsigned long)syscall); + printk("syscall%ld(%lx, %lx, %lx, %lx, %lx, %lx)\n", + s->nr_ret, + s->parm[0], s->parm[1], s->parm[2], + s->parm[3], s->parm[4], s->parm[5]); +#endif + + return syscall(s->parm[0], s->parm[1], s->parm[2], + s->parm[3], s->parm[4], s->parm[5]); +} +EXPORT_SYMBOL_GPL(spu_sys_callback); diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index 18ea8866c61a..c04e078c0fe5 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c @@ -76,6 +76,90 @@ static inline int spu_reacquire_runnable(struct spu_context *ctx, u32 *npc, return 0; } +/* + * SPU syscall restarting is tricky because we violate the basic + * assumption that the signal handler is running on the interrupted + * thread. Here instead, the handler runs on PowerPC user space code, + * while the syscall was called from the SPU. + * This means we can only do a very rough approximation of POSIX + * signal semantics. + */ +int spu_handle_restartsys(struct spu_context *ctx, long *spu_ret, + unsigned int *npc) +{ + int ret; + + switch (*spu_ret) { + case -ERESTARTSYS: + case -ERESTARTNOINTR: + /* + * Enter the regular syscall restarting for + * sys_spu_run, then restart the SPU syscall + * callback. + */ + *npc -= 8; + ret = -ERESTARTSYS; + break; + case -ERESTARTNOHAND: + case -ERESTART_RESTARTBLOCK: + /* + * Restart block is too hard for now, just return -EINTR + * to the SPU. + * ERESTARTNOHAND comes from sys_pause, we also return + * -EINTR from there. + * Assume that we need to be restarted ourselves though. + */ + *spu_ret = -EINTR; + ret = -ERESTARTSYS; + break; + default: + printk(KERN_WARNING "%s: unexpected return code %ld\n", + __FUNCTION__, *spu_ret); + ret = 0; + } + return ret; +} + +int spu_process_callback(struct spu_context *ctx) +{ + struct spu_syscall_block s; + u32 ls_pointer, npc; + char *ls; + long spu_ret; + int ret; + + /* get syscall block from local store */ + npc = ctx->ops->npc_read(ctx); + ls = ctx->ops->get_ls(ctx); + ls_pointer = *(u32*)(ls + npc); + if (ls_pointer > (LS_SIZE - sizeof(s))) + return -EFAULT; + memcpy(&s, ls + ls_pointer, sizeof (s)); + + /* do actual syscall without pinning the spu */ + ret = 0; + spu_ret = -ENOSYS; + npc += 4; + + if (s.nr_ret < __NR_syscalls) { + spu_release(ctx); + /* do actual system call from here */ + spu_ret = spu_sys_callback(&s); + if (spu_ret <= -ERESTARTSYS) { + ret = spu_handle_restartsys(ctx, &spu_ret, &npc); + } + spu_acquire(ctx); + if (ret == -ERESTARTSYS) + return ret; + } + + /* write result, jump over indirect pointer */ + memcpy(ls + ls_pointer, &spu_ret, sizeof (spu_ret)); + ctx->ops->npc_write(ctx, npc); + ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE); + return ret; +} + static inline int spu_process_events(struct spu_context *ctx) { struct spu *spu = ctx->spu; @@ -107,6 +191,13 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx, ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, status)); if (unlikely(ret)) break; + if ((*status & SPU_STATUS_STOPPED_BY_STOP) && + (*status >> SPU_STOP_STATUS_SHIFT == 0x2104)) { + ret = spu_process_callback(ctx); + if (ret) + break; + *status &= ~SPU_STATUS_STOPPED_BY_STOP; + } if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) { ret = spu_reacquire_runnable(ctx, npc, status); if (ret) -- cgit v1.2.2 From a33a7d7309d79656bc19a0e96fc4547a1633283e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 23 Mar 2006 00:00:11 +0100 Subject: [PATCH] spufs: implement mfc access for PPE-side DMA This patch adds a new file called 'mfc' to each spufs directory. The file accepts DMA commands that are a subset of what would be legal DMA commands for problem state register access. Upon reading the file, a bitmask is returned with the completed tag groups set. The file is meant to be used from an abstraction in libspe that is added by a different patch. From the kernel perspective, this means a process can now offload a memory copy from or into an SPE local store without having to run code on the SPE itself. The transfer will only be performed while the SPE is owned by one thread that is waiting in the spu_run system call and the data will be transferred into that thread's address space, independent of which thread started the transfer. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spu_base.c | 7 +- arch/powerpc/platforms/cell/spufs/backing_ops.c | 47 ++++ arch/powerpc/platforms/cell/spufs/context.c | 5 +- arch/powerpc/platforms/cell/spufs/file.c | 294 ++++++++++++++++++++++++ arch/powerpc/platforms/cell/spufs/hw_ops.c | 57 +++++ arch/powerpc/platforms/cell/spufs/sched.c | 2 + arch/powerpc/platforms/cell/spufs/spufs.h | 20 ++ arch/powerpc/platforms/cell/spufs/switch.c | 3 +- 8 files changed, 430 insertions(+), 5 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index a8fa1eeeb174..162b6cfa8a43 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -111,7 +111,7 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea) extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap); //XXX static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr) { - pr_debug("%s\n", __FUNCTION__); + pr_debug("%s, %lx, %lx\n", __FUNCTION__, dsisr, ea); /* Handle kernel space hash faults immediately. User hash faults need to be deferred to process context. */ @@ -168,7 +168,7 @@ static int __spu_trap_halt(struct spu *spu) static int __spu_trap_tag_group(struct spu *spu) { pr_debug("%s\n", __FUNCTION__); - /* wake_up(&spu->dma_wq); */ + spu->mfc_callback(spu); return 0; } @@ -242,6 +242,8 @@ spu_irq_class_1(int irq, void *data, struct pt_regs *regs) spu_mfc_dsisr_set(spu, 0ul); spu_int_stat_clear(spu, 1, stat); spin_unlock(&spu->register_lock); + pr_debug("%s: %lx %lx %lx %lx\n", __FUNCTION__, mask, stat, + dar, dsisr); if (stat & 1) /* segment fault */ __spu_trap_data_seg(spu, dar); @@ -632,6 +634,7 @@ static int __init create_spu(struct device_node *spe) spu->ibox_callback = NULL; spu->wbox_callback = NULL; spu->stop_callback = NULL; + spu->mfc_callback = NULL; mutex_lock(&spu_mutex); spu->number = number++; diff --git a/arch/powerpc/platforms/cell/spufs/backing_ops.c b/arch/powerpc/platforms/cell/spufs/backing_ops.c index a5c489a53c61..f1d35ddc9df3 100644 --- a/arch/powerpc/platforms/cell/spufs/backing_ops.c +++ b/arch/powerpc/platforms/cell/spufs/backing_ops.c @@ -285,6 +285,49 @@ static void spu_backing_runcntl_stop(struct spu_context *ctx) spu_backing_runcntl_write(ctx, SPU_RUNCNTL_STOP); } +static int spu_backing_set_mfc_query(struct spu_context * ctx, u32 mask, + u32 mode) +{ + struct spu_problem_collapsed *prob = &ctx->csa.prob; + int ret; + + spin_lock(&ctx->csa.register_lock); + ret = -EAGAIN; + if (prob->dma_querytype_RW) + goto out; + ret = 0; + /* FIXME: what are the side-effects of this? */ + prob->dma_querymask_RW = mask; + prob->dma_querytype_RW = mode; +out: + spin_unlock(&ctx->csa.register_lock); + + return ret; +} + +static u32 spu_backing_read_mfc_tagstatus(struct spu_context * ctx) +{ + return ctx->csa.prob.dma_tagstatus_R; +} + +static u32 spu_backing_get_mfc_free_elements(struct spu_context *ctx) +{ + return ctx->csa.prob.dma_qstatus_R; +} + +static int spu_backing_send_mfc_command(struct spu_context *ctx, + struct mfc_dma_command *cmd) +{ + int ret; + + spin_lock(&ctx->csa.register_lock); + ret = -EAGAIN; + /* FIXME: set up priv2->puq */ + spin_unlock(&ctx->csa.register_lock); + + return ret; +} + struct spu_context_ops spu_backing_ops = { .mbox_read = spu_backing_mbox_read, .mbox_stat_read = spu_backing_mbox_stat_read, @@ -305,4 +348,8 @@ struct spu_context_ops spu_backing_ops = { .get_ls = spu_backing_get_ls, .runcntl_write = spu_backing_runcntl_write, .runcntl_stop = spu_backing_runcntl_stop, + .set_mfc_query = spu_backing_set_mfc_query, + .read_mfc_tagstatus = spu_backing_read_mfc_tagstatus, + .get_mfc_free_elements = spu_backing_get_mfc_free_elements, + .send_mfc_command = spu_backing_send_mfc_command, }; diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c index 336f238102fd..7e016b9eab21 100644 --- a/arch/powerpc/platforms/cell/spufs/context.c +++ b/arch/powerpc/platforms/cell/spufs/context.c @@ -47,8 +47,11 @@ struct spu_context *alloc_spu_context(struct address_space *local_store) init_waitqueue_head(&ctx->ibox_wq); init_waitqueue_head(&ctx->wbox_wq); init_waitqueue_head(&ctx->stop_wq); + init_waitqueue_head(&ctx->mfc_wq); ctx->ibox_fasync = NULL; ctx->wbox_fasync = NULL; + ctx->mfc_fasync = NULL; + ctx->tagwait = 0; ctx->state = SPU_STATE_SAVED; ctx->local_store = local_store; ctx->spu = NULL; @@ -68,8 +71,6 @@ void destroy_spu_context(struct kref *kref) ctx = container_of(kref, struct spu_context, kref); down_write(&ctx->state_sema); spu_deactivate(ctx); - ctx->ibox_fasync = NULL; - ctx->wbox_fasync = NULL; up_write(&ctx->state_sema); spu_fini_csa(&ctx->csa); kfree(ctx); diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index dfa649c9b956..62fe9941ccee 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c @@ -20,6 +20,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#undef DEBUG + #include #include #include @@ -641,6 +643,297 @@ static u64 spufs_signal2_type_get(void *data) DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get, spufs_signal2_type_set, "%llu"); + +static int spufs_mfc_open(struct inode *inode, struct file *file) +{ + struct spufs_inode_info *i = SPUFS_I(inode); + struct spu_context *ctx = i->i_ctx; + + /* we don't want to deal with DMA into other processes */ + if (ctx->owner != current->mm) + return -EINVAL; + + if (atomic_read(&inode->i_count) != 1) + return -EBUSY; + + file->private_data = ctx; + return nonseekable_open(inode, file); +} + +/* interrupt-level mfc callback function. */ +void spufs_mfc_callback(struct spu *spu) +{ + struct spu_context *ctx = spu->ctx; + + wake_up_all(&ctx->mfc_wq); + + pr_debug("%s %s\n", __FUNCTION__, spu->name); + if (ctx->mfc_fasync) { + u32 free_elements, tagstatus; + unsigned int mask; + + /* no need for spu_acquire in interrupt context */ + free_elements = ctx->ops->get_mfc_free_elements(ctx); + tagstatus = ctx->ops->read_mfc_tagstatus(ctx); + + mask = 0; + if (free_elements & 0xffff) + mask |= POLLOUT; + if (tagstatus & ctx->tagwait) + mask |= POLLIN; + + kill_fasync(&ctx->mfc_fasync, SIGIO, mask); + } +} + +static int spufs_read_mfc_tagstatus(struct spu_context *ctx, u32 *status) +{ + /* See if there is one tag group is complete */ + /* FIXME we need locking around tagwait */ + *status = ctx->ops->read_mfc_tagstatus(ctx) & ctx->tagwait; + ctx->tagwait &= ~*status; + if (*status) + return 1; + + /* enable interrupt waiting for any tag group, + may silently fail if interrupts are already enabled */ + ctx->ops->set_mfc_query(ctx, ctx->tagwait, 1); + return 0; +} + +static ssize_t spufs_mfc_read(struct file *file, char __user *buffer, + size_t size, loff_t *pos) +{ + struct spu_context *ctx = file->private_data; + int ret = -EINVAL; + u32 status; + + if (size != 4) + goto out; + + spu_acquire(ctx); + if (file->f_flags & O_NONBLOCK) { + status = ctx->ops->read_mfc_tagstatus(ctx); + if (!(status & ctx->tagwait)) + ret = -EAGAIN; + else + ctx->tagwait &= ~status; + } else { + ret = spufs_wait(ctx->mfc_wq, + spufs_read_mfc_tagstatus(ctx, &status)); + } + spu_release(ctx); + + if (ret) + goto out; + + ret = 4; + if (copy_to_user(buffer, &status, 4)) + ret = -EFAULT; + +out: + return ret; +} + +static int spufs_check_valid_dma(struct mfc_dma_command *cmd) +{ + pr_debug("queueing DMA %x %lx %x %x %x\n", cmd->lsa, + cmd->ea, cmd->size, cmd->tag, cmd->cmd); + + switch (cmd->cmd) { + case MFC_PUT_CMD: + case MFC_PUTF_CMD: + case MFC_PUTB_CMD: + case MFC_GET_CMD: + case MFC_GETF_CMD: + case MFC_GETB_CMD: + break; + default: + pr_debug("invalid DMA opcode %x\n", cmd->cmd); + return -EIO; + } + + if ((cmd->lsa & 0xf) != (cmd->ea &0xf)) { + pr_debug("invalid DMA alignment, ea %lx lsa %x\n", + cmd->ea, cmd->lsa); + return -EIO; + } + + switch (cmd->size & 0xf) { + case 1: + break; + case 2: + if (cmd->lsa & 1) + goto error; + break; + case 4: + if (cmd->lsa & 3) + goto error; + break; + case 8: + if (cmd->lsa & 7) + goto error; + break; + case 0: + if (cmd->lsa & 15) + goto error; + break; + error: + default: + pr_debug("invalid DMA alignment %x for size %x\n", + cmd->lsa & 0xf, cmd->size); + return -EIO; + } + + if (cmd->size > 16 * 1024) { + pr_debug("invalid DMA size %x\n", cmd->size); + return -EIO; + } + + if (cmd->tag & 0xfff0) { + /* we reserve the higher tag numbers for kernel use */ + pr_debug("invalid DMA tag\n"); + return -EIO; + } + + if (cmd->class) { + /* not supported in this version */ + pr_debug("invalid DMA class\n"); + return -EIO; + } + + return 0; +} + +static int spu_send_mfc_command(struct spu_context *ctx, + struct mfc_dma_command cmd, + int *error) +{ + *error = ctx->ops->send_mfc_command(ctx, &cmd); + if (*error == -EAGAIN) { + /* wait for any tag group to complete + so we have space for the new command */ + ctx->ops->set_mfc_query(ctx, ctx->tagwait, 1); + /* try again, because the queue might be + empty again */ + *error = ctx->ops->send_mfc_command(ctx, &cmd); + if (*error == -EAGAIN) + return 0; + } + return 1; +} + +static ssize_t spufs_mfc_write(struct file *file, const char __user *buffer, + size_t size, loff_t *pos) +{ + struct spu_context *ctx = file->private_data; + struct mfc_dma_command cmd; + int ret = -EINVAL; + + if (size != sizeof cmd) + goto out; + + ret = -EFAULT; + if (copy_from_user(&cmd, buffer, sizeof cmd)) + goto out; + + ret = spufs_check_valid_dma(&cmd); + if (ret) + goto out; + + spu_acquire_runnable(ctx); + if (file->f_flags & O_NONBLOCK) { + ret = ctx->ops->send_mfc_command(ctx, &cmd); + } else { + int status; + ret = spufs_wait(ctx->mfc_wq, + spu_send_mfc_command(ctx, cmd, &status)); + if (status) + ret = status; + } + spu_release(ctx); + + if (ret) + goto out; + + ctx->tagwait |= 1 << cmd.tag; + +out: + return ret; +} + +static unsigned int spufs_mfc_poll(struct file *file,poll_table *wait) +{ + struct spu_context *ctx = file->private_data; + u32 free_elements, tagstatus; + unsigned int mask; + + spu_acquire(ctx); + ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2); + free_elements = ctx->ops->get_mfc_free_elements(ctx); + tagstatus = ctx->ops->read_mfc_tagstatus(ctx); + spu_release(ctx); + + poll_wait(file, &ctx->mfc_wq, wait); + + mask = 0; + if (free_elements & 0xffff) + mask |= POLLOUT | POLLWRNORM; + if (tagstatus & ctx->tagwait) + mask |= POLLIN | POLLRDNORM; + + pr_debug("%s: free %d tagstatus %d tagwait %d\n", __FUNCTION__, + free_elements, tagstatus, ctx->tagwait); + + return mask; +} + +static int spufs_mfc_flush(struct file *file) +{ + struct spu_context *ctx = file->private_data; + int ret; + + spu_acquire(ctx); +#if 0 +/* this currently hangs */ + ret = spufs_wait(ctx->mfc_wq, + ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2)); + if (ret) + goto out; + ret = spufs_wait(ctx->mfc_wq, + ctx->ops->read_mfc_tagstatus(ctx) == ctx->tagwait); +out: +#else + ret = 0; +#endif + spu_release(ctx); + + return ret; +} + +static int spufs_mfc_fsync(struct file *file, struct dentry *dentry, + int datasync) +{ + return spufs_mfc_flush(file); +} + +static int spufs_mfc_fasync(int fd, struct file *file, int on) +{ + struct spu_context *ctx = file->private_data; + + return fasync_helper(fd, file, on, &ctx->mfc_fasync); +} + +static struct file_operations spufs_mfc_fops = { + .open = spufs_mfc_open, + .read = spufs_mfc_read, + .write = spufs_mfc_write, + .poll = spufs_mfc_poll, + .flush = spufs_mfc_flush, + .fsync = spufs_mfc_fsync, + .fasync = spufs_mfc_fasync, +}; + static void spufs_npc_set(void *data, u64 val) { struct spu_context *ctx = data; @@ -783,6 +1076,7 @@ struct tree_descr spufs_dir_contents[] = { { "signal2", &spufs_signal2_fops, 0666, }, { "signal1_type", &spufs_signal1_type, 0666, }, { "signal2_type", &spufs_signal2_type, 0666, }, + { "mfc", &spufs_mfc_fops, 0666, }, { "npc", &spufs_npc_ops, 0666, }, { "fpcr", &spufs_fpcr_fops, 0666, }, { "decr", &spufs_decr_ops, 0666, }, diff --git a/arch/powerpc/platforms/cell/spufs/hw_ops.c b/arch/powerpc/platforms/cell/spufs/hw_ops.c index 5445719bff79..a13a8b5a014d 100644 --- a/arch/powerpc/platforms/cell/spufs/hw_ops.c +++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c @@ -232,6 +232,59 @@ static void spu_hw_runcntl_stop(struct spu_context *ctx) spin_unlock_irq(&ctx->spu->register_lock); } +static int spu_hw_set_mfc_query(struct spu_context * ctx, u32 mask, u32 mode) +{ + struct spu_problem *prob = ctx->spu->problem; + int ret; + + spin_lock_irq(&ctx->spu->register_lock); + ret = -EAGAIN; + if (in_be32(&prob->dma_querytype_RW)) + goto out; + ret = 0; + out_be32(&prob->dma_querymask_RW, mask); + out_be32(&prob->dma_querytype_RW, mode); +out: + spin_unlock_irq(&ctx->spu->register_lock); + return ret; +} + +static u32 spu_hw_read_mfc_tagstatus(struct spu_context * ctx) +{ + return in_be32(&ctx->spu->problem->dma_tagstatus_R); +} + +static u32 spu_hw_get_mfc_free_elements(struct spu_context *ctx) +{ + return in_be32(&ctx->spu->problem->dma_qstatus_R); +} + +static int spu_hw_send_mfc_command(struct spu_context *ctx, + struct mfc_dma_command *cmd) +{ + u32 status; + struct spu_problem *prob = ctx->spu->problem; + + spin_lock_irq(&ctx->spu->register_lock); + out_be32(&prob->mfc_lsa_W, cmd->lsa); + out_be64(&prob->mfc_ea_W, cmd->ea); + out_be32(&prob->mfc_union_W.by32.mfc_size_tag32, + cmd->size << 16 | cmd->tag); + out_be32(&prob->mfc_union_W.by32.mfc_class_cmd32, + cmd->class << 16 | cmd->cmd); + status = in_be32(&prob->mfc_union_W.by32.mfc_class_cmd32); + spin_unlock_irq(&ctx->spu->register_lock); + + switch (status & 0xffff) { + case 0: + return 0; + case 2: + return -EAGAIN; + default: + return -EINVAL; + } +} + struct spu_context_ops spu_hw_ops = { .mbox_read = spu_hw_mbox_read, .mbox_stat_read = spu_hw_mbox_stat_read, @@ -252,4 +305,8 @@ struct spu_context_ops spu_hw_ops = { .get_ls = spu_hw_get_ls, .runcntl_write = spu_hw_runcntl_write, .runcntl_stop = spu_hw_runcntl_stop, + .set_mfc_query = spu_hw_set_mfc_query, + .read_mfc_tagstatus = spu_hw_read_mfc_tagstatus, + .get_mfc_free_elements = spu_hw_get_mfc_free_elements, + .send_mfc_command = spu_hw_send_mfc_command, }; diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 963182fbd1aa..bf652cd77000 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c @@ -180,6 +180,7 @@ static inline void bind_context(struct spu *spu, struct spu_context *ctx) spu->ibox_callback = spufs_ibox_callback; spu->wbox_callback = spufs_wbox_callback; spu->stop_callback = spufs_stop_callback; + spu->mfc_callback = spufs_mfc_callback; mb(); spu_unmap_mappings(ctx); spu_restore(&ctx->csa, spu); @@ -197,6 +198,7 @@ static inline void unbind_context(struct spu *spu, struct spu_context *ctx) spu->ibox_callback = NULL; spu->wbox_callback = NULL; spu->stop_callback = NULL; + spu->mfc_callback = NULL; spu->mm = NULL; spu->pid = 0; spu->prio = MAX_PRIO; diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index db2601f0abd5..57d687ca3f03 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h @@ -55,13 +55,27 @@ struct spu_context { wait_queue_head_t ibox_wq; wait_queue_head_t wbox_wq; wait_queue_head_t stop_wq; + wait_queue_head_t mfc_wq; struct fasync_struct *ibox_fasync; struct fasync_struct *wbox_fasync; + struct fasync_struct *mfc_fasync; + u32 tagwait; struct spu_context_ops *ops; struct work_struct reap_work; u64 flags; }; +struct mfc_dma_command { + int32_t pad; /* reserved */ + uint32_t lsa; /* local storage address */ + uint64_t ea; /* effective address */ + uint16_t size; /* transfer size */ + uint16_t tag; /* command tag */ + uint16_t class; /* class ID */ + uint16_t cmd; /* command opcode */ +}; + + /* SPU context query/set operations. */ struct spu_context_ops { int (*mbox_read) (struct spu_context * ctx, u32 * data); @@ -84,6 +98,11 @@ struct spu_context_ops { char*(*get_ls) (struct spu_context * ctx); void (*runcntl_write) (struct spu_context * ctx, u32 data); void (*runcntl_stop) (struct spu_context * ctx); + int (*set_mfc_query)(struct spu_context * ctx, u32 mask, u32 mode); + u32 (*read_mfc_tagstatus)(struct spu_context * ctx); + u32 (*get_mfc_free_elements)(struct spu_context *ctx); + int (*send_mfc_command)(struct spu_context *ctx, + struct mfc_dma_command *cmd); }; extern struct spu_context_ops spu_hw_ops; @@ -159,5 +178,6 @@ size_t spu_ibox_read(struct spu_context *ctx, u32 *data); void spufs_ibox_callback(struct spu *spu); void spufs_wbox_callback(struct spu *spu); void spufs_stop_callback(struct spu *spu); +void spufs_mfc_callback(struct spu *spu); #endif diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index 212db28531fa..97898d5d34e5 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -2145,7 +2145,8 @@ static void init_priv1(struct spu_state *csa) csa->priv1.int_mask_class1_RW = CLASS1_ENABLE_SEGMENT_FAULT_INTR | CLASS1_ENABLE_STORAGE_FAULT_INTR; csa->priv1.int_mask_class2_RW = CLASS2_ENABLE_SPU_STOP_INTR | - CLASS2_ENABLE_SPU_HALT_INTR; + CLASS2_ENABLE_SPU_HALT_INTR | + CLASS2_ENABLE_SPU_DMA_TAG_GROUP_COMPLETE_INTR; } static void init_priv2(struct spu_state *csa) -- cgit v1.2.2 From 6df10a82f8de89c66eb91c371d62d76e87b2cbba Mon Sep 17 00:00:00 2001 From: Mark Nutter Date: Thu, 23 Mar 2006 00:00:12 +0100 Subject: [PATCH] spufs: enable SPE problem state MMIO access. This patch is layered on top of CONFIG_SPARSEMEM and is patterned after direct mapping of LS. This patch allows mmap() of the following regions: "mfc", which represents the area from [0x3000 - 0x3fff]; "cntl", which represents the area from [0x4000 - 0x4fff]; "signal1" which begins at offset 0x14000; "signal2" which begins at offset 0x1c000. The signal1 & signal2 files may be mmap()'d by regular user processes. The cntl and mfc file, on the other hand, may only be accessed if the owning process has CAP_SYS_RAWIO, because they have the potential to confuse the kernel with regard to parallel access to the same files with regular file operations: the kernel always holds a spinlock when accessing registers in these areas to serialize them, which can not be guaranteed with user mmaps, Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/Kconfig | 5 + arch/powerpc/platforms/cell/spu_base.c | 5 + arch/powerpc/platforms/cell/spufs/context.c | 18 ++- arch/powerpc/platforms/cell/spufs/file.c | 229 +++++++++++++++++++++++++++- arch/powerpc/platforms/cell/spufs/inode.c | 2 +- arch/powerpc/platforms/cell/spufs/spufs.h | 8 +- 6 files changed, 255 insertions(+), 12 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig index 3157071e241c..c2a3db8edb0c 100644 --- a/arch/powerpc/platforms/cell/Kconfig +++ b/arch/powerpc/platforms/cell/Kconfig @@ -10,4 +10,9 @@ config SPU_FS Units on machines implementing the Broadband Processor Architecture. +config SPUFS_MMAP + bool + depends on SPU_FS && SPARSEMEM && !PPC_64K_PAGES + default y + endmenu diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index 162b6cfa8a43..d152a3fbdb83 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -570,6 +570,11 @@ static int __init spu_map_device(struct spu *spu, struct device_node *spe) if (!spu->local_store) goto out; + prop = get_property(spe, "problem", NULL); + if (!prop) + goto out_unmap; + spu->problem_phys = *(unsigned long *)prop; + spu->problem= map_spe_prop(spe, "problem"); if (!spu->problem) goto out_unmap; diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c index 7e016b9eab21..3f75c1e7adea 100644 --- a/arch/powerpc/platforms/cell/spufs/context.c +++ b/arch/powerpc/platforms/cell/spufs/context.c @@ -27,7 +27,7 @@ #include #include "spufs.h" -struct spu_context *alloc_spu_context(struct address_space *local_store) +struct spu_context *alloc_spu_context(void) { struct spu_context *ctx; ctx = kmalloc(sizeof *ctx, GFP_KERNEL); @@ -53,7 +53,10 @@ struct spu_context *alloc_spu_context(struct address_space *local_store) ctx->mfc_fasync = NULL; ctx->tagwait = 0; ctx->state = SPU_STATE_SAVED; - ctx->local_store = local_store; + ctx->local_store = NULL; + ctx->cntl = NULL; + ctx->signal1 = NULL; + ctx->signal2 = NULL; ctx->spu = NULL; ctx->ops = &spu_backing_ops; ctx->owner = get_task_mm(current); @@ -110,7 +113,16 @@ void spu_release(struct spu_context *ctx) void spu_unmap_mappings(struct spu_context *ctx) { - unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1); + if (ctx->local_store) + unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1); + if (ctx->mfc) + unmap_mapping_range(ctx->mfc, 0, 0x4000, 1); + if (ctx->cntl) + unmap_mapping_range(ctx->cntl, 0, 0x4000, 1); + if (ctx->signal1) + unmap_mapping_range(ctx->signal1, 0, 0x4000, 1); + if (ctx->signal2) + unmap_mapping_range(ctx->signal2, 0, 0x4000, 1); } int spu_acquire_runnable(struct spu_context *ctx) diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 62fe9941ccee..366185e92667 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c @@ -41,8 +41,10 @@ static int spufs_mem_open(struct inode *inode, struct file *file) { struct spufs_inode_info *i = SPUFS_I(inode); - file->private_data = i->i_ctx; - file->f_mapping = i->i_ctx->local_store; + struct spu_context *ctx = i->i_ctx; + file->private_data = ctx; + file->f_mapping = inode->i_mapping; + ctx->local_store = inode->i_mapping; return 0; } @@ -86,7 +88,7 @@ spufs_mem_write(struct file *file, const char __user *buffer, return ret; } -#ifdef CONFIG_SPARSEMEM +#ifdef CONFIG_SPUFS_MMAP static struct page * spufs_mem_mmap_nopage(struct vm_area_struct *vma, unsigned long address, int *type) @@ -138,11 +140,113 @@ static struct file_operations spufs_mem_fops = { .read = spufs_mem_read, .write = spufs_mem_write, .llseek = generic_file_llseek, -#ifdef CONFIG_SPARSEMEM +#ifdef CONFIG_SPUFS_MMAP .mmap = spufs_mem_mmap, #endif }; +#ifdef CONFIG_SPUFS_MMAP +static struct page *spufs_ps_nopage(struct vm_area_struct *vma, + unsigned long address, + int *type, unsigned long ps_offs) +{ + struct page *page = NOPAGE_SIGBUS; + int fault_type = VM_FAULT_SIGBUS; + struct spu_context *ctx = vma->vm_file->private_data; + unsigned long offset = address - vma->vm_start; + unsigned long area; + int ret; + + offset += vma->vm_pgoff << PAGE_SHIFT; + if (offset >= 0x4000) + goto out; + + ret = spu_acquire_runnable(ctx); + if (ret) + goto out; + + area = ctx->spu->problem_phys + ps_offs; + page = pfn_to_page((area + offset) >> PAGE_SHIFT); + fault_type = VM_FAULT_MINOR; + page_cache_get(page); + + spu_release(ctx); + + out: + if (type) + *type = fault_type; + + return page; +} + +static struct page *spufs_cntl_mmap_nopage(struct vm_area_struct *vma, + unsigned long address, int *type) +{ + return spufs_ps_nopage(vma, address, type, 0x4000); +} + +static struct vm_operations_struct spufs_cntl_mmap_vmops = { + .nopage = spufs_cntl_mmap_nopage, +}; + +/* + * mmap support for problem state control area [0x4000 - 0x4fff]. + * Mapping this area requires that the application have CAP_SYS_RAWIO, + * as these registers require special care when read/writing. + */ +static int spufs_cntl_mmap(struct file *file, struct vm_area_struct *vma) +{ + if (!(vma->vm_flags & VM_SHARED)) + return -EINVAL; + + if (!capable(CAP_SYS_RAWIO)) + return -EPERM; + + vma->vm_flags |= VM_RESERVED; + vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) + | _PAGE_NO_CACHE); + + vma->vm_ops = &spufs_cntl_mmap_vmops; + return 0; +} +#endif + +static int spufs_cntl_open(struct inode *inode, struct file *file) +{ + struct spufs_inode_info *i = SPUFS_I(inode); + struct spu_context *ctx = i->i_ctx; + + file->private_data = ctx; + file->f_mapping = inode->i_mapping; + ctx->cntl = inode->i_mapping; + return 0; +} + +static ssize_t +spufs_cntl_read(struct file *file, char __user *buffer, + size_t size, loff_t *pos) +{ + /* FIXME: read from spu status */ + return -EINVAL; +} + +static ssize_t +spufs_cntl_write(struct file *file, const char __user *buffer, + size_t size, loff_t *pos) +{ + /* FIXME: write to runctl bit */ + return -EINVAL; +} + +static struct file_operations spufs_cntl_fops = { + .open = spufs_cntl_open, + .read = spufs_cntl_read, + .write = spufs_cntl_write, +#ifdef CONFIG_SPUFS_MMAP + .mmap = spufs_cntl_mmap, +#endif +}; + static int spufs_regs_open(struct inode *inode, struct file *file) { @@ -503,6 +607,16 @@ static struct file_operations spufs_wbox_stat_fops = { .read = spufs_wbox_stat_read, }; +static int spufs_signal1_open(struct inode *inode, struct file *file) +{ + struct spufs_inode_info *i = SPUFS_I(inode); + struct spu_context *ctx = i->i_ctx; + file->private_data = ctx; + file->f_mapping = inode->i_mapping; + ctx->signal1 = inode->i_mapping; + return nonseekable_open(inode, file); +} + static ssize_t spufs_signal1_read(struct file *file, char __user *buf, size_t len, loff_t *pos) { @@ -543,12 +657,50 @@ static ssize_t spufs_signal1_write(struct file *file, const char __user *buf, return 4; } +#ifdef CONFIG_SPUFS_MMAP +static struct page *spufs_signal1_mmap_nopage(struct vm_area_struct *vma, + unsigned long address, int *type) +{ + return spufs_ps_nopage(vma, address, type, 0x14000); +} + +static struct vm_operations_struct spufs_signal1_mmap_vmops = { + .nopage = spufs_signal1_mmap_nopage, +}; + +static int spufs_signal1_mmap(struct file *file, struct vm_area_struct *vma) +{ + if (!(vma->vm_flags & VM_SHARED)) + return -EINVAL; + + vma->vm_flags |= VM_RESERVED; + vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) + | _PAGE_NO_CACHE); + + vma->vm_ops = &spufs_signal1_mmap_vmops; + return 0; +} +#endif + static struct file_operations spufs_signal1_fops = { - .open = spufs_pipe_open, + .open = spufs_signal1_open, .read = spufs_signal1_read, .write = spufs_signal1_write, +#ifdef CONFIG_SPUFS_MMAP + .mmap = spufs_signal1_mmap, +#endif }; +static int spufs_signal2_open(struct inode *inode, struct file *file) +{ + struct spufs_inode_info *i = SPUFS_I(inode); + struct spu_context *ctx = i->i_ctx; + file->private_data = ctx; + file->f_mapping = inode->i_mapping; + ctx->signal2 = inode->i_mapping; + return nonseekable_open(inode, file); +} + static ssize_t spufs_signal2_read(struct file *file, char __user *buf, size_t len, loff_t *pos) { @@ -591,10 +743,39 @@ static ssize_t spufs_signal2_write(struct file *file, const char __user *buf, return 4; } +#ifdef CONFIG_SPUFS_MMAP +static struct page *spufs_signal2_mmap_nopage(struct vm_area_struct *vma, + unsigned long address, int *type) +{ + return spufs_ps_nopage(vma, address, type, 0x1c000); +} + +static struct vm_operations_struct spufs_signal2_mmap_vmops = { + .nopage = spufs_signal2_mmap_nopage, +}; + +static int spufs_signal2_mmap(struct file *file, struct vm_area_struct *vma) +{ + if (!(vma->vm_flags & VM_SHARED)) + return -EINVAL; + + /* FIXME: */ + vma->vm_flags |= VM_RESERVED; + vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) + | _PAGE_NO_CACHE); + + vma->vm_ops = &spufs_signal2_mmap_vmops; + return 0; +} +#endif + static struct file_operations spufs_signal2_fops = { - .open = spufs_pipe_open, + .open = spufs_signal2_open, .read = spufs_signal2_read, .write = spufs_signal2_write, +#ifdef CONFIG_SPUFS_MMAP + .mmap = spufs_signal2_mmap, +#endif }; static void spufs_signal1_type_set(void *data, u64 val) @@ -643,6 +824,38 @@ static u64 spufs_signal2_type_get(void *data) DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get, spufs_signal2_type_set, "%llu"); +#ifdef CONFIG_SPUFS_MMAP +static struct page *spufs_mfc_mmap_nopage(struct vm_area_struct *vma, + unsigned long address, int *type) +{ + return spufs_ps_nopage(vma, address, type, 0x3000); +} + +static struct vm_operations_struct spufs_mfc_mmap_vmops = { + .nopage = spufs_mfc_mmap_nopage, +}; + +/* + * mmap support for problem state MFC DMA area [0x0000 - 0x0fff]. + * Mapping this area requires that the application have CAP_SYS_RAWIO, + * as these registers require special care when read/writing. + */ +static int spufs_mfc_mmap(struct file *file, struct vm_area_struct *vma) +{ + if (!(vma->vm_flags & VM_SHARED)) + return -EINVAL; + + if (!capable(CAP_SYS_RAWIO)) + return -EPERM; + + vma->vm_flags |= VM_RESERVED; + vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) + | _PAGE_NO_CACHE); + + vma->vm_ops = &spufs_mfc_mmap_vmops; + return 0; +} +#endif static int spufs_mfc_open(struct inode *inode, struct file *file) { @@ -932,6 +1145,9 @@ static struct file_operations spufs_mfc_fops = { .flush = spufs_mfc_flush, .fsync = spufs_mfc_fsync, .fasync = spufs_mfc_fasync, +#ifdef CONFIG_SPUFS_MMAP + .mmap = spufs_mfc_mmap, +#endif }; static void spufs_npc_set(void *data, u64 val) @@ -1077,6 +1293,7 @@ struct tree_descr spufs_dir_contents[] = { { "signal1_type", &spufs_signal1_type, 0666, }, { "signal2_type", &spufs_signal2_type, 0666, }, { "mfc", &spufs_mfc_fops, 0666, }, + { "cntl", &spufs_cntl_fops, 0666, }, { "npc", &spufs_npc_ops, 0666, }, { "fpcr", &spufs_fpcr_fops, 0666, }, { "decr", &spufs_decr_ops, 0666, }, diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index b3962c3a0348..dc06305eecf5 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -241,7 +241,7 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, int mode) inode->i_gid = dir->i_gid; inode->i_mode &= S_ISGID; } - ctx = alloc_spu_context(inode->i_mapping); + ctx = alloc_spu_context(); SPUFS_I(inode)->i_ctx = ctx; if (!ctx) goto out_iput; diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index 57d687ca3f03..4485738e2102 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h @@ -43,7 +43,11 @@ struct spu_context { struct spu *spu; /* pointer to a physical SPU */ struct spu_state csa; /* SPU context save area. */ spinlock_t mmio_lock; /* protects mmio access */ - struct address_space *local_store;/* local store backing store */ + struct address_space *local_store; /* local store mapping. */ + struct address_space *mfc; /* 'mfc' area mappings. */ + struct address_space *cntl; /* 'control' area mappings. */ + struct address_space *signal1; /* 'signal1' area mappings. */ + struct address_space *signal2; /* 'signal2' area mappings. */ enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state; struct rw_semaphore state_sema; @@ -125,7 +129,7 @@ long spufs_create_thread(struct nameidata *nd, extern struct file_operations spufs_context_fops; /* context management */ -struct spu_context * alloc_spu_context(struct address_space *local_store); +struct spu_context * alloc_spu_context(void); void destroy_spu_context(struct kref *kref); struct spu_context * get_spu_context(struct spu_context *ctx); int put_spu_context(struct spu_context *ctx); -- cgit v1.2.2 From ca3e91cb0cd53da70621f85d24a080b23751a013 Mon Sep 17 00:00:00 2001 From: Dirk Herrendoerfer Date: Thu, 23 Mar 2006 00:00:13 +0100 Subject: [PATCH] spufs: initialize context correctly the mfc member of a new context was not initialized to zero, which potentially leads to wild memory accesses. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spufs/context.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c index 3f75c1e7adea..8bb33abfad17 100644 --- a/arch/powerpc/platforms/cell/spufs/context.c +++ b/arch/powerpc/platforms/cell/spufs/context.c @@ -51,6 +51,7 @@ struct spu_context *alloc_spu_context(void) ctx->ibox_fasync = NULL; ctx->wbox_fasync = NULL; ctx->mfc_fasync = NULL; + ctx->mfc = NULL; ctx->tagwait = 0; ctx->state = SPU_STATE_SAVED; ctx->local_store = NULL; -- cgit v1.2.2 From 6088857b169c64e6e9672a2a66e76db3e957d5db Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Thu, 23 Mar 2006 21:50:59 +0100 Subject: [PATCH] correct the comment about stackpointer alignment in __boot_from_prom The address of variable val in prom_init_stdout is passed to prom_getprop. prom_getprop casts the pointer to u32 and passes it to call_prom in the hope that OpenFirmware stores something there. But the pointer is truncated in the lower bits and the expected value is stored somewhere else. In my testing I had a stackpointer of 0x0023e6b4. val was at offset 120, wich has address 0x0023e72c. But the value passed to OF was 0x0023e728. c00000000040b710: 3b 01 00 78 addi r24,r1,120 ... c00000000040b754: 57 08 00 38 rlwinm r8,r24,0,0,28 ... c00000000040b784: 80 01 00 78 lwz r0,120(r1) ... c00000000040b798: 90 1b 00 0c stw r0,12(r27) ... The stackpointer came from 32bit code. The chain was yaboot -> zImage -> vmlinux PowerMac OpenFirmware does appearently not handle the ELF sections correctly. If yaboot was compiled in /usr/src/packages/BUILD/lilo-10.1.1/yaboot, then the stackpointer is unaligned. But the stackpointer is correct if yaboot is compiled in /tmp/yaboot. This bug triggered since 2.6.15, now prom_getprop is an inline function. gcc clears the lower bits, instead of just clearing the upper 32 bits. Signed-off-by: Olaf Hering Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/head_64.S | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 35084f3a841b..7e7f7d243304 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -1544,7 +1544,11 @@ _STATIC(__boot_from_prom) mr r28,r6 mr r27,r7 - /* Align the stack to 16-byte boundary for broken yaboot */ + /* + * Align the stack to 16-byte boundary + * Depending on the size and layout of the ELF sections in the initial + * boot binary, the stack pointer will be unalignet on PowerMac + */ rldicr r1,r1,0,59 /* Make sure we are running in 64 bits mode */ -- cgit v1.2.2 From 069007ae07ab9286fbe42e9a66b78e184f752a05 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 24 Mar 2006 02:34:46 -0800 Subject: [PATCH] powerpc: hot_add_scn_to_nid() build fix The return statement is to prevent `warning: 'nid' might be used uninitialized in this function'. Cc: Nathan Lynch Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras --- arch/powerpc/mm/numa.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/powerpc') diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index e89b22aa539e..0a335f34974c 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -756,6 +756,7 @@ int hot_add_scn_to_nid(unsigned long scn_addr) struct device_node *memory = NULL; nodemask_t nodes; int default_nid = any_online_node(NODE_MASK_ALL); + int nid; if (!numa_enabled || (min_common_depth < 0)) return default_nid; @@ -790,6 +791,7 @@ ha_new_range: goto ha_new_range; } BUG(); /* section address should be found above */ + return 0; /* Temporary code to ensure that returned node is not empty */ got_nid: -- cgit v1.2.2 From add60ef303809087999412209d24d400a1c96670 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Thu, 23 Mar 2006 22:03:57 +0100 Subject: [PATCH] powerpc: return to OF via trap, not exit Do not call prom exit prom_panic. It clears the screen and the exit message is lost. On some (or all?) pmacs it causes another crash when OF tries to print the date and time in its banner. Set of_platform earlier to catch more prom_panic() calls. Signed-off-by: Olaf Hering Acked-by: Segher Boessenkool Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom_init.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 813c2cd194c2..0d0887844501 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -397,6 +397,11 @@ static void __init __attribute__((noreturn)) prom_panic(const char *reason) reason = PTRRELOC(reason); #endif prom_print(reason); + /* Do not call exit because it clears the screen on pmac + * it also causes some sort of double-fault on early pmacs */ + if (RELOC(of_platform) == PLATFORM_POWERMAC) + asm("trap\n"); + /* ToDo: should put up an SRC here on p/iSeries */ call_prom("exit", 0, 0); @@ -2060,15 +2065,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, */ prom_init_stdout(); - /* Bail if this is a kdump kernel. */ - if (PHYSICAL_START > 0) - prom_panic("Error: You can't boot a kdump kernel from OF!\n"); - - /* - * Check for an initrd - */ - prom_check_initrd(r3, r4); - /* * Get default machine type. At this point, we do not differentiate * between pSeries SMP and pSeries LPAR @@ -2078,6 +2074,15 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, prom_setprop(_prom->chosen, "/chosen", "linux,platform", &getprop_rval, sizeof(getprop_rval)); + /* Bail if this is a kdump kernel. */ + if (PHYSICAL_START > 0) + prom_panic("Error: You can't boot a kdump kernel from OF!\n"); + + /* + * Check for an initrd + */ + prom_check_initrd(r3, r4); + #ifdef CONFIG_PPC_PSERIES /* * On pSeries, inform the firmware about our capabilities -- cgit v1.2.2 From 16cc11daff0230bcd1ae7327c1c256c0aa02cad6 Mon Sep 17 00:00:00 2001 From: John Rose Date: Fri, 24 Mar 2006 11:25:32 -0600 Subject: [PATCH] powerpc: dynamic probe - use ppc_md.pci_probe_mode() Change the dynamic PCI probe function for pSeries to use ppc_md.pci_probe_mode() when appropriate. Signed-off-by: John Rose Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/pci_dlpar.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index 44abdeb9ca03..b3c2dcb1e4f0 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c @@ -152,20 +152,24 @@ pcibios_pci_config_bridge(struct pci_dev *dev) void pcibios_add_pci_devices(struct pci_bus * bus) { - int slotno, num; + int slotno, num, mode; struct pci_dev *dev; struct device_node *dn = pci_bus_to_OF_node(bus); eeh_add_device_tree_early(dn); - if (_machine == PLATFORM_PSERIES_LPAR) { + mode = PCI_PROBE_NORMAL; + if (ppc_md.pci_probe_mode) + mode = ppc_md.pci_probe_mode(bus); + + if (mode == PCI_PROBE_DEVTREE) { /* use ofdt-based probe */ of_scan_bus(dn, bus); if (!list_empty(&bus->devices)) { pcibios_fixup_new_pci_devices(bus, 0); pci_bus_add_devices(bus); } - } else { + } else if (mode == PCI_PROBE_NORMAL) { /* use legacy probe */ slotno = PCI_SLOT(PCI_DN(dn->child)->devfn); num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0)); -- cgit v1.2.2 From 2fa68747dad290f4415e2ea8565d57876747b2d3 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 24 Mar 2006 19:46:29 +0100 Subject: [PATCH] powerpc: fix spider-pic affinity setting As noticed by Milton Miller, setting the initial affinity in spider-pic can go wrong if the target node field was not orinally empty. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spider-pic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c index 0e9bb0b72c50..9647a8dad4fe 100644 --- a/arch/powerpc/platforms/cell/spider-pic.c +++ b/arch/powerpc/platforms/cell/spider-pic.c @@ -88,7 +88,7 @@ static void spider_enable_irq(unsigned int irq) void __iomem *cfg = spider_get_irq_config(irq); irq = spider_get_nr(irq); - out_be32(cfg, in_be32(cfg) | 0x3107000eu | nodeid); + out_be32(cfg, (in_be32(cfg) & ~0xf0)| 0x3107000eu | nodeid); out_be32(cfg + 4, in_be32(cfg + 4) | 0x00020000u | irq); } -- cgit v1.2.2 From 47952d5ea67dc7098667a954483a82acf81eb4da Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 24 Mar 2006 19:47:52 +0100 Subject: [PATCH] powerpc: use guarded ioremap for cell on-chip mappings I'm not sure where the information came from, but I assumed that doing cache-inhibited mappings for mmio regions was sufficient. It seems we also need the guarded bit set, like everyone else, which is the default for ioremap. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/interrupt.c | 10 +++------- arch/powerpc/platforms/cell/iommu.c | 12 ++++++------ arch/powerpc/platforms/cell/pervasive.c | 2 +- arch/powerpc/platforms/cell/spider-pic.c | 4 ++-- 4 files changed, 12 insertions(+), 16 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index e3fffdfcc674..ae62f5d5c31b 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -226,9 +226,7 @@ static int setup_iic_hardcoded(void) regs += 0x20; printk(KERN_INFO "IIC for CPU %d at %lx\n", cpu, regs); - iic->regs = __ioremap(regs, sizeof(struct iic_regs), - _PAGE_NO_CACHE); - + iic->regs = ioremap(regs, sizeof(struct iic_regs)); iic->target_id = (nodeid << 4) + ((cpu & 1) ? 0xf : 0xe); } @@ -269,14 +267,12 @@ static int setup_iic(void) } iic = &per_cpu(iic, np[0]); - iic->regs = __ioremap(regs[0], sizeof(struct iic_regs), - _PAGE_NO_CACHE); + iic->regs = ioremap(regs[0], sizeof(struct iic_regs)); iic->target_id = ((np[0] & 2) << 3) + ((np[0] & 1) ? 0xf : 0xe); printk("IIC for CPU %d at %lx mapped to %p\n", np[0], regs[0], iic->regs); iic = &per_cpu(iic, np[1]); - iic->regs = __ioremap(regs[2], sizeof(struct iic_regs), - _PAGE_NO_CACHE); + iic->regs = ioremap(regs[2], sizeof(struct iic_regs)); iic->target_id = ((np[1] & 2) << 3) + ((np[1] & 1) ? 0xf : 0xe); printk("IIC for CPU %d at %lx mapped to %p\n", np[1], regs[2], iic->regs); diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index c8a98be8b6a1..a49ceb799a8e 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c @@ -344,8 +344,8 @@ static int cell_map_iommu_hardcoded(int num_nodes) /* node 0 */ iommu = &cell_iommus[0]; - iommu->mapped_base = __ioremap(0x20000511000, 0x1000, _PAGE_NO_CACHE); - iommu->mapped_mmio_base = __ioremap(0x20000510000, 0x1000, _PAGE_NO_CACHE); + iommu->mapped_base = ioremap(0x20000511000, 0x1000); + iommu->mapped_mmio_base = ioremap(0x20000510000, 0x1000); enable_mapping(iommu->mapped_base, iommu->mapped_mmio_base); @@ -357,8 +357,8 @@ static int cell_map_iommu_hardcoded(int num_nodes) /* node 1 */ iommu = &cell_iommus[1]; - iommu->mapped_base = __ioremap(0x30000511000, 0x1000, _PAGE_NO_CACHE); - iommu->mapped_mmio_base = __ioremap(0x30000510000, 0x1000, _PAGE_NO_CACHE); + iommu->mapped_base = ioremap(0x30000511000, 0x1000); + iommu->mapped_mmio_base = ioremap(0x30000510000, 0x1000); enable_mapping(iommu->mapped_base, iommu->mapped_mmio_base); @@ -407,8 +407,8 @@ static int cell_map_iommu(void) iommu->base = *base; iommu->mmio_base = *mmio_base; - iommu->mapped_base = __ioremap(*base, 0x1000, _PAGE_NO_CACHE); - iommu->mapped_mmio_base = __ioremap(*mmio_base, 0x1000, _PAGE_NO_CACHE); + iommu->mapped_base = ioremap(*base, 0x1000); + iommu->mapped_mmio_base = ioremap(*mmio_base, 0x1000); enable_mapping(iommu->mapped_base, iommu->mapped_mmio_base); diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c index e0e051c675dd..58baeb52f6fc 100644 --- a/arch/powerpc/platforms/cell/pervasive.c +++ b/arch/powerpc/platforms/cell/pervasive.c @@ -203,7 +203,7 @@ found: pr_debug("pervasive area for CPU %d at %lx, size %x\n", cpu, real_address, size); - p->regs = __ioremap(real_address, size, _PAGE_NO_CACHE); + p->regs = ioremap(real_address, size); p->thread = thread; return 0; } diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c index 9647a8dad4fe..55cbdd77a62d 100644 --- a/arch/powerpc/platforms/cell/spider-pic.c +++ b/arch/powerpc/platforms/cell/spider-pic.c @@ -159,7 +159,7 @@ void spider_init_IRQ_hardcoded(void) for (node = 0; node < num_present_cpus()/2; node++) { spiderpic = pics[node]; printk(KERN_DEBUG "SPIDER addr: %lx\n", spiderpic); - spider_pics[node] = __ioremap(spiderpic, 0x800, _PAGE_NO_CACHE); + spider_pics[node] = ioremap(spiderpic, 0x800); for (n = 0; n < IIC_NUM_EXT; n++) { int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE; get_irq_desc(irq)->handler = &spider_pic; @@ -210,7 +210,7 @@ void spider_init_IRQ(void) if ( n != 2) printk("reg property with invalid number of elements \n"); - spider_pics[node] = __ioremap(spider_reg, 0x800, _PAGE_NO_CACHE); + spider_pics[node] = ioremap(spider_reg, 0x800); printk("SPIDER addr: %lx with %i addr_cells mapped to %p\n", spider_reg, n, spider_pics[node]); -- cgit v1.2.2 From 79c227a92ce9fe0504e9c4aaadf3bfacb0f5f45e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 24 Mar 2006 19:49:27 +0100 Subject: [PATCH] spufs: Fix endless protection fault on LS writes by SPE. If an SPE attempts a DMA put to a local store after already doing a get, the kernel must update the HW PTE to allow the write access. This case was not being handled correctly. From: Mike Kistler Signed-off-by: Mike Kistler Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spu_base.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index d152a3fbdb83..269dda4fd0b4 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -486,14 +486,13 @@ int spu_irq_class_1_bottom(struct spu *spu) ea = spu->dar; dsisr = spu->dsisr; - if (dsisr & MFC_DSISR_PTE_NOT_FOUND) { + if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)) { access = (_PAGE_PRESENT | _PAGE_USER); access |= (dsisr & MFC_DSISR_ACCESS_PUT) ? _PAGE_RW : 0UL; if (hash_page(ea, access, 0x300) != 0) error |= CLASS1_ENABLE_STORAGE_FAULT_INTR; } - if ((error & CLASS1_ENABLE_STORAGE_FAULT_INTR) || - (dsisr & MFC_DSISR_ACCESS_DENIED)) { + if (error & CLASS1_ENABLE_STORAGE_FAULT_INTR) { if ((ret = spu_handle_mm_fault(spu)) != 0) error |= CLASS1_ENABLE_STORAGE_FAULT_INTR; else -- cgit v1.2.2 From b4f382a3e5e20ba867e7aa5b01189a3fd40eea2c Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 24 Mar 2006 17:11:29 -0600 Subject: [PATCH] powerpc/pseries: Cleanup device name printing. This avoids printk'ing a NULL string. Signed-off-by: Linas Vepstas Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/eeh_driver.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index b811d5ff92fe..cc2495a0cdd5 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c @@ -257,6 +257,7 @@ void handle_eeh_events (struct eeh_event *event) struct pci_bus *frozen_bus; int rc = 0; enum pci_ers_result result = PCI_ERS_RESULT_NONE; + const char *pci_str, *drv_str; frozen_dn = find_device_pe(event->dn); frozen_bus = pcibios_find_pci_bus(frozen_dn); @@ -291,6 +292,13 @@ void handle_eeh_events (struct eeh_event *event) frozen_pdn = PCI_DN(frozen_dn); frozen_pdn->eeh_freeze_count++; + + pci_str = pci_name (frozen_pdn->pcidev); + drv_str = pcid_name (frozen_pdn->pcidev); + if (!pci_str) { + pci_str = pci_name (event->dev); + drv_str = pcid_name (event->dev); + } if (frozen_pdn->eeh_freeze_count > EEH_MAX_ALLOWED_FREEZES) goto hard_fail; @@ -306,9 +314,7 @@ void handle_eeh_events (struct eeh_event *event) eeh_slot_error_detail(frozen_pdn, 1 /* Temporary Error */); printk(KERN_WARNING "EEH: This PCI device has failed %d times since last reboot: %s - %s\n", - frozen_pdn->eeh_freeze_count, - pci_name (frozen_pdn->pcidev), - pcid_name(frozen_pdn->pcidev)); + frozen_pdn->eeh_freeze_count, drv_str, pci_str); /* Walk the various device drivers attached to this slot through * a reset sequence, giving each an opportunity to do what it needs @@ -360,9 +366,7 @@ hard_fail: "EEH: PCI device %s - %s has failed %d times \n" "and has been permanently disabled. Please try reseating\n" "this device or replacing it.\n", - pci_name (frozen_pdn->pcidev), - pcid_name(frozen_pdn->pcidev), - frozen_pdn->eeh_freeze_count); + drv_str, pci_str, frozen_pdn->eeh_freeze_count); eeh_slot_error_detail(frozen_pdn, 2 /* Permanent Error */); -- cgit v1.2.2 From 4df20460a3ff0d60280738b094945c56cb5567a5 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Sat, 25 Mar 2006 17:25:17 +1100 Subject: [PATCH] powerpc: Allow non zero boot cpuids We currently have a hack to flip the boot cpu and its secondary thread to logical cpuid 0 and 1. This means the logical - physical mapping will differ depending on which cpu is boot cpu. This is most apparent on kexec, where we might kexec on any cpu and therefore change the mapping from boot to boot. The patch below does a first pass early on to work out the logical cpuid of the boot thread. We then fix up some paca structures to match. Ive also removed the boot_cpuid_phys variable for ppc64, to be consistent we use get_hard_smp_processor_id(boot_cpuid) everywhere. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/head_64.S | 26 +++++------ arch/powerpc/kernel/paca.c | 21 ++------- arch/powerpc/kernel/prom.c | 83 +++++++++++++++++++++++------------ arch/powerpc/kernel/setup-common.c | 16 +------ arch/powerpc/kernel/setup_64.c | 12 +++-- arch/powerpc/platforms/pseries/xics.c | 2 +- 6 files changed, 83 insertions(+), 77 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 7e7f7d243304..a5ae04a57c78 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -1851,21 +1851,6 @@ _STATIC(start_here_multiplatform) bl .__save_cpu_setup sync - /* Setup a valid physical PACA pointer in SPRG3 for early_setup - * note that boot_cpuid can always be 0 nowadays since there is - * nowhere it can be initialized differently before we reach this - * code - */ - LOAD_REG_IMMEDIATE(r27, boot_cpuid) - add r27,r27,r26 - lwz r27,0(r27) - - LOAD_REG_IMMEDIATE(r24, paca) /* Get base vaddr of paca array */ - mulli r13,r27,PACA_SIZE /* Calculate vaddr of right paca */ - add r13,r13,r24 /* for this processor. */ - add r13,r13,r26 /* convert to physical addr */ - mtspr SPRN_SPRG3,r13 - /* Do very early kernel initializations, including initial hash table, * stab and slb setup before we turn on relocation. */ @@ -1934,6 +1919,17 @@ _STATIC(start_here_common) /* Not reached */ BUG_OPCODE +/* Put the paca pointer into r13 and SPRG3 */ +_GLOBAL(setup_boot_paca) + LOAD_REG_IMMEDIATE(r3, boot_cpuid) + lwz r3,0(r3) + LOAD_REG_IMMEDIATE(r4, paca) /* Get base vaddr of paca array */ + mulli r3,r3,PACA_SIZE /* Calculate vaddr of right paca */ + add r13,r3,r4 /* for this processor. */ + mtspr SPRN_SPRG3,r13 + + blr + /* * We put a few things here that have to be page-aligned. * This stuff goes at the beginning of the bss, which is page-aligned. diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c index 5d1b708086bd..f505a8827e3e 100644 --- a/arch/powerpc/kernel/paca.c +++ b/arch/powerpc/kernel/paca.c @@ -56,14 +56,11 @@ struct lppaca lppaca[] = { * processors. The processor VPD array needs one entry per physical * processor (not thread). */ -#define PACA_INIT_COMMON(number, start, asrr, asrv) \ +#define PACA_INIT_COMMON(number) \ .lppaca_ptr = &lppaca[number], \ .lock_token = 0x8000, \ .paca_index = (number), /* Paca Index */ \ .kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL, \ - .stab_real = (asrr), /* Real pointer to segment table */ \ - .stab_addr = (asrv), /* Virt pointer to segment table */ \ - .cpu_start = (start), /* Processor start */ \ .hw_cpu_id = 0xffff, #ifdef CONFIG_PPC_ISERIES @@ -72,30 +69,20 @@ struct lppaca lppaca[] = { #define PACA_INIT(number) \ { \ - PACA_INIT_COMMON(number, 0, 0, 0) \ - PACA_INIT_ISERIES(number) \ -} - -#define BOOTCPU_PACA_INIT(number) \ -{ \ - PACA_INIT_COMMON(number, 1, 0, (u64)&initial_stab) \ + PACA_INIT_COMMON(number) \ PACA_INIT_ISERIES(number) \ } #else #define PACA_INIT(number) \ { \ - PACA_INIT_COMMON(number, 0, 0, 0) \ + PACA_INIT_COMMON(number) \ } -#define BOOTCPU_PACA_INIT(number) \ -{ \ - PACA_INIT_COMMON(number, 1, STAB0_PHYS_ADDR, (u64)&initial_stab) \ -} #endif struct paca_struct paca[] = { - BOOTCPU_PACA_INIT(0), + PACA_INIT(0), #if NR_CPUS > 1 PACA_INIT( 1), PACA_INIT( 2), PACA_INIT( 3), #if NR_CPUS > 4 diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index d63cd562d9d5..5a24415a2e3c 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -854,35 +854,70 @@ void __init unflatten_device_tree(void) DBG(" <- unflatten_device_tree()\n"); } - static int __init early_init_dt_scan_cpus(unsigned long node, - const char *uname, int depth, void *data) + const char *uname, int depth, + void *data) { - u32 *prop; - unsigned long size; - char *type = of_get_flat_dt_prop(node, "device_type", &size); + static int logical_cpuid = 0; + char *type = of_get_flat_dt_prop(node, "device_type", NULL); + u32 *prop, *intserv; + int i, nthreads; + unsigned long len; + int found = 0; /* We are scanning "cpu" nodes only */ if (type == NULL || strcmp(type, "cpu") != 0) return 0; - boot_cpuid = 0; - boot_cpuid_phys = 0; - if (initial_boot_params && initial_boot_params->version >= 2) { - /* version 2 of the kexec param format adds the phys cpuid - * of booted proc. - */ - boot_cpuid_phys = initial_boot_params->boot_cpuid_phys; + /* Get physical cpuid */ + intserv = of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", &len); + if (intserv) { + nthreads = len / sizeof(int); } else { - /* Check if it's the boot-cpu, set it's hw index now */ - if (of_get_flat_dt_prop(node, + intserv = of_get_flat_dt_prop(node, "reg", NULL); + nthreads = 1; + } + + /* + * Now see if any of these threads match our boot cpu. + * NOTE: This must match the parsing done in smp_setup_cpu_maps. + */ + for (i = 0; i < nthreads; i++) { + /* + * version 2 of the kexec param format adds the phys cpuid of + * booted proc. + */ + if (initial_boot_params && initial_boot_params->version >= 2) { + if (intserv[i] == + initial_boot_params->boot_cpuid_phys) { + found = 1; + break; + } + } else { + /* + * Check if it's the boot-cpu, set it's hw index now, + * unfortunately this format did not support booting + * off secondary threads. + */ + if (of_get_flat_dt_prop(node, "linux,boot-cpu", NULL) != NULL) { - prop = of_get_flat_dt_prop(node, "reg", NULL); - if (prop != NULL) - boot_cpuid_phys = *prop; + found = 1; + break; + } } + +#ifdef CONFIG_SMP + /* logical cpu id is always 0 on UP kernels */ + logical_cpuid++; +#endif + } + + if (found) { + DBG("boot cpu: logical %d physical %d\n", logical_cpuid, + intserv[i]); + boot_cpuid = logical_cpuid; + set_hard_smp_processor_id(boot_cpuid, intserv[i]); } - set_hard_smp_processor_id(0, boot_cpuid_phys); #ifdef CONFIG_ALTIVEC /* Check if we have a VMX and eventually update CPU features */ @@ -901,16 +936,10 @@ static int __init early_init_dt_scan_cpus(unsigned long node, #endif /* CONFIG_ALTIVEC */ #ifdef CONFIG_PPC_PSERIES - /* - * Check for an SMT capable CPU and set the CPU feature. We do - * this by looking at the size of the ibm,ppc-interrupt-server#s - * property - */ - prop = (u32 *)of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", - &size); - cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT; - if (prop && ((size / sizeof(u32)) > 1)) + if (nthreads > 1) cur_cpu_spec->cpu_features |= CPU_FTR_SMT; + else + cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT; #endif return 0; diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index c1d62bf11f29..b17630ad4ac7 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -352,12 +352,13 @@ void __init check_for_initrd(void) * must be called before using this. * * While we're here, we may as well set the "physical" cpu ids in the paca. + * + * NOTE: This must match the parsing done in early_init_dt_scan_cpus. */ void __init smp_setup_cpu_maps(void) { struct device_node *dn = NULL; int cpu = 0; - int swap_cpuid = 0; while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) { int *intserv; @@ -376,24 +377,11 @@ void __init smp_setup_cpu_maps(void) for (j = 0; j < nthreads && cpu < NR_CPUS; j++) { cpu_set(cpu, cpu_present_map); set_hard_smp_processor_id(cpu, intserv[j]); - - if (intserv[j] == boot_cpuid_phys) - swap_cpuid = cpu; cpu_set(cpu, cpu_possible_map); cpu++; } } - /* Swap CPU id 0 with boot_cpuid_phys, so we can always assume that - * boot cpu is logical 0. - */ - if (boot_cpuid_phys != get_hard_smp_processor_id(0)) { - u32 tmp; - tmp = get_hard_smp_processor_id(0); - set_hard_smp_processor_id(0, boot_cpuid_phys); - set_hard_smp_processor_id(swap_cpuid, tmp); - } - #ifdef CONFIG_PPC64 /* * On pSeries LPAR, we need to know how many cpus diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 2f3fdad35594..6c9b093c23a5 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -73,7 +73,6 @@ int have_of = 1; int boot_cpuid = 0; -int boot_cpuid_phys = 0; dev_t boot_dev; u64 ppc64_pft_size; @@ -208,7 +207,6 @@ static struct machdep_calls __initdata *machines[] = { void __init early_setup(unsigned long dt_ptr) { - struct paca_struct *lpaca = get_paca(); static struct machdep_calls **mach; /* Enable early debugging if any specified (see udbg.h) */ @@ -223,6 +221,14 @@ void __init early_setup(unsigned long dt_ptr) */ early_init_devtree(__va(dt_ptr)); + /* Now we know the logical id of our boot cpu, setup the paca. */ + setup_boot_paca(); + + /* Fix up paca fields required for the boot cpu */ + get_paca()->cpu_start = 1; + get_paca()->stab_real = __pa((u64)&initial_stab); + get_paca()->stab_addr = (u64)&initial_stab; + /* * Iterate all ppc_md structures until we find the proper * one for the current machine type @@ -260,7 +266,7 @@ void __init early_setup(unsigned long dt_ptr) if (cpu_has_feature(CPU_FTR_SLB)) slb_initialize(); else - stab_initialize(lpaca->stab_real); + stab_initialize(get_paca()->stab_real); } DBG(" <- early_setup()\n"); diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index eb86cdb9b802..c60d3ff25a2f 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -500,7 +500,7 @@ nextnode: np; np = of_find_node_by_type(np, "cpu")) { ireg = (uint *)get_property(np, "reg", &ilen); - if (ireg && ireg[0] == boot_cpuid_phys) { + if (ireg && ireg[0] == get_hard_smp_processor_id(boot_cpuid)) { ireg = (uint *)get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen); i = ilen / sizeof(int); -- cgit v1.2.2 From c258dd40ab8851c41873516ef90125e3bcd2e3e1 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Sat, 25 Mar 2006 17:27:09 +1100 Subject: [PATCH] powerpc: Consistent printing of node id We were printing node ids in hex in one spot. Lets be consistent and always print them in decimal. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/mm/mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index badac10d700c..4737f84bb19e 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -342,7 +342,7 @@ void __init mem_init(void) #ifdef CONFIG_NEED_MULTIPLE_NODES for_each_online_node(nid) { if (NODE_DATA(nid)->node_spanned_pages != 0) { - printk("freeing bootmem node %x\n", nid); + printk("freeing bootmem node %d\n", nid); totalram_pages += free_all_bootmem_node(NODE_DATA(nid)); } -- cgit v1.2.2 From 37a801c776109dce801875b12525a9eaa12481e6 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Sun, 26 Mar 2006 10:07:35 +1000 Subject: [PATCH] powerpc: legacy_serial loop cleanup We only ever execute the loop once, so let's move it to a function making it more readable. Cleanup patch, no functional change. Signed-off-by: Michael Neuling Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/legacy_serial.c | 38 ++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c index 09d9c825fa9c..6e67b5b49ba1 100644 --- a/arch/powerpc/kernel/legacy_serial.c +++ b/arch/powerpc/kernel/legacy_serial.c @@ -236,6 +236,23 @@ static int __init add_legacy_pci_port(struct device_node *np, } #endif +static void __init setup_legacy_serial_console(int console) +{ + struct legacy_serial_info *info = + &legacy_serial_infos[console]; + void __iomem *addr; + + if (info->taddr == 0) + return; + addr = ioremap(info->taddr, 0x1000); + if (addr == NULL) + return; + if (info->speed == 0) + info->speed = udbg_probe_uart_speed(addr, info->clock); + DBG("default console speed = %d\n", info->speed); + udbg_init_uart(addr, info->speed, info->clock); +} + /* * This is called very early, as part of setup_system() or eventually * setup_arch(), basically before anything else in this file. This function @@ -318,25 +335,8 @@ void __init find_legacy_serial_ports(void) #endif DBG("legacy_serial_console = %d\n", legacy_serial_console); - - /* udbg is 64 bits only for now, that will change soon though ... */ - while (legacy_serial_console >= 0) { - struct legacy_serial_info *info = - &legacy_serial_infos[legacy_serial_console]; - void __iomem *addr; - - if (info->taddr == 0) - break; - addr = ioremap(info->taddr, 0x1000); - if (addr == NULL) - break; - if (info->speed == 0) - info->speed = udbg_probe_uart_speed(addr, info->clock); - DBG("default console speed = %d\n", info->speed); - udbg_init_uart(addr, info->speed, info->clock); - break; - } - + if (legacy_serial_console >= 0) + setup_legacy_serial_console(legacy_serial_console); DBG(" <- find_legacy_serial_port()\n"); } -- cgit v1.2.2 From a0652fc9a28c3ef8cd59264bfcb089c44d1b0e06 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Mon, 27 Mar 2006 15:03:03 +1100 Subject: powerpc: Unify the 32 and 64 bit idle loops This unifies the 32-bit (ARCH=ppc and ARCH=powerpc) and 64-bit idle loops. It brings over the concept of having a ppc_md.power_save function from 32-bit to ARCH=powerpc, which lets us get rid of native_idle(). With this we will also be able to simplify the idle handling for pSeries and cell. Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/Makefile | 6 +- arch/powerpc/kernel/entry_32.S | 8 ++- arch/powerpc/kernel/idle.c | 122 ++++++++++++++++++++++++++++++++ arch/powerpc/kernel/idle_64.c | 121 ------------------------------- arch/powerpc/kernel/idle_6xx.S | 15 ---- arch/powerpc/kernel/idle_power4.S | 15 ---- arch/powerpc/kernel/setup_32.c | 7 +- arch/powerpc/kernel/setup_64.c | 6 -- arch/powerpc/platforms/maple/setup.c | 2 +- arch/powerpc/platforms/powermac/setup.c | 2 +- 10 files changed, 136 insertions(+), 168 deletions(-) create mode 100644 arch/powerpc/kernel/idle.c delete mode 100644 arch/powerpc/kernel/idle_64.c (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 80e9fe2632b8..f2c47e907037 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -12,12 +12,12 @@ endif obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ irq.o align.o signal_32.o pmc.o vdso.o \ - init_task.o process.o systbl.o + init_task.o process.o systbl.o idle.o obj-y += vdso32/ obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ signal_64.o ptrace32.o \ paca.o cpu_setup_power4.o \ - firmware.o sysfs.o idle_64.o + firmware.o sysfs.o obj-$(CONFIG_PPC64) += vdso64/ obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o obj-$(CONFIG_POWER4) += idle_power4.o @@ -34,6 +34,7 @@ obj-$(CONFIG_IBMEBUS) += ibmebus.o obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o obj-$(CONFIG_CRASH_DUMP) += crash_dump.o +obj-$(CONFIG_6xx) += idle_6xx.o ifeq ($(CONFIG_PPC_MERGE),y) @@ -51,7 +52,6 @@ obj-$(CONFIG_PPC64) += misc_64.o dma_64.o iommu.o obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o obj-$(CONFIG_MODULES) += ppc_ksyms.o obj-$(CONFIG_BOOTX_TEXT) += btext.o -obj-$(CONFIG_6xx) += idle_6xx.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 4827ca1ec89b..b3a979467225 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -135,10 +135,10 @@ transfer_to_handler: mfspr r11,SPRN_HID0 mtcr r11 BEGIN_FTR_SECTION - bt- 8,power_save_6xx_restore /* Check DOZE */ + bt- 8,4f /* Check DOZE */ END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE) BEGIN_FTR_SECTION - bt- 9,power_save_6xx_restore /* Check NAP */ + bt- 9,4f /* Check NAP */ END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP) #endif /* CONFIG_6xx */ .globl transfer_to_handler_cont @@ -157,6 +157,10 @@ transfer_to_handler_cont: SYNC RFI /* jump to handler, enable MMU */ +#ifdef CONFIG_6xx +4: b power_save_6xx_restore +#endif + /* * On kernel stack overflow, load up an initial stack pointer * and call StackOverflow(regs), which should not return. diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c new file mode 100644 index 000000000000..e9f321d74d85 --- /dev/null +++ b/arch/powerpc/kernel/idle.c @@ -0,0 +1,122 @@ +/* + * Idle daemon for PowerPC. Idle daemon will handle any action + * that needs to be taken when the system becomes idle. + * + * Originally written by Cort Dougan (cort@cs.nmt.edu). + * Subsequent 32-bit hacking by Tom Rini, Armin Kuster, + * Paul Mackerras and others. + * + * iSeries supported added by Mike Corrigan + * + * Additional shared processor, SMT, and firmware support + * Copyright (c) 2003 Dave Engebretsen + * + * 32-bit and 64-bit versions merged by Paul Mackerras + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_HOTPLUG_CPU +#define cpu_should_die() (cpu_is_offline(smp_processor_id()) && \ + system_state == SYSTEM_RUNNING) +#else +#define cpu_should_die() 0 +#endif + +/* + * The body of the idle task. + */ +void cpu_idle(void) +{ + if (ppc_md.idle_loop) + ppc_md.idle_loop(); /* doesn't return */ + + set_thread_flag(TIF_POLLING_NRFLAG); + while (1) { + ppc64_runlatch_off(); + + while (!need_resched() && !cpu_should_die()) { + if (ppc_md.power_save) { + clear_thread_flag(TIF_POLLING_NRFLAG); + /* + * smp_mb is so clearing of TIF_POLLING_NRFLAG + * is ordered w.r.t. need_resched() test. + */ + smp_mb(); + local_irq_disable(); + + /* check again after disabling irqs */ + if (!need_resched() && !cpu_should_die()) + ppc_md.power_save(); + + local_irq_enable(); + set_thread_flag(TIF_POLLING_NRFLAG); + + } else { + /* + * Go into low thread priority and possibly + * low power mode. + */ + HMT_low(); + HMT_very_low(); + } + } + + HMT_medium(); + ppc64_runlatch_on(); + if (cpu_should_die()) + cpu_die(); + preempt_enable_no_resched(); + schedule(); + preempt_disable(); + } +} + +int powersave_nap; + +#ifdef CONFIG_SYSCTL +/* + * Register the sysctl to set/clear powersave_nap. + */ +static ctl_table powersave_nap_ctl_table[]={ + { + .ctl_name = KERN_PPC_POWERSAVE_NAP, + .procname = "powersave-nap", + .data = &powersave_nap, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { 0, }, +}; +static ctl_table powersave_nap_sysctl_root[] = { + { 1, "kernel", NULL, 0, 0755, powersave_nap_ctl_table, }, + { 0,}, +}; + +static int __init +register_powersave_nap_sysctl(void) +{ + register_sysctl_table(powersave_nap_sysctl_root, 0); + + return 0; +} +__initcall(register_powersave_nap_sysctl); +#endif diff --git a/arch/powerpc/kernel/idle_64.c b/arch/powerpc/kernel/idle_64.c deleted file mode 100644 index b879d3057ef8..000000000000 --- a/arch/powerpc/kernel/idle_64.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Idle daemon for PowerPC. Idle daemon will handle any action - * that needs to be taken when the system becomes idle. - * - * Originally Written by Cort Dougan (cort@cs.nmt.edu) - * - * iSeries supported added by Mike Corrigan - * - * Additional shared processor, SMT, and firmware support - * Copyright (c) 2003 Dave Engebretsen - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -extern void power4_idle(void); - -void default_idle(void) -{ - unsigned int cpu = smp_processor_id(); - set_thread_flag(TIF_POLLING_NRFLAG); - - while (1) { - if (!need_resched()) { - while (!need_resched() && !cpu_is_offline(cpu)) { - ppc64_runlatch_off(); - - /* - * Go into low thread priority and possibly - * low power mode. - */ - HMT_low(); - HMT_very_low(); - } - - HMT_medium(); - } - - ppc64_runlatch_on(); - preempt_enable_no_resched(); - schedule(); - preempt_disable(); - if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING) - cpu_die(); - } -} - -void native_idle(void) -{ - while (1) { - ppc64_runlatch_off(); - - if (!need_resched()) - power4_idle(); - - if (need_resched()) { - ppc64_runlatch_on(); - preempt_enable_no_resched(); - schedule(); - preempt_disable(); - } - - if (cpu_is_offline(smp_processor_id()) && - system_state == SYSTEM_RUNNING) - cpu_die(); - } -} - -void cpu_idle(void) -{ - BUG_ON(NULL == ppc_md.idle_loop); - ppc_md.idle_loop(); -} - -int powersave_nap; - -#ifdef CONFIG_SYSCTL -/* - * Register the sysctl to set/clear powersave_nap. - */ -static ctl_table powersave_nap_ctl_table[]={ - { - .ctl_name = KERN_PPC_POWERSAVE_NAP, - .procname = "powersave-nap", - .data = &powersave_nap, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec, - }, - { 0, }, -}; -static ctl_table powersave_nap_sysctl_root[] = { - { 1, "kernel", NULL, 0, 0755, powersave_nap_ctl_table, }, - { 0,}, -}; - -static int __init -register_powersave_nap_sysctl(void) -{ - register_sysctl_table(powersave_nap_sysctl_root, 0); - - return 0; -} -__initcall(register_powersave_nap_sysctl); -#endif diff --git a/arch/powerpc/kernel/idle_6xx.S b/arch/powerpc/kernel/idle_6xx.S index 444fdcc769f1..1647ea361ef7 100644 --- a/arch/powerpc/kernel/idle_6xx.S +++ b/arch/powerpc/kernel/idle_6xx.S @@ -87,19 +87,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP) cmpwi 0,r3,0 beqlr - /* Clear MSR:EE */ - mfmsr r7 - rlwinm r0,r7,0,17,15 - mtmsr r0 - - /* Check current_thread_info()->flags */ - rlwinm r4,r1,0,0,18 - lwz r4,TI_FLAGS(r4) - andi. r0,r4,_TIF_NEED_RESCHED - beq 1f - mtmsr r7 /* out of line this ? */ - blr -1: /* Some pre-nap cleanups needed on some CPUs */ andis. r0,r3,HID0_NAP@h beq 2f @@ -220,8 +207,6 @@ _GLOBAL(nap_save_msscr0) _GLOBAL(nap_save_hid1) .space 4*NR_CPUS -_GLOBAL(powersave_nap) - .long 0 _GLOBAL(powersave_lowspeed) .long 0 diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S index c16b4afab582..692cf2ebe0f4 100644 --- a/arch/powerpc/kernel/idle_power4.S +++ b/arch/powerpc/kernel/idle_power4.S @@ -49,21 +49,6 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP) cmpwi 0,r4,0 beqlr - /* Clear MSR:EE */ - mfmsr r7 - li r4,0 - ori r4,r4,MSR_EE - andc r0,r7,r4 - mtmsrd r0 - - /* Check current_thread_info()->flags */ - clrrdi r4,r1,THREAD_SHIFT - ld r4,TI_FLAGS(r4) - andi. r0,r4,_TIF_NEED_RESCHED - beq 1f - mtmsrd r7 /* out of line this ? */ - blr -1: /* Go to NAP now */ BEGIN_FTR_SECTION DSSALL diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 676f894c3380..e39f830317a8 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -53,9 +53,6 @@ extern void platform_init(void); extern void bootx_init(unsigned long r4, unsigned long phys); -extern void ppc6xx_idle(void); -extern void power4_idle(void); - boot_infos_t *boot_infos; struct ide_machdep_calls ppc_ide_md; @@ -194,7 +191,9 @@ void __init machine_init(unsigned long dt_ptr, unsigned long phys) platform_init(); #ifdef CONFIG_6xx - ppc_md.power_save = ppc6xx_idle; + if (cpu_has_feature(CPU_FTR_CAN_DOZE) || + cpu_has_feature(CPU_FTR_CAN_NAP)) + ppc_md.power_save = ppc6xx_idle; #endif if (ppc_md.progress) diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 6c9b093c23a5..5b63a861ef43 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -607,12 +607,6 @@ void __init setup_arch(char **cmdline_p) ppc_md.setup_arch(); - /* Use the default idle loop if the platform hasn't provided one. */ - if (NULL == ppc_md.idle_loop) { - ppc_md.idle_loop = default_idle; - printk(KERN_INFO "Using default idle loop\n"); - } - paging_init(); ppc64_boot_msg(0x15, "Setup Done"); } diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index ec5c1e10c407..137d6063182b 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c @@ -290,7 +290,7 @@ struct machdep_calls __initdata maple_md = { .get_rtc_time = maple_get_rtc_time, .calibrate_decr = generic_calibrate_decr, .progress = maple_progress, - .idle_loop = native_idle, + .power_save = power4_idle, #ifdef CONFIG_KEXEC .machine_kexec = default_machine_kexec, .machine_kexec_prepare = default_machine_kexec_prepare, diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 385aab90c4d2..c2696d00672a 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -733,7 +733,7 @@ struct machdep_calls __initdata pmac_md = { .progress = udbg_progress, #ifdef CONFIG_PPC64 .pci_probe_mode = pmac_pci_probe_mode, - .idle_loop = native_idle, + .power_save = power4_idle, .enable_pmcs = power4_enable_pmcs, #ifdef CONFIG_KEXEC .machine_kexec = default_machine_kexec, -- cgit v1.2.2 From fbd7740fdfdf9475f92287a84085a1913541cd5d Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Mon, 27 Mar 2006 15:06:20 +1100 Subject: powerpc: Simplify pSeries idle loop Since pSeries only wants to do something different in the idle loop when there is no work to do, we can simplify the code by implementing ppc_md.power_save functions instead of complete idle loops. There are two versions: one for shared-processor partitions and one for dedicated- processor partitions. With this we also do a cede_processor() call on dedicated processor partitions if the poll_pending() call indicates that the hypervisor has work it wants to do. Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/setup.c | 190 ++++++++++++--------------------- 1 file changed, 70 insertions(+), 120 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 44d5c7fdcd97..213bf983242f 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -81,8 +81,8 @@ extern void find_udbg_vterm(void); int fwnmi_active; /* TRUE if an FWNMI handler is present */ -static void pseries_shared_idle(void); -static void pseries_dedicated_idle(void); +static void pseries_shared_idle_sleep(void); +static void pseries_dedicated_idle_sleep(void); struct mpic *pSeries_mpic; @@ -236,14 +236,13 @@ static void __init pSeries_setup_arch(void) vpa_init(boot_cpuid); if (get_lppaca()->shared_proc) { printk(KERN_INFO "Using shared processor idle loop\n"); - ppc_md.idle_loop = pseries_shared_idle; + ppc_md.power_save = pseries_shared_idle_sleep; } else { printk(KERN_INFO "Using dedicated idle loop\n"); - ppc_md.idle_loop = pseries_dedicated_idle; + ppc_md.power_save = pseries_dedicated_idle_sleep; } } else { printk(KERN_INFO "Using default idle loop\n"); - ppc_md.idle_loop = default_idle; } if (firmware_has_feature(FW_FEATURE_LPAR)) @@ -393,136 +392,87 @@ static int __init pSeries_probe(int platform) DECLARE_PER_CPU(unsigned long, smt_snooze_delay); -static inline void dedicated_idle_sleep(unsigned int cpu) -{ - struct lppaca *plppaca = &lppaca[cpu ^ 1]; - - /* Only sleep if the other thread is not idle */ - if (!(plppaca->idle)) { - local_irq_disable(); - - /* - * We are about to sleep the thread and so wont be polling any - * more. - */ - clear_thread_flag(TIF_POLLING_NRFLAG); - smp_mb__after_clear_bit(); - - /* - * SMT dynamic mode. Cede will result in this thread going - * dormant, if the partner thread is still doing work. Thread - * wakes up if partner goes idle, an interrupt is presented, or - * a prod occurs. Returning from the cede enables external - * interrupts. - */ - if (!need_resched()) - cede_processor(); - else - local_irq_enable(); - set_thread_flag(TIF_POLLING_NRFLAG); - } else { - /* - * Give the HV an opportunity at the processor, since we are - * not doing any work. - */ - poll_pending(); - } -} - -static void pseries_dedicated_idle(void) +static void pseries_dedicated_idle_sleep(void) { unsigned int cpu = smp_processor_id(); unsigned long start_snooze; unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay); - set_thread_flag(TIF_POLLING_NRFLAG); - - while (1) { - /* - * Indicate to the HV that we are idle. Now would be - * a good time to find other work to dispatch. - */ - get_lppaca()->idle = 1; - - if (!need_resched()) { - start_snooze = get_tb() + - *smt_snooze_delay * tb_ticks_per_usec; - - while (!need_resched() && !cpu_is_offline(cpu)) { - ppc64_runlatch_off(); - - /* - * Go into low thread priority and possibly - * low power mode. - */ - HMT_low(); - HMT_very_low(); - - if (*smt_snooze_delay != 0 && - get_tb() > start_snooze) { - HMT_medium(); - dedicated_idle_sleep(cpu); - } - - } - - HMT_medium(); - } - get_lppaca()->idle = 0; - ppc64_runlatch_on(); + /* + * Indicate to the HV that we are idle. Now would be + * a good time to find other work to dispatch. + */ + get_lppaca()->idle = 1; - preempt_enable_no_resched(); - schedule(); - preempt_disable(); + /* + * We come in with interrupts disabled, and need_resched() + * has been checked recently. If we should poll for a little + * while, do so. + */ + if (*smt_snooze_delay) { + start_snooze = get_tb() + + *smt_snooze_delay * tb_ticks_per_usec; + local_irq_enable(); + set_thread_flag(TIF_POLLING_NRFLAG); - if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING) - cpu_die(); + while (get_tb() < start_snooze) { + if (need_resched() || cpu_is_offline(cpu)) + goto out; + ppc64_runlatch_off(); + HMT_low(); + HMT_very_low(); + } + + HMT_medium(); + clear_thread_flag(TIF_POLLING_NRFLAG); + smp_mb(); + local_irq_disable(); + if (need_resched() || cpu_is_offline(cpu)) + goto out; } + + /* + * Cede if the other thread is not idle, so that it can + * go single-threaded. If the other thread is idle, + * we ask the hypervisor if it has pending work it + * wants to do and cede if it does. Otherwise we keep + * polling in order to reduce interrupt latency. + * + * Doing the cede when the other thread is active will + * result in this thread going dormant, meaning the other + * thread gets to run in single-threaded (ST) mode, which + * is slightly faster than SMT mode with this thread at + * very low priority. The cede enables interrupts, which + * doesn't matter here. + */ + if (!lppaca[cpu ^ 1].idle || poll_pending() == H_Pending) + cede_processor(); + +out: + HMT_medium(); + get_lppaca()->idle = 0; } -static void pseries_shared_idle(void) +static void pseries_shared_idle_sleep(void) { unsigned int cpu = smp_processor_id(); - while (1) { - /* - * Indicate to the HV that we are idle. Now would be - * a good time to find other work to dispatch. - */ - get_lppaca()->idle = 1; - - while (!need_resched() && !cpu_is_offline(cpu)) { - local_irq_disable(); - ppc64_runlatch_off(); - - /* - * Yield the processor to the hypervisor. We return if - * an external interrupt occurs (which are driven prior - * to returning here) or if a prod occurs from another - * processor. When returning here, external interrupts - * are enabled. - * - * Check need_resched() again with interrupts disabled - * to avoid a race. - */ - if (!need_resched()) - cede_processor(); - else - local_irq_enable(); - - HMT_medium(); - } - - get_lppaca()->idle = 0; - ppc64_runlatch_on(); + /* + * Indicate to the HV that we are idle. Now would be + * a good time to find other work to dispatch. + */ + get_lppaca()->idle = 1; - preempt_enable_no_resched(); - schedule(); - preempt_disable(); + /* + * Yield the processor to the hypervisor. We return if + * an external interrupt occurs (which are driven prior + * to returning here) or if a prod occurs from another + * processor. When returning here, external interrupts + * are enabled. + */ + cede_processor(); - if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING) - cpu_die(); - } + get_lppaca()->idle = 0; } static int pSeries_pci_probe_mode(struct pci_bus *bus) -- cgit v1.2.2 From 0eb4cb9b16aba6d610a0716503b96d299b308d44 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Mon, 27 Mar 2006 15:22:28 +1100 Subject: powerpc: Move l2cr.S over to arch/powerpc No functional changes, but call it l2cr_6xx.S since it is specific to 6xx-family (including G3/750 and G4/74xx) processors. Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/Makefile | 2 +- arch/powerpc/kernel/l2cr_6xx.S | 471 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 472 insertions(+), 1 deletion(-) create mode 100644 arch/powerpc/kernel/l2cr_6xx.S (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index f2c47e907037..e7fddf1e42c7 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -34,7 +34,7 @@ obj-$(CONFIG_IBMEBUS) += ibmebus.o obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o obj-$(CONFIG_CRASH_DUMP) += crash_dump.o -obj-$(CONFIG_6xx) += idle_6xx.o +obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o ifeq ($(CONFIG_PPC_MERGE),y) diff --git a/arch/powerpc/kernel/l2cr_6xx.S b/arch/powerpc/kernel/l2cr_6xx.S new file mode 100644 index 000000000000..d7f4e982b539 --- /dev/null +++ b/arch/powerpc/kernel/l2cr_6xx.S @@ -0,0 +1,471 @@ +/* + L2CR functions + Copyright © 1997-1998 by PowerLogix R & D, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +/* + Thur, Dec. 12, 1998. + - First public release, contributed by PowerLogix. + *********** + Sat, Aug. 7, 1999. + - Terry: Made sure code disabled interrupts before running. (Previously + it was assumed interrupts were already disabled). + - Terry: Updated for tentative G4 support. 4MB of memory is now flushed + instead of 2MB. (Prob. only 3 is necessary). + - Terry: Updated for workaround to HID0[DPM] processor bug + during global invalidates. + *********** + Thu, July 13, 2000. + - Terry: Added isync to correct for an errata. + + 22 August 2001. + - DanM: Finally added the 7450 patch I've had for the past + several months. The L2CR is similar, but I'm going + to assume the user of this functions knows what they + are doing. + + Author: Terry Greeniaus (tgree@phys.ualberta.ca) + Please e-mail updates to this file to me, thanks! +*/ +#include +#include +#include +#include +#include +#include + +/* Usage: + + When setting the L2CR register, you must do a few special + things. If you are enabling the cache, you must perform a + global invalidate. If you are disabling the cache, you must + flush the cache contents first. This routine takes care of + doing these things. When first enabling the cache, make sure + you pass in the L2CR you want, as well as passing in the + global invalidate bit set. A global invalidate will only be + performed if the L2I bit is set in applyThis. When enabling + the cache, you should also set the L2E bit in applyThis. If + you want to modify the L2CR contents after the cache has been + enabled, the recommended procedure is to first call + __setL2CR(0) to disable the cache and then call it again with + the new values for L2CR. Examples: + + _setL2CR(0) - disables the cache + _setL2CR(0xB3A04000) - enables my G3 upgrade card: + - L2E set to turn on the cache + - L2SIZ set to 1MB + - L2CLK set to 1:1 + - L2RAM set to pipelined synchronous late-write + - L2I set to perform a global invalidation + - L2OH set to 0.5 nS + - L2DF set because this upgrade card + requires it + + A similar call should work for your card. You need to know + the correct setting for your card and then place them in the + fields I have outlined above. Other fields support optional + features, such as L2DO which caches only data, or L2TS which + causes cache pushes from the L1 cache to go to the L2 cache + instead of to main memory. + +IMPORTANT: + Starting with the 7450, the bits in this register have moved + or behave differently. The Enable, Parity Enable, Size, + and L2 Invalidate are the only bits that have not moved. + The size is read-only for these processors with internal L2 + cache, and the invalidate is a control as well as status. + -- Dan + +*/ +/* + * Summary: this procedure ignores the L2I bit in the value passed in, + * flushes the cache if it was already enabled, always invalidates the + * cache, then enables the cache if the L2E bit is set in the value + * passed in. + * -- paulus. + */ +_GLOBAL(_set_L2CR) + /* Make sure this is a 750 or 7400 chip */ +BEGIN_FTR_SECTION + li r3,-1 + blr +END_FTR_SECTION_IFCLR(CPU_FTR_L2CR) + + mflr r9 + + /* Stop DST streams */ +BEGIN_FTR_SECTION + DSSALL + sync +END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) + + /* Turn off interrupts and data relocation. */ + mfmsr r7 /* Save MSR in r7 */ + rlwinm r4,r7,0,17,15 + rlwinm r4,r4,0,28,26 /* Turn off DR bit */ + sync + mtmsr r4 + isync + + /* Before we perform the global invalidation, we must disable dynamic + * power management via HID0[DPM] to work around a processor bug where + * DPM can possibly interfere with the state machine in the processor + * that invalidates the L2 cache tags. + */ + mfspr r8,SPRN_HID0 /* Save HID0 in r8 */ + rlwinm r4,r8,0,12,10 /* Turn off HID0[DPM] */ + sync + mtspr SPRN_HID0,r4 /* Disable DPM */ + sync + + /* Get the current enable bit of the L2CR into r4 */ + mfspr r4,SPRN_L2CR + + /* Tweak some bits */ + rlwinm r5,r3,0,0,0 /* r5 contains the new enable bit */ + rlwinm r3,r3,0,11,9 /* Turn off the invalidate bit */ + rlwinm r3,r3,0,1,31 /* Turn off the enable bit */ + + /* Check to see if we need to flush */ + rlwinm. r4,r4,0,0,0 + beq 2f + + /* Flush the cache. First, read the first 4MB of memory (physical) to + * put new data in the cache. (Actually we only need + * the size of the L2 cache plus the size of the L1 cache, but 4MB will + * cover everything just to be safe). + */ + + /**** Might be a good idea to set L2DO here - to prevent instructions + from getting into the cache. But since we invalidate + the next time we enable the cache it doesn't really matter. + Don't do this unless you accomodate all processor variations. + The bit moved on the 7450..... + ****/ + +BEGIN_FTR_SECTION + /* Disable L2 prefetch on some 745x and try to ensure + * L2 prefetch engines are idle. As explained by errata + * text, we can't be sure they are, we just hope very hard + * that well be enough (sic !). At least I noticed Apple + * doesn't even bother doing the dcbf's here... + */ + mfspr r4,SPRN_MSSCR0 + rlwinm r4,r4,0,0,29 + sync + mtspr SPRN_MSSCR0,r4 + sync + isync + lis r4,KERNELBASE@h + dcbf 0,r4 + dcbf 0,r4 + dcbf 0,r4 + dcbf 0,r4 +END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450) + + /* TODO: use HW flush assist when available */ + + lis r4,0x0002 + mtctr r4 + li r4,0 +1: + lwzx r0,r0,r4 + addi r4,r4,32 /* Go to start of next cache line */ + bdnz 1b + isync + + /* Now, flush the first 4MB of memory */ + lis r4,0x0002 + mtctr r4 + li r4,0 + sync +1: + dcbf 0,r4 + addi r4,r4,32 /* Go to start of next cache line */ + bdnz 1b + +2: + /* Set up the L2CR configuration bits (and switch L2 off) */ + /* CPU errata: Make sure the mtspr below is already in the + * L1 icache + */ + b 20f + .balign L1_CACHE_BYTES +22: + sync + mtspr SPRN_L2CR,r3 + sync + b 23f +20: + b 21f +21: sync + isync + b 22b + +23: + /* Perform a global invalidation */ + oris r3,r3,0x0020 + sync + mtspr SPRN_L2CR,r3 + sync + isync /* For errata */ + +BEGIN_FTR_SECTION + /* On the 7450, we wait for the L2I bit to clear...... + */ +10: mfspr r3,SPRN_L2CR + andis. r4,r3,0x0020 + bne 10b + b 11f +END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450) + + /* Wait for the invalidation to complete */ +3: mfspr r3,SPRN_L2CR + rlwinm. r4,r3,0,31,31 + bne 3b + +11: rlwinm r3,r3,0,11,9 /* Turn off the L2I bit */ + sync + mtspr SPRN_L2CR,r3 + sync + + /* See if we need to enable the cache */ + cmplwi r5,0 + beq 4f + + /* Enable the cache */ + oris r3,r3,0x8000 + mtspr SPRN_L2CR,r3 + sync + + /* Enable L2 HW prefetch on 744x/745x */ +BEGIN_FTR_SECTION + mfspr r3,SPRN_MSSCR0 + ori r3,r3,3 + sync + mtspr SPRN_MSSCR0,r3 + sync + isync +END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450) +4: + + /* Restore HID0[DPM] to whatever it was before */ + sync + mtspr 1008,r8 + sync + + /* Restore MSR (restores EE and DR bits to original state) */ + SYNC + mtmsr r7 + isync + + mtlr r9 + blr + +_GLOBAL(_get_L2CR) + /* Return the L2CR contents */ + li r3,0 +BEGIN_FTR_SECTION + mfspr r3,SPRN_L2CR +END_FTR_SECTION_IFSET(CPU_FTR_L2CR) + blr + + +/* + * Here is a similar routine for dealing with the L3 cache + * on the 745x family of chips + */ + +_GLOBAL(_set_L3CR) + /* Make sure this is a 745x chip */ +BEGIN_FTR_SECTION + li r3,-1 + blr +END_FTR_SECTION_IFCLR(CPU_FTR_L3CR) + + /* Turn off interrupts and data relocation. */ + mfmsr r7 /* Save MSR in r7 */ + rlwinm r4,r7,0,17,15 + rlwinm r4,r4,0,28,26 /* Turn off DR bit */ + sync + mtmsr r4 + isync + + /* Stop DST streams */ + DSSALL + sync + + /* Get the current enable bit of the L3CR into r4 */ + mfspr r4,SPRN_L3CR + + /* Tweak some bits */ + rlwinm r5,r3,0,0,0 /* r5 contains the new enable bit */ + rlwinm r3,r3,0,22,20 /* Turn off the invalidate bit */ + rlwinm r3,r3,0,2,31 /* Turn off the enable & PE bits */ + rlwinm r3,r3,0,5,3 /* Turn off the clken bit */ + /* Check to see if we need to flush */ + rlwinm. r4,r4,0,0,0 + beq 2f + + /* Flush the cache. + */ + + /* TODO: use HW flush assist */ + + lis r4,0x0008 + mtctr r4 + li r4,0 +1: + lwzx r0,r0,r4 + dcbf 0,r4 + addi r4,r4,32 /* Go to start of next cache line */ + bdnz 1b + +2: + /* Set up the L3CR configuration bits (and switch L3 off) */ + sync + mtspr SPRN_L3CR,r3 + sync + + oris r3,r3,L3CR_L3RES@h /* Set reserved bit 5 */ + mtspr SPRN_L3CR,r3 + sync + oris r3,r3,L3CR_L3CLKEN@h /* Set clken */ + mtspr SPRN_L3CR,r3 + sync + + /* Wait for stabilize */ + li r0,256 + mtctr r0 +1: bdnz 1b + + /* Perform a global invalidation */ + ori r3,r3,0x0400 + sync + mtspr SPRN_L3CR,r3 + sync + isync + + /* We wait for the L3I bit to clear...... */ +10: mfspr r3,SPRN_L3CR + andi. r4,r3,0x0400 + bne 10b + + /* Clear CLKEN */ + rlwinm r3,r3,0,5,3 /* Turn off the clken bit */ + mtspr SPRN_L3CR,r3 + sync + + /* Wait for stabilize */ + li r0,256 + mtctr r0 +1: bdnz 1b + + /* See if we need to enable the cache */ + cmplwi r5,0 + beq 4f + + /* Enable the cache */ + oris r3,r3,(L3CR_L3E | L3CR_L3CLKEN)@h + mtspr SPRN_L3CR,r3 + sync + + /* Wait for stabilize */ + li r0,256 + mtctr r0 +1: bdnz 1b + + /* Restore MSR (restores EE and DR bits to original state) */ +4: SYNC + mtmsr r7 + isync + blr + +_GLOBAL(_get_L3CR) + /* Return the L3CR contents */ + li r3,0 +BEGIN_FTR_SECTION + mfspr r3,SPRN_L3CR +END_FTR_SECTION_IFSET(CPU_FTR_L3CR) + blr + +/* --- End of PowerLogix code --- + */ + + +/* flush_disable_L1() - Flush and disable L1 cache + * + * clobbers r0, r3, ctr, cr0 + * Must be called with interrupts disabled and MMU enabled. + */ +_GLOBAL(__flush_disable_L1) + /* Stop pending alitvec streams and memory accesses */ +BEGIN_FTR_SECTION + DSSALL +END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) + sync + + /* Load counter to 0x4000 cache lines (512k) and + * load cache with datas + */ + li r3,0x4000 /* 512kB / 32B */ + mtctr r3 + lis r3,KERNELBASE@h +1: + lwz r0,0(r3) + addi r3,r3,0x0020 /* Go to start of next cache line */ + bdnz 1b + isync + sync + + /* Now flush those cache lines */ + li r3,0x4000 /* 512kB / 32B */ + mtctr r3 + lis r3,KERNELBASE@h +1: + dcbf 0,r3 + addi r3,r3,0x0020 /* Go to start of next cache line */ + bdnz 1b + sync + + /* We can now disable the L1 cache (HID0:DCE, HID0:ICE) */ + mfspr r3,SPRN_HID0 + rlwinm r3,r3,0,18,15 + mtspr SPRN_HID0,r3 + sync + isync + blr + +/* inval_enable_L1 - Invalidate and enable L1 cache + * + * Assumes L1 is already disabled and MSR:EE is off + * + * clobbers r3 + */ +_GLOBAL(__inval_enable_L1) + /* Enable and then Flash inval the instruction & data cache */ + mfspr r3,SPRN_HID0 + ori r3,r3, HID0_ICE|HID0_ICFI|HID0_DCE|HID0_DCI + sync + isync + mtspr SPRN_HID0,r3 + xori r3,r3, HID0_ICFI|HID0_DCI + mtspr SPRN_HID0,r3 + sync + + blr + + -- cgit v1.2.2 From 9b781727fd1062671afa144b93e8c69b14bcac4d Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Mon, 27 Mar 2006 19:15:26 +1100 Subject: powerpc: Move cpu_setup_6xx.S and temp.c over to arch/powerpc Also renamed temp.c to tau_6xx.c (for thermal assist unit) and updated the Kconfig option description and help text for CONFIG_TAU. Signed-off-by: Paul Mackerras --- arch/powerpc/Kconfig | 4 +- arch/powerpc/kernel/Makefile | 3 +- arch/powerpc/kernel/cpu_setup_6xx.S | 474 ++++++++++++++++++++++++++++++++++++ arch/powerpc/kernel/tau_6xx.c | 271 +++++++++++++++++++++ 4 files changed, 749 insertions(+), 3 deletions(-) create mode 100644 arch/powerpc/kernel/cpu_setup_6xx.S create mode 100644 arch/powerpc/kernel/tau_6xx.c (limited to 'arch/powerpc') diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index a433b7126d33..2cdc35ce8045 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -491,7 +491,7 @@ config PPC601_SYNC_FIX If in doubt, say Y here. config TAU - bool "Thermal Management Support" + bool "On-chip CPU temperature sensor support" depends on 6xx help G3 and G4 processors have an on-chip temperature sensor called the @@ -500,7 +500,7 @@ config TAU on-die temperature in /proc/cpuinfo if the cpu supports it. Unfortunately, on some chip revisions, this sensor is very inaccurate - and in some cases, does not work at all, so don't assume the cpu + and in many cases, does not work at all, so don't assume the cpu temp is actually what /proc/cpuinfo says it is. config TAU_INT diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index e7fddf1e42c7..754c227835bb 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -34,7 +34,8 @@ obj-$(CONFIG_IBMEBUS) += ibmebus.o obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o obj-$(CONFIG_CRASH_DUMP) += crash_dump.o -obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o +obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o +obj-$(CONFIG_TAU) += tau_6xx.o ifeq ($(CONFIG_PPC_MERGE),y) diff --git a/arch/powerpc/kernel/cpu_setup_6xx.S b/arch/powerpc/kernel/cpu_setup_6xx.S new file mode 100644 index 000000000000..55ed7716636f --- /dev/null +++ b/arch/powerpc/kernel/cpu_setup_6xx.S @@ -0,0 +1,474 @@ +/* + * This file contains low level CPU setup functions. + * Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +_GLOBAL(__setup_cpu_603) + b setup_common_caches +_GLOBAL(__setup_cpu_604) + mflr r4 + bl setup_common_caches + bl setup_604_hid0 + mtlr r4 + blr +_GLOBAL(__setup_cpu_750) + mflr r4 + bl __init_fpu_registers + bl setup_common_caches + bl setup_750_7400_hid0 + mtlr r4 + blr +_GLOBAL(__setup_cpu_750cx) + mflr r4 + bl __init_fpu_registers + bl setup_common_caches + bl setup_750_7400_hid0 + bl setup_750cx + mtlr r4 + blr +_GLOBAL(__setup_cpu_750fx) + mflr r4 + bl __init_fpu_registers + bl setup_common_caches + bl setup_750_7400_hid0 + bl setup_750fx + mtlr r4 + blr +_GLOBAL(__setup_cpu_7400) + mflr r4 + bl __init_fpu_registers + bl setup_7400_workarounds + bl setup_common_caches + bl setup_750_7400_hid0 + mtlr r4 + blr +_GLOBAL(__setup_cpu_7410) + mflr r4 + bl __init_fpu_registers + bl setup_7410_workarounds + bl setup_common_caches + bl setup_750_7400_hid0 + li r3,0 + mtspr SPRN_L2CR2,r3 + mtlr r4 + blr +_GLOBAL(__setup_cpu_745x) + mflr r4 + bl setup_common_caches + bl setup_745x_specifics + mtlr r4 + blr + +/* Enable caches for 603's, 604, 750 & 7400 */ +setup_common_caches: + mfspr r11,SPRN_HID0 + andi. r0,r11,HID0_DCE + ori r11,r11,HID0_ICE|HID0_DCE + ori r8,r11,HID0_ICFI + bne 1f /* don't invalidate the D-cache */ + ori r8,r8,HID0_DCI /* unless it wasn't enabled */ +1: sync + mtspr SPRN_HID0,r8 /* enable and invalidate caches */ + sync + mtspr SPRN_HID0,r11 /* enable caches */ + sync + isync + blr + +/* 604, 604e, 604ev, ... + * Enable superscalar execution & branch history table + */ +setup_604_hid0: + mfspr r11,SPRN_HID0 + ori r11,r11,HID0_SIED|HID0_BHTE + ori r8,r11,HID0_BTCD + sync + mtspr SPRN_HID0,r8 /* flush branch target address cache */ + sync /* on 604e/604r */ + mtspr SPRN_HID0,r11 + sync + isync + blr + +/* 7400 <= rev 2.7 and 7410 rev = 1.0 suffer from some + * erratas we work around here. + * Moto MPC710CE.pdf describes them, those are errata + * #3, #4 and #5 + * Note that we assume the firmware didn't choose to + * apply other workarounds (there are other ones documented + * in the .pdf). It appear that Apple firmware only works + * around #3 and with the same fix we use. We may want to + * check if the CPU is using 60x bus mode in which case + * the workaround for errata #4 is useless. Also, we may + * want to explicitely clear HID0_NOPDST as this is not + * needed once we have applied workaround #5 (though it's + * not set by Apple's firmware at least). + */ +setup_7400_workarounds: + mfpvr r3 + rlwinm r3,r3,0,20,31 + cmpwi 0,r3,0x0207 + ble 1f + blr +setup_7410_workarounds: + mfpvr r3 + rlwinm r3,r3,0,20,31 + cmpwi 0,r3,0x0100 + bnelr +1: + mfspr r11,SPRN_MSSSR0 + /* Errata #3: Set L1OPQ_SIZE to 0x10 */ + rlwinm r11,r11,0,9,6 + oris r11,r11,0x0100 + /* Errata #4: Set L2MQ_SIZE to 1 (check for MPX mode first ?) */ + oris r11,r11,0x0002 + /* Errata #5: Set DRLT_SIZE to 0x01 */ + rlwinm r11,r11,0,5,2 + oris r11,r11,0x0800 + sync + mtspr SPRN_MSSSR0,r11 + sync + isync + blr + +/* 740/750/7400/7410 + * Enable Store Gathering (SGE), Address Brodcast (ABE), + * Branch History Table (BHTE), Branch Target ICache (BTIC) + * Dynamic Power Management (DPM), Speculative (SPD) + * Clear Instruction cache throttling (ICTC) + */ +setup_750_7400_hid0: + mfspr r11,SPRN_HID0 + ori r11,r11,HID0_SGE | HID0_ABE | HID0_BHTE | HID0_BTIC + oris r11,r11,HID0_DPM@h +BEGIN_FTR_SECTION + xori r11,r11,HID0_BTIC +END_FTR_SECTION_IFSET(CPU_FTR_NO_BTIC) +BEGIN_FTR_SECTION + xoris r11,r11,HID0_DPM@h /* disable dynamic power mgmt */ +END_FTR_SECTION_IFSET(CPU_FTR_NO_DPM) + li r3,HID0_SPD + andc r11,r11,r3 /* clear SPD: enable speculative */ + li r3,0 + mtspr SPRN_ICTC,r3 /* Instruction Cache Throttling off */ + isync + mtspr SPRN_HID0,r11 + sync + isync + blr + +/* 750cx specific + * Looks like we have to disable NAP feature for some PLL settings... + * (waiting for confirmation) + */ +setup_750cx: + mfspr r10, SPRN_HID1 + rlwinm r10,r10,4,28,31 + cmpwi cr0,r10,7 + cmpwi cr1,r10,9 + cmpwi cr2,r10,11 + cror 4*cr0+eq,4*cr0+eq,4*cr1+eq + cror 4*cr0+eq,4*cr0+eq,4*cr2+eq + bnelr + lwz r6,CPU_SPEC_FEATURES(r5) + li r7,CPU_FTR_CAN_NAP + andc r6,r6,r7 + stw r6,CPU_SPEC_FEATURES(r5) + blr + +/* 750fx specific + */ +setup_750fx: + blr + +/* MPC 745x + * Enable Store Gathering (SGE), Branch Folding (FOLD) + * Branch History Table (BHTE), Branch Target ICache (BTIC) + * Dynamic Power Management (DPM), Speculative (SPD) + * Ensure our data cache instructions really operate. + * Timebase has to be running or we wouldn't have made it here, + * just ensure we don't disable it. + * Clear Instruction cache throttling (ICTC) + * Enable L2 HW prefetch + */ +setup_745x_specifics: + /* We check for the presence of an L3 cache setup by + * the firmware. If any, we disable NAP capability as + * it's known to be bogus on rev 2.1 and earlier + */ + mfspr r11,SPRN_L3CR + andis. r11,r11,L3CR_L3E@h + beq 1f + lwz r6,CPU_SPEC_FEATURES(r5) + andi. r0,r6,CPU_FTR_L3_DISABLE_NAP + beq 1f + li r7,CPU_FTR_CAN_NAP + andc r6,r6,r7 + stw r6,CPU_SPEC_FEATURES(r5) +1: + mfspr r11,SPRN_HID0 + + /* All of the bits we have to set..... + */ + ori r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE + ori r11,r11,HID0_LRSTK | HID0_BTIC + oris r11,r11,HID0_DPM@h +BEGIN_FTR_SECTION + xori r11,r11,HID0_BTIC +END_FTR_SECTION_IFSET(CPU_FTR_NO_BTIC) +BEGIN_FTR_SECTION + xoris r11,r11,HID0_DPM@h /* disable dynamic power mgmt */ +END_FTR_SECTION_IFSET(CPU_FTR_NO_DPM) + + /* All of the bits we have to clear.... + */ + li r3,HID0_SPD | HID0_NOPDST | HID0_NOPTI + andc r11,r11,r3 /* clear SPD: enable speculative */ + li r3,0 + + mtspr SPRN_ICTC,r3 /* Instruction Cache Throttling off */ + isync + mtspr SPRN_HID0,r11 + sync + isync + + /* Enable L2 HW prefetch, if L2 is enabled + */ + mfspr r3,SPRN_L2CR + andis. r3,r3,L2CR_L2E@h + beqlr + mfspr r3,SPRN_MSSCR0 + ori r3,r3,3 + sync + mtspr SPRN_MSSCR0,r3 + sync + isync + blr + +/* + * Initialize the FPU registers. This is needed to work around an errata + * in some 750 cpus where using a not yet initialized FPU register after + * power on reset may hang the CPU + */ +_GLOBAL(__init_fpu_registers) + mfmsr r10 + ori r11,r10,MSR_FP + mtmsr r11 + isync + addis r9,r3,empty_zero_page@ha + addi r9,r9,empty_zero_page@l + REST_32FPRS(0,r9) + sync + mtmsr r10 + isync + blr + + +/* Definitions for the table use to save CPU states */ +#define CS_HID0 0 +#define CS_HID1 4 +#define CS_HID2 8 +#define CS_MSSCR0 12 +#define CS_MSSSR0 16 +#define CS_ICTRL 20 +#define CS_LDSTCR 24 +#define CS_LDSTDB 28 +#define CS_SIZE 32 + + .data + .balign L1_CACHE_BYTES +cpu_state_storage: + .space CS_SIZE + .balign L1_CACHE_BYTES,0 + .text + +/* Called in normal context to backup CPU 0 state. This + * does not include cache settings. This function is also + * called for machine sleep. This does not include the MMU + * setup, BATs, etc... but rather the "special" registers + * like HID0, HID1, MSSCR0, etc... + */ +_GLOBAL(__save_cpu_setup) + /* Some CR fields are volatile, we back it up all */ + mfcr r7 + + /* Get storage ptr */ + lis r5,cpu_state_storage@h + ori r5,r5,cpu_state_storage@l + + /* Save HID0 (common to all CONFIG_6xx cpus) */ + mfspr r3,SPRN_HID0 + stw r3,CS_HID0(r5) + + /* Now deal with CPU type dependent registers */ + mfspr r3,SPRN_PVR + srwi r3,r3,16 + cmplwi cr0,r3,0x8000 /* 7450 */ + cmplwi cr1,r3,0x000c /* 7400 */ + cmplwi cr2,r3,0x800c /* 7410 */ + cmplwi cr3,r3,0x8001 /* 7455 */ + cmplwi cr4,r3,0x8002 /* 7457 */ + cmplwi cr5,r3,0x8003 /* 7447A */ + cmplwi cr6,r3,0x7000 /* 750FX */ + cmplwi cr7,r3,0x8004 /* 7448 */ + /* cr1 is 7400 || 7410 */ + cror 4*cr1+eq,4*cr1+eq,4*cr2+eq + /* cr0 is 74xx */ + cror 4*cr0+eq,4*cr0+eq,4*cr3+eq + cror 4*cr0+eq,4*cr0+eq,4*cr4+eq + cror 4*cr0+eq,4*cr0+eq,4*cr1+eq + cror 4*cr0+eq,4*cr0+eq,4*cr5+eq + cror 4*cr0+eq,4*cr0+eq,4*cr7+eq + bne 1f + /* Backup 74xx specific regs */ + mfspr r4,SPRN_MSSCR0 + stw r4,CS_MSSCR0(r5) + mfspr r4,SPRN_MSSSR0 + stw r4,CS_MSSSR0(r5) + beq cr1,1f + /* Backup 745x specific registers */ + mfspr r4,SPRN_HID1 + stw r4,CS_HID1(r5) + mfspr r4,SPRN_ICTRL + stw r4,CS_ICTRL(r5) + mfspr r4,SPRN_LDSTCR + stw r4,CS_LDSTCR(r5) + mfspr r4,SPRN_LDSTDB + stw r4,CS_LDSTDB(r5) +1: + bne cr6,1f + /* Backup 750FX specific registers */ + mfspr r4,SPRN_HID1 + stw r4,CS_HID1(r5) + /* If rev 2.x, backup HID2 */ + mfspr r3,SPRN_PVR + andi. r3,r3,0xff00 + cmpwi cr0,r3,0x0200 + bne 1f + mfspr r4,SPRN_HID2 + stw r4,CS_HID2(r5) +1: + mtcr r7 + blr + +/* Called with no MMU context (typically MSR:IR/DR off) to + * restore CPU state as backed up by the previous + * function. This does not include cache setting + */ +_GLOBAL(__restore_cpu_setup) + /* Some CR fields are volatile, we back it up all */ + mfcr r7 + + /* Get storage ptr */ + lis r5,(cpu_state_storage-KERNELBASE)@h + ori r5,r5,cpu_state_storage@l + + /* Restore HID0 */ + lwz r3,CS_HID0(r5) + sync + isync + mtspr SPRN_HID0,r3 + sync + isync + + /* Now deal with CPU type dependent registers */ + mfspr r3,SPRN_PVR + srwi r3,r3,16 + cmplwi cr0,r3,0x8000 /* 7450 */ + cmplwi cr1,r3,0x000c /* 7400 */ + cmplwi cr2,r3,0x800c /* 7410 */ + cmplwi cr3,r3,0x8001 /* 7455 */ + cmplwi cr4,r3,0x8002 /* 7457 */ + cmplwi cr5,r3,0x8003 /* 7447A */ + cmplwi cr6,r3,0x7000 /* 750FX */ + cmplwi cr7,r3,0x8004 /* 7448 */ + /* cr1 is 7400 || 7410 */ + cror 4*cr1+eq,4*cr1+eq,4*cr2+eq + /* cr0 is 74xx */ + cror 4*cr0+eq,4*cr0+eq,4*cr3+eq + cror 4*cr0+eq,4*cr0+eq,4*cr4+eq + cror 4*cr0+eq,4*cr0+eq,4*cr1+eq + cror 4*cr0+eq,4*cr0+eq,4*cr5+eq + cror 4*cr0+eq,4*cr0+eq,4*cr7+eq + bne 2f + /* Restore 74xx specific regs */ + lwz r4,CS_MSSCR0(r5) + sync + mtspr SPRN_MSSCR0,r4 + sync + isync + lwz r4,CS_MSSSR0(r5) + sync + mtspr SPRN_MSSSR0,r4 + sync + isync + bne cr2,1f + /* Clear 7410 L2CR2 */ + li r4,0 + mtspr SPRN_L2CR2,r4 +1: beq cr1,2f + /* Restore 745x specific registers */ + lwz r4,CS_HID1(r5) + sync + mtspr SPRN_HID1,r4 + isync + sync + lwz r4,CS_ICTRL(r5) + sync + mtspr SPRN_ICTRL,r4 + isync + sync + lwz r4,CS_LDSTCR(r5) + sync + mtspr SPRN_LDSTCR,r4 + isync + sync + lwz r4,CS_LDSTDB(r5) + sync + mtspr SPRN_LDSTDB,r4 + isync + sync +2: bne cr6,1f + /* Restore 750FX specific registers + * that is restore HID2 on rev 2.x and PLL config & switch + * to PLL 0 on all + */ + /* If rev 2.x, restore HID2 with low voltage bit cleared */ + mfspr r3,SPRN_PVR + andi. r3,r3,0xff00 + cmpwi cr0,r3,0x0200 + bne 4f + lwz r4,CS_HID2(r5) + rlwinm r4,r4,0,19,17 + mtspr SPRN_HID2,r4 + sync +4: + lwz r4,CS_HID1(r5) + rlwinm r5,r4,0,16,14 + mtspr SPRN_HID1,r5 + /* Wait for PLL to stabilize */ + mftbl r5 +3: mftbl r6 + sub r6,r6,r5 + cmplwi cr0,r6,10000 + ble 3b + /* Setup final PLL */ + mtspr SPRN_HID1,r4 +1: + mtcr r7 + blr + diff --git a/arch/powerpc/kernel/tau_6xx.c b/arch/powerpc/kernel/tau_6xx.c new file mode 100644 index 000000000000..26bd8ea35a4e --- /dev/null +++ b/arch/powerpc/kernel/tau_6xx.c @@ -0,0 +1,271 @@ +/* + * temp.c Thermal management for cpu's with Thermal Assist Units + * + * Written by Troy Benjegerdes + * + * TODO: + * dynamic power management to limit peak CPU temp (using ICTC) + * calibration??? + * + * Silly, crazy ideas: use cpu load (from scheduler) and ICTC to extend battery + * life in portables, and add a 'performance/watt' metric somewhere in /proc + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +static struct tau_temp +{ + int interrupts; + unsigned char low; + unsigned char high; + unsigned char grew; +} tau[NR_CPUS]; + +struct timer_list tau_timer; + +#undef DEBUG + +/* TODO: put these in a /proc interface, with some sanity checks, and maybe + * dynamic adjustment to minimize # of interrupts */ +/* configurable values for step size and how much to expand the window when + * we get an interrupt. These are based on the limit that was out of range */ +#define step_size 2 /* step size when temp goes out of range */ +#define window_expand 1 /* expand the window by this much */ +/* configurable values for shrinking the window */ +#define shrink_timer 2*HZ /* period between shrinking the window */ +#define min_window 2 /* minimum window size, degrees C */ + +void set_thresholds(unsigned long cpu) +{ +#ifdef CONFIG_TAU_INT + /* + * setup THRM1, + * threshold, valid bit, enable interrupts, interrupt when below threshold + */ + mtspr(SPRN_THRM1, THRM1_THRES(tau[cpu].low) | THRM1_V | THRM1_TIE | THRM1_TID); + + /* setup THRM2, + * threshold, valid bit, enable interrupts, interrupt when above threshhold + */ + mtspr (SPRN_THRM2, THRM1_THRES(tau[cpu].high) | THRM1_V | THRM1_TIE); +#else + /* same thing but don't enable interrupts */ + mtspr(SPRN_THRM1, THRM1_THRES(tau[cpu].low) | THRM1_V | THRM1_TID); + mtspr(SPRN_THRM2, THRM1_THRES(tau[cpu].high) | THRM1_V); +#endif +} + +void TAUupdate(int cpu) +{ + unsigned thrm; + +#ifdef DEBUG + printk("TAUupdate "); +#endif + + /* if both thresholds are crossed, the step_sizes cancel out + * and the window winds up getting expanded twice. */ + if((thrm = mfspr(SPRN_THRM1)) & THRM1_TIV){ /* is valid? */ + if(thrm & THRM1_TIN){ /* crossed low threshold */ + if (tau[cpu].low >= step_size){ + tau[cpu].low -= step_size; + tau[cpu].high -= (step_size - window_expand); + } + tau[cpu].grew = 1; +#ifdef DEBUG + printk("low threshold crossed "); +#endif + } + } + if((thrm = mfspr(SPRN_THRM2)) & THRM1_TIV){ /* is valid? */ + if(thrm & THRM1_TIN){ /* crossed high threshold */ + if (tau[cpu].high <= 127-step_size){ + tau[cpu].low += (step_size - window_expand); + tau[cpu].high += step_size; + } + tau[cpu].grew = 1; +#ifdef DEBUG + printk("high threshold crossed "); +#endif + } + } + +#ifdef DEBUG + printk("grew = %d\n", tau[cpu].grew); +#endif + +#ifndef CONFIG_TAU_INT /* tau_timeout will do this if not using interrupts */ + set_thresholds(cpu); +#endif + +} + +#ifdef CONFIG_TAU_INT +/* + * TAU interrupts - called when we have a thermal assist unit interrupt + * with interrupts disabled + */ + +void TAUException(struct pt_regs * regs) +{ + int cpu = smp_processor_id(); + + irq_enter(); + tau[cpu].interrupts++; + + TAUupdate(cpu); + + irq_exit(); +} +#endif /* CONFIG_TAU_INT */ + +static void tau_timeout(void * info) +{ + int cpu; + unsigned long flags; + int size; + int shrink; + + /* disabling interrupts *should* be okay */ + local_irq_save(flags); + cpu = smp_processor_id(); + +#ifndef CONFIG_TAU_INT + TAUupdate(cpu); +#endif + + size = tau[cpu].high - tau[cpu].low; + if (size > min_window && ! tau[cpu].grew) { + /* do an exponential shrink of half the amount currently over size */ + shrink = (2 + size - min_window) / 4; + if (shrink) { + tau[cpu].low += shrink; + tau[cpu].high -= shrink; + } else { /* size must have been min_window + 1 */ + tau[cpu].low += 1; +#if 1 /* debug */ + if ((tau[cpu].high - tau[cpu].low) != min_window){ + printk(KERN_ERR "temp.c: line %d, logic error\n", __LINE__); + } +#endif + } + } + + tau[cpu].grew = 0; + + set_thresholds(cpu); + + /* + * Do the enable every time, since otherwise a bunch of (relatively) + * complex sleep code needs to be added. One mtspr every time + * tau_timeout is called is probably not a big deal. + * + * Enable thermal sensor and set up sample interval timer + * need 20 us to do the compare.. until a nice 'cpu_speed' function + * call is implemented, just assume a 500 mhz clock. It doesn't really + * matter if we take too long for a compare since it's all interrupt + * driven anyway. + * + * use a extra long time.. (60 us @ 500 mhz) + */ + mtspr(SPRN_THRM3, THRM3_SITV(500*60) | THRM3_E); + + local_irq_restore(flags); +} + +static void tau_timeout_smp(unsigned long unused) +{ + + /* schedule ourselves to be run again */ + mod_timer(&tau_timer, jiffies + shrink_timer) ; + on_each_cpu(tau_timeout, NULL, 1, 0); +} + +/* + * setup the TAU + * + * Set things up to use THRM1 as a temperature lower bound, and THRM2 as an upper bound. + * Start off at zero + */ + +int tau_initialized = 0; + +void __init TAU_init_smp(void * info) +{ + unsigned long cpu = smp_processor_id(); + + /* set these to a reasonable value and let the timer shrink the + * window */ + tau[cpu].low = 5; + tau[cpu].high = 120; + + set_thresholds(cpu); +} + +int __init TAU_init(void) +{ + /* We assume in SMP that if one CPU has TAU support, they + * all have it --BenH + */ + if (!cpu_has_feature(CPU_FTR_TAU)) { + printk("Thermal assist unit not available\n"); + tau_initialized = 0; + return 1; + } + + + /* first, set up the window shrinking timer */ + init_timer(&tau_timer); + tau_timer.function = tau_timeout_smp; + tau_timer.expires = jiffies + shrink_timer; + add_timer(&tau_timer); + + on_each_cpu(TAU_init_smp, NULL, 1, 0); + + printk("Thermal assist unit "); +#ifdef CONFIG_TAU_INT + printk("using interrupts, "); +#else + printk("using timers, "); +#endif + printk("shrink_timer: %d jiffies\n", shrink_timer); + tau_initialized = 1; + + return 0; +} + +__initcall(TAU_init); + +/* + * return current temp + */ + +u32 cpu_temp_both(unsigned long cpu) +{ + return ((tau[cpu].high << 16) | tau[cpu].low); +} + +int cpu_temp(unsigned long cpu) +{ + return ((tau[cpu].high + tau[cpu].low) / 2); +} + +int tau_interrupts(unsigned long cpu) +{ + return (tau[cpu].interrupts); +} -- cgit v1.2.2 From 45320bcbabfa9149f43a5beb4b9a4f108dd98929 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Mon, 27 Mar 2006 19:21:46 +1100 Subject: powerpc: Move swsusp.S over to arch/powerpc ... and rename it to swsusp_32.S, since it's 32-bit only at this stage. Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/swsusp_32.S | 349 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 349 insertions(+) create mode 100644 arch/powerpc/kernel/swsusp_32.S (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/swsusp_32.S b/arch/powerpc/kernel/swsusp_32.S new file mode 100644 index 000000000000..69773cc1a85f --- /dev/null +++ b/arch/powerpc/kernel/swsusp_32.S @@ -0,0 +1,349 @@ +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + * Structure for storing CPU registers on the save area. + */ +#define SL_SP 0 +#define SL_PC 4 +#define SL_MSR 8 +#define SL_SDR1 0xc +#define SL_SPRG0 0x10 /* 4 sprg's */ +#define SL_DBAT0 0x20 +#define SL_IBAT0 0x28 +#define SL_DBAT1 0x30 +#define SL_IBAT1 0x38 +#define SL_DBAT2 0x40 +#define SL_IBAT2 0x48 +#define SL_DBAT3 0x50 +#define SL_IBAT3 0x58 +#define SL_TB 0x60 +#define SL_R2 0x68 +#define SL_CR 0x6c +#define SL_LR 0x70 +#define SL_R12 0x74 /* r12 to r31 */ +#define SL_SIZE (SL_R12 + 80) + + .section .data + .align 5 + +_GLOBAL(swsusp_save_area) + .space SL_SIZE + + + .section .text + .align 5 + +_GLOBAL(swsusp_arch_suspend) + + lis r11,swsusp_save_area@h + ori r11,r11,swsusp_save_area@l + + mflr r0 + stw r0,SL_LR(r11) + mfcr r0 + stw r0,SL_CR(r11) + stw r1,SL_SP(r11) + stw r2,SL_R2(r11) + stmw r12,SL_R12(r11) + + /* Save MSR & SDR1 */ + mfmsr r4 + stw r4,SL_MSR(r11) + mfsdr1 r4 + stw r4,SL_SDR1(r11) + + /* Get a stable timebase and save it */ +1: mftbu r4 + stw r4,SL_TB(r11) + mftb r5 + stw r5,SL_TB+4(r11) + mftbu r3 + cmpw r3,r4 + bne 1b + + /* Save SPRGs */ + mfsprg r4,0 + stw r4,SL_SPRG0(r11) + mfsprg r4,1 + stw r4,SL_SPRG0+4(r11) + mfsprg r4,2 + stw r4,SL_SPRG0+8(r11) + mfsprg r4,3 + stw r4,SL_SPRG0+12(r11) + + /* Save BATs */ + mfdbatu r4,0 + stw r4,SL_DBAT0(r11) + mfdbatl r4,0 + stw r4,SL_DBAT0+4(r11) + mfdbatu r4,1 + stw r4,SL_DBAT1(r11) + mfdbatl r4,1 + stw r4,SL_DBAT1+4(r11) + mfdbatu r4,2 + stw r4,SL_DBAT2(r11) + mfdbatl r4,2 + stw r4,SL_DBAT2+4(r11) + mfdbatu r4,3 + stw r4,SL_DBAT3(r11) + mfdbatl r4,3 + stw r4,SL_DBAT3+4(r11) + mfibatu r4,0 + stw r4,SL_IBAT0(r11) + mfibatl r4,0 + stw r4,SL_IBAT0+4(r11) + mfibatu r4,1 + stw r4,SL_IBAT1(r11) + mfibatl r4,1 + stw r4,SL_IBAT1+4(r11) + mfibatu r4,2 + stw r4,SL_IBAT2(r11) + mfibatl r4,2 + stw r4,SL_IBAT2+4(r11) + mfibatu r4,3 + stw r4,SL_IBAT3(r11) + mfibatl r4,3 + stw r4,SL_IBAT3+4(r11) + +#if 0 + /* Backup various CPU config stuffs */ + bl __save_cpu_setup +#endif + /* Call the low level suspend stuff (we should probably have made + * a stackframe... + */ + bl swsusp_save + + /* Restore LR from the save area */ + lis r11,swsusp_save_area@h + ori r11,r11,swsusp_save_area@l + lwz r0,SL_LR(r11) + mtlr r0 + + blr + + +/* Resume code */ +_GLOBAL(swsusp_arch_resume) + + /* Stop pending alitvec streams and memory accesses */ +BEGIN_FTR_SECTION + DSSALL +END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) + sync + + /* Disable MSR:DR to make sure we don't take a TLB or + * hash miss during the copy, as our hash table will + * for a while be unuseable. For .text, we assume we are + * covered by a BAT. This works only for non-G5 at this + * point. G5 will need a better approach, possibly using + * a small temporary hash table filled with large mappings, + * disabling the MMU completely isn't a good option for + * performance reasons. + * (Note that 750's may have the same performance issue as + * the G5 in this case, we should investigate using moving + * BATs for these CPUs) + */ + mfmsr r0 + sync + rlwinm r0,r0,0,28,26 /* clear MSR_DR */ + mtmsr r0 + sync + isync + + /* Load ptr the list of pages to copy in r3 */ + lis r11,(pagedir_nosave - KERNELBASE)@h + ori r11,r11,pagedir_nosave@l + lwz r10,0(r11) + + /* Copy the pages. This is a very basic implementation, to + * be replaced by something more cache efficient */ +1: + tophys(r3,r10) + li r0,256 + mtctr r0 + lwz r11,pbe_address(r3) /* source */ + tophys(r5,r11) + lwz r10,pbe_orig_address(r3) /* destination */ + tophys(r6,r10) +2: + lwz r8,0(r5) + lwz r9,4(r5) + lwz r10,8(r5) + lwz r11,12(r5) + addi r5,r5,16 + stw r8,0(r6) + stw r9,4(r6) + stw r10,8(r6) + stw r11,12(r6) + addi r6,r6,16 + bdnz 2b + lwz r10,pbe_next(r3) + cmpwi 0,r10,0 + bne 1b + + /* Do a very simple cache flush/inval of the L1 to ensure + * coherency of the icache + */ + lis r3,0x0002 + mtctr r3 + li r3, 0 +1: + lwz r0,0(r3) + addi r3,r3,0x0020 + bdnz 1b + isync + sync + + /* Now flush those cache lines */ + lis r3,0x0002 + mtctr r3 + li r3, 0 +1: + dcbf 0,r3 + addi r3,r3,0x0020 + bdnz 1b + sync + + /* Ok, we are now running with the kernel data of the old + * kernel fully restored. We can get to the save area + * easily now. As for the rest of the code, it assumes the + * loader kernel and the booted one are exactly identical + */ + lis r11,swsusp_save_area@h + ori r11,r11,swsusp_save_area@l + tophys(r11,r11) + +#if 0 + /* Restore various CPU config stuffs */ + bl __restore_cpu_setup +#endif + /* Restore the BATs, and SDR1. Then we can turn on the MMU. + * This is a bit hairy as we are running out of those BATs, + * but first, our code is probably in the icache, and we are + * writing the same value to the BAT, so that should be fine, + * though a better solution will have to be found long-term + */ + lwz r4,SL_SDR1(r11) + mtsdr1 r4 + lwz r4,SL_SPRG0(r11) + mtsprg 0,r4 + lwz r4,SL_SPRG0+4(r11) + mtsprg 1,r4 + lwz r4,SL_SPRG0+8(r11) + mtsprg 2,r4 + lwz r4,SL_SPRG0+12(r11) + mtsprg 3,r4 + +#if 0 + lwz r4,SL_DBAT0(r11) + mtdbatu 0,r4 + lwz r4,SL_DBAT0+4(r11) + mtdbatl 0,r4 + lwz r4,SL_DBAT1(r11) + mtdbatu 1,r4 + lwz r4,SL_DBAT1+4(r11) + mtdbatl 1,r4 + lwz r4,SL_DBAT2(r11) + mtdbatu 2,r4 + lwz r4,SL_DBAT2+4(r11) + mtdbatl 2,r4 + lwz r4,SL_DBAT3(r11) + mtdbatu 3,r4 + lwz r4,SL_DBAT3+4(r11) + mtdbatl 3,r4 + lwz r4,SL_IBAT0(r11) + mtibatu 0,r4 + lwz r4,SL_IBAT0+4(r11) + mtibatl 0,r4 + lwz r4,SL_IBAT1(r11) + mtibatu 1,r4 + lwz r4,SL_IBAT1+4(r11) + mtibatl 1,r4 + lwz r4,SL_IBAT2(r11) + mtibatu 2,r4 + lwz r4,SL_IBAT2+4(r11) + mtibatl 2,r4 + lwz r4,SL_IBAT3(r11) + mtibatu 3,r4 + lwz r4,SL_IBAT3+4(r11) + mtibatl 3,r4 +#endif + +BEGIN_FTR_SECTION + li r4,0 + mtspr SPRN_DBAT4U,r4 + mtspr SPRN_DBAT4L,r4 + mtspr SPRN_DBAT5U,r4 + mtspr SPRN_DBAT5L,r4 + mtspr SPRN_DBAT6U,r4 + mtspr SPRN_DBAT6L,r4 + mtspr SPRN_DBAT7U,r4 + mtspr SPRN_DBAT7L,r4 + mtspr SPRN_IBAT4U,r4 + mtspr SPRN_IBAT4L,r4 + mtspr SPRN_IBAT5U,r4 + mtspr SPRN_IBAT5L,r4 + mtspr SPRN_IBAT6U,r4 + mtspr SPRN_IBAT6L,r4 + mtspr SPRN_IBAT7U,r4 + mtspr SPRN_IBAT7L,r4 +END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS) + + /* Flush all TLBs */ + lis r4,0x1000 +1: addic. r4,r4,-0x1000 + tlbie r4 + blt 1b + sync + + /* restore the MSR and turn on the MMU */ + lwz r3,SL_MSR(r11) + bl turn_on_mmu + tovirt(r11,r11) + + /* Restore TB */ + li r3,0 + mttbl r3 + lwz r3,SL_TB(r11) + lwz r4,SL_TB+4(r11) + mttbu r3 + mttbl r4 + + /* Kick decrementer */ + li r0,1 + mtdec r0 + + /* Restore the callee-saved registers and return */ + lwz r0,SL_CR(r11) + mtcr r0 + lwz r2,SL_R2(r11) + lmw r12,SL_R12(r11) + lwz r1,SL_SP(r11) + lwz r0,SL_LR(r11) + mtlr r0 + + // XXX Note: we don't really need to call swsusp_resume + + li r3,0 + blr + +/* FIXME:This construct is actually not useful since we don't shut + * down the instruction MMU, we could just flip back MSR-DR on. + */ +turn_on_mmu: + mflr r4 + mtsrr0 r4 + mtsrr1 r3 + sync + isync + rfi + -- cgit v1.2.2 From ed981856ca8af30912fd61a6a4ac8d30a453a5ec Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Mon, 27 Mar 2006 19:28:58 +1100 Subject: powerpc: Move module.c over to arch/powerpc ... and rename it to module_32.c since it is the 32-bit version. The 32-bit and 64-bit ABIs are sufficiently different that having a merged version isn't really practical. Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/Makefile | 3 + arch/powerpc/kernel/module_32.c | 320 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 323 insertions(+) create mode 100644 arch/powerpc/kernel/module_32.c (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 754c227835bb..b86d380f01b4 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -36,6 +36,8 @@ obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o obj-$(CONFIG_TAU) += tau_6xx.o +obj32-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_32.o +obj32-$(CONFIG_MODULES) += module_32.o ifeq ($(CONFIG_PPC_MERGE),y) @@ -78,6 +80,7 @@ smpobj-$(CONFIG_SMP) += smp.o endif +obj-$(CONFIG_PPC32) += $(obj32-y) obj-$(CONFIG_PPC64) += $(obj64-y) extra-$(CONFIG_PPC_FPU) += fpu.o diff --git a/arch/powerpc/kernel/module_32.c b/arch/powerpc/kernel/module_32.c new file mode 100644 index 000000000000..92f4e5f64f02 --- /dev/null +++ b/arch/powerpc/kernel/module_32.c @@ -0,0 +1,320 @@ +/* Kernel module help for PPC. + Copyright (C) 2001 Rusty Russell. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include +#include +#include +#include +#include +#include +#include +#include + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(fmt , ...) +#endif + +LIST_HEAD(module_bug_list); + +void *module_alloc(unsigned long size) +{ + if (size == 0) + return NULL; + return vmalloc(size); +} + +/* Free memory returned from module_alloc */ +void module_free(struct module *mod, void *module_region) +{ + vfree(module_region); + /* FIXME: If module_region == mod->init_region, trim exception + table entries. */ +} + +/* Count how many different relocations (different symbol, different + addend) */ +static unsigned int count_relocs(const Elf32_Rela *rela, unsigned int num) +{ + unsigned int i, j, ret = 0; + + /* Sure, this is order(n^2), but it's usually short, and not + time critical */ + for (i = 0; i < num; i++) { + for (j = 0; j < i; j++) { + /* If this addend appeared before, it's + already been counted */ + if (ELF32_R_SYM(rela[i].r_info) + == ELF32_R_SYM(rela[j].r_info) + && rela[i].r_addend == rela[j].r_addend) + break; + } + if (j == i) ret++; + } + return ret; +} + +/* Get the potential trampolines size required of the init and + non-init sections */ +static unsigned long get_plt_size(const Elf32_Ehdr *hdr, + const Elf32_Shdr *sechdrs, + const char *secstrings, + int is_init) +{ + unsigned long ret = 0; + unsigned i; + + /* Everything marked ALLOC (this includes the exported + symbols) */ + for (i = 1; i < hdr->e_shnum; i++) { + /* If it's called *.init*, and we're not init, we're + not interested */ + if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0) + != is_init) + continue; + + /* We don't want to look at debug sections. */ + if (strstr(secstrings + sechdrs[i].sh_name, ".debug") != 0) + continue; + + if (sechdrs[i].sh_type == SHT_RELA) { + DEBUGP("Found relocations in section %u\n", i); + DEBUGP("Ptr: %p. Number: %u\n", + (void *)hdr + sechdrs[i].sh_offset, + sechdrs[i].sh_size / sizeof(Elf32_Rela)); + ret += count_relocs((void *)hdr + + sechdrs[i].sh_offset, + sechdrs[i].sh_size + / sizeof(Elf32_Rela)) + * sizeof(struct ppc_plt_entry); + } + } + + return ret; +} + +int module_frob_arch_sections(Elf32_Ehdr *hdr, + Elf32_Shdr *sechdrs, + char *secstrings, + struct module *me) +{ + unsigned int i; + + /* Find .plt and .init.plt sections */ + for (i = 0; i < hdr->e_shnum; i++) { + if (strcmp(secstrings + sechdrs[i].sh_name, ".init.plt") == 0) + me->arch.init_plt_section = i; + else if (strcmp(secstrings + sechdrs[i].sh_name, ".plt") == 0) + me->arch.core_plt_section = i; + } + if (!me->arch.core_plt_section || !me->arch.init_plt_section) { + printk("Module doesn't contain .plt or .init.plt sections.\n"); + return -ENOEXEC; + } + + /* Override their sizes */ + sechdrs[me->arch.core_plt_section].sh_size + = get_plt_size(hdr, sechdrs, secstrings, 0); + sechdrs[me->arch.init_plt_section].sh_size + = get_plt_size(hdr, sechdrs, secstrings, 1); + return 0; +} + +int apply_relocate(Elf32_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *module) +{ + printk(KERN_ERR "%s: Non-ADD RELOCATION unsupported\n", + module->name); + return -ENOEXEC; +} + +static inline int entry_matches(struct ppc_plt_entry *entry, Elf32_Addr val) +{ + if (entry->jump[0] == 0x3d600000 + ((val + 0x8000) >> 16) + && entry->jump[1] == 0x396b0000 + (val & 0xffff)) + return 1; + return 0; +} + +/* Set up a trampoline in the PLT to bounce us to the distant function */ +static uint32_t do_plt_call(void *location, + Elf32_Addr val, + Elf32_Shdr *sechdrs, + struct module *mod) +{ + struct ppc_plt_entry *entry; + + DEBUGP("Doing plt for call to 0x%x at 0x%x\n", val, (unsigned int)location); + /* Init, or core PLT? */ + if (location >= mod->module_core + && location < mod->module_core + mod->core_size) + entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr; + else + entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr; + + /* Find this entry, or if that fails, the next avail. entry */ + while (entry->jump[0]) { + if (entry_matches(entry, val)) return (uint32_t)entry; + entry++; + } + + /* Stolen from Paul Mackerras as well... */ + entry->jump[0] = 0x3d600000+((val+0x8000)>>16); /* lis r11,sym@ha */ + entry->jump[1] = 0x396b0000 + (val&0xffff); /* addi r11,r11,sym@l*/ + entry->jump[2] = 0x7d6903a6; /* mtctr r11 */ + entry->jump[3] = 0x4e800420; /* bctr */ + + DEBUGP("Initialized plt for 0x%x at %p\n", val, entry); + return (uint32_t)entry; +} + +int apply_relocate_add(Elf32_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *module) +{ + unsigned int i; + Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr; + Elf32_Sym *sym; + uint32_t *location; + uint32_t value; + + DEBUGP("Applying ADD relocate section %u to %u\n", relsec, + sechdrs[relsec].sh_info); + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) { + /* This is where to make the change */ + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + + rela[i].r_offset; + /* This is the symbol it is referring to. Note that all + undefined symbols have been resolved. */ + sym = (Elf32_Sym *)sechdrs[symindex].sh_addr + + ELF32_R_SYM(rela[i].r_info); + /* `Everything is relative'. */ + value = sym->st_value + rela[i].r_addend; + + switch (ELF32_R_TYPE(rela[i].r_info)) { + case R_PPC_ADDR32: + /* Simply set it */ + *(uint32_t *)location = value; + break; + + case R_PPC_ADDR16_LO: + /* Low half of the symbol */ + *(uint16_t *)location = value; + break; + + case R_PPC_ADDR16_HA: + /* Sign-adjusted lower 16 bits: PPC ELF ABI says: + (((x >> 16) + ((x & 0x8000) ? 1 : 0))) & 0xFFFF. + This is the same, only sane. + */ + *(uint16_t *)location = (value + 0x8000) >> 16; + break; + + case R_PPC_REL24: + if ((int)(value - (uint32_t)location) < -0x02000000 + || (int)(value - (uint32_t)location) >= 0x02000000) + value = do_plt_call(location, value, + sechdrs, module); + + /* Only replace bits 2 through 26 */ + DEBUGP("REL24 value = %08X. location = %08X\n", + value, (uint32_t)location); + DEBUGP("Location before: %08X.\n", + *(uint32_t *)location); + *(uint32_t *)location + = (*(uint32_t *)location & ~0x03fffffc) + | ((value - (uint32_t)location) + & 0x03fffffc); + DEBUGP("Location after: %08X.\n", + *(uint32_t *)location); + DEBUGP("ie. jump to %08X+%08X = %08X\n", + *(uint32_t *)location & 0x03fffffc, + (uint32_t)location, + (*(uint32_t *)location & 0x03fffffc) + + (uint32_t)location); + break; + + case R_PPC_REL32: + /* 32-bit relative jump. */ + *(uint32_t *)location = value - (uint32_t)location; + break; + + default: + printk("%s: unknown ADD relocation: %u\n", + module->name, + ELF32_R_TYPE(rela[i].r_info)); + return -ENOEXEC; + } + } + return 0; +} + +int module_finalize(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, + struct module *me) +{ + char *secstrings; + unsigned int i; + + me->arch.bug_table = NULL; + me->arch.num_bugs = 0; + + /* Find the __bug_table section, if present */ + secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; + for (i = 1; i < hdr->e_shnum; i++) { + if (strcmp(secstrings+sechdrs[i].sh_name, "__bug_table")) + continue; + me->arch.bug_table = (void *) sechdrs[i].sh_addr; + me->arch.num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry); + break; + } + + /* + * Strictly speaking this should have a spinlock to protect against + * traversals, but since we only traverse on BUG()s, a spinlock + * could potentially lead to deadlock and thus be counter-productive. + */ + list_add(&me->arch.bug_list, &module_bug_list); + + return 0; +} + +void module_arch_cleanup(struct module *mod) +{ + list_del(&mod->arch.bug_list); +} + +struct bug_entry *module_find_bug(unsigned long bugaddr) +{ + struct mod_arch_specific *mod; + unsigned int i; + struct bug_entry *bug; + + list_for_each_entry(mod, &module_bug_list, bug_list) { + bug = mod->bug_table; + for (i = 0; i < mod->num_bugs; ++i, ++bug) + if (bugaddr == bug->bug_addr) + return bug; + } + return NULL; +} -- cgit v1.2.2 From 8b844dd7591a820a618a8fb33c9c43186d43d1b9 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Mon, 27 Mar 2006 20:09:04 +1100 Subject: powerpc: Move perfmon_fsl_booke.c over to arch/powerpc Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/Makefile | 1 + arch/powerpc/kernel/perfmon_fsl_booke.c | 222 ++++++++++++++++++++++++++++++++ 2 files changed, 223 insertions(+) create mode 100644 arch/powerpc/kernel/perfmon_fsl_booke.c (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index b86d380f01b4..0cc0995b81b0 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o obj-$(CONFIG_TAU) += tau_6xx.o obj32-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_32.o obj32-$(CONFIG_MODULES) += module_32.o +obj-$(CONFIG_E500) += perfmon_fsl_booke.o ifeq ($(CONFIG_PPC_MERGE),y) diff --git a/arch/powerpc/kernel/perfmon_fsl_booke.c b/arch/powerpc/kernel/perfmon_fsl_booke.c new file mode 100644 index 000000000000..32455dfcc36b --- /dev/null +++ b/arch/powerpc/kernel/perfmon_fsl_booke.c @@ -0,0 +1,222 @@ +/* kernel/perfmon_fsl_booke.c + * Freescale Book-E Performance Monitor code + * + * Author: Andy Fleming + * Copyright (c) 2004 Freescale Semiconductor, Inc + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +static inline u32 get_pmlca(int ctr); +static inline void set_pmlca(int ctr, u32 pmlca); + +static inline u32 get_pmlca(int ctr) +{ + u32 pmlca; + + switch (ctr) { + case 0: + pmlca = mfpmr(PMRN_PMLCA0); + break; + case 1: + pmlca = mfpmr(PMRN_PMLCA1); + break; + case 2: + pmlca = mfpmr(PMRN_PMLCA2); + break; + case 3: + pmlca = mfpmr(PMRN_PMLCA3); + break; + default: + panic("Bad ctr number\n"); + } + + return pmlca; +} + +static inline void set_pmlca(int ctr, u32 pmlca) +{ + switch (ctr) { + case 0: + mtpmr(PMRN_PMLCA0, pmlca); + break; + case 1: + mtpmr(PMRN_PMLCA1, pmlca); + break; + case 2: + mtpmr(PMRN_PMLCA2, pmlca); + break; + case 3: + mtpmr(PMRN_PMLCA3, pmlca); + break; + default: + panic("Bad ctr number\n"); + } +} + +void init_pmc_stop(int ctr) +{ + u32 pmlca = (PMLCA_FC | PMLCA_FCS | PMLCA_FCU | + PMLCA_FCM1 | PMLCA_FCM0); + u32 pmlcb = 0; + + switch (ctr) { + case 0: + mtpmr(PMRN_PMLCA0, pmlca); + mtpmr(PMRN_PMLCB0, pmlcb); + break; + case 1: + mtpmr(PMRN_PMLCA1, pmlca); + mtpmr(PMRN_PMLCB1, pmlcb); + break; + case 2: + mtpmr(PMRN_PMLCA2, pmlca); + mtpmr(PMRN_PMLCB2, pmlcb); + break; + case 3: + mtpmr(PMRN_PMLCA3, pmlca); + mtpmr(PMRN_PMLCB3, pmlcb); + break; + default: + panic("Bad ctr number!\n"); + } +} + +void set_pmc_event(int ctr, int event) +{ + u32 pmlca; + + pmlca = get_pmlca(ctr); + + pmlca = (pmlca & ~PMLCA_EVENT_MASK) | + ((event << PMLCA_EVENT_SHIFT) & + PMLCA_EVENT_MASK); + + set_pmlca(ctr, pmlca); +} + +void set_pmc_user_kernel(int ctr, int user, int kernel) +{ + u32 pmlca; + + pmlca = get_pmlca(ctr); + + if(user) + pmlca &= ~PMLCA_FCU; + else + pmlca |= PMLCA_FCU; + + if(kernel) + pmlca &= ~PMLCA_FCS; + else + pmlca |= PMLCA_FCS; + + set_pmlca(ctr, pmlca); +} + +void set_pmc_marked(int ctr, int mark0, int mark1) +{ + u32 pmlca = get_pmlca(ctr); + + if(mark0) + pmlca &= ~PMLCA_FCM0; + else + pmlca |= PMLCA_FCM0; + + if(mark1) + pmlca &= ~PMLCA_FCM1; + else + pmlca |= PMLCA_FCM1; + + set_pmlca(ctr, pmlca); +} + +void pmc_start_ctr(int ctr, int enable) +{ + u32 pmlca = get_pmlca(ctr); + + pmlca &= ~PMLCA_FC; + + if (enable) + pmlca |= PMLCA_CE; + else + pmlca &= ~PMLCA_CE; + + set_pmlca(ctr, pmlca); +} + +void pmc_start_ctrs(int enable) +{ + u32 pmgc0 = mfpmr(PMRN_PMGC0); + + pmgc0 &= ~PMGC0_FAC; + pmgc0 |= PMGC0_FCECE; + + if (enable) + pmgc0 |= PMGC0_PMIE; + else + pmgc0 &= ~PMGC0_PMIE; + + mtpmr(PMRN_PMGC0, pmgc0); +} + +void pmc_stop_ctrs(void) +{ + u32 pmgc0 = mfpmr(PMRN_PMGC0); + + pmgc0 |= PMGC0_FAC; + + pmgc0 &= ~(PMGC0_PMIE | PMGC0_FCECE); + + mtpmr(PMRN_PMGC0, pmgc0); +} + +void dump_pmcs(void) +{ + printk("pmgc0: %x\n", mfpmr(PMRN_PMGC0)); + printk("pmc\t\tpmlca\t\tpmlcb\n"); + printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC0), + mfpmr(PMRN_PMLCA0), mfpmr(PMRN_PMLCB0)); + printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC1), + mfpmr(PMRN_PMLCA1), mfpmr(PMRN_PMLCB1)); + printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC2), + mfpmr(PMRN_PMLCA2), mfpmr(PMRN_PMLCB2)); + printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC3), + mfpmr(PMRN_PMLCA3), mfpmr(PMRN_PMLCB3)); +} + +EXPORT_SYMBOL(init_pmc_stop); +EXPORT_SYMBOL(set_pmc_event); +EXPORT_SYMBOL(set_pmc_user_kernel); +EXPORT_SYMBOL(set_pmc_marked); +EXPORT_SYMBOL(pmc_start_ctr); +EXPORT_SYMBOL(pmc_start_ctrs); +EXPORT_SYMBOL(pmc_stop_ctrs); +EXPORT_SYMBOL(dump_pmcs); -- cgit v1.2.2 From e7e2d2da26384b07dfee83f63e6090e386c63d7e Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Mon, 27 Mar 2006 20:17:06 +1100 Subject: powerpc: Don't compile in arch/ppc/kernel for 32-bit ARCH=powerpc All of the things needed for 32-bit ARCH=powerpc builds have now moved to arch/powerpc/kernel, so we don't need to go down into arch/ppc/kernel any more, and we can remove the CONFIG_PPC_MERGE conditional from arch/ppc/kernel/Makefile. There were two files still referenced in the merge section of arch/ppc/kernel/Makefile: ppc-stub.o, depending on CONFIG_KGDB, and dma-mapping.o, depending on CONFIG_NOT_COHERENT_CACHE. None of the platforms currently in ARCH=powerpc have caches that aren't coherent with DMA, but when we do get one we'll move dma-mapping.c over. As for CONFIG_KGDB, none of the Kconfig files in the tree define it, so I'll let it languish for now. Signed-off-by: Paul Mackerras --- arch/powerpc/Makefile | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 829e017b8a54..9586899de68a 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -129,7 +129,6 @@ core-y += arch/powerpc/kernel/ \ arch/powerpc/lib/ \ arch/powerpc/sysdev/ \ arch/powerpc/platforms/ -core-$(CONFIG_PPC32) += arch/ppc/kernel/ core-$(CONFIG_MATH_EMULATION) += arch/ppc/math-emu/ core-$(CONFIG_XMON) += arch/powerpc/xmon/ core-$(CONFIG_APUS) += arch/ppc/amiga/ -- cgit v1.2.2 From 9618edab82fda8dbce5ea3abcdac9ded07abb2d4 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Mon, 27 Mar 2006 21:48:57 +1100 Subject: powerpc: Fix event-scan code for 32-bit CHRP On CHRP machines we are supposed to call into firmware (RTAS) periodically, to give it a chance to check for errors and other events. Under ppc we had some special code in timer_interrupt to do this, but that didn't get transferred over to arch/powerpc. Instead, we use an array of timer_list structs, one per CPU, and use add_timer_on to make sure each one gets called on the appropriate CPU. With this we can remove the heartbeat_* elements of the ppc_md struct. Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/chrp/chrp.h | 2 +- arch/powerpc/platforms/chrp/setup.c | 64 ++++++++++++++++++++++++++----------- 2 files changed, 46 insertions(+), 20 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/chrp/chrp.h b/arch/powerpc/platforms/chrp/chrp.h index 814f54742e0f..63f0aee4c158 100644 --- a/arch/powerpc/platforms/chrp/chrp.h +++ b/arch/powerpc/platforms/chrp/chrp.h @@ -8,4 +8,4 @@ extern int chrp_set_rtc_time(struct rtc_time *); extern long chrp_time_init(void); extern void chrp_find_bridges(void); -extern void chrp_event_scan(void); +extern void chrp_event_scan(unsigned long); diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 8bf4307e323d..9c718bb2305e 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -61,6 +62,10 @@ EXPORT_SYMBOL(_chrp_type); struct mpic *chrp_mpic; +/* Used for doing CHRP event-scans */ +DEFINE_PER_CPU(struct timer_list, heartbeat_timer); +unsigned long event_scan_interval; + /* * XXX this should be in xmon.h, but putting it there means xmon.h * has to include (to get irqreturn_t), which @@ -229,8 +234,6 @@ void __init chrp_setup_arch(void) { struct device_node *root = find_path_device ("/"); char *machine = NULL; - struct device_node *device; - unsigned int *p = NULL; /* init to some ~sane value until calibrate_delay() runs */ loops_per_jiffy = 50000000/HZ; @@ -287,21 +290,6 @@ void __init chrp_setup_arch(void) */ sio_init(); - /* Get the event scan rate for the rtas so we know how - * often it expects a heartbeat. -- Cort - */ - device = find_devices("rtas"); - if (device) - p = (unsigned int *) get_property - (device, "rtas-event-scan-rate", NULL); - if (p && *p) { - ppc_md.heartbeat = chrp_event_scan; - ppc_md.heartbeat_reset = HZ / (*p * 30) - 1; - ppc_md.heartbeat_count = 1; - printk("RTAS Event Scan Rate: %u (%lu jiffies)\n", - *p, ppc_md.heartbeat_reset); - } - pci_create_OF_bus_map(); /* @@ -312,7 +300,7 @@ void __init chrp_setup_arch(void) } void -chrp_event_scan(void) +chrp_event_scan(unsigned long unused) { unsigned char log[1024]; int ret = 0; @@ -320,7 +308,8 @@ chrp_event_scan(void) /* XXX: we should loop until the hardware says no more error logs -- Cort */ rtas_call(rtas_token("event-scan"), 4, 1, &ret, 0xffffffff, 0, __pa(log), 1024); - ppc_md.heartbeat_count = ppc_md.heartbeat_reset; + mod_timer(&__get_cpu_var(heartbeat_timer), + jiffies + event_scan_interval); } /* @@ -465,6 +454,9 @@ void __init chrp_init_IRQ(void) void __init chrp_init2(void) { + struct device_node *device; + unsigned int *p = NULL; + #ifdef CONFIG_NVRAM chrp_nvram_init(); #endif @@ -476,6 +468,40 @@ chrp_init2(void) request_region(0x80,0x10,"dma page reg"); request_region(0xc0,0x20,"dma2"); + /* Get the event scan rate for the rtas so we know how + * often it expects a heartbeat. -- Cort + */ + device = find_devices("rtas"); + if (device) + p = (unsigned int *) get_property + (device, "rtas-event-scan-rate", NULL); + if (p && *p) { + /* + * Arrange to call chrp_event_scan at least *p times + * per minute. We use 59 rather than 60 here so that + * the rate will be slightly higher than the minimum. + * This all assumes we don't do hotplug CPU on any + * machine that needs the event scans done. + */ + unsigned long interval, offset; + int cpu, ncpus; + struct timer_list *timer; + + interval = HZ * 59 / *p; + offset = HZ; + ncpus = num_online_cpus(); + event_scan_interval = ncpus * interval; + for (cpu = 0; cpu < ncpus; ++cpu) { + timer = &per_cpu(heartbeat_timer, cpu); + setup_timer(timer, chrp_event_scan, 0); + timer->expires = jiffies + offset; + add_timer_on(timer, cpu); + offset += interval; + } + printk("RTAS Event Scan Rate: %u (%lu jiffies)\n", + *p, interval); + } + if (ppc_md.progress) ppc_md.progress(" Have fun! ", 0x7777); } -- cgit v1.2.2 From ec936fc563715a9e2b2e363eb060655b49529325 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Mon, 27 Mar 2006 01:15:59 -0800 Subject: [PATCH] for_each_online_pgdat: renaming for_each_pgdat Replace for_each_pgdat() with for_each_online_pgdat(). Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/mm/mem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index badac10d700c..5e435a9c3431 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -195,7 +195,7 @@ void show_mem(void) printk("Mem-info:\n"); show_free_areas(); printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); - for_each_pgdat(pgdat) { + for_each_online_pgdat(pgdat) { unsigned long flags; pgdat_resize_lock(pgdat, &flags); for (i = 0; i < pgdat->node_spanned_pages; i++) { @@ -351,7 +351,7 @@ void __init mem_init(void) max_mapnr = max_pfn; totalram_pages += free_all_bootmem(); #endif - for_each_pgdat(pgdat) { + for_each_online_pgdat(pgdat) { for (i = 0; i < pgdat->node_spanned_pages; i++) { if (!pfn_valid(pgdat->node_start_pfn + i)) continue; -- cgit v1.2.2 From e041c683412d5bf44dc2b109053e3b837b71742d Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 27 Mar 2006 01:16:30 -0800 Subject: [PATCH] Notifier chain update: API changes The kernel's implementation of notifier chains is unsafe. There is no protection against entries being added to or removed from a chain while the chain is in use. The issues were discussed in this thread: http://marc.theaimsgroup.com/?l=linux-kernel&m=113018709002036&w=2 We noticed that notifier chains in the kernel fall into two basic usage classes: "Blocking" chains are always called from a process context and the callout routines are allowed to sleep; "Atomic" chains can be called from an atomic context and the callout routines are not allowed to sleep. We decided to codify this distinction and make it part of the API. Therefore this set of patches introduces three new, parallel APIs: one for blocking notifiers, one for atomic notifiers, and one for "raw" notifiers (which is really just the old API under a new name). New kinds of data structures are used for the heads of the chains, and new routines are defined for registration, unregistration, and calling a chain. The three APIs are explained in include/linux/notifier.h and their implementation is in kernel/sys.c. With atomic and blocking chains, the implementation guarantees that the chain links will not be corrupted and that chain callers will not get messed up by entries being added or removed. For raw chains the implementation provides no guarantees at all; users of this API must provide their own protections. (The idea was that situations may come up where the assumptions of the atomic and blocking APIs are not appropriate, so it should be possible for users to handle these things in their own way.) There are some limitations, which should not be too hard to live with. For atomic/blocking chains, registration and unregistration must always be done in a process context since the chain is protected by a mutex/rwsem. Also, a callout routine for a non-raw chain must not try to register or unregister entries on its own chain. (This did happen in a couple of places and the code had to be changed to avoid it.) Since atomic chains may be called from within an NMI handler, they cannot use spinlocks for synchronization. Instead we use RCU. The overhead falls almost entirely in the unregister routine, which is okay since unregistration is much less frequent that calling a chain. Here is the list of chains that we adjusted and their classifications. None of them use the raw API, so for the moment it is only a placeholder. ATOMIC CHAINS ------------- arch/i386/kernel/traps.c: i386die_chain arch/ia64/kernel/traps.c: ia64die_chain arch/powerpc/kernel/traps.c: powerpc_die_chain arch/sparc64/kernel/traps.c: sparc64die_chain arch/x86_64/kernel/traps.c: die_chain drivers/char/ipmi/ipmi_si_intf.c: xaction_notifier_list kernel/panic.c: panic_notifier_list kernel/profile.c: task_free_notifier net/bluetooth/hci_core.c: hci_notifier net/ipv4/netfilter/ip_conntrack_core.c: ip_conntrack_chain net/ipv4/netfilter/ip_conntrack_core.c: ip_conntrack_expect_chain net/ipv6/addrconf.c: inet6addr_chain net/netfilter/nf_conntrack_core.c: nf_conntrack_chain net/netfilter/nf_conntrack_core.c: nf_conntrack_expect_chain net/netlink/af_netlink.c: netlink_chain BLOCKING CHAINS --------------- arch/powerpc/platforms/pseries/reconfig.c: pSeries_reconfig_chain arch/s390/kernel/process.c: idle_chain arch/x86_64/kernel/process.c idle_notifier drivers/base/memory.c: memory_chain drivers/cpufreq/cpufreq.c cpufreq_policy_notifier_list drivers/cpufreq/cpufreq.c cpufreq_transition_notifier_list drivers/macintosh/adb.c: adb_client_list drivers/macintosh/via-pmu.c sleep_notifier_list drivers/macintosh/via-pmu68k.c sleep_notifier_list drivers/macintosh/windfarm_core.c wf_client_list drivers/usb/core/notify.c usb_notifier_list drivers/video/fbmem.c fb_notifier_list kernel/cpu.c cpu_chain kernel/module.c module_notify_list kernel/profile.c munmap_notifier kernel/profile.c task_exit_notifier kernel/sys.c reboot_notifier_list net/core/dev.c netdev_chain net/decnet/dn_dev.c: dnaddr_chain net/ipv4/devinet.c: inetaddr_chain It's possible that some of these classifications are wrong. If they are, please let us know or submit a patch to fix them. Note that any chain that gets called very frequently should be atomic, because the rwsem read-locking used for blocking chains is very likely to incur cache misses on SMP systems. (However, if the chain's callout routines may sleep then the chain cannot be atomic.) The patch set was written by Alan Stern and Chandra Seetharaman, incorporating material written by Keith Owens and suggestions from Paul McKenney and Andrew Morton. [jes@sgi.com: restructure the notifier chain initialization macros] Signed-off-by: Alan Stern Signed-off-by: Chandra Seetharaman Signed-off-by: Jes Sorensen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/kernel/setup_64.c | 3 ++- arch/powerpc/kernel/traps.c | 16 ++++++++-------- arch/powerpc/platforms/pseries/reconfig.c | 10 +++++----- 3 files changed, 15 insertions(+), 14 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 2f3fdad35594..e20c1fae3423 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -579,7 +579,8 @@ void __init setup_arch(char **cmdline_p) panic_timeout = 180; if (ppc_md.panic) - notifier_chain_register(&panic_notifier_list, &ppc64_panic_block); + atomic_notifier_chain_register(&panic_notifier_list, + &ppc64_panic_block); init_mm.start_code = PAGE_OFFSET; init_mm.end_code = (unsigned long) _etext; diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 98660aedeeb7..9763faab6739 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -74,19 +74,19 @@ EXPORT_SYMBOL(__debugger_dabr_match); EXPORT_SYMBOL(__debugger_fault_handler); #endif -struct notifier_block *powerpc_die_chain; -static DEFINE_SPINLOCK(die_notifier_lock); +ATOMIC_NOTIFIER_HEAD(powerpc_die_chain); int register_die_notifier(struct notifier_block *nb) { - int err = 0; - unsigned long flags; + return atomic_notifier_chain_register(&powerpc_die_chain, nb); +} +EXPORT_SYMBOL(register_die_notifier); - spin_lock_irqsave(&die_notifier_lock, flags); - err = notifier_chain_register(&powerpc_die_chain, nb); - spin_unlock_irqrestore(&die_notifier_lock, flags); - return err; +int unregister_die_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(&powerpc_die_chain, nb); } +EXPORT_SYMBOL(unregister_die_notifier); /* * Trap & Exception support diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 86cfa6ecdcf3..5ad90676567a 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c @@ -94,16 +94,16 @@ static struct device_node *derive_parent(const char *path) return parent; } -static struct notifier_block *pSeries_reconfig_chain; +static BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain); int pSeries_reconfig_notifier_register(struct notifier_block *nb) { - return notifier_chain_register(&pSeries_reconfig_chain, nb); + return blocking_notifier_chain_register(&pSeries_reconfig_chain, nb); } void pSeries_reconfig_notifier_unregister(struct notifier_block *nb) { - notifier_chain_unregister(&pSeries_reconfig_chain, nb); + blocking_notifier_chain_unregister(&pSeries_reconfig_chain, nb); } static int pSeries_reconfig_add_node(const char *path, struct property *proplist) @@ -131,7 +131,7 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist goto out_err; } - err = notifier_call_chain(&pSeries_reconfig_chain, + err = blocking_notifier_call_chain(&pSeries_reconfig_chain, PSERIES_RECONFIG_ADD, np); if (err == NOTIFY_BAD) { printk(KERN_ERR "Failed to add device node %s\n", path); @@ -171,7 +171,7 @@ static int pSeries_reconfig_remove_node(struct device_node *np) remove_node_proc_entries(np); - notifier_call_chain(&pSeries_reconfig_chain, + blocking_notifier_call_chain(&pSeries_reconfig_chain, PSERIES_RECONFIG_REMOVE, np); of_detach_node(np); -- cgit v1.2.2 From ff2e6d7e27cf1f757ab0d97e1a9e46de47152a0e Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 28 Mar 2006 09:28:14 +1100 Subject: powerpc: Fix goof in 6xx and POWER4 idle power-save functions This fixes a mistake I made when editing these functions - when I took out the interrupt disabling code (because interrupts are now disabled by the caller) I left the register that is used for the MSR value to be used during doze/nap uninitialized. This fixes it. Also updated some of the comments in idle_power4.S and removed some code that was copied over from idle_6xx.S but is no longer relevant (we don't ever clear the CPU_FTR_CAN_NAP bit at runtime for POWER4). Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/idle_6xx.S | 3 ++- arch/powerpc/kernel/idle_power4.S | 23 +++-------------------- 2 files changed, 5 insertions(+), 21 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/idle_6xx.S b/arch/powerpc/kernel/idle_6xx.S index 1647ea361ef7..12a4efbaa08f 100644 --- a/arch/powerpc/kernel/idle_6xx.S +++ b/arch/powerpc/kernel/idle_6xx.S @@ -144,7 +144,8 @@ BEGIN_FTR_SECTION DSSALL sync END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) - ori r7,r7,MSR_EE /* Could be ommited (already set) */ + mfmsr r7 + ori r7,r7,MSR_EE oris r7,r7,MSR_POW@h sync isync diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S index 692cf2ebe0f4..6dad1c02496e 100644 --- a/arch/powerpc/kernel/idle_power4.S +++ b/arch/powerpc/kernel/idle_power4.S @@ -1,11 +1,5 @@ /* - * This file contains the power_save function for 6xx & 7xxx CPUs - * rewritten in assembler - * - * Warning ! This code assumes that if your machine has a 750fx - * it will have PLL 1 set to low speed mode (used during NAP/DOZE). - * if this is not the case some additional changes will have to - * be done to check a runtime var (a bit like powersave-nap) + * This file contains the power_save function for 970-family CPUs. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -26,23 +20,10 @@ .text -/* - * Here is the power_save_6xx function. This could eventually be - * split into several functions & changing the function pointer - * depending on the various features. - */ _GLOBAL(power4_idle) BEGIN_FTR_SECTION blr END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP) - /* We must dynamically check for the NAP feature as it - * can be cleared by CPU init after the fixups are done - */ - LOAD_REG_ADDRBASE(r3,cur_cpu_spec) - ld r4,ADDROFF(cur_cpu_spec)(r3) - ld r4,CPU_SPEC_FEATURES(r4) - andi. r0,r4,CPU_FTR_CAN_NAP - beqlr /* Now check if user or arch enabled NAP mode */ LOAD_REG_ADDRBASE(r3,powersave_nap) lwz r4,ADDROFF(powersave_nap)(r3) @@ -54,6 +35,8 @@ BEGIN_FTR_SECTION DSSALL sync END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) + mfmsr r7 + ori r7,r7,MSR_EE oris r7,r7,MSR_POW@h sync isync -- cgit v1.2.2 From 10d713aef238b02a774766b2622027361630e28d Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Mon, 27 Mar 2006 18:26:42 -0600 Subject: powerpc: use memparse() for mem= command line parsing Use memparse() instead of our own code for handling the parsing of mem= Signed-off-by: Kumar Gala --- arch/powerpc/kernel/prom.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 5a24415a2e3c..95d15eb5c03f 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1030,25 +1030,13 @@ static int __init early_init_dt_scan_chosen(unsigned long node, if (strstr(cmd_line, "mem=")) { char *p, *q; - unsigned long maxmem = 0; for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) { q = p + 4; if (p > cmd_line && p[-1] != ' ') continue; - maxmem = simple_strtoul(q, &q, 0); - if (*q == 'k' || *q == 'K') { - maxmem <<= 10; - ++q; - } else if (*q == 'm' || *q == 'M') { - maxmem <<= 20; - ++q; - } else if (*q == 'g' || *q == 'G') { - maxmem <<= 30; - ++q; - } + memory_limit = memparse(q, &q); } - memory_limit = maxmem; } /* break now */ -- cgit v1.2.2 From 2f25194dbe0c4b2472ce133ea3e9bcbb14936ae7 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 27 Mar 2006 11:46:18 +1100 Subject: [PATCH] powerpc: export validate_sp for oprofile calltrace Export validate_sp so we can use it in the oprofile calltrace code. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/process.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index c6e81bbd615c..706090c99f47 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -770,7 +770,7 @@ out: return error; } -static int validate_sp(unsigned long sp, struct task_struct *p, +int validate_sp(unsigned long sp, struct task_struct *p, unsigned long nbytes) { unsigned long stack_page = (unsigned long)task_stack_page(p); @@ -808,6 +808,8 @@ static int validate_sp(unsigned long sp, struct task_struct *p, #define FRAME_MARKER 2 #endif +EXPORT_SYMBOL(validate_sp); + unsigned long get_wchan(struct task_struct *p) { unsigned long ip, sp; -- cgit v1.2.2 From 5cd272085bbc905532869f3e1fd18a7100496b56 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Mon, 27 Mar 2006 23:43:27 -0600 Subject: powerpc: move math-emu over to arch/powerpc Towards the goal of having arch/powerpc not build anything over in arch/ppc move math-emu over. Also, killed some references to arch/ppc/ in the arch/powerpc Makefile which should belong in drivers/ when the particular sub-arch's move over to arch/powerpc. Signed-off-by: Kumar Gala --- arch/powerpc/Makefile | 6 +- arch/powerpc/math-emu/Makefile | 13 + arch/powerpc/math-emu/double.h | 129 +++++++ arch/powerpc/math-emu/fabs.c | 18 + arch/powerpc/math-emu/fadd.c | 38 ++ arch/powerpc/math-emu/fadds.c | 39 ++ arch/powerpc/math-emu/fcmpo.c | 46 +++ arch/powerpc/math-emu/fcmpu.c | 42 +++ arch/powerpc/math-emu/fctiw.c | 25 ++ arch/powerpc/math-emu/fctiwz.c | 32 ++ arch/powerpc/math-emu/fdiv.c | 53 +++ arch/powerpc/math-emu/fdivs.c | 55 +++ arch/powerpc/math-emu/fmadd.c | 48 +++ arch/powerpc/math-emu/fmadds.c | 49 +++ arch/powerpc/math-emu/fmr.c | 18 + arch/powerpc/math-emu/fmsub.c | 51 +++ arch/powerpc/math-emu/fmsubs.c | 52 +++ arch/powerpc/math-emu/fmul.c | 42 +++ arch/powerpc/math-emu/fmuls.c | 43 +++ arch/powerpc/math-emu/fnabs.c | 18 + arch/powerpc/math-emu/fneg.c | 18 + arch/powerpc/math-emu/fnmadd.c | 51 +++ arch/powerpc/math-emu/fnmadds.c | 52 +++ arch/powerpc/math-emu/fnmsub.c | 54 +++ arch/powerpc/math-emu/fnmsubs.c | 55 +++ arch/powerpc/math-emu/fres.c | 12 + arch/powerpc/math-emu/frsp.c | 25 ++ arch/powerpc/math-emu/frsqrte.c | 12 + arch/powerpc/math-emu/fsel.c | 38 ++ arch/powerpc/math-emu/fsqrt.c | 37 ++ arch/powerpc/math-emu/fsqrts.c | 38 ++ arch/powerpc/math-emu/fsub.c | 41 +++ arch/powerpc/math-emu/fsubs.c | 42 +++ arch/powerpc/math-emu/lfd.c | 19 + arch/powerpc/math-emu/lfs.c | 37 ++ arch/powerpc/math-emu/math.c | 483 +++++++++++++++++++++++++ arch/powerpc/math-emu/mcrfs.c | 31 ++ arch/powerpc/math-emu/mffs.c | 17 + arch/powerpc/math-emu/mtfsb0.c | 18 + arch/powerpc/math-emu/mtfsb1.c | 18 + arch/powerpc/math-emu/mtfsf.c | 45 +++ arch/powerpc/math-emu/mtfsfi.c | 23 ++ arch/powerpc/math-emu/op-1.h | 245 +++++++++++++ arch/powerpc/math-emu/op-2.h | 433 +++++++++++++++++++++++ arch/powerpc/math-emu/op-4.h | 297 ++++++++++++++++ arch/powerpc/math-emu/op-common.h | 688 ++++++++++++++++++++++++++++++++++++ arch/powerpc/math-emu/sfp-machine.h | 377 ++++++++++++++++++++ arch/powerpc/math-emu/single.h | 66 ++++ arch/powerpc/math-emu/soft-fp.h | 104 ++++++ arch/powerpc/math-emu/stfd.c | 20 ++ arch/powerpc/math-emu/stfiwx.c | 16 + arch/powerpc/math-emu/stfs.c | 41 +++ arch/powerpc/math-emu/types.c | 51 +++ arch/powerpc/math-emu/udivmodti4.c | 191 ++++++++++ 54 files changed, 4507 insertions(+), 5 deletions(-) create mode 100644 arch/powerpc/math-emu/Makefile create mode 100644 arch/powerpc/math-emu/double.h create mode 100644 arch/powerpc/math-emu/fabs.c create mode 100644 arch/powerpc/math-emu/fadd.c create mode 100644 arch/powerpc/math-emu/fadds.c create mode 100644 arch/powerpc/math-emu/fcmpo.c create mode 100644 arch/powerpc/math-emu/fcmpu.c create mode 100644 arch/powerpc/math-emu/fctiw.c create mode 100644 arch/powerpc/math-emu/fctiwz.c create mode 100644 arch/powerpc/math-emu/fdiv.c create mode 100644 arch/powerpc/math-emu/fdivs.c create mode 100644 arch/powerpc/math-emu/fmadd.c create mode 100644 arch/powerpc/math-emu/fmadds.c create mode 100644 arch/powerpc/math-emu/fmr.c create mode 100644 arch/powerpc/math-emu/fmsub.c create mode 100644 arch/powerpc/math-emu/fmsubs.c create mode 100644 arch/powerpc/math-emu/fmul.c create mode 100644 arch/powerpc/math-emu/fmuls.c create mode 100644 arch/powerpc/math-emu/fnabs.c create mode 100644 arch/powerpc/math-emu/fneg.c create mode 100644 arch/powerpc/math-emu/fnmadd.c create mode 100644 arch/powerpc/math-emu/fnmadds.c create mode 100644 arch/powerpc/math-emu/fnmsub.c create mode 100644 arch/powerpc/math-emu/fnmsubs.c create mode 100644 arch/powerpc/math-emu/fres.c create mode 100644 arch/powerpc/math-emu/frsp.c create mode 100644 arch/powerpc/math-emu/frsqrte.c create mode 100644 arch/powerpc/math-emu/fsel.c create mode 100644 arch/powerpc/math-emu/fsqrt.c create mode 100644 arch/powerpc/math-emu/fsqrts.c create mode 100644 arch/powerpc/math-emu/fsub.c create mode 100644 arch/powerpc/math-emu/fsubs.c create mode 100644 arch/powerpc/math-emu/lfd.c create mode 100644 arch/powerpc/math-emu/lfs.c create mode 100644 arch/powerpc/math-emu/math.c create mode 100644 arch/powerpc/math-emu/mcrfs.c create mode 100644 arch/powerpc/math-emu/mffs.c create mode 100644 arch/powerpc/math-emu/mtfsb0.c create mode 100644 arch/powerpc/math-emu/mtfsb1.c create mode 100644 arch/powerpc/math-emu/mtfsf.c create mode 100644 arch/powerpc/math-emu/mtfsfi.c create mode 100644 arch/powerpc/math-emu/op-1.h create mode 100644 arch/powerpc/math-emu/op-2.h create mode 100644 arch/powerpc/math-emu/op-4.h create mode 100644 arch/powerpc/math-emu/op-common.h create mode 100644 arch/powerpc/math-emu/sfp-machine.h create mode 100644 arch/powerpc/math-emu/single.h create mode 100644 arch/powerpc/math-emu/soft-fp.h create mode 100644 arch/powerpc/math-emu/stfd.c create mode 100644 arch/powerpc/math-emu/stfiwx.c create mode 100644 arch/powerpc/math-emu/stfs.c create mode 100644 arch/powerpc/math-emu/types.c create mode 100644 arch/powerpc/math-emu/udivmodti4.c (limited to 'arch/powerpc') diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 9586899de68a..6ec84d37a337 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -129,12 +129,8 @@ core-y += arch/powerpc/kernel/ \ arch/powerpc/lib/ \ arch/powerpc/sysdev/ \ arch/powerpc/platforms/ -core-$(CONFIG_MATH_EMULATION) += arch/ppc/math-emu/ +core-$(CONFIG_MATH_EMULATION) += arch/powerpc/math-emu/ core-$(CONFIG_XMON) += arch/powerpc/xmon/ -core-$(CONFIG_APUS) += arch/ppc/amiga/ -drivers-$(CONFIG_8xx) += arch/ppc/8xx_io/ -drivers-$(CONFIG_4xx) += arch/ppc/4xx_io/ -drivers-$(CONFIG_CPM2) += arch/ppc/8260_io/ drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/ diff --git a/arch/powerpc/math-emu/Makefile b/arch/powerpc/math-emu/Makefile new file mode 100644 index 000000000000..754143e8936b --- /dev/null +++ b/arch/powerpc/math-emu/Makefile @@ -0,0 +1,13 @@ + +obj-y := math.o fmr.o lfd.o stfd.o + +obj-$(CONFIG_MATH_EMULATION) += fabs.o fadd.o fadds.o fcmpo.o fcmpu.o \ + fctiw.o fctiwz.o fdiv.o fdivs.o \ + fmadd.o fmadds.o fmsub.o fmsubs.o \ + fmul.o fmuls.o fnabs.o fneg.o types.o \ + fnmadd.o fnmadds.o fnmsub.o fnmsubs.o \ + fres.o frsp.o frsqrte.o fsel.o lfs.o \ + fsqrt.o fsqrts.o fsub.o fsubs.o \ + mcrfs.o mffs.o mtfsb0.o mtfsb1.o \ + mtfsf.o mtfsfi.o stfiwx.o stfs.o \ + udivmodti4.o diff --git a/arch/powerpc/math-emu/double.h b/arch/powerpc/math-emu/double.h new file mode 100644 index 000000000000..ffba8b67f059 --- /dev/null +++ b/arch/powerpc/math-emu/double.h @@ -0,0 +1,129 @@ +/* + * Definitions for IEEE Double Precision + */ + +#if _FP_W_TYPE_SIZE < 32 +#error "Here's a nickel kid. Go buy yourself a real computer." +#endif + +#if _FP_W_TYPE_SIZE < 64 +#define _FP_FRACTBITS_D (2 * _FP_W_TYPE_SIZE) +#else +#define _FP_FRACTBITS_D _FP_W_TYPE_SIZE +#endif + +#define _FP_FRACBITS_D 53 +#define _FP_FRACXBITS_D (_FP_FRACTBITS_D - _FP_FRACBITS_D) +#define _FP_WFRACBITS_D (_FP_WORKBITS + _FP_FRACBITS_D) +#define _FP_WFRACXBITS_D (_FP_FRACTBITS_D - _FP_WFRACBITS_D) +#define _FP_EXPBITS_D 11 +#define _FP_EXPBIAS_D 1023 +#define _FP_EXPMAX_D 2047 + +#define _FP_QNANBIT_D \ + ((_FP_W_TYPE)1 << ((_FP_FRACBITS_D-2) % _FP_W_TYPE_SIZE)) +#define _FP_IMPLBIT_D \ + ((_FP_W_TYPE)1 << ((_FP_FRACBITS_D-1) % _FP_W_TYPE_SIZE)) +#define _FP_OVERFLOW_D \ + ((_FP_W_TYPE)1 << (_FP_WFRACBITS_D % _FP_W_TYPE_SIZE)) + +#if _FP_W_TYPE_SIZE < 64 + +union _FP_UNION_D +{ + double flt; + struct { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned sign : 1; + unsigned exp : _FP_EXPBITS_D; + unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE; + unsigned frac0 : _FP_W_TYPE_SIZE; +#else + unsigned frac0 : _FP_W_TYPE_SIZE; + unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE; + unsigned exp : _FP_EXPBITS_D; + unsigned sign : 1; +#endif + } bits __attribute__((packed)); +}; + +#define FP_DECL_D(X) _FP_DECL(2,X) +#define FP_UNPACK_RAW_D(X,val) _FP_UNPACK_RAW_2(D,X,val) +#define FP_PACK_RAW_D(val,X) _FP_PACK_RAW_2(D,val,X) + +#define FP_UNPACK_D(X,val) \ + do { \ + _FP_UNPACK_RAW_2(D,X,val); \ + _FP_UNPACK_CANONICAL(D,2,X); \ + } while (0) + +#define FP_PACK_D(val,X) \ + do { \ + _FP_PACK_CANONICAL(D,2,X); \ + _FP_PACK_RAW_2(D,val,X); \ + } while (0) + +#define FP_NEG_D(R,X) _FP_NEG(D,2,R,X) +#define FP_ADD_D(R,X,Y) _FP_ADD(D,2,R,X,Y) +#define FP_SUB_D(R,X,Y) _FP_SUB(D,2,R,X,Y) +#define FP_MUL_D(R,X,Y) _FP_MUL(D,2,R,X,Y) +#define FP_DIV_D(R,X,Y) _FP_DIV(D,2,R,X,Y) +#define FP_SQRT_D(R,X) _FP_SQRT(D,2,R,X) + +#define FP_CMP_D(r,X,Y,un) _FP_CMP(D,2,r,X,Y,un) +#define FP_CMP_EQ_D(r,X,Y) _FP_CMP_EQ(D,2,r,X,Y) + +#define FP_TO_INT_D(r,X,rsz,rsg) _FP_TO_INT(D,2,r,X,rsz,rsg) +#define FP_FROM_INT_D(X,r,rs,rt) _FP_FROM_INT(D,2,X,r,rs,rt) + +#else + +union _FP_UNION_D +{ + double flt; + struct { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned sign : 1; + unsigned exp : _FP_EXPBITS_D; + unsigned long frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0); +#else + unsigned long frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0); + unsigned exp : _FP_EXPBITS_D; + unsigned sign : 1; +#endif + } bits __attribute__((packed)); +}; + +#define FP_DECL_D(X) _FP_DECL(1,X) +#define FP_UNPACK_RAW_D(X,val) _FP_UNPACK_RAW_1(D,X,val) +#define FP_PACK_RAW_D(val,X) _FP_PACK_RAW_1(D,val,X) + +#define FP_UNPACK_D(X,val) \ + do { \ + _FP_UNPACK_RAW_1(D,X,val); \ + _FP_UNPACK_CANONICAL(D,1,X); \ + } while (0) + +#define FP_PACK_D(val,X) \ + do { \ + _FP_PACK_CANONICAL(D,1,X); \ + _FP_PACK_RAW_1(D,val,X); \ + } while (0) + +#define FP_NEG_D(R,X) _FP_NEG(D,1,R,X) +#define FP_ADD_D(R,X,Y) _FP_ADD(D,1,R,X,Y) +#define FP_SUB_D(R,X,Y) _FP_SUB(D,1,R,X,Y) +#define FP_MUL_D(R,X,Y) _FP_MUL(D,1,R,X,Y) +#define FP_DIV_D(R,X,Y) _FP_DIV(D,1,R,X,Y) +#define FP_SQRT_D(R,X) _FP_SQRT(D,1,R,X) + +/* The implementation of _FP_MUL_D and _FP_DIV_D should be chosen by + the target machine. */ + +#define FP_CMP_D(r,X,Y,un) _FP_CMP(D,1,r,X,Y,un) +#define FP_CMP_EQ_D(r,X,Y) _FP_CMP_EQ(D,1,r,X,Y) + +#define FP_TO_INT_D(r,X,rsz,rsg) _FP_TO_INT(D,1,r,X,rsz,rsg) +#define FP_FROM_INT_D(X,r,rs,rt) _FP_FROM_INT(D,1,X,r,rs,rt) + +#endif /* W_TYPE_SIZE < 64 */ diff --git a/arch/powerpc/math-emu/fabs.c b/arch/powerpc/math-emu/fabs.c new file mode 100644 index 000000000000..41f0617f3d3a --- /dev/null +++ b/arch/powerpc/math-emu/fabs.c @@ -0,0 +1,18 @@ +#include +#include +#include + +int +fabs(u32 *frD, u32 *frB) +{ + frD[0] = frB[0] & 0x7fffffff; + frD[1] = frB[1]; + +#ifdef DEBUG + printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB); + dump_double(frD); + printk("\n"); +#endif + + return 0; +} diff --git a/arch/powerpc/math-emu/fadd.c b/arch/powerpc/math-emu/fadd.c new file mode 100644 index 000000000000..fc8836488b64 --- /dev/null +++ b/arch/powerpc/math-emu/fadd.c @@ -0,0 +1,38 @@ +#include +#include +#include + +#include "soft-fp.h" +#include "double.h" + +int +fadd(void *frD, void *frA, void *frB) +{ + FP_DECL_D(A); + FP_DECL_D(B); + FP_DECL_D(R); + int ret = 0; + +#ifdef DEBUG + printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB); +#endif + + __FP_UNPACK_D(A, frA); + __FP_UNPACK_D(B, frB); + +#ifdef DEBUG + printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); + printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); +#endif + + if (A_s != B_s && A_c == FP_CLS_INF && B_c == FP_CLS_INF) + ret |= EFLAG_VXISI; + + FP_ADD_D(R, A, B); + +#ifdef DEBUG + printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); +#endif + + return (ret | __FP_PACK_D(frD, R)); +} diff --git a/arch/powerpc/math-emu/fadds.c b/arch/powerpc/math-emu/fadds.c new file mode 100644 index 000000000000..93025b6c8f3c --- /dev/null +++ b/arch/powerpc/math-emu/fadds.c @@ -0,0 +1,39 @@ +#include +#include +#include + +#include "soft-fp.h" +#include "double.h" +#include "single.h" + +int +fadds(void *frD, void *frA, void *frB) +{ + FP_DECL_D(A); + FP_DECL_D(B); + FP_DECL_D(R); + int ret = 0; + +#ifdef DEBUG + printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB); +#endif + + __FP_UNPACK_D(A, frA); + __FP_UNPACK_D(B, frB); + +#ifdef DEBUG + printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); + printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); +#endif + + if (A_s != B_s && A_c == FP_CLS_INF && B_c == FP_CLS_INF) + ret |= EFLAG_VXISI; + + FP_ADD_D(R, A, B); + +#ifdef DEBUG + printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); +#endif + + return (ret | __FP_PACK_DS(frD, R)); +} diff --git a/arch/powerpc/math-emu/fcmpo.c b/arch/powerpc/math-emu/fcmpo.c new file mode 100644 index 000000000000..4efac394b4cb --- /dev/null +++ b/arch/powerpc/math-emu/fcmpo.c @@ -0,0 +1,46 @@ +#include +#include +#include + +#include "soft-fp.h" +#include "double.h" + +int +fcmpo(u32 *ccr, int crfD, void *frA, void *frB) +{ + FP_DECL_D(A); + FP_DECL_D(B); + int code[4] = { (1 << 3), (1 << 1), (1 << 2), (1 << 0) }; + long cmp; + int ret = 0; + +#ifdef DEBUG + printk("%s: %p (%08x) %d %p %p\n", __FUNCTION__, ccr, *ccr, crfD, frA, frB); +#endif + + __FP_UNPACK_D(A, frA); + __FP_UNPACK_D(B, frB); + +#ifdef DEBUG + printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); + printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); +#endif + + if (A_c == FP_CLS_NAN || B_c == FP_CLS_NAN) + ret |= EFLAG_VXVC; + + FP_CMP_D(cmp, A, B, 2); + cmp = code[(cmp + 1) & 3]; + + __FPU_FPSCR &= ~(0x1f000); + __FPU_FPSCR |= (cmp << 12); + + *ccr &= ~(15 << ((7 - crfD) << 2)); + *ccr |= (cmp << ((7 - crfD) << 2)); + +#ifdef DEBUG + printk("CR: %08x\n", *ccr); +#endif + + return ret; +} diff --git a/arch/powerpc/math-emu/fcmpu.c b/arch/powerpc/math-emu/fcmpu.c new file mode 100644 index 000000000000..b7e33176e618 --- /dev/null +++ b/arch/powerpc/math-emu/fcmpu.c @@ -0,0 +1,42 @@ +#include +#include +#include + +#include "soft-fp.h" +#include "double.h" + +int +fcmpu(u32 *ccr, int crfD, void *frA, void *frB) +{ + FP_DECL_D(A); + FP_DECL_D(B); + int code[4] = { (1 << 3), (1 << 1), (1 << 2), (1 << 0) }; + long cmp; + +#ifdef DEBUG + printk("%s: %p (%08x) %d %p %p\n", __FUNCTION__, ccr, *ccr, crfD, frA, frB); +#endif + + __FP_UNPACK_D(A, frA); + __FP_UNPACK_D(B, frB); + +#ifdef DEBUG + printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); + printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); +#endif + + FP_CMP_D(cmp, A, B, 2); + cmp = code[(cmp + 1) & 3]; + + __FPU_FPSCR &= ~(0x1f000); + __FPU_FPSCR |= (cmp << 12); + + *ccr &= ~(15 << ((7 - crfD) << 2)); + *ccr |= (cmp << ((7 - crfD) << 2)); + +#ifdef DEBUG + printk("CR: %08x\n", *ccr); +#endif + + return 0; +} diff --git a/arch/powerpc/math-emu/fctiw.c b/arch/powerpc/math-emu/fctiw.c new file mode 100644 index 000000000000..3b3c98b840cf --- /dev/null +++ b/arch/powerpc/math-emu/fctiw.c @@ -0,0 +1,25 @@ +#include +#include +#include + +#include "soft-fp.h" +#include "double.h" + +int +fctiw(u32 *frD, void *frB) +{ + FP_DECL_D(B); + unsigned int r; + + __FP_UNPACK_D(B, frB); + FP_TO_INT_D(r, B, 32, 1); + frD[1] = r; + +#ifdef DEBUG + printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB); + dump_double(frD); + printk("\n"); +#endif + + return 0; +} diff --git a/arch/powerpc/math-emu/fctiwz.c b/arch/powerpc/math-emu/fctiwz.c new file mode 100644 index 000000000000..7717eb6fcfb6 --- /dev/null +++ b/arch/powerpc/math-emu/fctiwz.c @@ -0,0 +1,32 @@ +#include +#include +#include + +#include "soft-fp.h" +#include "double.h" + +int +fctiwz(u32 *frD, void *frB) +{ + FP_DECL_D(B); + u32 fpscr; + unsigned int r; + + fpscr = __FPU_FPSCR; + __FPU_FPSCR &= ~(3); + __FPU_FPSCR |= FP_RND_ZERO; + + __FP_UNPACK_D(B, frB); + FP_TO_INT_D(r, B, 32, 1); + frD[1] = r; + + __FPU_FPSCR = fpscr; + +#ifdef DEBUG + printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB); + dump_double(frD); + printk("\n"); +#endif + + return 0; +} diff --git a/arch/powerpc/math-emu/fdiv.c b/arch/powerpc/math-emu/fdiv.c new file mode 100644 index 000000000000..f2fba825b2d0 --- /dev/null +++ b/arch/powerpc/math-emu/fdiv.c @@ -0,0 +1,53 @@ +#include +#include +#include + +#include "soft-fp.h" +#include "double.h" + +int +fdiv(void *frD, void *frA, void *frB) +{ + FP_DECL_D(A); + FP_DECL_D(B); + FP_DECL_D(R); + int ret = 0; + +#ifdef DEBUG + printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB); +#endif + + __FP_UNPACK_D(A, frA); + __FP_UNPACK_D(B, frB); + +#ifdef DEBUG + printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); + printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); +#endif + + if (A_c == FP_CLS_ZERO && B_c == FP_CLS_ZERO) { + ret |= EFLAG_VXZDZ; +#ifdef DEBUG + printk("%s: FPSCR_VXZDZ raised\n", __FUNCTION__); +#endif + } + if (A_c == FP_CLS_INF && B_c == FP_CLS_INF) { + ret |= EFLAG_VXIDI; +#ifdef DEBUG + printk("%s: FPSCR_VXIDI raised\n", __FUNCTION__); +#endif + } + + if (B_c == FP_CLS_ZERO && A_c != FP_CLS_ZERO) { + ret |= EFLAG_DIVZERO; + if (__FPU_TRAP_P(EFLAG_DIVZERO)) + return ret; + } + FP_DIV_D(R, A, B); + +#ifdef DEBUG + printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); +#endif + + return (ret | __FP_PACK_D(frD, R)); +} diff --git a/arch/powerpc/math-emu/fdivs.c b/arch/powerpc/math-emu/fdivs.c new file mode 100644 index 000000000000..b971196e3175 --- /dev/null +++ b/arch/powerpc/math-emu/fdivs.c @@ -0,0 +1,55 @@ +#include +#include +#include + +#include "soft-fp.h" +#include "double.h" +#include "single.h" + +int +fdivs(void *frD, void *frA, void *frB) +{ + FP_DECL_D(A); + FP_DECL_D(B); + FP_DECL_D(R); + int ret = 0; + +#ifdef DEBUG + printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB); +#endif + + __FP_UNPACK_D(A, frA); + __FP_UNPACK_D(B, frB); + +#ifdef DEBUG + printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); + printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); +#endif + + if (A_c == FP_CLS_ZERO && B_c == FP_CLS_ZERO) { + ret |= EFLAG_VXZDZ; +#ifdef DEBUG + printk("%s: FPSCR_VXZDZ raised\n", __FUNCTION__); +#endif + } + if (A_c == FP_CLS_INF && B_c == FP_CLS_INF) { + ret |= EFLAG_VXIDI; +#ifdef DEBUG + printk("%s: FPSCR_VXIDI raised\n", __FUNCTION__); +#endif + } + + if (B_c == FP_CLS_ZERO && A_c != FP_CLS_ZERO) { + ret |= EFLAG_DIVZERO; + if (__FPU_TRAP_P(EFLAG_DIVZERO)) + return ret; + } + + FP_DIV_D(R, A, B); + +#ifdef DEBUG + printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); +#endif + + return (ret | __FP_PACK_DS(frD, R)); +} diff --git a/arch/powerpc/math-emu/fmadd.c b/arch/powerpc/math-emu/fmadd.c new file mode 100644 index 000000000000..0a1dbce793e9 --- /dev/null +++ b/arch/powerpc/math-emu/fmadd.c @@ -0,0 +1,48 @@ +#include +#include +#include + +#include "soft-fp.h" +#include "double.h" + +int +fmadd(void *frD, void *frA, void *frB, void *frC) +{ + FP_DECL_D(R); + FP_DECL_D(A); + FP_DECL_D(B); + FP_DECL_D(C); + FP_DECL_D(T); + int ret = 0; + +#ifdef DEBUG + printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC); +#endif + + __FP_UNPACK_D(A, frA); + __FP_UNPACK_D(B, frB); + __FP_UNPACK_D(C, frC); + +#ifdef DEBUG + printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); + printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); + printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c); +#endif + + if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) || + (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF)) + ret |= EFLAG_VXIMZ; + + FP_MUL_D(T, A, C); + + if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF) + ret |= EFLAG_VXISI; + + FP_ADD_D(R, T, B); + +#ifdef DEBUG + printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); +#endif + + return (ret | __FP_PACK_D(frD, R)); +} diff --git a/arch/powerpc/math-emu/fmadds.c b/arch/powerpc/math-emu/fmadds.c new file mode 100644 index 000000000000..0f70bba9445e --- /dev/null +++ b/arch/powerpc/math-emu/fmadds.c @@ -0,0 +1,49 @@ +#include +#include +#include + +#include "soft-fp.h" +#include "double.h" +#include "single.h" + +int +fmadds(void *frD, void *frA, void *frB, void *frC) +{ + FP_DECL_D(R); + FP_DECL_D(A); + FP_DECL_D(B); + FP_DECL_D(C); + FP_DECL_D(T); + int ret = 0; + +#ifdef DEBUG + printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC); +#endif + + __FP_UNPACK_D(A, frA); + __FP_UNPACK_D(B, frB); + __FP_UNPACK_D(C, frC); + +#ifdef DEBUG + printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); + printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); + printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c); +#endif + + if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) || + (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF)) + ret |= EFLAG_VXIMZ; + + FP_MUL_D(T, A, C); + + if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF) + ret |= EFLAG_VXISI; + + FP_ADD_D(R, T, B); + +#ifdef DEBUG + printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); +#endif + + return (ret | __FP_PACK_DS(frD, R)); +} diff --git a/arch/powerpc/math-emu/fmr.c b/arch/powerpc/math-emu/fmr.c new file mode 100644 index 000000000000..28df700c0c7e --- /dev/null +++ b/arch/powerpc/math-emu/fmr.c @@ -0,0 +1,18 @@ +#include +#include +#include + +int +fmr(u32 *frD, u32 *frB) +{ + frD[0] = frB[0]; + frD[1] = frB[1]; + +#ifdef DEBUG + printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB); + dump_double(frD); + printk("\n"); +#endif + + return 0; +} diff --git a/arch/powerpc/math-emu/fmsub.c b/arch/powerpc/math-emu/fmsub.c new file mode 100644 index 000000000000..203fd48a6fec --- /dev/null +++ b/arch/powerpc/math-emu/fmsub.c @@ -0,0 +1,51 @@ +#include +#include +#include + +#include "soft-fp.h" +#include "double.h" + +int +fmsub(void *frD, void *frA, void *frB, void *frC) +{ + FP_DECL_D(R); + FP_DECL_D(A); + FP_DECL_D(B); + FP_DECL_D(C); + FP_DECL_D(T); + int ret = 0; + +#ifdef DEBUG + printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC); +#endif + + __FP_UNPACK_D(A, frA); + __FP_UNPACK_D(B, frB); + __FP_UNPACK_D(C, frC); + +#ifdef DEBUG + printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); + printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); + printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c); +#endif + + if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) || + (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF)) + ret |= EFLAG_VXIMZ; + + FP_MUL_D(T, A, C); + + if (B_c != FP_CLS_NAN) + B_s ^= 1; + + if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF) + ret |= EFLAG_VXISI; + + FP_ADD_D(R, T, B); + +#ifdef DEBUG + printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); +#endif + + return (ret | __FP_PACK_D(frD, R)); +} diff --git a/arch/powerpc/math-emu/fmsubs.c b/arch/powerpc/math-emu/fmsubs.c new file mode 100644 index 000000000000..8ce68624c189 --- /dev/null +++ b/arch/powerpc/math-emu/fmsubs.c @@ -0,0 +1,52 @@ +#include +#include +#include + +#include "soft-fp.h" +#include "double.h" +#include "single.h" + +int +fmsubs(void *frD, void *frA, void *frB, void *frC) +{ + FP_DECL_D(R); + FP_DECL_D(A); + FP_DECL_D(B); + FP_DECL_D(C); + FP_DECL_D(T); + int ret = 0; + +#ifdef DEBUG + printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC); +#endif + + __FP_UNPACK_D(A, frA); + __FP_UNPACK_D(B, frB); + __FP_UNPACK_D(C, frC); + +#ifdef DEBUG + printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); + printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); + printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c); +#endif + + if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) || + (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF)) + ret |= EFLAG_VXIMZ; + + FP_MUL_D(T, A, C); + + if (B_c != FP_CLS_NAN) + B_s ^= 1; + + if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF) + ret |= EFLAG_VXISI; + + FP_ADD_D(R, T, B); + +#ifdef DEBUG + printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); +#endif + + return (ret | __FP_PACK_DS(frD, R)); +} diff --git a/arch/powerpc/math-emu/fmul.c b/arch/powerpc/math-emu/fmul.c new file mode 100644 index 000000000000..66c7e79aae2e --- /dev/null +++ b/arch/powerpc/math-emu/fmul.c @@ -0,0 +1,42 @@ +#include +#include +#include + +#include "soft-fp.h" +#include "double.h" + +int +fmul(void *frD, void *frA, void *frB) +{ + FP_DECL_D(A); + FP_DECL_D(B); + FP_DECL_D(R); + int ret = 0; + +#ifdef DEBUG + printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB); +#endif + + __FP_UNPACK_D(A, frA); + __FP_UNPACK_D(B, frB); + +#ifdef DEBUG + printk("A: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n", + A_s, A_f1, A_f0, A_e, A_c, A_f1, A_f0, A_e + 1023); + printk("B: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n", + B_s, B_f1, B_f0, B_e, B_c, B_f1, B_f0, B_e + 1023); +#endif + + if ((A_c == FP_CLS_INF && B_c == FP_CLS_ZERO) || + (A_c == FP_CLS_ZERO && B_c == FP_CLS_INF)) + ret |= EFLAG_VXIMZ; + + FP_MUL_D(R, A, B); + +#ifdef DEBUG + printk("D: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n", + R_s, R_f1, R_f0, R_e, R_c, R_f1, R_f0, R_e + 1023); +#endif + + return (ret | __FP_PACK_D(frD, R)); +} diff --git a/arch/powerpc/math-emu/fmuls.c b/arch/powerpc/math-emu/fmuls.c new file mode 100644 index 000000000000..26bc4278271c --- /dev/null +++ b/arch/powerpc/math-emu/fmuls.c @@ -0,0 +1,43 @@ +#include +#include +#include + +#include "soft-fp.h" +#include "double.h" +#include "single.h" + +int +fmuls(void *frD, void *frA, void *frB) +{ + FP_DECL_D(A); + FP_DECL_D(B); + FP_DECL_D(R); + int ret = 0; + +#ifdef DEBUG + printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB); +#endif + + __FP_UNPACK_D(A, frA); + __FP_UNPACK_D(B, frB); + +#ifdef DEBUG + printk("A: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n", + A_s, A_f1, A_f0, A_e, A_c, A_f1, A_f0, A_e + 1023); + printk("B: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n", + B_s, B_f1, B_f0, B_e, B_c, B_f1, B_f0, B_e + 1023); +#endif + + if ((A_c == FP_CLS_INF && B_c == FP_CLS_ZERO) || + (A_c == FP_CLS_ZERO && B_c == FP_CLS_INF)) + ret |= EFLAG_VXIMZ; + + FP_MUL_D(R, A, B); + +#ifdef DEBUG + printk("D: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n", + R_s, R_f1, R_f0, R_e, R_c, R_f1, R_f0, R_e + 1023); +#endif + + return (ret | __FP_PACK_DS(frD, R)); +} diff --git a/arch/powerpc/math-emu/fnabs.c b/arch/powerpc/math-emu/fnabs.c new file mode 100644 index 000000000000..c6b913d179e0 --- /dev/null +++ b/arch/powerpc/math-emu/fnabs.c @@ -0,0 +1,18 @@ +#include +#include +#include + +int +fnabs(u32 *frD, u32 *frB) +{ + frD[0] = frB[0] | 0x80000000; + frD[1] = frB[1]; + +#ifdef DEBUG + printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB); + dump_double(frD); + printk("\n"); +#endif + + return 0; +} diff --git a/arch/powerpc/math-emu/fneg.c b/arch/powerpc/math-emu/fneg.c new file mode 100644 index 000000000000..fe9a98deff69 --- /dev/null +++ b/arch/powerpc/math-emu/fneg.c @@ -0,0 +1,18 @@ +#include +#include +#include + +int +fneg(u32 *frD, u32 *frB) +{ + frD[0] = frB[0] ^ 0x80000000; + frD[1] = frB[1]; + +#ifdef DEBUG + printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB); + dump_double(frD); + printk("\n"); +#endif + + return 0; +} diff --git a/arch/powerpc/math-emu/fnmadd.c b/arch/powerpc/math-emu/fnmadd.c new file mode 100644 index 000000000000..7f312276d920 --- /dev/null +++ b/arch/powerpc/math-emu/fnmadd.c @@ -0,0 +1,51 @@ +#include +#include +#include + +#include "soft-fp.h" +#include "double.h" + +int +fnmadd(void *frD, void *frA, void *frB, void *frC) +{ + FP_DECL_D(R); + FP_DECL_D(A); + FP_DECL_D(B); + FP_DECL_D(C); + FP_DECL_D(T); + int ret = 0; + +#ifdef DEBUG + printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC); +#endif + + __FP_UNPACK_D(A, frA); + __FP_UNPACK_D(B, frB); + __FP_UNPACK_D(C, frC); + +#ifdef DEBUG + printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); + printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); + printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c); +#endif + + if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) || + (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF)) + ret |= EFLAG_VXIMZ; + + FP_MUL_D(T, A, C); + + if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF) + ret |= EFLAG_VXISI; + + FP_ADD_D(R, T, B); + + if (R_c != FP_CLS_NAN) + R_s ^= 1; + +#ifdef DEBUG + printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); +#endif + + return (ret | __FP_PACK_D(frD, R)); +} diff --git a/arch/powerpc/math-emu/fnmadds.c b/arch/powerpc/math-emu/fnmadds.c new file mode 100644 index 000000000000..65454c9c70bc --- /dev/null +++ b/arch/powerpc/math-emu/fnmadds.c @@ -0,0 +1,52 @@ +#include +#include +#include + +#include "soft-fp.h" +#include "double.h" +#include "single.h" + +int +fnmadds(void *frD, void *frA, void *frB, void *frC) +{ + FP_DECL_D(R); + FP_DECL_D(A); + FP_DECL_D(B); + FP_DECL_D(C); + FP_DECL_D(T); + int ret = 0; + +#ifdef DEBUG + printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC); +#endif + + __FP_UNPACK_D(A, frA); + __FP_UNPACK_D(B, frB); + __FP_UNPACK_D(C, frC); + +#ifdef DEBUG + printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); + printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); + printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c); +#endif + + if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) || + (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF)) + ret |= EFLAG_VXIMZ; + + FP_MUL_D(T, A, C); + + if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF) + ret |= EFLAG_VXISI; + + FP_ADD_D(R, T, B); + + if (R_c != FP_CLS_NAN) + R_s ^= 1; + +#ifdef DEBUG + printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); +#endif + + return (ret | __FP_PACK_DS(frD, R)); +} diff --git a/arch/powerpc/math-emu/fnmsub.c b/arch/powerpc/math-emu/fnmsub.c new file mode 100644 index 000000000000..f1ca7482b5f0 --- /dev/null +++ b/arch/powerpc/math-emu/fnmsub.c @@ -0,0 +1,54 @@ +#include +#include +#include + +#include "soft-fp.h" +#include "double.h" + +int +fnmsub(void *frD, void *frA, void *frB, void *frC) +{ + FP_DECL_D(R); + FP_DECL_D(A); + FP_DECL_D(B); + FP_DECL_D(C); + FP_DECL_D(T); + int ret = 0; + +#ifdef DEBUG + printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC); +#endif + + __FP_UNPACK_D(A, frA); + __FP_UNPACK_D(B, frB); + __FP_UNPACK_D(C, frC); + +#ifdef DEBUG + printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); + printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); + printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c); +#endif + + if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) || + (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF)) + ret |= EFLAG_VXIMZ; + + FP_MUL_D(T, A, C); + + if (B_c != FP_CLS_NAN) + B_s ^= 1; + + if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF) + ret |= EFLAG_VXISI; + + FP_ADD_D(R, T, B); + + if (R_c != FP_CLS_NAN) + R_s ^= 1; + +#ifdef DEBUG + printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); +#endif + + return (ret | __FP_PACK_D(frD, R)); +} diff --git a/arch/powerpc/math-emu/fnmsubs.c b/arch/powerpc/math-emu/fnmsubs.c new file mode 100644 index 000000000000..5c9a09a87dc7 --- /dev/null +++ b/arch/powerpc/math-emu/fnmsubs.c @@ -0,0 +1,55 @@ +#include +#include +#include + +#include "soft-fp.h" +#include "double.h" +#include "single.h" + +int +fnmsubs(void *frD, void *frA, void *frB, void *frC) +{ + FP_DECL_D(R); + FP_DECL_D(A); + FP_DECL_D(B); + FP_DECL_D(C); + FP_DECL_D(T); + int ret = 0; + +#ifdef DEBUG + printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC); +#endif + + __FP_UNPACK_D(A, frA); + __FP_UNPACK_D(B, frB); + __FP_UNPACK_D(C, frC); + +#ifdef DEBUG + printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); + printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); + printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c); +#endif + + if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) || + (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF)) + ret |= EFLAG_VXIMZ; + + FP_MUL_D(T, A, C); + + if (B_c != FP_CLS_NAN) + B_s ^= 1; + + if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF) + ret |= EFLAG_VXISI; + + FP_ADD_D(R, T, B); + + if (R_c != FP_CLS_NAN) + R_s ^= 1; + +#ifdef DEBUG + printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); +#endif + + return (ret | __FP_PACK_DS(frD, R)); +} diff --git a/arch/powerpc/math-emu/fres.c b/arch/powerpc/math-emu/fres.c new file mode 100644 index 000000000000..ec11e46d20af --- /dev/null +++ b/arch/powerpc/math-emu/fres.c @@ -0,0 +1,12 @@ +#include +#include +#include + +int +fres(void *frD, void *frB) +{ +#ifdef DEBUG + printk("%s: %p %p\n", __FUNCTION__, frD, frB); +#endif + return -ENOSYS; +} diff --git a/arch/powerpc/math-emu/frsp.c b/arch/powerpc/math-emu/frsp.c new file mode 100644 index 000000000000..d879b2a3d0c9 --- /dev/null +++ b/arch/powerpc/math-emu/frsp.c @@ -0,0 +1,25 @@ +#include +#include +#include + +#include "soft-fp.h" +#include "double.h" +#include "single.h" + +int +frsp(void *frD, void *frB) +{ + FP_DECL_D(B); + +#ifdef DEBUG + printk("%s: D %p, B %p\n", __FUNCTION__, frD, frB); +#endif + + __FP_UNPACK_D(B, frB); + +#ifdef DEBUG + printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); +#endif + + return __FP_PACK_DS(frD, B); +} diff --git a/arch/powerpc/math-emu/frsqrte.c b/arch/powerpc/math-emu/frsqrte.c new file mode 100644 index 000000000000..a11ae1829850 --- /dev/null +++ b/arch/powerpc/math-emu/frsqrte.c @@ -0,0 +1,12 @@ +#include +#include +#include + +int +frsqrte(void *frD, void *frB) +{ +#ifdef DEBUG + printk("%s: %p %p\n", __FUNCTION__, frD, frB); +#endif + return 0; +} diff --git a/arch/powerpc/math-emu/fsel.c b/arch/powerpc/math-emu/fsel.c new file mode 100644 index 000000000000..e36e6e72819a --- /dev/null +++ b/arch/powerpc/math-emu/fsel.c @@ -0,0 +1,38 @@ +#include +#include +#include + +#include "soft-fp.h" +#include "double.h" + +int +fsel(u32 *frD, void *frA, u32 *frB, u32 *frC) +{ + FP_DECL_D(A); + +#ifdef DEBUG + printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC); +#endif + + __FP_UNPACK_D(A, frA); + +#ifdef DEBUG + printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); + printk("B: %08x %08x\n", frB[0], frB[1]); + printk("C: %08x %08x\n", frC[0], frC[1]); +#endif + + if (A_c == FP_CLS_NAN || (A_c != FP_CLS_ZERO && A_s)) { + frD[0] = frB[0]; + frD[1] = frB[1]; + } else { + frD[0] = frC[0]; + frD[1] = frC[1]; + } + +#ifdef DEBUG + printk("D: %08x.%08x\n", frD[0], frD[1]); +#endif + + return 0; +} diff --git a/arch/powerpc/math-emu/fsqrt.c b/arch/powerpc/math-emu/fsqrt.c new file mode 100644 index 000000000000..6f8319f64a8a --- /dev/null +++ b/arch/powerpc/math-emu/fsqrt.c @@ -0,0 +1,37 @@ +#include +#include +#include + +#include "soft-fp.h" +#include "double.h" + +int +fsqrt(void *frD, void *frB) +{ + FP_DECL_D(B); + FP_DECL_D(R); + int ret = 0; + +#ifdef DEBUG + printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frB); +#endif + + __FP_UNPACK_D(B, frB); + +#ifdef DEBUG + printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); +#endif + + if (B_s && B_c != FP_CLS_ZERO) + ret |= EFLAG_VXSQRT; + if (B_c == FP_CLS_NAN) + ret |= EFLAG_VXSNAN; + + FP_SQRT_D(R, B); + +#ifdef DEBUG + printk("R: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); +#endif + + return (ret | __FP_PACK_D(frD, R)); +} diff --git a/arch/powerpc/math-emu/fsqrts.c b/arch/powerpc/math-emu/fsqrts.c new file mode 100644 index 000000000000..3b2b1cf55c12 --- /dev/null +++ b/arch/powerpc/math-emu/fsqrts.c @@ -0,0 +1,38 @@ +#include +#include +#include + +#include "soft-fp.h" +#include "double.h" +#include "single.h" + +int +fsqrts(void *frD, void *frB) +{ + FP_DECL_D(B); + FP_DECL_D(R); + int ret = 0; + +#ifdef DEBUG + printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frB); +#endif + + __FP_UNPACK_D(B, frB); + +#ifdef DEBUG + printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); +#endif + + if (B_s && B_c != FP_CLS_ZERO) + ret |= EFLAG_VXSQRT; + if (B_c == FP_CLS_NAN) + ret |= EFLAG_VXSNAN; + + FP_SQRT_D(R, B); + +#ifdef DEBUG + printk("R: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); +#endif + + return (ret | __FP_PACK_DS(frD, R)); +} diff --git a/arch/powerpc/math-emu/fsub.c b/arch/powerpc/math-emu/fsub.c new file mode 100644 index 000000000000..956679042bb2 --- /dev/null +++ b/arch/powerpc/math-emu/fsub.c @@ -0,0 +1,41 @@ +#include +#include +#include + +#include "soft-fp.h" +#include "double.h" + +int +fsub(void *frD, void *frA, void *frB) +{ + FP_DECL_D(A); + FP_DECL_D(B); + FP_DECL_D(R); + int ret = 0; + +#ifdef DEBUG + printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB); +#endif + + __FP_UNPACK_D(A, frA); + __FP_UNPACK_D(B, frB); + +#ifdef DEBUG + printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); + printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); +#endif + + if (B_c != FP_CLS_NAN) + B_s ^= 1; + + if (A_s != B_s && A_c == FP_CLS_INF && B_c == FP_CLS_INF) + ret |= EFLAG_VXISI; + + FP_ADD_D(R, A, B); + +#ifdef DEBUG + printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); +#endif + + return (ret | __FP_PACK_D(frD, R)); +} diff --git a/arch/powerpc/math-emu/fsubs.c b/arch/powerpc/math-emu/fsubs.c new file mode 100644 index 000000000000..3428117dfe8c --- /dev/null +++ b/arch/powerpc/math-emu/fsubs.c @@ -0,0 +1,42 @@ +#include +#include +#include + +#include "soft-fp.h" +#include "double.h" +#include "single.h" + +int +fsubs(void *frD, void *frA, void *frB) +{ + FP_DECL_D(A); + FP_DECL_D(B); + FP_DECL_D(R); + int ret = 0; + +#ifdef DEBUG + printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB); +#endif + + __FP_UNPACK_D(A, frA); + __FP_UNPACK_D(B, frB); + +#ifdef DEBUG + printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); + printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); +#endif + + if (B_c != FP_CLS_NAN) + B_s ^= 1; + + if (A_s != B_s && A_c == FP_CLS_INF && B_c == FP_CLS_INF) + ret |= EFLAG_VXISI; + + FP_ADD_D(R, A, B); + +#ifdef DEBUG + printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); +#endif + + return (ret | __FP_PACK_DS(frD, R)); +} diff --git a/arch/powerpc/math-emu/lfd.c b/arch/powerpc/math-emu/lfd.c new file mode 100644 index 000000000000..7d38101c329b --- /dev/null +++ b/arch/powerpc/math-emu/lfd.c @@ -0,0 +1,19 @@ +#include +#include +#include + +#include "sfp-machine.h" +#include "double.h" + +int +lfd(void *frD, void *ea) +{ + if (copy_from_user(frD, ea, sizeof(double))) + return -EFAULT; +#ifdef DEBUG + printk("%s: D %p, ea %p: ", __FUNCTION__, frD, ea); + dump_double(frD); + printk("\n"); +#endif + return 0; +} diff --git a/arch/powerpc/math-emu/lfs.c b/arch/powerpc/math-emu/lfs.c new file mode 100644 index 000000000000..c86dee3d7655 --- /dev/null +++ b/arch/powerpc/math-emu/lfs.c @@ -0,0 +1,37 @@ +#include +#include +#include + +#include "soft-fp.h" +#include "double.h" +#include "single.h" + +int +lfs(void *frD, void *ea) +{ + FP_DECL_D(R); + FP_DECL_S(A); + float f; + +#ifdef DEBUG + printk("%s: D %p, ea %p\n", __FUNCTION__, frD, ea); +#endif + + if (copy_from_user(&f, ea, sizeof(float))) + return -EFAULT; + + __FP_UNPACK_S(A, &f); + +#ifdef DEBUG + printk("A: %ld %lu %ld (%ld) [%08lx]\n", A_s, A_f, A_e, A_c, + *(unsigned long *)&f); +#endif + + FP_CONV(D, S, 2, 1, R, A); + +#ifdef DEBUG + printk("R: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); +#endif + + return __FP_PACK_D(frD, R); +} diff --git a/arch/powerpc/math-emu/math.c b/arch/powerpc/math-emu/math.c new file mode 100644 index 000000000000..589153472761 --- /dev/null +++ b/arch/powerpc/math-emu/math.c @@ -0,0 +1,483 @@ +/* + * Copyright (C) 1999 Eddie C. Dost (ecd@atecom.com) + */ + +#include +#include +#include + +#include +#include + +#include "sfp-machine.h" +#include "double.h" + +#define FLOATFUNC(x) extern int x(void *, void *, void *, void *) + +FLOATFUNC(fadd); +FLOATFUNC(fadds); +FLOATFUNC(fdiv); +FLOATFUNC(fdivs); +FLOATFUNC(fmul); +FLOATFUNC(fmuls); +FLOATFUNC(fsub); +FLOATFUNC(fsubs); + +FLOATFUNC(fmadd); +FLOATFUNC(fmadds); +FLOATFUNC(fmsub); +FLOATFUNC(fmsubs); +FLOATFUNC(fnmadd); +FLOATFUNC(fnmadds); +FLOATFUNC(fnmsub); +FLOATFUNC(fnmsubs); + +FLOATFUNC(fctiw); +FLOATFUNC(fctiwz); +FLOATFUNC(frsp); + +FLOATFUNC(fcmpo); +FLOATFUNC(fcmpu); + +FLOATFUNC(mcrfs); +FLOATFUNC(mffs); +FLOATFUNC(mtfsb0); +FLOATFUNC(mtfsb1); +FLOATFUNC(mtfsf); +FLOATFUNC(mtfsfi); + +FLOATFUNC(lfd); +FLOATFUNC(lfs); + +FLOATFUNC(stfd); +FLOATFUNC(stfs); +FLOATFUNC(stfiwx); + +FLOATFUNC(fabs); +FLOATFUNC(fmr); +FLOATFUNC(fnabs); +FLOATFUNC(fneg); + +/* Optional */ +FLOATFUNC(fres); +FLOATFUNC(frsqrte); +FLOATFUNC(fsel); +FLOATFUNC(fsqrt); +FLOATFUNC(fsqrts); + + +#define OP31 0x1f /* 31 */ +#define LFS 0x30 /* 48 */ +#define LFSU 0x31 /* 49 */ +#define LFD 0x32 /* 50 */ +#define LFDU 0x33 /* 51 */ +#define STFS 0x34 /* 52 */ +#define STFSU 0x35 /* 53 */ +#define STFD 0x36 /* 54 */ +#define STFDU 0x37 /* 55 */ +#define OP59 0x3b /* 59 */ +#define OP63 0x3f /* 63 */ + +/* Opcode 31: */ +/* X-Form: */ +#define LFSX 0x217 /* 535 */ +#define LFSUX 0x237 /* 567 */ +#define LFDX 0x257 /* 599 */ +#define LFDUX 0x277 /* 631 */ +#define STFSX 0x297 /* 663 */ +#define STFSUX 0x2b7 /* 695 */ +#define STFDX 0x2d7 /* 727 */ +#define STFDUX 0x2f7 /* 759 */ +#define STFIWX 0x3d7 /* 983 */ + +/* Opcode 59: */ +/* A-Form: */ +#define FDIVS 0x012 /* 18 */ +#define FSUBS 0x014 /* 20 */ +#define FADDS 0x015 /* 21 */ +#define FSQRTS 0x016 /* 22 */ +#define FRES 0x018 /* 24 */ +#define FMULS 0x019 /* 25 */ +#define FMSUBS 0x01c /* 28 */ +#define FMADDS 0x01d /* 29 */ +#define FNMSUBS 0x01e /* 30 */ +#define FNMADDS 0x01f /* 31 */ + +/* Opcode 63: */ +/* A-Form: */ +#define FDIV 0x012 /* 18 */ +#define FSUB 0x014 /* 20 */ +#define FADD 0x015 /* 21 */ +#define FSQRT 0x016 /* 22 */ +#define FSEL 0x017 /* 23 */ +#define FMUL 0x019 /* 25 */ +#define FRSQRTE 0x01a /* 26 */ +#define FMSUB 0x01c /* 28 */ +#define FMADD 0x01d /* 29 */ +#define FNMSUB 0x01e /* 30 */ +#define FNMADD 0x01f /* 31 */ + +/* X-Form: */ +#define FCMPU 0x000 /* 0 */ +#define FRSP 0x00c /* 12 */ +#define FCTIW 0x00e /* 14 */ +#define FCTIWZ 0x00f /* 15 */ +#define FCMPO 0x020 /* 32 */ +#define MTFSB1 0x026 /* 38 */ +#define FNEG 0x028 /* 40 */ +#define MCRFS 0x040 /* 64 */ +#define MTFSB0 0x046 /* 70 */ +#define FMR 0x048 /* 72 */ +#define MTFSFI 0x086 /* 134 */ +#define FNABS 0x088 /* 136 */ +#define FABS 0x108 /* 264 */ +#define MFFS 0x247 /* 583 */ +#define MTFSF 0x2c7 /* 711 */ + + +#define AB 2 +#define AC 3 +#define ABC 4 +#define D 5 +#define DU 6 +#define X 7 +#define XA 8 +#define XB 9 +#define XCR 11 +#define XCRB 12 +#define XCRI 13 +#define XCRL 16 +#define XE 14 +#define XEU 15 +#define XFLB 10 + +#ifdef CONFIG_MATH_EMULATION +static int +record_exception(struct pt_regs *regs, int eflag) +{ + u32 fpscr; + + fpscr = __FPU_FPSCR; + + if (eflag) { + fpscr |= FPSCR_FX; + if (eflag & EFLAG_OVERFLOW) + fpscr |= FPSCR_OX; + if (eflag & EFLAG_UNDERFLOW) + fpscr |= FPSCR_UX; + if (eflag & EFLAG_DIVZERO) + fpscr |= FPSCR_ZX; + if (eflag & EFLAG_INEXACT) + fpscr |= FPSCR_XX; + if (eflag & EFLAG_VXSNAN) + fpscr |= FPSCR_VXSNAN; + if (eflag & EFLAG_VXISI) + fpscr |= FPSCR_VXISI; + if (eflag & EFLAG_VXIDI) + fpscr |= FPSCR_VXIDI; + if (eflag & EFLAG_VXZDZ) + fpscr |= FPSCR_VXZDZ; + if (eflag & EFLAG_VXIMZ) + fpscr |= FPSCR_VXIMZ; + if (eflag & EFLAG_VXVC) + fpscr |= FPSCR_VXVC; + if (eflag & EFLAG_VXSOFT) + fpscr |= FPSCR_VXSOFT; + if (eflag & EFLAG_VXSQRT) + fpscr |= FPSCR_VXSQRT; + if (eflag & EFLAG_VXCVI) + fpscr |= FPSCR_VXCVI; + } + + fpscr &= ~(FPSCR_VX); + if (fpscr & (FPSCR_VXSNAN | FPSCR_VXISI | FPSCR_VXIDI | + FPSCR_VXZDZ | FPSCR_VXIMZ | FPSCR_VXVC | + FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI)) + fpscr |= FPSCR_VX; + + fpscr &= ~(FPSCR_FEX); + if (((fpscr & FPSCR_VX) && (fpscr & FPSCR_VE)) || + ((fpscr & FPSCR_OX) && (fpscr & FPSCR_OE)) || + ((fpscr & FPSCR_UX) && (fpscr & FPSCR_UE)) || + ((fpscr & FPSCR_ZX) && (fpscr & FPSCR_ZE)) || + ((fpscr & FPSCR_XX) && (fpscr & FPSCR_XE))) + fpscr |= FPSCR_FEX; + + __FPU_FPSCR = fpscr; + + return (fpscr & FPSCR_FEX) ? 1 : 0; +} +#endif /* CONFIG_MATH_EMULATION */ + +int +do_mathemu(struct pt_regs *regs) +{ + void *op0 = 0, *op1 = 0, *op2 = 0, *op3 = 0; + unsigned long pc = regs->nip; + signed short sdisp; + u32 insn = 0; + int idx = 0; +#ifdef CONFIG_MATH_EMULATION + int (*func)(void *, void *, void *, void *); + int type = 0; + int eflag, trap; +#endif + + if (get_user(insn, (u32 *)pc)) + return -EFAULT; + +#ifndef CONFIG_MATH_EMULATION + switch (insn >> 26) { + case LFD: + idx = (insn >> 16) & 0x1f; + sdisp = (insn & 0xffff); + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; + op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp); + lfd(op0, op1, op2, op3); + break; + case LFDU: + idx = (insn >> 16) & 0x1f; + sdisp = (insn & 0xffff); + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; + op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp); + lfd(op0, op1, op2, op3); + regs->gpr[idx] = (unsigned long)op1; + break; + case STFD: + idx = (insn >> 16) & 0x1f; + sdisp = (insn & 0xffff); + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; + op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp); + stfd(op0, op1, op2, op3); + break; + case STFDU: + idx = (insn >> 16) & 0x1f; + sdisp = (insn & 0xffff); + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; + op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp); + stfd(op0, op1, op2, op3); + regs->gpr[idx] = (unsigned long)op1; + break; + case OP63: + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; + op1 = (void *)¤t->thread.fpr[(insn >> 11) & 0x1f]; + fmr(op0, op1, op2, op3); + break; + default: + goto illegal; + } +#else /* CONFIG_MATH_EMULATION */ + switch (insn >> 26) { + case LFS: func = lfs; type = D; break; + case LFSU: func = lfs; type = DU; break; + case LFD: func = lfd; type = D; break; + case LFDU: func = lfd; type = DU; break; + case STFS: func = stfs; type = D; break; + case STFSU: func = stfs; type = DU; break; + case STFD: func = stfd; type = D; break; + case STFDU: func = stfd; type = DU; break; + + case OP31: + switch ((insn >> 1) & 0x3ff) { + case LFSX: func = lfs; type = XE; break; + case LFSUX: func = lfs; type = XEU; break; + case LFDX: func = lfd; type = XE; break; + case LFDUX: func = lfd; type = XEU; break; + case STFSX: func = stfs; type = XE; break; + case STFSUX: func = stfs; type = XEU; break; + case STFDX: func = stfd; type = XE; break; + case STFDUX: func = stfd; type = XEU; break; + case STFIWX: func = stfiwx; type = XE; break; + default: + goto illegal; + } + break; + + case OP59: + switch ((insn >> 1) & 0x1f) { + case FDIVS: func = fdivs; type = AB; break; + case FSUBS: func = fsubs; type = AB; break; + case FADDS: func = fadds; type = AB; break; + case FSQRTS: func = fsqrts; type = AB; break; + case FRES: func = fres; type = AB; break; + case FMULS: func = fmuls; type = AC; break; + case FMSUBS: func = fmsubs; type = ABC; break; + case FMADDS: func = fmadds; type = ABC; break; + case FNMSUBS: func = fnmsubs; type = ABC; break; + case FNMADDS: func = fnmadds; type = ABC; break; + default: + goto illegal; + } + break; + + case OP63: + if (insn & 0x20) { + switch ((insn >> 1) & 0x1f) { + case FDIV: func = fdiv; type = AB; break; + case FSUB: func = fsub; type = AB; break; + case FADD: func = fadd; type = AB; break; + case FSQRT: func = fsqrt; type = AB; break; + case FSEL: func = fsel; type = ABC; break; + case FMUL: func = fmul; type = AC; break; + case FRSQRTE: func = frsqrte; type = AB; break; + case FMSUB: func = fmsub; type = ABC; break; + case FMADD: func = fmadd; type = ABC; break; + case FNMSUB: func = fnmsub; type = ABC; break; + case FNMADD: func = fnmadd; type = ABC; break; + default: + goto illegal; + } + break; + } + + switch ((insn >> 1) & 0x3ff) { + case FCMPU: func = fcmpu; type = XCR; break; + case FRSP: func = frsp; type = XB; break; + case FCTIW: func = fctiw; type = XB; break; + case FCTIWZ: func = fctiwz; type = XB; break; + case FCMPO: func = fcmpo; type = XCR; break; + case MTFSB1: func = mtfsb1; type = XCRB; break; + case FNEG: func = fneg; type = XB; break; + case MCRFS: func = mcrfs; type = XCRL; break; + case MTFSB0: func = mtfsb0; type = XCRB; break; + case FMR: func = fmr; type = XB; break; + case MTFSFI: func = mtfsfi; type = XCRI; break; + case FNABS: func = fnabs; type = XB; break; + case FABS: func = fabs; type = XB; break; + case MFFS: func = mffs; type = X; break; + case MTFSF: func = mtfsf; type = XFLB; break; + default: + goto illegal; + } + break; + + default: + goto illegal; + } + + switch (type) { + case AB: + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; + op1 = (void *)¤t->thread.fpr[(insn >> 16) & 0x1f]; + op2 = (void *)¤t->thread.fpr[(insn >> 11) & 0x1f]; + break; + + case AC: + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; + op1 = (void *)¤t->thread.fpr[(insn >> 16) & 0x1f]; + op2 = (void *)¤t->thread.fpr[(insn >> 6) & 0x1f]; + break; + + case ABC: + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; + op1 = (void *)¤t->thread.fpr[(insn >> 16) & 0x1f]; + op2 = (void *)¤t->thread.fpr[(insn >> 11) & 0x1f]; + op3 = (void *)¤t->thread.fpr[(insn >> 6) & 0x1f]; + break; + + case D: + idx = (insn >> 16) & 0x1f; + sdisp = (insn & 0xffff); + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; + op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp); + break; + + case DU: + idx = (insn >> 16) & 0x1f; + if (!idx) + goto illegal; + + sdisp = (insn & 0xffff); + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; + op1 = (void *)(regs->gpr[idx] + sdisp); + break; + + case X: + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; + break; + + case XA: + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; + op1 = (void *)¤t->thread.fpr[(insn >> 16) & 0x1f]; + break; + + case XB: + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; + op1 = (void *)¤t->thread.fpr[(insn >> 11) & 0x1f]; + break; + + case XE: + idx = (insn >> 16) & 0x1f; + if (!idx) + goto illegal; + + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; + op1 = (void *)(regs->gpr[idx] + regs->gpr[(insn >> 11) & 0x1f]); + break; + + case XEU: + idx = (insn >> 16) & 0x1f; + op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; + op1 = (void *)((idx ? regs->gpr[idx] : 0) + + regs->gpr[(insn >> 11) & 0x1f]); + break; + + case XCR: + op0 = (void *)®s->ccr; + op1 = (void *)((insn >> 23) & 0x7); + op2 = (void *)¤t->thread.fpr[(insn >> 16) & 0x1f]; + op3 = (void *)¤t->thread.fpr[(insn >> 11) & 0x1f]; + break; + + case XCRL: + op0 = (void *)®s->ccr; + op1 = (void *)((insn >> 23) & 0x7); + op2 = (void *)((insn >> 18) & 0x7); + break; + + case XCRB: + op0 = (void *)((insn >> 21) & 0x1f); + break; + + case XCRI: + op0 = (void *)((insn >> 23) & 0x7); + op1 = (void *)((insn >> 12) & 0xf); + break; + + case XFLB: + op0 = (void *)((insn >> 17) & 0xff); + op1 = (void *)¤t->thread.fpr[(insn >> 11) & 0x1f]; + break; + + default: + goto illegal; + } + + eflag = func(op0, op1, op2, op3); + + if (insn & 1) { + regs->ccr &= ~(0x0f000000); + regs->ccr |= (__FPU_FPSCR >> 4) & 0x0f000000; + } + + trap = record_exception(regs, eflag); + if (trap) + return 1; + + switch (type) { + case DU: + case XEU: + regs->gpr[idx] = (unsigned long)op1; + break; + + default: + break; + } +#endif /* CONFIG_MATH_EMULATION */ + + regs->nip += 4; + return 0; + +illegal: + return -ENOSYS; +} diff --git a/arch/powerpc/math-emu/mcrfs.c b/arch/powerpc/math-emu/mcrfs.c new file mode 100644 index 000000000000..106dd912914b --- /dev/null +++ b/arch/powerpc/math-emu/mcrfs.c @@ -0,0 +1,31 @@ +#include +#include +#include + +#include "soft-fp.h" + +int +mcrfs(u32 *ccr, u32 crfD, u32 crfS) +{ + u32 value, clear; + +#ifdef DEBUG + printk("%s: %p (%08x) %d %d\n", __FUNCTION__, ccr, *ccr, crfD, crfS); +#endif + + clear = 15 << ((7 - crfS) << 2); + if (!crfS) + clear = 0x90000000; + + value = (__FPU_FPSCR >> ((7 - crfS) << 2)) & 15; + __FPU_FPSCR &= ~(clear); + + *ccr &= ~(15 << ((7 - crfD) << 2)); + *ccr |= (value << ((7 - crfD) << 2)); + +#ifdef DEBUG + printk("CR: %08x\n", __FUNCTION__, *ccr); +#endif + + return 0; +} diff --git a/arch/powerpc/math-emu/mffs.c b/arch/powerpc/math-emu/mffs.c new file mode 100644 index 000000000000..f477c9170e75 --- /dev/null +++ b/arch/powerpc/math-emu/mffs.c @@ -0,0 +1,17 @@ +#include +#include +#include + +#include "soft-fp.h" + +int +mffs(u32 *frD) +{ + frD[1] = __FPU_FPSCR; + +#ifdef DEBUG + printk("%s: frD %p: %08x.%08x\n", __FUNCTION__, frD, frD[0], frD[1]); +#endif + + return 0; +} diff --git a/arch/powerpc/math-emu/mtfsb0.c b/arch/powerpc/math-emu/mtfsb0.c new file mode 100644 index 000000000000..99bfd80f4af3 --- /dev/null +++ b/arch/powerpc/math-emu/mtfsb0.c @@ -0,0 +1,18 @@ +#include +#include +#include + +#include "soft-fp.h" + +int +mtfsb0(int crbD) +{ + if ((crbD != 1) && (crbD != 2)) + __FPU_FPSCR &= ~(1 << (31 - crbD)); + +#ifdef DEBUG + printk("%s: %d %08lx\n", __FUNCTION__, crbD, __FPU_FPSCR); +#endif + + return 0; +} diff --git a/arch/powerpc/math-emu/mtfsb1.c b/arch/powerpc/math-emu/mtfsb1.c new file mode 100644 index 000000000000..3d9e7ed92d2b --- /dev/null +++ b/arch/powerpc/math-emu/mtfsb1.c @@ -0,0 +1,18 @@ +#include +#include +#include + +#include "soft-fp.h" + +int +mtfsb1(int crbD) +{ + if ((crbD != 1) && (crbD != 2)) + __FPU_FPSCR |= (1 << (31 - crbD)); + +#ifdef DEBUG + printk("%s: %d %08lx\n", __FUNCTION__, crbD, __FPU_FPSCR); +#endif + + return 0; +} diff --git a/arch/powerpc/math-emu/mtfsf.c b/arch/powerpc/math-emu/mtfsf.c new file mode 100644 index 000000000000..d70cf714994c --- /dev/null +++ b/arch/powerpc/math-emu/mtfsf.c @@ -0,0 +1,45 @@ +#include +#include +#include + +#include "soft-fp.h" + +int +mtfsf(unsigned int FM, u32 *frB) +{ + u32 mask; + + if (FM == 0) + return 0; + + if (FM == 0xff) + mask = 0x9fffffff; + else { + mask = 0; + if (FM & (1 << 0)) + mask |= 0x90000000; + if (FM & (1 << 1)) + mask |= 0x0f000000; + if (FM & (1 << 2)) + mask |= 0x00f00000; + if (FM & (1 << 3)) + mask |= 0x000f0000; + if (FM & (1 << 4)) + mask |= 0x0000f000; + if (FM & (1 << 5)) + mask |= 0x00000f00; + if (FM & (1 << 6)) + mask |= 0x000000f0; + if (FM & (1 << 7)) + mask |= 0x0000000f; + } + + __FPU_FPSCR &= ~(mask); + __FPU_FPSCR |= (frB[1] & mask); + +#ifdef DEBUG + printk("%s: %02x %p: %08lx\n", __FUNCTION__, FM, frB, __FPU_FPSCR); +#endif + + return 0; +} diff --git a/arch/powerpc/math-emu/mtfsfi.c b/arch/powerpc/math-emu/mtfsfi.c new file mode 100644 index 000000000000..71df854baa7e --- /dev/null +++ b/arch/powerpc/math-emu/mtfsfi.c @@ -0,0 +1,23 @@ +#include +#include +#include + +#include "soft-fp.h" + +int +mtfsfi(unsigned int crfD, unsigned int IMM) +{ + u32 mask = 0xf; + + if (!crfD) + mask = 9; + + __FPU_FPSCR &= ~(mask << ((7 - crfD) << 2)); + __FPU_FPSCR |= (IMM & 0xf) << ((7 - crfD) << 2); + +#ifdef DEBUG + printk("%s: %d %x: %08lx\n", __FUNCTION__, crfD, IMM, __FPU_FPSCR); +#endif + + return 0; +} diff --git a/arch/powerpc/math-emu/op-1.h b/arch/powerpc/math-emu/op-1.h new file mode 100644 index 000000000000..c92fa95f562e --- /dev/null +++ b/arch/powerpc/math-emu/op-1.h @@ -0,0 +1,245 @@ +/* + * Basic one-word fraction declaration and manipulation. + */ + +#define _FP_FRAC_DECL_1(X) _FP_W_TYPE X##_f +#define _FP_FRAC_COPY_1(D,S) (D##_f = S##_f) +#define _FP_FRAC_SET_1(X,I) (X##_f = I) +#define _FP_FRAC_HIGH_1(X) (X##_f) +#define _FP_FRAC_LOW_1(X) (X##_f) +#define _FP_FRAC_WORD_1(X,w) (X##_f) + +#define _FP_FRAC_ADDI_1(X,I) (X##_f += I) +#define _FP_FRAC_SLL_1(X,N) \ + do { \ + if (__builtin_constant_p(N) && (N) == 1) \ + X##_f += X##_f; \ + else \ + X##_f <<= (N); \ + } while (0) +#define _FP_FRAC_SRL_1(X,N) (X##_f >>= N) + +/* Right shift with sticky-lsb. */ +#define _FP_FRAC_SRS_1(X,N,sz) __FP_FRAC_SRS_1(X##_f, N, sz) + +#define __FP_FRAC_SRS_1(X,N,sz) \ + (X = (X >> (N) | (__builtin_constant_p(N) && (N) == 1 \ + ? X & 1 : (X << (_FP_W_TYPE_SIZE - (N))) != 0))) + +#define _FP_FRAC_ADD_1(R,X,Y) (R##_f = X##_f + Y##_f) +#define _FP_FRAC_SUB_1(R,X,Y) (R##_f = X##_f - Y##_f) +#define _FP_FRAC_CLZ_1(z, X) __FP_CLZ(z, X##_f) + +/* Predicates */ +#define _FP_FRAC_NEGP_1(X) ((_FP_WS_TYPE)X##_f < 0) +#define _FP_FRAC_ZEROP_1(X) (X##_f == 0) +#define _FP_FRAC_OVERP_1(fs,X) (X##_f & _FP_OVERFLOW_##fs) +#define _FP_FRAC_EQ_1(X, Y) (X##_f == Y##_f) +#define _FP_FRAC_GE_1(X, Y) (X##_f >= Y##_f) +#define _FP_FRAC_GT_1(X, Y) (X##_f > Y##_f) + +#define _FP_ZEROFRAC_1 0 +#define _FP_MINFRAC_1 1 + +/* + * Unpack the raw bits of a native fp value. Do not classify or + * normalize the data. + */ + +#define _FP_UNPACK_RAW_1(fs, X, val) \ + do { \ + union _FP_UNION_##fs _flo; _flo.flt = (val); \ + \ + X##_f = _flo.bits.frac; \ + X##_e = _flo.bits.exp; \ + X##_s = _flo.bits.sign; \ + } while (0) + + +/* + * Repack the raw bits of a native fp value. + */ + +#define _FP_PACK_RAW_1(fs, val, X) \ + do { \ + union _FP_UNION_##fs _flo; \ + \ + _flo.bits.frac = X##_f; \ + _flo.bits.exp = X##_e; \ + _flo.bits.sign = X##_s; \ + \ + (val) = _flo.flt; \ + } while (0) + + +/* + * Multiplication algorithms: + */ + +/* Basic. Assuming the host word size is >= 2*FRACBITS, we can do the + multiplication immediately. */ + +#define _FP_MUL_MEAT_1_imm(fs, R, X, Y) \ + do { \ + R##_f = X##_f * Y##_f; \ + /* Normalize since we know where the msb of the multiplicands \ + were (bit B), we know that the msb of the of the product is \ + at either 2B or 2B-1. */ \ + _FP_FRAC_SRS_1(R, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs); \ + } while (0) + +/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */ + +#define _FP_MUL_MEAT_1_wide(fs, R, X, Y, doit) \ + do { \ + _FP_W_TYPE _Z_f0, _Z_f1; \ + doit(_Z_f1, _Z_f0, X##_f, Y##_f); \ + /* Normalize since we know where the msb of the multiplicands \ + were (bit B), we know that the msb of the of the product is \ + at either 2B or 2B-1. */ \ + _FP_FRAC_SRS_2(_Z, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs); \ + R##_f = _Z_f0; \ + } while (0) + +/* Finally, a simple widening multiply algorithm. What fun! */ + +#define _FP_MUL_MEAT_1_hard(fs, R, X, Y) \ + do { \ + _FP_W_TYPE _xh, _xl, _yh, _yl, _z_f0, _z_f1, _a_f0, _a_f1; \ + \ + /* split the words in half */ \ + _xh = X##_f >> (_FP_W_TYPE_SIZE/2); \ + _xl = X##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1); \ + _yh = Y##_f >> (_FP_W_TYPE_SIZE/2); \ + _yl = Y##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1); \ + \ + /* multiply the pieces */ \ + _z_f0 = _xl * _yl; \ + _a_f0 = _xh * _yl; \ + _a_f1 = _xl * _yh; \ + _z_f1 = _xh * _yh; \ + \ + /* reassemble into two full words */ \ + if ((_a_f0 += _a_f1) < _a_f1) \ + _z_f1 += (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2); \ + _a_f1 = _a_f0 >> (_FP_W_TYPE_SIZE/2); \ + _a_f0 = _a_f0 << (_FP_W_TYPE_SIZE/2); \ + _FP_FRAC_ADD_2(_z, _z, _a); \ + \ + /* normalize */ \ + _FP_FRAC_SRS_2(_z, _FP_WFRACBITS_##fs - 1, 2*_FP_WFRACBITS_##fs); \ + R##_f = _z_f0; \ + } while (0) + + +/* + * Division algorithms: + */ + +/* Basic. Assuming the host word size is >= 2*FRACBITS, we can do the + division immediately. Give this macro either _FP_DIV_HELP_imm for + C primitives or _FP_DIV_HELP_ldiv for the ISO function. Which you + choose will depend on what the compiler does with divrem4. */ + +#define _FP_DIV_MEAT_1_imm(fs, R, X, Y, doit) \ + do { \ + _FP_W_TYPE _q, _r; \ + X##_f <<= (X##_f < Y##_f \ + ? R##_e--, _FP_WFRACBITS_##fs \ + : _FP_WFRACBITS_##fs - 1); \ + doit(_q, _r, X##_f, Y##_f); \ + R##_f = _q | (_r != 0); \ + } while (0) + +/* GCC's longlong.h defines a 2W / 1W => (1W,1W) primitive udiv_qrnnd + that may be useful in this situation. This first is for a primitive + that requires normalization, the second for one that does not. Look + for UDIV_NEEDS_NORMALIZATION to tell which your machine needs. */ + +#define _FP_DIV_MEAT_1_udiv_norm(fs, R, X, Y) \ + do { \ + _FP_W_TYPE _nh, _nl, _q, _r; \ + \ + /* Normalize Y -- i.e. make the most significant bit set. */ \ + Y##_f <<= _FP_WFRACXBITS_##fs - 1; \ + \ + /* Shift X op correspondingly high, that is, up one full word. */ \ + if (X##_f <= Y##_f) \ + { \ + _nl = 0; \ + _nh = X##_f; \ + } \ + else \ + { \ + R##_e++; \ + _nl = X##_f << (_FP_W_TYPE_SIZE-1); \ + _nh = X##_f >> 1; \ + } \ + \ + udiv_qrnnd(_q, _r, _nh, _nl, Y##_f); \ + R##_f = _q | (_r != 0); \ + } while (0) + +#define _FP_DIV_MEAT_1_udiv(fs, R, X, Y) \ + do { \ + _FP_W_TYPE _nh, _nl, _q, _r; \ + if (X##_f < Y##_f) \ + { \ + R##_e--; \ + _nl = X##_f << _FP_WFRACBITS_##fs; \ + _nh = X##_f >> _FP_WFRACXBITS_##fs; \ + } \ + else \ + { \ + _nl = X##_f << (_FP_WFRACBITS_##fs - 1); \ + _nh = X##_f >> (_FP_WFRACXBITS_##fs + 1); \ + } \ + udiv_qrnnd(_q, _r, _nh, _nl, Y##_f); \ + R##_f = _q | (_r != 0); \ + } while (0) + + +/* + * Square root algorithms: + * We have just one right now, maybe Newton approximation + * should be added for those machines where division is fast. + */ + +#define _FP_SQRT_MEAT_1(R, S, T, X, q) \ + do { \ + while (q) \ + { \ + T##_f = S##_f + q; \ + if (T##_f <= X##_f) \ + { \ + S##_f = T##_f + q; \ + X##_f -= T##_f; \ + R##_f += q; \ + } \ + _FP_FRAC_SLL_1(X, 1); \ + q >>= 1; \ + } \ + } while (0) + +/* + * Assembly/disassembly for converting to/from integral types. + * No shifting or overflow handled here. + */ + +#define _FP_FRAC_ASSEMBLE_1(r, X, rsize) (r = X##_f) +#define _FP_FRAC_DISASSEMBLE_1(X, r, rsize) (X##_f = r) + + +/* + * Convert FP values between word sizes + */ + +#define _FP_FRAC_CONV_1_1(dfs, sfs, D, S) \ + do { \ + D##_f = S##_f; \ + if (_FP_WFRACBITS_##sfs > _FP_WFRACBITS_##dfs) \ + _FP_FRAC_SRS_1(D, (_FP_WFRACBITS_##sfs-_FP_WFRACBITS_##dfs), \ + _FP_WFRACBITS_##sfs); \ + else \ + D##_f <<= _FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs; \ + } while (0) diff --git a/arch/powerpc/math-emu/op-2.h b/arch/powerpc/math-emu/op-2.h new file mode 100644 index 000000000000..b9b06b4c6ea1 --- /dev/null +++ b/arch/powerpc/math-emu/op-2.h @@ -0,0 +1,433 @@ +/* + * Basic two-word fraction declaration and manipulation. + */ + +#define _FP_FRAC_DECL_2(X) _FP_W_TYPE X##_f0, X##_f1 +#define _FP_FRAC_COPY_2(D,S) (D##_f0 = S##_f0, D##_f1 = S##_f1) +#define _FP_FRAC_SET_2(X,I) __FP_FRAC_SET_2(X, I) +#define _FP_FRAC_HIGH_2(X) (X##_f1) +#define _FP_FRAC_LOW_2(X) (X##_f0) +#define _FP_FRAC_WORD_2(X,w) (X##_f##w) + +#define _FP_FRAC_SLL_2(X,N) \ + do { \ + if ((N) < _FP_W_TYPE_SIZE) \ + { \ + if (__builtin_constant_p(N) && (N) == 1) \ + { \ + X##_f1 = X##_f1 + X##_f1 + (((_FP_WS_TYPE)(X##_f0)) < 0); \ + X##_f0 += X##_f0; \ + } \ + else \ + { \ + X##_f1 = X##_f1 << (N) | X##_f0 >> (_FP_W_TYPE_SIZE - (N)); \ + X##_f0 <<= (N); \ + } \ + } \ + else \ + { \ + X##_f1 = X##_f0 << ((N) - _FP_W_TYPE_SIZE); \ + X##_f0 = 0; \ + } \ + } while (0) + +#define _FP_FRAC_SRL_2(X,N) \ + do { \ + if ((N) < _FP_W_TYPE_SIZE) \ + { \ + X##_f0 = X##_f0 >> (N) | X##_f1 << (_FP_W_TYPE_SIZE - (N)); \ + X##_f1 >>= (N); \ + } \ + else \ + { \ + X##_f0 = X##_f1 >> ((N) - _FP_W_TYPE_SIZE); \ + X##_f1 = 0; \ + } \ + } while (0) + +/* Right shift with sticky-lsb. */ +#define _FP_FRAC_SRS_2(X,N,sz) \ + do { \ + if ((N) < _FP_W_TYPE_SIZE) \ + { \ + X##_f0 = (X##_f1 << (_FP_W_TYPE_SIZE - (N)) | X##_f0 >> (N) | \ + (__builtin_constant_p(N) && (N) == 1 \ + ? X##_f0 & 1 \ + : (X##_f0 << (_FP_W_TYPE_SIZE - (N))) != 0)); \ + X##_f1 >>= (N); \ + } \ + else \ + { \ + X##_f0 = (X##_f1 >> ((N) - _FP_W_TYPE_SIZE) | \ + (((X##_f1 << (sz - (N))) | X##_f0) != 0)); \ + X##_f1 = 0; \ + } \ + } while (0) + +#define _FP_FRAC_ADDI_2(X,I) \ + __FP_FRAC_ADDI_2(X##_f1, X##_f0, I) + +#define _FP_FRAC_ADD_2(R,X,Y) \ + __FP_FRAC_ADD_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0) + +#define _FP_FRAC_SUB_2(R,X,Y) \ + __FP_FRAC_SUB_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0) + +#define _FP_FRAC_CLZ_2(R,X) \ + do { \ + if (X##_f1) \ + __FP_CLZ(R,X##_f1); \ + else \ + { \ + __FP_CLZ(R,X##_f0); \ + R += _FP_W_TYPE_SIZE; \ + } \ + } while(0) + +/* Predicates */ +#define _FP_FRAC_NEGP_2(X) ((_FP_WS_TYPE)X##_f1 < 0) +#define _FP_FRAC_ZEROP_2(X) ((X##_f1 | X##_f0) == 0) +#define _FP_FRAC_OVERP_2(fs,X) (X##_f1 & _FP_OVERFLOW_##fs) +#define _FP_FRAC_EQ_2(X, Y) (X##_f1 == Y##_f1 && X##_f0 == Y##_f0) +#define _FP_FRAC_GT_2(X, Y) \ + ((X##_f1 > Y##_f1) || (X##_f1 == Y##_f1 && X##_f0 > Y##_f0)) +#define _FP_FRAC_GE_2(X, Y) \ + ((X##_f1 > Y##_f1) || (X##_f1 == Y##_f1 && X##_f0 >= Y##_f0)) + +#define _FP_ZEROFRAC_2 0, 0 +#define _FP_MINFRAC_2 0, 1 + +/* + * Internals + */ + +#define __FP_FRAC_SET_2(X,I1,I0) (X##_f0 = I0, X##_f1 = I1) + +#define __FP_CLZ_2(R, xh, xl) \ + do { \ + if (xh) \ + __FP_CLZ(R,xl); \ + else \ + { \ + __FP_CLZ(R,xl); \ + R += _FP_W_TYPE_SIZE; \ + } \ + } while(0) + +#if 0 + +#ifndef __FP_FRAC_ADDI_2 +#define __FP_FRAC_ADDI_2(xh, xl, i) \ + (xh += ((xl += i) < i)) +#endif +#ifndef __FP_FRAC_ADD_2 +#define __FP_FRAC_ADD_2(rh, rl, xh, xl, yh, yl) \ + (rh = xh + yh + ((rl = xl + yl) < xl)) +#endif +#ifndef __FP_FRAC_SUB_2 +#define __FP_FRAC_SUB_2(rh, rl, xh, xl, yh, yl) \ + (rh = xh - yh - ((rl = xl - yl) > xl)) +#endif + +#else + +#undef __FP_FRAC_ADDI_2 +#define __FP_FRAC_ADDI_2(xh, xl, i) add_ssaaaa(xh, xl, xh, xl, 0, i) +#undef __FP_FRAC_ADD_2 +#define __FP_FRAC_ADD_2 add_ssaaaa +#undef __FP_FRAC_SUB_2 +#define __FP_FRAC_SUB_2 sub_ddmmss + +#endif + +/* + * Unpack the raw bits of a native fp value. Do not classify or + * normalize the data. + */ + +#define _FP_UNPACK_RAW_2(fs, X, val) \ + do { \ + union _FP_UNION_##fs _flo; _flo.flt = (val); \ + \ + X##_f0 = _flo.bits.frac0; \ + X##_f1 = _flo.bits.frac1; \ + X##_e = _flo.bits.exp; \ + X##_s = _flo.bits.sign; \ + } while (0) + + +/* + * Repack the raw bits of a native fp value. + */ + +#define _FP_PACK_RAW_2(fs, val, X) \ + do { \ + union _FP_UNION_##fs _flo; \ + \ + _flo.bits.frac0 = X##_f0; \ + _flo.bits.frac1 = X##_f1; \ + _flo.bits.exp = X##_e; \ + _flo.bits.sign = X##_s; \ + \ + (val) = _flo.flt; \ + } while (0) + + +/* + * Multiplication algorithms: + */ + +/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */ + +#define _FP_MUL_MEAT_2_wide(fs, R, X, Y, doit) \ + do { \ + _FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \ + \ + doit(_FP_FRAC_WORD_4(_z,1), _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0); \ + doit(_b_f1, _b_f0, X##_f0, Y##_f1); \ + doit(_c_f1, _c_f0, X##_f1, Y##_f0); \ + doit(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2), X##_f1, Y##_f1); \ + \ + __FP_FRAC_ADD_4(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \ + _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0), \ + 0, _b_f1, _b_f0, 0, \ + _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \ + _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0)); \ + __FP_FRAC_ADD_4(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \ + _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0), \ + 0, _c_f1, _c_f0, 0, \ + _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \ + _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0)); \ + \ + /* Normalize since we know where the msb of the multiplicands \ + were (bit B), we know that the msb of the of the product is \ + at either 2B or 2B-1. */ \ + _FP_FRAC_SRS_4(_z, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs); \ + R##_f0 = _FP_FRAC_WORD_4(_z,0); \ + R##_f1 = _FP_FRAC_WORD_4(_z,1); \ + } while (0) + +/* This next macro appears to be totally broken. Fortunately nowhere + * seems to use it :-> The problem is that we define _z[4] but + * then use it in _FP_FRAC_SRS_4, which will attempt to access + * _z_f[n] which will cause an error. The fix probably involves + * declaring it with _FP_FRAC_DECL_4, see previous macro. -- PMM 02/1998 + */ +#define _FP_MUL_MEAT_2_gmp(fs, R, X, Y) \ + do { \ + _FP_W_TYPE _x[2], _y[2], _z[4]; \ + _x[0] = X##_f0; _x[1] = X##_f1; \ + _y[0] = Y##_f0; _y[1] = Y##_f1; \ + \ + mpn_mul_n(_z, _x, _y, 2); \ + \ + /* Normalize since we know where the msb of the multiplicands \ + were (bit B), we know that the msb of the of the product is \ + at either 2B or 2B-1. */ \ + _FP_FRAC_SRS_4(_z, _FP_WFRACBITS##_fs-1, 2*_FP_WFRACBITS_##fs); \ + R##_f0 = _z[0]; \ + R##_f1 = _z[1]; \ + } while (0) + + +/* + * Division algorithms: + * This seems to be giving me difficulties -- PMM + * Look, NetBSD seems to be able to comment algorithms. Can't you? + * I've thrown printks at the problem. + * This now appears to work, but I still don't really know why. + * Also, I don't think the result is properly normalised... + */ + +#define _FP_DIV_MEAT_2_udiv_64(fs, R, X, Y) \ + do { \ + extern void _fp_udivmodti4(_FP_W_TYPE q[2], _FP_W_TYPE r[2], \ + _FP_W_TYPE n1, _FP_W_TYPE n0, \ + _FP_W_TYPE d1, _FP_W_TYPE d0); \ + _FP_W_TYPE _n_f3, _n_f2, _n_f1, _n_f0, _r_f1, _r_f0; \ + _FP_W_TYPE _q_f1, _q_f0, _m_f1, _m_f0; \ + _FP_W_TYPE _rmem[2], _qmem[2]; \ + /* I think this check is to ensure that the result is normalised. \ + * Assuming X,Y normalised (ie in [1.0,2.0)) X/Y will be in \ + * [0.5,2.0). Furthermore, it will be less than 1.0 iff X < Y. \ + * In this case we tweak things. (this is based on comments in \ + * the NetBSD FPU emulation code. ) \ + * We know X,Y are normalised because we ensure this as part of \ + * the unpacking process. -- PMM \ + */ \ + if (_FP_FRAC_GT_2(X, Y)) \ + { \ +/* R##_e++; */ \ + _n_f3 = X##_f1 >> 1; \ + _n_f2 = X##_f1 << (_FP_W_TYPE_SIZE - 1) | X##_f0 >> 1; \ + _n_f1 = X##_f0 << (_FP_W_TYPE_SIZE - 1); \ + _n_f0 = 0; \ + } \ + else \ + { \ + R##_e--; \ + _n_f3 = X##_f1; \ + _n_f2 = X##_f0; \ + _n_f1 = _n_f0 = 0; \ + } \ + \ + /* Normalize, i.e. make the most significant bit of the \ + denominator set. CHANGED: - 1 to nothing -- PMM */ \ + _FP_FRAC_SLL_2(Y, _FP_WFRACXBITS_##fs /* -1 */); \ + \ + /* Do the 256/128 bit division given the 128-bit _fp_udivmodtf4 \ + primitive snagged from libgcc2.c. */ \ + \ + _fp_udivmodti4(_qmem, _rmem, _n_f3, _n_f2, 0, Y##_f1); \ + _q_f1 = _qmem[0]; \ + umul_ppmm(_m_f1, _m_f0, _q_f1, Y##_f0); \ + _r_f1 = _rmem[0]; \ + _r_f0 = _n_f1; \ + if (_FP_FRAC_GT_2(_m, _r)) \ + { \ + _q_f1--; \ + _FP_FRAC_ADD_2(_r, _r, Y); \ + if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r)) \ + { \ + _q_f1--; \ + _FP_FRAC_ADD_2(_r, _r, Y); \ + } \ + } \ + _FP_FRAC_SUB_2(_r, _r, _m); \ + \ + _fp_udivmodti4(_qmem, _rmem, _r_f1, _r_f0, 0, Y##_f1); \ + _q_f0 = _qmem[0]; \ + umul_ppmm(_m_f1, _m_f0, _q_f0, Y##_f0); \ + _r_f1 = _rmem[0]; \ + _r_f0 = _n_f0; \ + if (_FP_FRAC_GT_2(_m, _r)) \ + { \ + _q_f0--; \ + _FP_FRAC_ADD_2(_r, _r, Y); \ + if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r)) \ + { \ + _q_f0--; \ + _FP_FRAC_ADD_2(_r, _r, Y); \ + } \ + } \ + _FP_FRAC_SUB_2(_r, _r, _m); \ + \ + R##_f1 = _q_f1; \ + R##_f0 = _q_f0 | ((_r_f1 | _r_f0) != 0); \ + /* adjust so answer is normalized again. I'm not sure what the \ + * final sz param should be. In practice it's never used since \ + * N is 1 which is always going to be < _FP_W_TYPE_SIZE... \ + */ \ + /* _FP_FRAC_SRS_2(R,1,_FP_WFRACBITS_##fs); */ \ + } while (0) + + +#define _FP_DIV_MEAT_2_gmp(fs, R, X, Y) \ + do { \ + _FP_W_TYPE _x[4], _y[2], _z[4]; \ + _y[0] = Y##_f0; _y[1] = Y##_f1; \ + _x[0] = _x[3] = 0; \ + if (_FP_FRAC_GT_2(X, Y)) \ + { \ + R##_e++; \ + _x[1] = (X##_f0 << (_FP_WFRACBITS-1 - _FP_W_TYPE_SIZE) | \ + X##_f1 >> (_FP_W_TYPE_SIZE - \ + (_FP_WFRACBITS-1 - _FP_W_TYPE_SIZE))); \ + _x[2] = X##_f1 << (_FP_WFRACBITS-1 - _FP_W_TYPE_SIZE); \ + } \ + else \ + { \ + _x[1] = (X##_f0 << (_FP_WFRACBITS - _FP_W_TYPE_SIZE) | \ + X##_f1 >> (_FP_W_TYPE_SIZE - \ + (_FP_WFRACBITS - _FP_W_TYPE_SIZE))); \ + _x[2] = X##_f1 << (_FP_WFRACBITS - _FP_W_TYPE_SIZE); \ + } \ + \ + (void) mpn_divrem (_z, 0, _x, 4, _y, 2); \ + R##_f1 = _z[1]; \ + R##_f0 = _z[0] | ((_x[0] | _x[1]) != 0); \ + } while (0) + + +/* + * Square root algorithms: + * We have just one right now, maybe Newton approximation + * should be added for those machines where division is fast. + */ + +#define _FP_SQRT_MEAT_2(R, S, T, X, q) \ + do { \ + while (q) \ + { \ + T##_f1 = S##_f1 + q; \ + if (T##_f1 <= X##_f1) \ + { \ + S##_f1 = T##_f1 + q; \ + X##_f1 -= T##_f1; \ + R##_f1 += q; \ + } \ + _FP_FRAC_SLL_2(X, 1); \ + q >>= 1; \ + } \ + q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \ + while (q) \ + { \ + T##_f0 = S##_f0 + q; \ + T##_f1 = S##_f1; \ + if (T##_f1 < X##_f1 || \ + (T##_f1 == X##_f1 && T##_f0 < X##_f0)) \ + { \ + S##_f0 = T##_f0 + q; \ + if (((_FP_WS_TYPE)T##_f0) < 0 && \ + ((_FP_WS_TYPE)S##_f0) >= 0) \ + S##_f1++; \ + _FP_FRAC_SUB_2(X, X, T); \ + R##_f0 += q; \ + } \ + _FP_FRAC_SLL_2(X, 1); \ + q >>= 1; \ + } \ + } while (0) + + +/* + * Assembly/disassembly for converting to/from integral types. + * No shifting or overflow handled here. + */ + +#define _FP_FRAC_ASSEMBLE_2(r, X, rsize) \ + do { \ + if (rsize <= _FP_W_TYPE_SIZE) \ + r = X##_f0; \ + else \ + { \ + r = X##_f1; \ + r <<= _FP_W_TYPE_SIZE; \ + r += X##_f0; \ + } \ + } while (0) + +#define _FP_FRAC_DISASSEMBLE_2(X, r, rsize) \ + do { \ + X##_f0 = r; \ + X##_f1 = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE); \ + } while (0) + +/* + * Convert FP values between word sizes + */ + +#define _FP_FRAC_CONV_1_2(dfs, sfs, D, S) \ + do { \ + _FP_FRAC_SRS_2(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs), \ + _FP_WFRACBITS_##sfs); \ + D##_f = S##_f0; \ + } while (0) + +#define _FP_FRAC_CONV_2_1(dfs, sfs, D, S) \ + do { \ + D##_f0 = S##_f; \ + D##_f1 = 0; \ + _FP_FRAC_SLL_2(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs)); \ + } while (0) + diff --git a/arch/powerpc/math-emu/op-4.h b/arch/powerpc/math-emu/op-4.h new file mode 100644 index 000000000000..fcdd6d064c54 --- /dev/null +++ b/arch/powerpc/math-emu/op-4.h @@ -0,0 +1,297 @@ +/* + * Basic four-word fraction declaration and manipulation. + * + * When adding quadword support for 32 bit machines, we need + * to be a little careful as double multiply uses some of these + * macros: (in op-2.h) + * _FP_MUL_MEAT_2_wide() uses _FP_FRAC_DECL_4, _FP_FRAC_WORD_4, + * _FP_FRAC_ADD_4, _FP_FRAC_SRS_4 + * _FP_MUL_MEAT_2_gmp() uses _FP_FRAC_SRS_4 (and should use + * _FP_FRAC_DECL_4: it appears to be broken and is not used + * anywhere anyway. ) + * + * I've now fixed all the macros that were here from the sparc64 code. + * [*none* of the shift macros were correct!] -- PMM 02/1998 + * + * The only quadword stuff that remains to be coded is: + * 1) the conversion to/from ints, which requires + * that we check (in op-common.h) that the following do the right thing + * for quadwords: _FP_TO_INT(Q,4,r,X,rsz,rsg), _FP_FROM_INT(Q,4,X,r,rs,rt) + * 2) multiply, divide and sqrt, which require: + * _FP_MUL_MEAT_4_*(R,X,Y), _FP_DIV_MEAT_4_*(R,X,Y), _FP_SQRT_MEAT_4(R,S,T,X,q), + * This also needs _FP_MUL_MEAT_Q and _FP_DIV_MEAT_Q to be defined to + * some suitable _FP_MUL_MEAT_4_* macros in sfp-machine.h. + * [we're free to choose whatever FP_MUL_MEAT_4_* macros we need for + * these; they are used nowhere else. ] + */ + +#define _FP_FRAC_DECL_4(X) _FP_W_TYPE X##_f[4] +#define _FP_FRAC_COPY_4(D,S) \ + (D##_f[0] = S##_f[0], D##_f[1] = S##_f[1], \ + D##_f[2] = S##_f[2], D##_f[3] = S##_f[3]) +/* The _FP_FRAC_SET_n(X,I) macro is intended for use with another + * macro such as _FP_ZEROFRAC_n which returns n comma separated values. + * The result is that we get an expansion of __FP_FRAC_SET_n(X,I0,I1,I2,I3) + * which just assigns the In values to the array X##_f[]. + * This is why the number of parameters doesn't appear to match + * at first glance... -- PMM + */ +#define _FP_FRAC_SET_4(X,I) __FP_FRAC_SET_4(X, I) +#define _FP_FRAC_HIGH_4(X) (X##_f[3]) +#define _FP_FRAC_LOW_4(X) (X##_f[0]) +#define _FP_FRAC_WORD_4(X,w) (X##_f[w]) + +#define _FP_FRAC_SLL_4(X,N) \ + do { \ + _FP_I_TYPE _up, _down, _skip, _i; \ + _skip = (N) / _FP_W_TYPE_SIZE; \ + _up = (N) % _FP_W_TYPE_SIZE; \ + _down = _FP_W_TYPE_SIZE - _up; \ + for (_i = 3; _i > _skip; --_i) \ + X##_f[_i] = X##_f[_i-_skip] << _up | X##_f[_i-_skip-1] >> _down; \ +/* bugfixed: was X##_f[_i] <<= _up; -- PMM 02/1998 */ \ + X##_f[_i] = X##_f[0] << _up; \ + for (--_i; _i >= 0; --_i) \ + X##_f[_i] = 0; \ + } while (0) + +/* This one was broken too */ +#define _FP_FRAC_SRL_4(X,N) \ + do { \ + _FP_I_TYPE _up, _down, _skip, _i; \ + _skip = (N) / _FP_W_TYPE_SIZE; \ + _down = (N) % _FP_W_TYPE_SIZE; \ + _up = _FP_W_TYPE_SIZE - _down; \ + for (_i = 0; _i < 3-_skip; ++_i) \ + X##_f[_i] = X##_f[_i+_skip] >> _down | X##_f[_i+_skip+1] << _up; \ + X##_f[_i] = X##_f[3] >> _down; \ + for (++_i; _i < 4; ++_i) \ + X##_f[_i] = 0; \ + } while (0) + + +/* Right shift with sticky-lsb. + * What this actually means is that we do a standard right-shift, + * but that if any of the bits that fall off the right hand side + * were one then we always set the LSbit. + */ +#define _FP_FRAC_SRS_4(X,N,size) \ + do { \ + _FP_I_TYPE _up, _down, _skip, _i; \ + _FP_W_TYPE _s; \ + _skip = (N) / _FP_W_TYPE_SIZE; \ + _down = (N) % _FP_W_TYPE_SIZE; \ + _up = _FP_W_TYPE_SIZE - _down; \ + for (_s = _i = 0; _i < _skip; ++_i) \ + _s |= X##_f[_i]; \ + _s |= X##_f[_i] << _up; \ +/* s is now != 0 if we want to set the LSbit */ \ + for (_i = 0; _i < 3-_skip; ++_i) \ + X##_f[_i] = X##_f[_i+_skip] >> _down | X##_f[_i+_skip+1] << _up; \ + X##_f[_i] = X##_f[3] >> _down; \ + for (++_i; _i < 4; ++_i) \ + X##_f[_i] = 0; \ + /* don't fix the LSB until the very end when we're sure f[0] is stable */ \ + X##_f[0] |= (_s != 0); \ + } while (0) + +#define _FP_FRAC_ADD_4(R,X,Y) \ + __FP_FRAC_ADD_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0], \ + X##_f[3], X##_f[2], X##_f[1], X##_f[0], \ + Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0]) + +#define _FP_FRAC_SUB_4(R,X,Y) \ + __FP_FRAC_SUB_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0], \ + X##_f[3], X##_f[2], X##_f[1], X##_f[0], \ + Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0]) + +#define _FP_FRAC_ADDI_4(X,I) \ + __FP_FRAC_ADDI_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], I) + +#define _FP_ZEROFRAC_4 0,0,0,0 +#define _FP_MINFRAC_4 0,0,0,1 + +#define _FP_FRAC_ZEROP_4(X) ((X##_f[0] | X##_f[1] | X##_f[2] | X##_f[3]) == 0) +#define _FP_FRAC_NEGP_4(X) ((_FP_WS_TYPE)X##_f[3] < 0) +#define _FP_FRAC_OVERP_4(fs,X) (X##_f[0] & _FP_OVERFLOW_##fs) + +#define _FP_FRAC_EQ_4(X,Y) \ + (X##_f[0] == Y##_f[0] && X##_f[1] == Y##_f[1] \ + && X##_f[2] == Y##_f[2] && X##_f[3] == Y##_f[3]) + +#define _FP_FRAC_GT_4(X,Y) \ + (X##_f[3] > Y##_f[3] || \ + (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] || \ + (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] || \ + (X##_f[1] == Y##_f[1] && X##_f[0] > Y##_f[0]) \ + )) \ + )) \ + ) + +#define _FP_FRAC_GE_4(X,Y) \ + (X##_f[3] > Y##_f[3] || \ + (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] || \ + (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] || \ + (X##_f[1] == Y##_f[1] && X##_f[0] >= Y##_f[0]) \ + )) \ + )) \ + ) + + +#define _FP_FRAC_CLZ_4(R,X) \ + do { \ + if (X##_f[3]) \ + { \ + __FP_CLZ(R,X##_f[3]); \ + } \ + else if (X##_f[2]) \ + { \ + __FP_CLZ(R,X##_f[2]); \ + R += _FP_W_TYPE_SIZE; \ + } \ + else if (X##_f[1]) \ + { \ + __FP_CLZ(R,X##_f[2]); \ + R += _FP_W_TYPE_SIZE*2; \ + } \ + else \ + { \ + __FP_CLZ(R,X##_f[0]); \ + R += _FP_W_TYPE_SIZE*3; \ + } \ + } while(0) + + +#define _FP_UNPACK_RAW_4(fs, X, val) \ + do { \ + union _FP_UNION_##fs _flo; _flo.flt = (val); \ + X##_f[0] = _flo.bits.frac0; \ + X##_f[1] = _flo.bits.frac1; \ + X##_f[2] = _flo.bits.frac2; \ + X##_f[3] = _flo.bits.frac3; \ + X##_e = _flo.bits.exp; \ + X##_s = _flo.bits.sign; \ + } while (0) + +#define _FP_PACK_RAW_4(fs, val, X) \ + do { \ + union _FP_UNION_##fs _flo; \ + _flo.bits.frac0 = X##_f[0]; \ + _flo.bits.frac1 = X##_f[1]; \ + _flo.bits.frac2 = X##_f[2]; \ + _flo.bits.frac3 = X##_f[3]; \ + _flo.bits.exp = X##_e; \ + _flo.bits.sign = X##_s; \ + (val) = _flo.flt; \ + } while (0) + + +/* + * Internals + */ + +#define __FP_FRAC_SET_4(X,I3,I2,I1,I0) \ + (X##_f[3] = I3, X##_f[2] = I2, X##_f[1] = I1, X##_f[0] = I0) + +#ifndef __FP_FRAC_ADD_4 +#define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \ + (r0 = x0 + y0, \ + r1 = x1 + y1 + (r0 < x0), \ + r2 = x2 + y2 + (r1 < x1), \ + r3 = x3 + y3 + (r2 < x2)) +#endif + +#ifndef __FP_FRAC_SUB_4 +#define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \ + (r0 = x0 - y0, \ + r1 = x1 - y1 - (r0 > x0), \ + r2 = x2 - y2 - (r1 > x1), \ + r3 = x3 - y3 - (r2 > x2)) +#endif + +#ifndef __FP_FRAC_ADDI_4 +/* I always wanted to be a lisp programmer :-> */ +#define __FP_FRAC_ADDI_4(x3,x2,x1,x0,i) \ + (x3 += ((x2 += ((x1 += ((x0 += i) < x0)) < x1) < x2))) +#endif + +/* Convert FP values between word sizes. This appears to be more + * complicated than I'd have expected it to be, so these might be + * wrong... These macros are in any case somewhat bogus because they + * use information about what various FRAC_n variables look like + * internally [eg, that 2 word vars are X_f0 and x_f1]. But so do + * the ones in op-2.h and op-1.h. + */ +#define _FP_FRAC_CONV_1_4(dfs, sfs, D, S) \ + do { \ + _FP_FRAC_SRS_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs), \ + _FP_WFRACBITS_##sfs); \ + D##_f = S##_f[0]; \ + } while (0) + +#define _FP_FRAC_CONV_2_4(dfs, sfs, D, S) \ + do { \ + _FP_FRAC_SRS_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs), \ + _FP_WFRACBITS_##sfs); \ + D##_f0 = S##_f[0]; \ + D##_f1 = S##_f[1]; \ + } while (0) + +/* Assembly/disassembly for converting to/from integral types. + * No shifting or overflow handled here. + */ +/* Put the FP value X into r, which is an integer of size rsize. */ +#define _FP_FRAC_ASSEMBLE_4(r, X, rsize) \ + do { \ + if (rsize <= _FP_W_TYPE_SIZE) \ + r = X##_f[0]; \ + else if (rsize <= 2*_FP_W_TYPE_SIZE) \ + { \ + r = X##_f[1]; \ + r <<= _FP_W_TYPE_SIZE; \ + r += X##_f[0]; \ + } \ + else \ + { \ + /* I'm feeling lazy so we deal with int == 3words (implausible)*/ \ + /* and int == 4words as a single case. */ \ + r = X##_f[3]; \ + r <<= _FP_W_TYPE_SIZE; \ + r += X##_f[2]; \ + r <<= _FP_W_TYPE_SIZE; \ + r += X##_f[1]; \ + r <<= _FP_W_TYPE_SIZE; \ + r += X##_f[0]; \ + } \ + } while (0) + +/* "No disassemble Number Five!" */ +/* move an integer of size rsize into X's fractional part. We rely on + * the _f[] array consisting of words of size _FP_W_TYPE_SIZE to avoid + * having to mask the values we store into it. + */ +#define _FP_FRAC_DISASSEMBLE_4(X, r, rsize) \ + do { \ + X##_f[0] = r; \ + X##_f[1] = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE); \ + X##_f[2] = (rsize <= 2*_FP_W_TYPE_SIZE ? 0 : r >> 2*_FP_W_TYPE_SIZE); \ + X##_f[3] = (rsize <= 3*_FP_W_TYPE_SIZE ? 0 : r >> 3*_FP_W_TYPE_SIZE); \ + } while (0) + +#define _FP_FRAC_CONV_4_1(dfs, sfs, D, S) \ + do { \ + D##_f[0] = S##_f; \ + D##_f[1] = D##_f[2] = D##_f[3] = 0; \ + _FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs)); \ + } while (0) + +#define _FP_FRAC_CONV_4_2(dfs, sfs, D, S) \ + do { \ + D##_f[0] = S##_f0; \ + D##_f[1] = S##_f1; \ + D##_f[2] = D##_f[3] = 0; \ + _FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs)); \ + } while (0) + +/* FIXME! This has to be written */ +#define _FP_SQRT_MEAT_4(R, S, T, X, q) diff --git a/arch/powerpc/math-emu/op-common.h b/arch/powerpc/math-emu/op-common.h new file mode 100644 index 000000000000..afb82b6498ce --- /dev/null +++ b/arch/powerpc/math-emu/op-common.h @@ -0,0 +1,688 @@ +#define _FP_DECL(wc, X) \ + _FP_I_TYPE X##_c, X##_s, X##_e; \ + _FP_FRAC_DECL_##wc(X) + +/* + * Finish truely unpacking a native fp value by classifying the kind + * of fp value and normalizing both the exponent and the fraction. + */ + +#define _FP_UNPACK_CANONICAL(fs, wc, X) \ +do { \ + switch (X##_e) \ + { \ + default: \ + _FP_FRAC_HIGH_##wc(X) |= _FP_IMPLBIT_##fs; \ + _FP_FRAC_SLL_##wc(X, _FP_WORKBITS); \ + X##_e -= _FP_EXPBIAS_##fs; \ + X##_c = FP_CLS_NORMAL; \ + break; \ + \ + case 0: \ + if (_FP_FRAC_ZEROP_##wc(X)) \ + X##_c = FP_CLS_ZERO; \ + else \ + { \ + /* a denormalized number */ \ + _FP_I_TYPE _shift; \ + _FP_FRAC_CLZ_##wc(_shift, X); \ + _shift -= _FP_FRACXBITS_##fs; \ + _FP_FRAC_SLL_##wc(X, (_shift+_FP_WORKBITS)); \ + X##_e -= _FP_EXPBIAS_##fs - 1 + _shift; \ + X##_c = FP_CLS_NORMAL; \ + } \ + break; \ + \ + case _FP_EXPMAX_##fs: \ + if (_FP_FRAC_ZEROP_##wc(X)) \ + X##_c = FP_CLS_INF; \ + else \ + /* we don't differentiate between signaling and quiet nans */ \ + X##_c = FP_CLS_NAN; \ + break; \ + } \ +} while (0) + + +/* + * Before packing the bits back into the native fp result, take care + * of such mundane things as rounding and overflow. Also, for some + * kinds of fp values, the original parts may not have been fully + * extracted -- but that is ok, we can regenerate them now. + */ + +#define _FP_PACK_CANONICAL(fs, wc, X) \ +({int __ret = 0; \ + switch (X##_c) \ + { \ + case FP_CLS_NORMAL: \ + X##_e += _FP_EXPBIAS_##fs; \ + if (X##_e > 0) \ + { \ + __ret |= _FP_ROUND(wc, X); \ + if (_FP_FRAC_OVERP_##wc(fs, X)) \ + { \ + _FP_FRAC_SRL_##wc(X, (_FP_WORKBITS+1)); \ + X##_e++; \ + } \ + else \ + _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \ + if (X##_e >= _FP_EXPMAX_##fs) \ + { \ + /* overflow to infinity */ \ + X##_e = _FP_EXPMAX_##fs; \ + _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ + __ret |= EFLAG_OVERFLOW; \ + } \ + } \ + else \ + { \ + /* we've got a denormalized number */ \ + X##_e = -X##_e + 1; \ + if (X##_e <= _FP_WFRACBITS_##fs) \ + { \ + _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs); \ + _FP_FRAC_SLL_##wc(X, 1); \ + if (_FP_FRAC_OVERP_##wc(fs, X)) \ + { \ + X##_e = 1; \ + _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ + } \ + else \ + { \ + X##_e = 0; \ + _FP_FRAC_SRL_##wc(X, _FP_WORKBITS+1); \ + __ret |= EFLAG_UNDERFLOW; \ + } \ + } \ + else \ + { \ + /* underflow to zero */ \ + X##_e = 0; \ + _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ + __ret |= EFLAG_UNDERFLOW; \ + } \ + } \ + break; \ + \ + case FP_CLS_ZERO: \ + X##_e = 0; \ + _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ + break; \ + \ + case FP_CLS_INF: \ + X##_e = _FP_EXPMAX_##fs; \ + _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ + break; \ + \ + case FP_CLS_NAN: \ + X##_e = _FP_EXPMAX_##fs; \ + if (!_FP_KEEPNANFRACP) \ + { \ + _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs); \ + X##_s = 0; \ + } \ + else \ + _FP_FRAC_HIGH_##wc(X) |= _FP_QNANBIT_##fs; \ + break; \ + } \ + __ret; \ +}) + + +/* + * Main addition routine. The input values should be cooked. + */ + +#define _FP_ADD(fs, wc, R, X, Y) \ +do { \ + switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \ + { \ + case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \ + { \ + /* shift the smaller number so that its exponent matches the larger */ \ + _FP_I_TYPE diff = X##_e - Y##_e; \ + \ + if (diff < 0) \ + { \ + diff = -diff; \ + if (diff <= _FP_WFRACBITS_##fs) \ + _FP_FRAC_SRS_##wc(X, diff, _FP_WFRACBITS_##fs); \ + else if (!_FP_FRAC_ZEROP_##wc(X)) \ + _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \ + else \ + _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ + R##_e = Y##_e; \ + } \ + else \ + { \ + if (diff > 0) \ + { \ + if (diff <= _FP_WFRACBITS_##fs) \ + _FP_FRAC_SRS_##wc(Y, diff, _FP_WFRACBITS_##fs); \ + else if (!_FP_FRAC_ZEROP_##wc(Y)) \ + _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc); \ + else \ + _FP_FRAC_SET_##wc(Y, _FP_ZEROFRAC_##wc); \ + } \ + R##_e = X##_e; \ + } \ + \ + R##_c = FP_CLS_NORMAL; \ + \ + if (X##_s == Y##_s) \ + { \ + R##_s = X##_s; \ + _FP_FRAC_ADD_##wc(R, X, Y); \ + if (_FP_FRAC_OVERP_##wc(fs, R)) \ + { \ + _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \ + R##_e++; \ + } \ + } \ + else \ + { \ + R##_s = X##_s; \ + _FP_FRAC_SUB_##wc(R, X, Y); \ + if (_FP_FRAC_ZEROP_##wc(R)) \ + { \ + /* return an exact zero */ \ + if (FP_ROUNDMODE == FP_RND_MINF) \ + R##_s |= Y##_s; \ + else \ + R##_s &= Y##_s; \ + R##_c = FP_CLS_ZERO; \ + } \ + else \ + { \ + if (_FP_FRAC_NEGP_##wc(R)) \ + { \ + _FP_FRAC_SUB_##wc(R, Y, X); \ + R##_s = Y##_s; \ + } \ + \ + /* renormalize after subtraction */ \ + _FP_FRAC_CLZ_##wc(diff, R); \ + diff -= _FP_WFRACXBITS_##fs; \ + if (diff) \ + { \ + R##_e -= diff; \ + _FP_FRAC_SLL_##wc(R, diff); \ + } \ + } \ + } \ + break; \ + } \ + \ + case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \ + _FP_CHOOSENAN(fs, wc, R, X, Y); \ + break; \ + \ + case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \ + R##_e = X##_e; \ + case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \ + case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \ + case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \ + _FP_FRAC_COPY_##wc(R, X); \ + R##_s = X##_s; \ + R##_c = X##_c; \ + break; \ + \ + case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \ + R##_e = Y##_e; \ + case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \ + case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \ + case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \ + _FP_FRAC_COPY_##wc(R, Y); \ + R##_s = Y##_s; \ + R##_c = Y##_c; \ + break; \ + \ + case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \ + if (X##_s != Y##_s) \ + { \ + /* +INF + -INF => NAN */ \ + _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ + R##_s = X##_s ^ Y##_s; \ + R##_c = FP_CLS_NAN; \ + break; \ + } \ + /* FALLTHRU */ \ + \ + case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \ + case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \ + R##_s = X##_s; \ + R##_c = FP_CLS_INF; \ + break; \ + \ + case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \ + case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \ + R##_s = Y##_s; \ + R##_c = FP_CLS_INF; \ + break; \ + \ + case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \ + /* make sure the sign is correct */ \ + if (FP_ROUNDMODE == FP_RND_MINF) \ + R##_s = X##_s | Y##_s; \ + else \ + R##_s = X##_s & Y##_s; \ + R##_c = FP_CLS_ZERO; \ + break; \ + \ + default: \ + abort(); \ + } \ +} while (0) + + +/* + * Main negation routine. FIXME -- when we care about setting exception + * bits reliably, this will not do. We should examine all of the fp classes. + */ + +#define _FP_NEG(fs, wc, R, X) \ + do { \ + _FP_FRAC_COPY_##wc(R, X); \ + R##_c = X##_c; \ + R##_e = X##_e; \ + R##_s = 1 ^ X##_s; \ + } while (0) + + +/* + * Main multiplication routine. The input values should be cooked. + */ + +#define _FP_MUL(fs, wc, R, X, Y) \ +do { \ + R##_s = X##_s ^ Y##_s; \ + switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \ + { \ + case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \ + R##_c = FP_CLS_NORMAL; \ + R##_e = X##_e + Y##_e + 1; \ + \ + _FP_MUL_MEAT_##fs(R,X,Y); \ + \ + if (_FP_FRAC_OVERP_##wc(fs, R)) \ + _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \ + else \ + R##_e--; \ + break; \ + \ + case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \ + _FP_CHOOSENAN(fs, wc, R, X, Y); \ + break; \ + \ + case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \ + case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \ + case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \ + R##_s = X##_s; \ + \ + case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \ + case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \ + case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \ + case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \ + _FP_FRAC_COPY_##wc(R, X); \ + R##_c = X##_c; \ + break; \ + \ + case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \ + case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \ + case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \ + R##_s = Y##_s; \ + \ + case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \ + case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \ + _FP_FRAC_COPY_##wc(R, Y); \ + R##_c = Y##_c; \ + break; \ + \ + case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \ + case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \ + R##_c = FP_CLS_NAN; \ + _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ + break; \ + \ + default: \ + abort(); \ + } \ +} while (0) + + +/* + * Main division routine. The input values should be cooked. + */ + +#define _FP_DIV(fs, wc, R, X, Y) \ +do { \ + R##_s = X##_s ^ Y##_s; \ + switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \ + { \ + case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \ + R##_c = FP_CLS_NORMAL; \ + R##_e = X##_e - Y##_e; \ + \ + _FP_DIV_MEAT_##fs(R,X,Y); \ + break; \ + \ + case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \ + _FP_CHOOSENAN(fs, wc, R, X, Y); \ + break; \ + \ + case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \ + case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \ + case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \ + R##_s = X##_s; \ + _FP_FRAC_COPY_##wc(R, X); \ + R##_c = X##_c; \ + break; \ + \ + case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \ + case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \ + case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \ + R##_s = Y##_s; \ + _FP_FRAC_COPY_##wc(R, Y); \ + R##_c = Y##_c; \ + break; \ + \ + case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \ + case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \ + case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \ + R##_c = FP_CLS_ZERO; \ + break; \ + \ + case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \ + case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \ + case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \ + R##_c = FP_CLS_INF; \ + break; \ + \ + case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \ + case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \ + R##_c = FP_CLS_NAN; \ + _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ + break; \ + \ + default: \ + abort(); \ + } \ +} while (0) + + +/* + * Main differential comparison routine. The inputs should be raw not + * cooked. The return is -1,0,1 for normal values, 2 otherwise. + */ + +#define _FP_CMP(fs, wc, ret, X, Y, un) \ + do { \ + /* NANs are unordered */ \ + if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \ + || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \ + { \ + ret = un; \ + } \ + else \ + { \ + int __x_zero = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0; \ + int __y_zero = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0; \ + \ + if (__x_zero && __y_zero) \ + ret = 0; \ + else if (__x_zero) \ + ret = Y##_s ? 1 : -1; \ + else if (__y_zero) \ + ret = X##_s ? -1 : 1; \ + else if (X##_s != Y##_s) \ + ret = X##_s ? -1 : 1; \ + else if (X##_e > Y##_e) \ + ret = X##_s ? -1 : 1; \ + else if (X##_e < Y##_e) \ + ret = X##_s ? 1 : -1; \ + else if (_FP_FRAC_GT_##wc(X, Y)) \ + ret = X##_s ? -1 : 1; \ + else if (_FP_FRAC_GT_##wc(Y, X)) \ + ret = X##_s ? 1 : -1; \ + else \ + ret = 0; \ + } \ + } while (0) + + +/* Simplification for strict equality. */ + +#define _FP_CMP_EQ(fs, wc, ret, X, Y) \ + do { \ + /* NANs are unordered */ \ + if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \ + || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \ + { \ + ret = 1; \ + } \ + else \ + { \ + ret = !(X##_e == Y##_e \ + && _FP_FRAC_EQ_##wc(X, Y) \ + && (X##_s == Y##_s || !X##_e && _FP_FRAC_ZEROP_##wc(X))); \ + } \ + } while (0) + +/* + * Main square root routine. The input value should be cooked. + */ + +#define _FP_SQRT(fs, wc, R, X) \ +do { \ + _FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S); \ + _FP_W_TYPE q; \ + switch (X##_c) \ + { \ + case FP_CLS_NAN: \ + R##_s = 0; \ + R##_c = FP_CLS_NAN; \ + _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ + break; \ + case FP_CLS_INF: \ + if (X##_s) \ + { \ + R##_s = 0; \ + R##_c = FP_CLS_NAN; /* sNAN */ \ + } \ + else \ + { \ + R##_s = 0; \ + R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */ \ + } \ + break; \ + case FP_CLS_ZERO: \ + R##_s = X##_s; \ + R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */ \ + break; \ + case FP_CLS_NORMAL: \ + R##_s = 0; \ + if (X##_s) \ + { \ + R##_c = FP_CLS_NAN; /* sNAN */ \ + break; \ + } \ + R##_c = FP_CLS_NORMAL; \ + if (X##_e & 1) \ + _FP_FRAC_SLL_##wc(X, 1); \ + R##_e = X##_e >> 1; \ + _FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc); \ + _FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc); \ + q = _FP_OVERFLOW_##fs; \ + _FP_FRAC_SLL_##wc(X, 1); \ + _FP_SQRT_MEAT_##wc(R, S, T, X, q); \ + _FP_FRAC_SRL_##wc(R, 1); \ + } \ + } while (0) + +/* + * Convert from FP to integer + */ + +/* "When a NaN, infinity, large positive argument >= 2147483648.0, or + * large negative argument <= -2147483649.0 is converted to an integer, + * the invalid_current bit...should be set and fp_exception_IEEE_754 should + * be raised. If the floating point invalid trap is disabled, no trap occurs + * and a numerical result is generated: if the sign bit of the operand + * is 0, the result is 2147483647; if the sign bit of the operand is 1, + * the result is -2147483648." + * Similarly for conversion to extended ints, except that the boundaries + * are >= 2^63, <= -(2^63 + 1), and the results are 2^63 + 1 for s=0 and + * -2^63 for s=1. + * -- SPARC Architecture Manual V9, Appendix B, which specifies how + * SPARCs resolve implementation dependencies in the IEEE-754 spec. + * I don't believe that the code below follows this. I'm not even sure + * it's right! + * It doesn't cope with needing to convert to an n bit integer when there + * is no n bit integer type. Fortunately gcc provides long long so this + * isn't a problem for sparc32. + * I have, however, fixed its NaN handling to conform as above. + * -- PMM 02/1998 + * NB: rsigned is not 'is r declared signed?' but 'should the value stored + * in r be signed or unsigned?'. r is always(?) declared unsigned. + * Comments below are mine, BTW -- PMM + */ +#define _FP_TO_INT(fs, wc, r, X, rsize, rsigned) \ + do { \ + switch (X##_c) \ + { \ + case FP_CLS_NORMAL: \ + if (X##_e < 0) \ + { \ + /* case FP_CLS_NAN: see above! */ \ + case FP_CLS_ZERO: \ + r = 0; \ + } \ + else if (X##_e >= rsize - (rsigned != 0)) \ + { /* overflow */ \ + case FP_CLS_NAN: \ + case FP_CLS_INF: \ + if (rsigned) \ + { \ + r = 1; \ + r <<= rsize - 1; \ + r -= 1 - X##_s; \ + } \ + else \ + { \ + r = 0; \ + if (!X##_s) \ + r = ~r; \ + } \ + } \ + else \ + { \ + if (_FP_W_TYPE_SIZE*wc < rsize) \ + { \ + _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \ + r <<= X##_e - _FP_WFRACBITS_##fs; \ + } \ + else \ + { \ + if (X##_e >= _FP_WFRACBITS_##fs) \ + _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1));\ + else \ + _FP_FRAC_SRL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1));\ + _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \ + } \ + if (rsigned && X##_s) \ + r = -r; \ + } \ + break; \ + } \ + } while (0) + +#define _FP_FROM_INT(fs, wc, X, r, rsize, rtype) \ + do { \ + if (r) \ + { \ + X##_c = FP_CLS_NORMAL; \ + \ + if ((X##_s = (r < 0))) \ + r = -r; \ + /* Note that `r' is now considered unsigned, so we don't have \ + to worry about the single signed overflow case. */ \ + \ + if (rsize <= _FP_W_TYPE_SIZE) \ + __FP_CLZ(X##_e, r); \ + else \ + __FP_CLZ_2(X##_e, (_FP_W_TYPE)(r >> _FP_W_TYPE_SIZE), \ + (_FP_W_TYPE)r); \ + if (rsize < _FP_W_TYPE_SIZE) \ + X##_e -= (_FP_W_TYPE_SIZE - rsize); \ + X##_e = rsize - X##_e - 1; \ + \ + if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs < X##_e) \ + __FP_FRAC_SRS_1(r, (X##_e - _FP_WFRACBITS_##fs), rsize); \ + r &= ~((_FP_W_TYPE)1 << X##_e); \ + _FP_FRAC_DISASSEMBLE_##wc(X, ((unsigned rtype)r), rsize); \ + _FP_FRAC_SLL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1)); \ + } \ + else \ + { \ + X##_c = FP_CLS_ZERO, X##_s = 0; \ + } \ + } while (0) + + +#define FP_CONV(dfs,sfs,dwc,swc,D,S) \ + do { \ + _FP_FRAC_CONV_##dwc##_##swc(dfs, sfs, D, S); \ + D##_e = S##_e; \ + D##_c = S##_c; \ + D##_s = S##_s; \ + } while (0) + +/* + * Helper primitives. + */ + +/* Count leading zeros in a word. */ + +#ifndef __FP_CLZ +#if _FP_W_TYPE_SIZE < 64 +/* this is just to shut the compiler up about shifts > word length -- PMM 02/1998 */ +#define __FP_CLZ(r, x) \ + do { \ + _FP_W_TYPE _t = (x); \ + r = _FP_W_TYPE_SIZE - 1; \ + if (_t > 0xffff) r -= 16; \ + if (_t > 0xffff) _t >>= 16; \ + if (_t > 0xff) r -= 8; \ + if (_t > 0xff) _t >>= 8; \ + if (_t & 0xf0) r -= 4; \ + if (_t & 0xf0) _t >>= 4; \ + if (_t & 0xc) r -= 2; \ + if (_t & 0xc) _t >>= 2; \ + if (_t & 0x2) r -= 1; \ + } while (0) +#else /* not _FP_W_TYPE_SIZE < 64 */ +#define __FP_CLZ(r, x) \ + do { \ + _FP_W_TYPE _t = (x); \ + r = _FP_W_TYPE_SIZE - 1; \ + if (_t > 0xffffffff) r -= 32; \ + if (_t > 0xffffffff) _t >>= 32; \ + if (_t > 0xffff) r -= 16; \ + if (_t > 0xffff) _t >>= 16; \ + if (_t > 0xff) r -= 8; \ + if (_t > 0xff) _t >>= 8; \ + if (_t & 0xf0) r -= 4; \ + if (_t & 0xf0) _t >>= 4; \ + if (_t & 0xc) r -= 2; \ + if (_t & 0xc) _t >>= 2; \ + if (_t & 0x2) r -= 1; \ + } while (0) +#endif /* not _FP_W_TYPE_SIZE < 64 */ +#endif /* ndef __FP_CLZ */ + +#define _FP_DIV_HELP_imm(q, r, n, d) \ + do { \ + q = n / d, r = n % d; \ + } while (0) + diff --git a/arch/powerpc/math-emu/sfp-machine.h b/arch/powerpc/math-emu/sfp-machine.h new file mode 100644 index 000000000000..4b17d83cfcdd --- /dev/null +++ b/arch/powerpc/math-emu/sfp-machine.h @@ -0,0 +1,377 @@ +/* Machine-dependent software floating-point definitions. PPC version. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Actually, this is a PPC (32bit) version, written based on the + i386, sparc, and sparc64 versions, by me, + Peter Maydell (pmaydell@chiark.greenend.org.uk). + Comments are by and large also mine, although they may be inaccurate. + + In picking out asm fragments I've gone with the lowest common + denominator, which also happens to be the hardware I have :-> + That is, a SPARC without hardware multiply and divide. + */ + +/* basic word size definitions */ +#define _FP_W_TYPE_SIZE 32 +#define _FP_W_TYPE unsigned long +#define _FP_WS_TYPE signed long +#define _FP_I_TYPE long + +#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2)) +#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1)) +#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2)) + +/* You can optionally code some things like addition in asm. For + * example, i386 defines __FP_FRAC_ADD_2 as asm. If you don't + * then you get a fragment of C code [if you change an #ifdef 0 + * in op-2.h] or a call to add_ssaaaa (see below). + * Good places to look for asm fragments to use are gcc and glibc. + * gcc's longlong.h is useful. + */ + +/* We need to know how to multiply and divide. If the host word size + * is >= 2*fracbits you can use FP_MUL_MEAT_n_imm(t,R,X,Y) which + * codes the multiply with whatever gcc does to 'a * b'. + * _FP_MUL_MEAT_n_wide(t,R,X,Y,f) is used when you have an asm + * function that can multiply two 1W values and get a 2W result. + * Otherwise you're stuck with _FP_MUL_MEAT_n_hard(t,R,X,Y) which + * does bitshifting to avoid overflow. + * For division there is FP_DIV_MEAT_n_imm(t,R,X,Y,f) for word size + * >= 2*fracbits, where f is either _FP_DIV_HELP_imm or + * _FP_DIV_HELP_ldiv (see op-1.h). + * _FP_DIV_MEAT_udiv() is if you have asm to do 2W/1W => (1W, 1W). + * [GCC and glibc have longlong.h which has the asm macro udiv_qrnnd + * to do this.] + * In general, 'n' is the number of words required to hold the type, + * and 't' is either S, D or Q for single/double/quad. + * -- PMM + */ +/* Example: SPARC64: + * #define _FP_MUL_MEAT_S(R,X,Y) _FP_MUL_MEAT_1_imm(S,R,X,Y) + * #define _FP_MUL_MEAT_D(R,X,Y) _FP_MUL_MEAT_1_wide(D,R,X,Y,umul_ppmm) + * #define _FP_MUL_MEAT_Q(R,X,Y) _FP_MUL_MEAT_2_wide(Q,R,X,Y,umul_ppmm) + * + * #define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm) + * #define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_1_udiv(D,R,X,Y) + * #define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_2_udiv_64(Q,R,X,Y) + * + * Example: i386: + * #define _FP_MUL_MEAT_S(R,X,Y) _FP_MUL_MEAT_1_wide(S,R,X,Y,_i386_mul_32_64) + * #define _FP_MUL_MEAT_D(R,X,Y) _FP_MUL_MEAT_2_wide(D,R,X,Y,_i386_mul_32_64) + * + * #define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_udiv(S,R,X,Y,_i386_div_64_32) + * #define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv_64(D,R,X,Y) + */ + +#define _FP_MUL_MEAT_S(R,X,Y) _FP_MUL_MEAT_1_wide(S,R,X,Y,umul_ppmm) +#define _FP_MUL_MEAT_D(R,X,Y) _FP_MUL_MEAT_2_wide(D,R,X,Y,umul_ppmm) + +#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_udiv(S,R,X,Y) +#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv_64(D,R,X,Y) + +/* These macros define what NaN looks like. They're supposed to expand to + * a comma-separated set of 32bit unsigned ints that encode NaN. + */ +#define _FP_NANFRAC_S _FP_QNANBIT_S +#define _FP_NANFRAC_D _FP_QNANBIT_D, 0 +#define _FP_NANFRAC_Q _FP_QNANBIT_Q, 0, 0, 0 + +#define _FP_KEEPNANFRACP 1 + +/* This macro appears to be called when both X and Y are NaNs, and + * has to choose one and copy it to R. i386 goes for the larger of the + * two, sparc64 just picks Y. I don't understand this at all so I'll + * go with sparc64 because it's shorter :-> -- PMM + */ +#define _FP_CHOOSENAN(fs, wc, R, X, Y) \ + do { \ + R##_s = Y##_s; \ + _FP_FRAC_COPY_##wc(R,Y); \ + R##_c = FP_CLS_NAN; \ + } while (0) + + +extern void fp_unpack_d(long *, unsigned long *, unsigned long *, + long *, long *, void *); +extern int fp_pack_d(void *, long, unsigned long, unsigned long, long, long); +extern int fp_pack_ds(void *, long, unsigned long, unsigned long, long, long); + +#define __FP_UNPACK_RAW_1(fs, X, val) \ + do { \ + union _FP_UNION_##fs *_flo = \ + (union _FP_UNION_##fs *)val; \ + \ + X##_f = _flo->bits.frac; \ + X##_e = _flo->bits.exp; \ + X##_s = _flo->bits.sign; \ + } while (0) + +#define __FP_UNPACK_RAW_2(fs, X, val) \ + do { \ + union _FP_UNION_##fs *_flo = \ + (union _FP_UNION_##fs *)val; \ + \ + X##_f0 = _flo->bits.frac0; \ + X##_f1 = _flo->bits.frac1; \ + X##_e = _flo->bits.exp; \ + X##_s = _flo->bits.sign; \ + } while (0) + +#define __FP_UNPACK_S(X,val) \ + do { \ + __FP_UNPACK_RAW_1(S,X,val); \ + _FP_UNPACK_CANONICAL(S,1,X); \ + } while (0) + +#define __FP_UNPACK_D(X,val) \ + fp_unpack_d(&X##_s, &X##_f1, &X##_f0, &X##_e, &X##_c, val) + +#define __FP_PACK_RAW_1(fs, val, X) \ + do { \ + union _FP_UNION_##fs *_flo = \ + (union _FP_UNION_##fs *)val; \ + \ + _flo->bits.frac = X##_f; \ + _flo->bits.exp = X##_e; \ + _flo->bits.sign = X##_s; \ + } while (0) + +#define __FP_PACK_RAW_2(fs, val, X) \ + do { \ + union _FP_UNION_##fs *_flo = \ + (union _FP_UNION_##fs *)val; \ + \ + _flo->bits.frac0 = X##_f0; \ + _flo->bits.frac1 = X##_f1; \ + _flo->bits.exp = X##_e; \ + _flo->bits.sign = X##_s; \ + } while (0) + +#include +#include + +#define __FPU_FPSCR (current->thread.fpscr.val) + +/* We only actually write to the destination register + * if exceptions signalled (if any) will not trap. + */ +#define __FPU_ENABLED_EXC \ +({ \ + (__FPU_FPSCR >> 3) & 0x1f; \ +}) + +#define __FPU_TRAP_P(bits) \ + ((__FPU_ENABLED_EXC & (bits)) != 0) + +#define __FP_PACK_S(val,X) \ +({ int __exc = _FP_PACK_CANONICAL(S,1,X); \ + if(!__exc || !__FPU_TRAP_P(__exc)) \ + __FP_PACK_RAW_1(S,val,X); \ + __exc; \ +}) + +#define __FP_PACK_D(val,X) \ + fp_pack_d(val, X##_s, X##_f1, X##_f0, X##_e, X##_c) + +#define __FP_PACK_DS(val,X) \ + fp_pack_ds(val, X##_s, X##_f1, X##_f0, X##_e, X##_c) + +/* Obtain the current rounding mode. */ +#define FP_ROUNDMODE \ +({ \ + __FPU_FPSCR & 0x3; \ +}) + +/* the asm fragments go here: all these are taken from glibc-2.0.5's + * stdlib/longlong.h + */ + +#include +#include + +/* add_ssaaaa is used in op-2.h and should be equivalent to + * #define add_ssaaaa(sh,sl,ah,al,bh,bl) (sh = ah+bh+ (( sl = al+bl) < al)) + * add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1, + * high_addend_2, low_addend_2) adds two UWtype integers, composed by + * HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2 + * respectively. The result is placed in HIGH_SUM and LOW_SUM. Overflow + * (i.e. carry out) is not stored anywhere, and is lost. + */ +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%r" ((USItype)(ah)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl))); \ + else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%r" ((USItype)(ah)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl))); \ + else \ + __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%r" ((USItype)(ah)), \ + "r" ((USItype)(bh)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl))); \ + } while (0) + +/* sub_ddmmss is used in op-2.h and udivmodti4.c and should be equivalent to + * #define sub_ddmmss(sh, sl, ah, al, bh, bl) (sh = ah-bh - ((sl = al-bl) > al)) + * sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend, + * high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers, + * composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and + * LOW_SUBTRAHEND_2 respectively. The result is placed in HIGH_DIFFERENCE + * and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere, + * and is lost. + */ +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (ah) && (ah) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(bh)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + else if (__builtin_constant_p (ah) && (ah) ==~(USItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(bh)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + else if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(ah)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(ah)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + else \ + __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(ah)), \ + "r" ((USItype)(bh)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + } while (0) + +/* asm fragments for mul and div */ + +/* umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two + * UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype + * word product in HIGH_PROD and LOW_PROD. + */ +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhwu %0,%1,%2" \ + : "=r" ((USItype)(ph)) \ + : "%r" (__m0), \ + "r" (__m1)); \ + (pl) = __m0 * __m1; \ + } while (0) + +/* udiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + * denominator) divides a UDWtype, composed by the UWtype integers + * HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient + * in QUOTIENT and the remainder in REMAINDER. HIGH_NUMERATOR must be less + * than DENOMINATOR for correct operation. If, in addition, the most + * significant bit of DENOMINATOR must be 1, then the pre-processor symbol + * UDIV_NEEDS_NORMALIZATION is defined to 1. + */ +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { \ + UWtype __d1, __d0, __q1, __q0, __r1, __r0, __m; \ + __d1 = __ll_highpart (d); \ + __d0 = __ll_lowpart (d); \ + \ + __r1 = (n1) % __d1; \ + __q1 = (n1) / __d1; \ + __m = (UWtype) __q1 * __d0; \ + __r1 = __r1 * __ll_B | __ll_highpart (n0); \ + if (__r1 < __m) \ + { \ + __q1--, __r1 += (d); \ + if (__r1 >= (d)) /* we didn't get carry when adding to __r1 */ \ + if (__r1 < __m) \ + __q1--, __r1 += (d); \ + } \ + __r1 -= __m; \ + \ + __r0 = __r1 % __d1; \ + __q0 = __r1 / __d1; \ + __m = (UWtype) __q0 * __d0; \ + __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ + if (__r0 < __m) \ + { \ + __q0--, __r0 += (d); \ + if (__r0 >= (d)) \ + if (__r0 < __m) \ + __q0--, __r0 += (d); \ + } \ + __r0 -= __m; \ + \ + (q) = (UWtype) __q1 * __ll_B | __q0; \ + (r) = __r0; \ + } while (0) + +#define UDIV_NEEDS_NORMALIZATION 1 + +#define abort() \ + return 0 + +#ifdef __BIG_ENDIAN +#define __BYTE_ORDER __BIG_ENDIAN +#else +#define __BYTE_ORDER __LITTLE_ENDIAN +#endif + +/* Exception flags. */ +#define EFLAG_INVALID (1 << (31 - 2)) +#define EFLAG_OVERFLOW (1 << (31 - 3)) +#define EFLAG_UNDERFLOW (1 << (31 - 4)) +#define EFLAG_DIVZERO (1 << (31 - 5)) +#define EFLAG_INEXACT (1 << (31 - 6)) + +#define EFLAG_VXSNAN (1 << (31 - 7)) +#define EFLAG_VXISI (1 << (31 - 8)) +#define EFLAG_VXIDI (1 << (31 - 9)) +#define EFLAG_VXZDZ (1 << (31 - 10)) +#define EFLAG_VXIMZ (1 << (31 - 11)) +#define EFLAG_VXVC (1 << (31 - 12)) +#define EFLAG_VXSOFT (1 << (31 - 21)) +#define EFLAG_VXSQRT (1 << (31 - 22)) +#define EFLAG_VXCVI (1 << (31 - 23)) diff --git a/arch/powerpc/math-emu/single.h b/arch/powerpc/math-emu/single.h new file mode 100644 index 000000000000..f19d99451815 --- /dev/null +++ b/arch/powerpc/math-emu/single.h @@ -0,0 +1,66 @@ +/* + * Definitions for IEEE Single Precision + */ + +#if _FP_W_TYPE_SIZE < 32 +#error "Here's a nickel kid. Go buy yourself a real computer." +#endif + +#define _FP_FRACBITS_S 24 +#define _FP_FRACXBITS_S (_FP_W_TYPE_SIZE - _FP_FRACBITS_S) +#define _FP_WFRACBITS_S (_FP_WORKBITS + _FP_FRACBITS_S) +#define _FP_WFRACXBITS_S (_FP_W_TYPE_SIZE - _FP_WFRACBITS_S) +#define _FP_EXPBITS_S 8 +#define _FP_EXPBIAS_S 127 +#define _FP_EXPMAX_S 255 +#define _FP_QNANBIT_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-2)) +#define _FP_IMPLBIT_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-1)) +#define _FP_OVERFLOW_S ((_FP_W_TYPE)1 << (_FP_WFRACBITS_S)) + +/* The implementation of _FP_MUL_MEAT_S and _FP_DIV_MEAT_S should be + chosen by the target machine. */ + +union _FP_UNION_S +{ + float flt; + struct { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned sign : 1; + unsigned exp : _FP_EXPBITS_S; + unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0); +#else + unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0); + unsigned exp : _FP_EXPBITS_S; + unsigned sign : 1; +#endif + } bits __attribute__((packed)); +}; + +#define FP_DECL_S(X) _FP_DECL(1,X) +#define FP_UNPACK_RAW_S(X,val) _FP_UNPACK_RAW_1(S,X,val) +#define FP_PACK_RAW_S(val,X) _FP_PACK_RAW_1(S,val,X) + +#define FP_UNPACK_S(X,val) \ + do { \ + _FP_UNPACK_RAW_1(S,X,val); \ + _FP_UNPACK_CANONICAL(S,1,X); \ + } while (0) + +#define FP_PACK_S(val,X) \ + do { \ + _FP_PACK_CANONICAL(S,1,X); \ + _FP_PACK_RAW_1(S,val,X); \ + } while (0) + +#define FP_NEG_S(R,X) _FP_NEG(S,1,R,X) +#define FP_ADD_S(R,X,Y) _FP_ADD(S,1,R,X,Y) +#define FP_SUB_S(R,X,Y) _FP_SUB(S,1,R,X,Y) +#define FP_MUL_S(R,X,Y) _FP_MUL(S,1,R,X,Y) +#define FP_DIV_S(R,X,Y) _FP_DIV(S,1,R,X,Y) +#define FP_SQRT_S(R,X) _FP_SQRT(S,1,R,X) + +#define FP_CMP_S(r,X,Y,un) _FP_CMP(S,1,r,X,Y,un) +#define FP_CMP_EQ_S(r,X,Y) _FP_CMP_EQ(S,1,r,X,Y) + +#define FP_TO_INT_S(r,X,rsz,rsg) _FP_TO_INT(S,1,r,X,rsz,rsg) +#define FP_FROM_INT_S(X,r,rs,rt) _FP_FROM_INT(S,1,X,r,rs,rt) diff --git a/arch/powerpc/math-emu/soft-fp.h b/arch/powerpc/math-emu/soft-fp.h new file mode 100644 index 000000000000..cca39598f873 --- /dev/null +++ b/arch/powerpc/math-emu/soft-fp.h @@ -0,0 +1,104 @@ +#ifndef SOFT_FP_H +#define SOFT_FP_H + +#include "sfp-machine.h" + +#define _FP_WORKBITS 3 +#define _FP_WORK_LSB ((_FP_W_TYPE)1 << 3) +#define _FP_WORK_ROUND ((_FP_W_TYPE)1 << 2) +#define _FP_WORK_GUARD ((_FP_W_TYPE)1 << 1) +#define _FP_WORK_STICKY ((_FP_W_TYPE)1 << 0) + +#ifndef FP_RND_NEAREST +# define FP_RND_NEAREST 0 +# define FP_RND_ZERO 1 +# define FP_RND_PINF 2 +# define FP_RND_MINF 3 +#ifndef FP_ROUNDMODE +# define FP_ROUNDMODE FP_RND_NEAREST +#endif +#endif + +#define _FP_ROUND_NEAREST(wc, X) \ +({ int __ret = 0; \ + int __frac = _FP_FRAC_LOW_##wc(X) & 15; \ + if (__frac & 7) { \ + __ret = EFLAG_INEXACT; \ + if ((__frac & 7) != _FP_WORK_ROUND) \ + _FP_FRAC_ADDI_##wc(X, _FP_WORK_ROUND); \ + else if (__frac & _FP_WORK_LSB) \ + _FP_FRAC_ADDI_##wc(X, _FP_WORK_ROUND); \ + } \ + __ret; \ +}) + +#define _FP_ROUND_ZERO(wc, X) \ +({ int __ret = 0; \ + if (_FP_FRAC_LOW_##wc(X) & 7) \ + __ret = EFLAG_INEXACT; \ + __ret; \ +}) + +#define _FP_ROUND_PINF(wc, X) \ +({ int __ret = EFLAG_INEXACT; \ + if (!X##_s && (_FP_FRAC_LOW_##wc(X) & 7)) \ + _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB); \ + else __ret = 0; \ + __ret; \ +}) + +#define _FP_ROUND_MINF(wc, X) \ +({ int __ret = EFLAG_INEXACT; \ + if (X##_s && (_FP_FRAC_LOW_##wc(X) & 7)) \ + _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB); \ + else __ret = 0; \ + __ret; \ +}) + +#define _FP_ROUND(wc, X) \ +({ int __ret = 0; \ + switch (FP_ROUNDMODE) \ + { \ + case FP_RND_NEAREST: \ + __ret |= _FP_ROUND_NEAREST(wc,X); \ + break; \ + case FP_RND_ZERO: \ + __ret |= _FP_ROUND_ZERO(wc,X); \ + break; \ + case FP_RND_PINF: \ + __ret |= _FP_ROUND_PINF(wc,X); \ + break; \ + case FP_RND_MINF: \ + __ret |= _FP_ROUND_MINF(wc,X); \ + break; \ + }; \ + __ret; \ +}) + +#define FP_CLS_NORMAL 0 +#define FP_CLS_ZERO 1 +#define FP_CLS_INF 2 +#define FP_CLS_NAN 3 + +#define _FP_CLS_COMBINE(x,y) (((x) << 2) | (y)) + +#include "op-1.h" +#include "op-2.h" +#include "op-4.h" +#include "op-common.h" + +/* Sigh. Silly things longlong.h needs. */ +#define UWtype _FP_W_TYPE +#define W_TYPE_SIZE _FP_W_TYPE_SIZE + +typedef int SItype __attribute__((mode(SI))); +typedef int DItype __attribute__((mode(DI))); +typedef unsigned int USItype __attribute__((mode(SI))); +typedef unsigned int UDItype __attribute__((mode(DI))); +#if _FP_W_TYPE_SIZE == 32 +typedef unsigned int UHWtype __attribute__((mode(HI))); +#elif _FP_W_TYPE_SIZE == 64 +typedef USItype UHWtype; +#endif + +#endif diff --git a/arch/powerpc/math-emu/stfd.c b/arch/powerpc/math-emu/stfd.c new file mode 100644 index 000000000000..3f8c2558a9e8 --- /dev/null +++ b/arch/powerpc/math-emu/stfd.c @@ -0,0 +1,20 @@ +#include +#include +#include + +int +stfd(void *frS, void *ea) +{ +#if 0 +#ifdef DEBUG + printk("%s: S %p, ea %p: ", __FUNCTION__, frS, ea); + dump_double(frS); + printk("\n"); +#endif +#endif + + if (copy_to_user(ea, frS, sizeof(double))) + return -EFAULT; + + return 0; +} diff --git a/arch/powerpc/math-emu/stfiwx.c b/arch/powerpc/math-emu/stfiwx.c new file mode 100644 index 000000000000..95caaeec6a08 --- /dev/null +++ b/arch/powerpc/math-emu/stfiwx.c @@ -0,0 +1,16 @@ +#include +#include +#include + +int +stfiwx(u32 *frS, void *ea) +{ +#ifdef DEBUG + printk("%s: %p %p\n", __FUNCTION__, frS, ea); +#endif + + if (copy_to_user(ea, &frS[1], sizeof(frS[1]))) + return -EFAULT; + + return 0; +} diff --git a/arch/powerpc/math-emu/stfs.c b/arch/powerpc/math-emu/stfs.c new file mode 100644 index 000000000000..e87ca23c6dc3 --- /dev/null +++ b/arch/powerpc/math-emu/stfs.c @@ -0,0 +1,41 @@ +#include +#include +#include + +#include "soft-fp.h" +#include "double.h" +#include "single.h" + +int +stfs(void *frS, void *ea) +{ + FP_DECL_D(A); + FP_DECL_S(R); + float f; + int err; + +#ifdef DEBUG + printk("%s: S %p, ea %p\n", __FUNCTION__, frS, ea); +#endif + + __FP_UNPACK_D(A, frS); + +#ifdef DEBUG + printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); +#endif + + FP_CONV(S, D, 1, 2, R, A); + +#ifdef DEBUG + printk("R: %ld %lu %ld (%ld)\n", R_s, R_f, R_e, R_c); +#endif + + err = _FP_PACK_CANONICAL(S, 1, R); + if (!err || !__FPU_TRAP_P(err)) { + __FP_PACK_RAW_1(S, &f, R); + if (copy_to_user(ea, &f, sizeof(float))) + return -EFAULT; + } + + return err; +} diff --git a/arch/powerpc/math-emu/types.c b/arch/powerpc/math-emu/types.c new file mode 100644 index 000000000000..e1ed15d829db --- /dev/null +++ b/arch/powerpc/math-emu/types.c @@ -0,0 +1,51 @@ +#include "soft-fp.h" +#include "double.h" +#include "single.h" + +void +fp_unpack_d(long *_s, unsigned long *_f1, unsigned long *_f0, + long *_e, long *_c, void *val) +{ + FP_DECL_D(X); + + __FP_UNPACK_RAW_2(D, X, val); + + _FP_UNPACK_CANONICAL(D, 2, X); + + *_s = X_s; + *_f1 = X_f1; + *_f0 = X_f0; + *_e = X_e; + *_c = X_c; +} + +int +fp_pack_d(void *val, long X_s, unsigned long X_f1, + unsigned long X_f0, long X_e, long X_c) +{ + int exc; + + exc = _FP_PACK_CANONICAL(D, 2, X); + if (!exc || !__FPU_TRAP_P(exc)) + __FP_PACK_RAW_2(D, val, X); + return exc; +} + +int +fp_pack_ds(void *val, long X_s, unsigned long X_f1, + unsigned long X_f0, long X_e, long X_c) +{ + FP_DECL_S(__X); + int exc; + + FP_CONV(S, D, 1, 2, __X, X); + exc = _FP_PACK_CANONICAL(S, 1, __X); + if (!exc || !__FPU_TRAP_P(exc)) { + _FP_UNPACK_CANONICAL(S, 1, __X); + FP_CONV(D, S, 2, 1, X, __X); + exc |= _FP_PACK_CANONICAL(D, 2, X); + if (!exc || !__FPU_TRAP_P(exc)) + __FP_PACK_RAW_2(D, val, X); + } + return exc; +} diff --git a/arch/powerpc/math-emu/udivmodti4.c b/arch/powerpc/math-emu/udivmodti4.c new file mode 100644 index 000000000000..7e112dc1e2f2 --- /dev/null +++ b/arch/powerpc/math-emu/udivmodti4.c @@ -0,0 +1,191 @@ +/* This has so very few changes over libgcc2's __udivmoddi4 it isn't funny. */ + +#include "soft-fp.h" + +#undef count_leading_zeros +#define count_leading_zeros __FP_CLZ + +void +_fp_udivmodti4(_FP_W_TYPE q[2], _FP_W_TYPE r[2], + _FP_W_TYPE n1, _FP_W_TYPE n0, + _FP_W_TYPE d1, _FP_W_TYPE d0) +{ + _FP_W_TYPE q0, q1, r0, r1; + _FP_I_TYPE b, bm; + + if (d1 == 0) + { +#if !UDIV_NEEDS_NORMALIZATION + if (d0 > n1) + { + /* 0q = nn / 0D */ + + udiv_qrnnd (q0, n0, n1, n0, d0); + q1 = 0; + + /* Remainder in n0. */ + } + else + { + /* qq = NN / 0d */ + + if (d0 == 0) + d0 = 1 / d0; /* Divide intentionally by zero. */ + + udiv_qrnnd (q1, n1, 0, n1, d0); + udiv_qrnnd (q0, n0, n1, n0, d0); + + /* Remainder in n0. */ + } + + r0 = n0; + r1 = 0; + +#else /* UDIV_NEEDS_NORMALIZATION */ + + if (d0 > n1) + { + /* 0q = nn / 0D */ + + count_leading_zeros (bm, d0); + + if (bm != 0) + { + /* Normalize, i.e. make the most significant bit of the + denominator set. */ + + d0 = d0 << bm; + n1 = (n1 << bm) | (n0 >> (_FP_W_TYPE_SIZE - bm)); + n0 = n0 << bm; + } + + udiv_qrnnd (q0, n0, n1, n0, d0); + q1 = 0; + + /* Remainder in n0 >> bm. */ + } + else + { + /* qq = NN / 0d */ + + if (d0 == 0) + d0 = 1 / d0; /* Divide intentionally by zero. */ + + count_leading_zeros (bm, d0); + + if (bm == 0) + { + /* From (n1 >= d0) /\ (the most significant bit of d0 is set), + conclude (the most significant bit of n1 is set) /\ (the + leading quotient digit q1 = 1). + + This special case is necessary, not an optimization. + (Shifts counts of SI_TYPE_SIZE are undefined.) */ + + n1 -= d0; + q1 = 1; + } + else + { + _FP_W_TYPE n2; + + /* Normalize. */ + + b = _FP_W_TYPE_SIZE - bm; + + d0 = d0 << bm; + n2 = n1 >> b; + n1 = (n1 << bm) | (n0 >> b); + n0 = n0 << bm; + + udiv_qrnnd (q1, n1, n2, n1, d0); + } + + /* n1 != d0... */ + + udiv_qrnnd (q0, n0, n1, n0, d0); + + /* Remainder in n0 >> bm. */ + } + + r0 = n0 >> bm; + r1 = 0; +#endif /* UDIV_NEEDS_NORMALIZATION */ + } + else + { + if (d1 > n1) + { + /* 00 = nn / DD */ + + q0 = 0; + q1 = 0; + + /* Remainder in n1n0. */ + r0 = n0; + r1 = n1; + } + else + { + /* 0q = NN / dd */ + + count_leading_zeros (bm, d1); + if (bm == 0) + { + /* From (n1 >= d1) /\ (the most significant bit of d1 is set), + conclude (the most significant bit of n1 is set) /\ (the + quotient digit q0 = 0 or 1). + + This special case is necessary, not an optimization. */ + + /* The condition on the next line takes advantage of that + n1 >= d1 (true due to program flow). */ + if (n1 > d1 || n0 >= d0) + { + q0 = 1; + sub_ddmmss (n1, n0, n1, n0, d1, d0); + } + else + q0 = 0; + + q1 = 0; + + r0 = n0; + r1 = n1; + } + else + { + _FP_W_TYPE m1, m0, n2; + + /* Normalize. */ + + b = _FP_W_TYPE_SIZE - bm; + + d1 = (d1 << bm) | (d0 >> b); + d0 = d0 << bm; + n2 = n1 >> b; + n1 = (n1 << bm) | (n0 >> b); + n0 = n0 << bm; + + udiv_qrnnd (q0, n1, n2, n1, d1); + umul_ppmm (m1, m0, q0, d0); + + if (m1 > n1 || (m1 == n1 && m0 > n0)) + { + q0--; + sub_ddmmss (m1, m0, m1, m0, d1, d0); + } + + q1 = 0; + + /* Remainder in (n1n0 - m1m0) >> bm. */ + sub_ddmmss (n1, n0, n1, n0, m1, m0); + r0 = (n1 << b) | (n0 >> bm); + r1 = n1 >> bm; + } + } + } + + q[0] = q0; q[1] = q1; + r[0] = r0, r[1] = r1; +} -- cgit v1.2.2 From 9cf8ca38719e08e5388ddd37ef1c46442b8f99a4 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Mon, 27 Mar 2006 23:44:37 -0600 Subject: powerpc: Make uImage default build output for MPC8540 ADS When we build for the MPC8540 ADS produce a uImage by default. Updated the defconfig to reflect this as well. Signed-off-by: Kumar Gala --- arch/powerpc/configs/mpc8540_ads_defconfig | 43 +++++++++++++++++------------- arch/powerpc/platforms/85xx/Kconfig | 1 + 2 files changed, 26 insertions(+), 18 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/configs/mpc8540_ads_defconfig b/arch/powerpc/configs/mpc8540_ads_defconfig index 2a8290ee15c6..7f0780f1aa39 100644 --- a/arch/powerpc/configs/mpc8540_ads_defconfig +++ b/arch/powerpc/configs/mpc8540_ads_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: -# Sat Jan 14 15:57:54 2006 +# Linux kernel version: 2.6.16 +# Mon Mar 27 23:37:36 2006 # # CONFIG_PPC64 is not set CONFIG_PPC32=y @@ -9,6 +9,7 @@ CONFIG_PPC_MERGE=y CONFIG_MMU=y CONFIG_GENERIC_HARDIRQS=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_PPC=y CONFIG_EARLY_PRINTK=y @@ -18,6 +19,7 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_PPC_OF=y CONFIG_PPC_UDBG_16550=y # CONFIG_GENERIC_TBSYNC is not set +CONFIG_DEFAULT_UIMAGE=y # # Processor support @@ -42,7 +44,6 @@ CONFIG_SPE=y # Code maturity level options # CONFIG_EXPERIMENTAL=y -CONFIG_CLEAN_COMPILE=y CONFIG_BROKEN_ON_SMP=y CONFIG_INIT_ENV_ARG_LIMIT=32 @@ -58,6 +59,7 @@ CONFIG_SYSVIPC=y CONFIG_SYSCTL=y # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_EMBEDDED=y @@ -72,10 +74,6 @@ CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 CONFIG_SLAB=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 @@ -90,6 +88,8 @@ CONFIG_BASE_SMALL=0 # Block layer # # CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set # # IO Schedulers @@ -183,6 +183,7 @@ CONFIG_NET=y # # Networking options # +# CONFIG_NETDEBUG is not set CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y @@ -220,6 +221,11 @@ CONFIG_TCP_CONG_BIC=y # SCTP Configuration (EXPERIMENTAL) # # CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set @@ -229,11 +235,6 @@ CONFIG_TCP_CONG_BIC=y # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set - -# -# TIPC Configuration (EXPERIMENTAL) -# -# CONFIG_TIPC is not set # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -486,6 +487,12 @@ CONFIG_GEN_RTC=y # # CONFIG_I2C is not set +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + # # Dallas's 1-wire bus # @@ -496,16 +503,13 @@ CONFIG_GEN_RTC=y # CONFIG_HWMON=y # CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_F71805F is not set # CONFIG_HWMON_DEBUG_CHIP is not set # # Misc devices # -# -# Multimedia Capabilities Port drivers -# - # # Multimedia devices # @@ -531,6 +535,7 @@ CONFIG_HWMON=y # # CONFIG_USB_ARCH_HAS_HCD is not set # CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set # # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' @@ -551,7 +556,7 @@ CONFIG_HWMON=y # # -# SN Devices +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) # # @@ -603,7 +608,6 @@ CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y -# CONFIG_RELAYFS_FS is not set # CONFIG_CONFIGFS_FS is not set # @@ -658,6 +662,7 @@ CONFIG_PARTITION_ADVANCED=y # CONFIG_SGI_PARTITION is not set # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set # CONFIG_EFI_PARTITION is not set # @@ -695,6 +700,8 @@ CONFIG_DEBUG_MUTEXES=y # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_FS is not set # CONFIG_DEBUG_VM is not set +# CONFIG_UNWIND_INFO is not set +CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_DEBUGGER is not set # CONFIG_BDI_SWITCH is not set diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index d3d0ff745e84..06e371282f57 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig @@ -7,6 +7,7 @@ choice config MPC8540_ADS bool "Freescale MPC8540 ADS" + select DEFAULT_UIMAGE help This option enables support for the MPC 8540 ADS board -- cgit v1.2.2 From d0160bf0b3e87032be8e85f80ddd2f18e107b86f Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Mon, 27 Mar 2006 14:26:25 +1100 Subject: [PATCH] powerpc: Rename and export ppc64_firmware_features We need to export ppc64_firmware_features for modules. Before we do that I think we should probably rename it to powerpc_firmware_features. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/firmware.c | 4 +++- arch/powerpc/platforms/iseries/setup.c | 4 ++-- arch/powerpc/platforms/pseries/firmware.c | 2 +- arch/powerpc/platforms/pseries/setup.c | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/firmware.c b/arch/powerpc/kernel/firmware.c index 4d37a3cb80f6..0bfe9061720a 100644 --- a/arch/powerpc/kernel/firmware.c +++ b/arch/powerpc/kernel/firmware.c @@ -14,7 +14,9 @@ */ #include +#include #include -unsigned long ppc64_firmware_features; +unsigned long powerpc_firmware_features; +EXPORT_SYMBOL_GPL(powerpc_firmware_features); diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index fa4550611c11..155aa690e4bb 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -680,8 +680,8 @@ static int __init iseries_probe(int platform) if (PLATFORM_ISERIES_LPAR != platform) return 0; - ppc64_firmware_features |= FW_FEATURE_ISERIES; - ppc64_firmware_features |= FW_FEATURE_LPAR; + powerpc_firmware_features |= FW_FEATURE_ISERIES; + powerpc_firmware_features |= FW_FEATURE_LPAR; return 1; } diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c index 989f4bc136cb..c01d8f0cbe6d 100644 --- a/arch/powerpc/platforms/pseries/firmware.c +++ b/arch/powerpc/platforms/pseries/firmware.c @@ -91,7 +91,7 @@ void __init fw_feature_init(void) continue; /* we have a match */ - ppc64_firmware_features |= + powerpc_firmware_features |= firmware_features_table[i].val; break; } diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 213bf983242f..f736234db9b2 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -385,7 +385,7 @@ static int __init pSeries_probe(int platform) */ if (platform == PLATFORM_PSERIES_LPAR) - ppc64_firmware_features |= FW_FEATURE_LPAR; + powerpc_firmware_features |= FW_FEATURE_LPAR; return 1; } -- cgit v1.2.2 From 11089f08d9dd8b89cd07d6f126ccb4849e3c61a3 Mon Sep 17 00:00:00 2001 From: Laurent MEYER Date: Mon, 27 Mar 2006 11:37:41 +0200 Subject: [PATCH] powerpc: fix incorrect SA_ONSTACK behaviour for 64-bit processes *) When setting a sighandler using sigaction() call, if the flag SA_ONSTACK is set and no alternate stack is provided via sigaltstack(), the kernel still try to install the alternate stack. This behavior is the opposite of the one which is documented in Single Unix Specifications V3. *) Also when setting an alternate stack using sigaltstack() with the flag SS_DISABLE, the kernel try to install the alternate stack on signal delivery. These two use cases makes the process crash at signal delivery. This fixes it. Signed-off-by: Laurent Meyer Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/signal_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 82ec2f3f6713..27f65b95184d 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -212,7 +212,7 @@ static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs /* Default to using normal stack */ newsp = regs->gpr[1]; - if (ka->sa.sa_flags & SA_ONSTACK) { + if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size) { if (! on_sig_stack(regs->gpr[1])) newsp = (current->sas_ss_sp + current->sas_ss_size); } -- cgit v1.2.2 From 45d607ed92695d7543f5e1fc5b133cd69834e3e4 Mon Sep 17 00:00:00 2001 From: "Ryan S. Arnold" Date: Mon, 27 Mar 2006 21:25:16 +0200 Subject: [PATCH] powerpc: hvc_console updates These are some updates from both Ryan and Arnd for the hvc_console driver: The main point is to enable the inclusion of a console driver for rtas, which is currrently needed for the cell platform. Also shuffle around some data-type declarations and moves some functions out of include/asm-ppc64/hvconsole.h and into a new drivers/char/hvc_console.h file. Signed-off-by: "Ryan S. Arnold" Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/hvconsole.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/pseries/hvconsole.c b/arch/powerpc/platforms/pseries/hvconsole.c index 138e128a3886..ba6befd96636 100644 --- a/arch/powerpc/platforms/pseries/hvconsole.c +++ b/arch/powerpc/platforms/pseries/hvconsole.c @@ -62,6 +62,11 @@ int hvc_put_chars(uint32_t vtermno, const char *buf, int count) unsigned long *lbuf = (unsigned long *) buf; long ret; + + /* hcall will ret H_PARAMETER if 'count' exceeds firmware max.*/ + if (count > MAX_VIO_PUT_CHARS) + count = MAX_VIO_PUT_CHARS; + ret = plpar_hcall_norets(H_PUT_TERM_CHAR, vtermno, count, lbuf[0], lbuf[1]); if (ret == H_Success) -- cgit v1.2.2 From e78b47a59026f04eb98b9d392901be13b56f444f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 27 Mar 2006 21:27:40 +0200 Subject: [PATCH] spufs: fix __init/__exit annotations spufs_init and spufs_exit should be marked correctly so they can be removed when not needed. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spufs/inode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index dc06305eecf5..61e70d35d808 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -442,7 +442,7 @@ static struct file_system_type spufs_type = { .kill_sb = kill_litter_super, }; -static int spufs_init(void) +static int __init spufs_init(void) { int ret; ret = -ENOMEM; @@ -472,7 +472,7 @@ out: } module_init(spufs_init); -static void spufs_exit(void) +static void __exit spufs_exit(void) { spu_sched_exit(); unregister_spu_syscalls(&spufs_calls); -- cgit v1.2.2 From 9fe901d124871f5781b9c4ccbb7ff93fdff9d39e Mon Sep 17 00:00:00 2001 From: Mike Kravetz Date: Mon, 27 Mar 2006 15:20:00 -0800 Subject: [PATCH] powerpc: Workaround for pSeries RTAS bug A bug in the RTAS services incorrectly interprets some bits in the CR when called from the OS. Specifically, bits in CR4. The result could be a firmware crash that also takes down the partition. A firmware fix is in the works. We have seen this situation when performing DLPAR operations. As a temporary workaround, clear the CR in enter_rtas(). Note that enter_rtas() will not set any bits in CR4 before calling RTAS. Also note that the 32 bit version of enter_rtas() should have the same work around even though the chances of hitting the bug are much smaller due to the lack of DLPAR on 32 bit kernels. However, my assembly skills are a bit rusty and the 32 bit code doesn't seem to follow the conventions for where things should be saved. In addition, I don't have a system to test 32 bit kernels. Help creating and at least touch testing the same workaround for 32 bit would be appreciated. Signed-off-by: Mike Kravetz Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/entry_64.S | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 1060155d84c3..19ad5c6b1818 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -617,6 +617,12 @@ _GLOBAL(enter_rtas) mfsrr1 r10 std r10,_SRR1(r1) + /* Temporary workaround to clear CR until RTAS can be modified to + * ignore all bits. + */ + li r0,0 + mtcr r0 + /* There is no way it is acceptable to get here with interrupts enabled, * check it with the asm equivalent of WARN_ON */ -- cgit v1.2.2 From 69ed3324983bb937d78a8579ed91b90242ee5aaa Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 28 Mar 2006 14:08:39 +1100 Subject: [PATCH] powerpc: Fix some initcall return values Non zero initcalls (except for -ENODEV) have started warning at boot. Fix smt_setup and init_ras_IRQ. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/sysfs.c | 6 +++--- arch/powerpc/platforms/pseries/ras.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 0f0c3a9ae2e5..aca2f09cd842 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -65,11 +65,11 @@ static int __init smt_setup(void) unsigned int cpu; if (!cpu_has_feature(CPU_FTR_SMT)) - return 1; + return -ENODEV; options = find_path_device("/options"); if (!options) - return 1; + return -ENODEV; val = (unsigned int *)get_property(options, "ibm,smt-snooze-delay", NULL); @@ -78,7 +78,7 @@ static int __init smt_setup(void) per_cpu(smt_snooze_delay, cpu) = *val; } - return 1; + return 0; } __initcall(smt_setup); diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c index b046bcf7443d..9639c66b453d 100644 --- a/arch/powerpc/platforms/pseries/ras.c +++ b/arch/powerpc/platforms/pseries/ras.c @@ -132,7 +132,7 @@ static int __init init_ras_IRQ(void) of_node_put(np); } - return 1; + return 0; } __initcall(init_ras_IRQ); -- cgit v1.2.2 From b239cbe957ae730caa8af2f169a4d35b8c1bb299 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Tue, 28 Mar 2006 14:40:58 +1100 Subject: [PATCH] powerpc: make ISA floppies work again We used to assume that a DMA mapping request with a NULL dev was for ISA DMA. This assumption was broken at some point. Now we explicitly pass the detected ISA PCI device in the floppy setup. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_64.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index ba92bab7cc2c..4c4449be81ce 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -78,6 +78,7 @@ int global_phb_number; /* Global phb counter */ /* Cached ISA bridge dev. */ struct pci_dev *ppc64_isabridge_dev = NULL; +EXPORT_SYMBOL_GPL(ppc64_isabridge_dev); static void fixup_broken_pcnet32(struct pci_dev* dev) { -- cgit v1.2.2 From 78af90629ce98c8383ea16928e110eb97b889be6 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Mon, 27 Mar 2006 23:48:37 -0600 Subject: powerpc: remove OCP references OCP isn't used in arch/powerpc and hopefully will never be. Signed-off-by: Kumar Gala --- arch/powerpc/Kconfig.debug | 5 ----- arch/powerpc/kernel/setup_32.c | 6 ------ 2 files changed, 11 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index 9254806f7032..8d48e9e7162a 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug @@ -110,11 +110,6 @@ config SERIAL_TEXT_DEBUG depends on 4xx || LOPEC || MV64X60 || PPLUS || PRPMC800 || \ PPC_GEN550 || PPC_MPC52xx -config PPC_OCP - bool - depends on IBM_OCP || XILINX_OCP - default y - choice prompt "Early debugging (dangerous)" bool diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index e39f830317a8..a2c89435abec 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -351,12 +351,6 @@ void __init setup_arch(char **cmdline_p) do_init_bootmem(); if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab); -#ifdef CONFIG_PPC_OCP - /* Initialize OCP device list */ - ocp_early_init(); - if ( ppc_md.progress ) ppc_md.progress("ocp: exit", 0x3eab); -#endif - #ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; #endif -- cgit v1.2.2 From 4d177fbfdadb011f1bac96f9ccba0cc9f21da8de Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Tue, 28 Mar 2006 17:14:44 +1100 Subject: [PATCH] powerpc: a couple of trivial compile warning fixes Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom.c | 5 ++++- arch/powerpc/platforms/pseries/setup.c | 2 -- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 95d15eb5c03f..a2bc433f3610 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -860,7 +860,10 @@ static int __init early_init_dt_scan_cpus(unsigned long node, { static int logical_cpuid = 0; char *type = of_get_flat_dt_prop(node, "device_type", NULL); - u32 *prop, *intserv; +#ifdef CONFIG_ALTIVEC + u32 *prop; +#endif + u32 *intserv; int i, nthreads; unsigned long len; int found = 0; diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index f736234db9b2..1b0c4c034a26 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -455,8 +455,6 @@ out: static void pseries_shared_idle_sleep(void) { - unsigned int cpu = smp_processor_id(); - /* * Indicate to the HV that we are idle. Now would be * a good time to find other work to dispatch. -- cgit v1.2.2 From e8222502ee6157e2713da9e0792c21f4ad458d50 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 28 Mar 2006 23:15:54 +1100 Subject: [PATCH] powerpc: Kill _machine and hard-coded platform numbers This removes statically assigned platform numbers and reworks the powerpc platform probe code to use a better mechanism. With this, board support files can simply declare a new machine type with a macro, and implement a probe() function that uses the flattened device-tree to detect if they apply for a given machine. We now have a machine_is() macro that replaces the comparisons of _machine with the various PLATFORM_* constants. This commit also changes various drivers to use the new macro instead of looking at _machine. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/asm-offsets.c | 2 - arch/powerpc/kernel/nvram_64.c | 4 +- arch/powerpc/kernel/pci_32.c | 4 +- arch/powerpc/kernel/proc_ppc64.c | 3 +- arch/powerpc/kernel/prom.c | 56 ++-- arch/powerpc/kernel/prom_init.c | 51 ++-- arch/powerpc/kernel/rtas-proc.c | 2 +- arch/powerpc/kernel/rtas.c | 3 +- arch/powerpc/kernel/setup-common.c | 52 +++- arch/powerpc/kernel/setup_32.c | 58 +--- arch/powerpc/kernel/setup_64.c | 56 +--- arch/powerpc/kernel/traps.c | 35 +-- arch/powerpc/kernel/vdso.c | 9 +- arch/powerpc/kernel/vmlinux.lds.S | 381 +++++++++++++-------------- arch/powerpc/mm/hash_utils_64.c | 7 +- arch/powerpc/platforms/cell/setup.c | 11 +- arch/powerpc/platforms/chrp/setup.c | 13 +- arch/powerpc/platforms/iseries/setup.c | 9 +- arch/powerpc/platforms/maple/setup.c | 8 +- arch/powerpc/platforms/powermac/bootx_init.c | 4 +- arch/powerpc/platforms/powermac/feature.c | 2 +- arch/powerpc/platforms/powermac/low_i2c.c | 3 + arch/powerpc/platforms/powermac/nvram.c | 2 +- arch/powerpc/platforms/powermac/pci.c | 5 +- arch/powerpc/platforms/powermac/pfunc_base.c | 2 + arch/powerpc/platforms/powermac/setup.c | 72 ++--- arch/powerpc/platforms/powermac/time.c | 4 +- arch/powerpc/platforms/pseries/eeh.c | 2 +- arch/powerpc/platforms/pseries/pci.c | 2 +- arch/powerpc/platforms/pseries/pci_dlpar.c | 1 + arch/powerpc/platforms/pseries/reconfig.c | 5 +- arch/powerpc/platforms/pseries/rtasd.c | 3 +- arch/powerpc/platforms/pseries/setup.c | 39 ++- 33 files changed, 451 insertions(+), 459 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 882889b15926..54b48f330051 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -105,8 +105,6 @@ int main(void) DEFINE(ICACHEL1LINESIZE, offsetof(struct ppc64_caches, iline_size)); DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size)); DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page)); - DEFINE(PLATFORM_LPAR, PLATFORM_LPAR); - /* paca */ DEFINE(PACA_SIZE, sizeof(struct paca_struct)); DEFINE(PACAPACAINDEX, offsetof(struct paca_struct, paca_index)); diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c index 6c3989f6247d..ada50aa5b600 100644 --- a/arch/powerpc/kernel/nvram_64.c +++ b/arch/powerpc/kernel/nvram_64.c @@ -160,7 +160,7 @@ static int dev_nvram_ioctl(struct inode *inode, struct file *file, case IOC_NVRAM_GET_OFFSET: { int part, offset; - if (_machine != PLATFORM_POWERMAC) + if (!machine_is(powermac)) return -EINVAL; if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0) return -EFAULT; @@ -444,7 +444,7 @@ static int nvram_setup_partition(void) * in our nvram, as Apple defined partitions use pretty much * all of the space */ - if (_machine == PLATFORM_POWERMAC) + if (machine_is(powermac)) return -ENOSPC; /* see if we have an OS partition that meets our needs. diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index 704c846b2b0f..b129d2e4b759 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c @@ -787,7 +787,7 @@ pci_busdev_to_OF_node(struct pci_bus *bus, int devfn) * fix has to be done by making the remapping per-host and always * filling the pci_to_OF map. --BenH */ - if (_machine == _MACH_Pmac && busnr >= 0xf0) + if (machine_is(powermac) && busnr >= 0xf0) busnr -= 0xf0; else #endif @@ -1728,7 +1728,7 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn) * (bus 0 is HT root), we return the AGP one instead. */ #ifdef CONFIG_PPC_PMAC - if (_machine == _MACH_Pmac && machine_is_compatible("MacRISC4")) + if (machine_is(powermac) && machine_is_compatible("MacRISC4")) if (bus == 0) bus = 0xf0; #endif /* CONFIG_PPC_PMAC */ diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c index 7ba42a405f41..3c2cf661f6d9 100644 --- a/arch/powerpc/kernel/proc_ppc64.c +++ b/arch/powerpc/kernel/proc_ppc64.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -51,7 +52,7 @@ static int __init proc_ppc64_create(void) if (!root) return 1; - if (!(platform_is_pseries() || _machine == PLATFORM_CELL)) + if (!machine_is(pseries) && !machine_is(cell)) return 0; if (!proc_mkdir("rtas", root)) diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index a2bc433f3610..4336390bcf34 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -383,14 +383,14 @@ static int __devinit finish_node_interrupts(struct device_node *np, /* Apple uses bits in there in a different way, let's * only keep the real sense bit on macs */ - if (_machine == PLATFORM_POWERMAC) + if (machine_is(powermac)) sense &= 0x1; np->intrs[intrcount].sense = map_mpic_senses[sense]; } #ifdef CONFIG_PPC64 /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ - if (_machine == PLATFORM_POWERMAC && ic && ic->parent) { + if (machine_is(powermac) && ic && ic->parent) { char *name = get_property(ic->parent, "name", NULL); if (name && !strcmp(name, "u3")) np->intrs[intrcount].line += 128; @@ -570,6 +570,18 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node, return rc; } +unsigned long __init of_get_flat_dt_root(void) +{ + unsigned long p = ((unsigned long)initial_boot_params) + + initial_boot_params->off_dt_struct; + + while(*((u32 *)p) == OF_DT_NOP) + p += 4; + BUG_ON (*((u32 *)p) != OF_DT_BEGIN_NODE); + p += 4; + return _ALIGN(p + strlen((char *)p) + 1, 4); +} + /** * This function can be used within scan_flattened_dt callback to get * access to properties @@ -612,6 +624,25 @@ void* __init of_get_flat_dt_prop(unsigned long node, const char *name, } while(1); } +int __init of_flat_dt_is_compatible(unsigned long node, const char *compat) +{ + const char* cp; + unsigned long cplen, l; + + cp = of_get_flat_dt_prop(node, "compatible", &cplen); + if (cp == NULL) + return 0; + while (cplen > 0) { + if (strncasecmp(cp, compat, strlen(compat)) == 0) + return 1; + l = strlen(cp) + 1; + cp += l; + cplen -= l; + } + + return 0; +} + static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, unsigned long align) { @@ -686,7 +717,7 @@ static unsigned long __init unflatten_dt_node(unsigned long mem, #ifdef DEBUG if ((strlen(p) + l + 1) != allocl) { DBG("%s: p: %d, l: %d, a: %d\n", - pathp, strlen(p), l, allocl); + pathp, (int)strlen(p), l, allocl); } #endif p += strlen(p); @@ -951,7 +982,6 @@ static int __init early_init_dt_scan_cpus(unsigned long node, static int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, int depth, void *data) { - u32 *prop; unsigned long *lprop; unsigned long l; char *p; @@ -962,14 +992,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node, (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) return 0; - /* get platform type */ - prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL); - if (prop == NULL) - return 0; -#ifdef CONFIG_PPC_MULTIPLATFORM - _machine = *prop; -#endif - #ifdef CONFIG_PPC64 /* check if iommu is forced on or off */ if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) @@ -996,15 +1018,15 @@ static int __init early_init_dt_scan_chosen(unsigned long node, * set of RTAS infos now if available */ { - u64 *basep, *entryp; + u64 *basep, *entryp, *sizep; basep = of_get_flat_dt_prop(node, "linux,rtas-base", NULL); entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL); - prop = of_get_flat_dt_prop(node, "linux,rtas-size", NULL); - if (basep && entryp && prop) { + sizep = of_get_flat_dt_prop(node, "linux,rtas-size", NULL); + if (basep && entryp && sizep) { rtas.base = *basep; rtas.entry = *entryp; - rtas.size = *prop; + rtas.size = *sizep; } } #endif /* CONFIG_PPC_RTAS */ @@ -1775,7 +1797,7 @@ static int of_finish_dynamic_node(struct device_node *node) /* We don't support that function on PowerMac, at least * not yet */ - if (_machine == PLATFORM_POWERMAC) + if (machine_is(powermac)) return -ENODEV; /* fix up new node's linux_phandle field */ diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 0d0887844501..d66c5e77fcff 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -180,6 +180,16 @@ static unsigned long __initdata prom_tce_alloc_start; static unsigned long __initdata prom_tce_alloc_end; #endif +/* Platforms codes are now obsolete in the kernel. Now only used within this + * file and ultimately gone too. Feel free to change them if you need, they + * are not shared with anything outside of this file anymore + */ +#define PLATFORM_PSERIES 0x0100 +#define PLATFORM_PSERIES_LPAR 0x0101 +#define PLATFORM_LPAR 0x0001 +#define PLATFORM_POWERMAC 0x0400 +#define PLATFORM_GENERIC 0x0500 + static int __initdata of_platform; static char __initdata prom_cmd_line[COMMAND_LINE_SIZE]; @@ -1492,7 +1502,10 @@ static int __init prom_find_machine_type(void) int len, i = 0; #ifdef CONFIG_PPC64 phandle rtas; + int x; #endif + + /* Look for a PowerMac */ len = prom_getprop(_prom->root, "compatible", compat, sizeof(compat)-1); if (len > 0) { @@ -1505,28 +1518,36 @@ static int __init prom_find_machine_type(void) if (strstr(p, RELOC("Power Macintosh")) || strstr(p, RELOC("MacRISC"))) return PLATFORM_POWERMAC; -#ifdef CONFIG_PPC64 - if (strstr(p, RELOC("Momentum,Maple"))) - return PLATFORM_MAPLE; - if (strstr(p, RELOC("IBM,CPB"))) - return PLATFORM_CELL; -#endif i += sl + 1; } } #ifdef CONFIG_PPC64 + /* If not a mac, try to figure out if it's an IBM pSeries or any other + * PAPR compliant platform. We assume it is if : + * - /device_type is "chrp" (please, do NOT use that for future + * non-IBM designs ! + * - it has /rtas + */ + len = prom_getprop(_prom->root, "model", + compat, sizeof(compat)-1); + if (len <= 0) + return PLATFORM_GENERIC; + compat[len] = 0; + if (strcmp(compat, "chrp")) + return PLATFORM_GENERIC; + /* Default to pSeries. We need to know if we are running LPAR */ rtas = call_prom("finddevice", 1, 1, ADDR("/rtas")); - if (PHANDLE_VALID(rtas)) { - int x = prom_getproplen(rtas, "ibm,hypertas-functions"); - if (x != PROM_ERROR) { - prom_printf("Hypertas detected, assuming LPAR !\n"); - return PLATFORM_PSERIES_LPAR; - } + if (!PHANDLE_VALID(rtas)) + return PLATFORM_GENERIC; + x = prom_getproplen(rtas, "ibm,hypertas-functions"); + if (x != PROM_ERROR) { + prom_printf("Hypertas detected, assuming LPAR !\n"); + return PLATFORM_PSERIES_LPAR; } return PLATFORM_PSERIES; #else - return PLATFORM_CHRP; + return PLATFORM_GENERIC; #endif } @@ -2034,7 +2055,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, { struct prom_t *_prom; unsigned long hdr; - u32 getprop_rval; unsigned long offset = reloc_offset(); #ifdef CONFIG_PPC32 @@ -2070,9 +2090,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, * between pSeries SMP and pSeries LPAR */ RELOC(of_platform) = prom_find_machine_type(); - getprop_rval = RELOC(of_platform); - prom_setprop(_prom->chosen, "/chosen", "linux,platform", - &getprop_rval, sizeof(getprop_rval)); /* Bail if this is a kdump kernel. */ if (PHYSICAL_START > 0) diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c index 1f03fb28cc0a..456286cf1d14 100644 --- a/arch/powerpc/kernel/rtas-proc.c +++ b/arch/powerpc/kernel/rtas-proc.c @@ -257,7 +257,7 @@ static int __init proc_rtas_init(void) { struct proc_dir_entry *entry; - if (_machine != PLATFORM_PSERIES && _machine != PLATFORM_PSERIES_LPAR) + if (!machine_is(pseries)) return 1; rtas_node = of_find_node_by_name(NULL, "rtas"); diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 142d818a31a6..4b78ee0e5867 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -768,7 +769,7 @@ void __init rtas_initialize(void) * the stop-self token if any */ #ifdef CONFIG_PPC64 - if (_machine == PLATFORM_PSERIES_LPAR) { + if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR)) { rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX); ibm_suspend_me_token = rtas_token("ibm,suspend-me"); } diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index b17630ad4ac7..3473cb9cb0ab 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -9,6 +9,9 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ + +#undef DEBUG + #include #include #include @@ -41,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -56,8 +60,6 @@ #include "setup.h" -#undef DEBUG - #ifdef DEBUG #include #define DBG(fmt...) udbg_printf(fmt) @@ -65,10 +67,12 @@ #define DBG(fmt...) #endif -#ifdef CONFIG_PPC_MULTIPLATFORM -int _machine = 0; -EXPORT_SYMBOL(_machine); -#endif +/* The main machine-dep calls structure + */ +struct machdep_calls ppc_md; +EXPORT_SYMBOL(ppc_md); +struct machdep_calls *machine_id; +EXPORT_SYMBOL(machine_id); unsigned long klimit = (unsigned long) _end; @@ -168,7 +172,8 @@ static int show_cpuinfo(struct seq_file *m, void *v) bogosum/(500000/HZ), bogosum/(5000/HZ) % 100); #endif /* CONFIG_SMP && CONFIG_PPC32 */ seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq); - + if (ppc_md.name) + seq_printf(m, "platform\t: %s\n", ppc_md.name); if (ppc_md.show_cpuinfo != NULL) ppc_md.show_cpuinfo(m); @@ -387,7 +392,7 @@ void __init smp_setup_cpu_maps(void) * On pSeries LPAR, we need to know how many cpus * could possibly be added to this partition. */ - if (_machine == PLATFORM_PSERIES_LPAR && + if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR) && (dn = of_find_node_by_path("/rtas"))) { int num_addr_cell, num_size_cell, maxcpus; unsigned int *ireg; @@ -456,3 +461,34 @@ static int __init early_xmon(char *p) } early_param("xmon", early_xmon); #endif + +void probe_machine(void) +{ + extern struct machdep_calls __machine_desc_start; + extern struct machdep_calls __machine_desc_end; + + /* + * Iterate all ppc_md structures until we find the proper + * one for the current machine type + */ + DBG("Probing machine type ...\n"); + + for (machine_id = &__machine_desc_start; + machine_id < &__machine_desc_end; + machine_id++) { + DBG(" %s ...", machine_id->name); + memcpy(&ppc_md, machine_id, sizeof(struct machdep_calls)); + if (ppc_md.probe()) { + DBG(" match !\n"); + break; + } + DBG("\n"); + } + /* What can we do if we didn't find ? */ + if (machine_id >= &__machine_desc_end) { + DBG("No suitable machine found !\n"); + for (;;); + } + + printk(KERN_INFO "Using %s machine description\n", ppc_md.name); +} diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index a2c89435abec..ae9c33d70731 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -67,10 +67,6 @@ unsigned int DMA_MODE_WRITE; int have_of = 1; #ifdef CONFIG_PPC_MULTIPLATFORM -extern void prep_init(void); -extern void pmac_init(void); -extern void chrp_init(void); - dev_t boot_dev; #endif /* CONFIG_PPC_MULTIPLATFORM */ @@ -82,9 +78,6 @@ unsigned long SYSRQ_KEY = 0x54; unsigned long vgacon_remap_base; #endif -struct machdep_calls ppc_md; -EXPORT_SYMBOL(ppc_md); - /* * These are used in binfmt_elf.c to put aux entries on the stack * for each elf executable being started. @@ -120,48 +113,6 @@ unsigned long __init early_init(unsigned long dt_ptr) return KERNELBASE + offset; } -#ifdef CONFIG_PPC_MULTIPLATFORM -/* - * The PPC_MULTIPLATFORM version of platform_init... - */ -void __init platform_init(void) -{ - /* if we didn't get any bootinfo telling us what we are... */ - if (_machine == 0) { - /* prep boot loader tells us if we're prep or not */ - if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) ) - _machine = _MACH_prep; - } - -#ifdef CONFIG_PPC_PREP - /* not much more to do here, if prep */ - if (_machine == _MACH_prep) { - prep_init(); - return; - } -#endif - -#ifdef CONFIG_ADB - if (strstr(cmd_line, "adb_sync")) { - extern int __adb_probe_sync; - __adb_probe_sync = 1; - } -#endif /* CONFIG_ADB */ - - switch (_machine) { -#ifdef CONFIG_PPC_PMAC - case _MACH_Pmac: - pmac_init(); - break; -#endif -#ifdef CONFIG_PPC_CHRP - case _MACH_chrp: - chrp_init(); - break; -#endif - } -} -#endif /* * Find out what kind of machine we're on and save any data we need @@ -187,8 +138,12 @@ void __init machine_init(unsigned long dt_ptr, unsigned long phys) strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line)); #endif /* CONFIG_CMDLINE */ - /* Base init based on machine type */ +#ifdef CONFIG_PPC_MULTIPLATFORM + probe_machine(); +#else + /* Base init based on machine type. Obsoloete, please kill ! */ platform_init(); +#endif #ifdef CONFIG_6xx if (cpu_has_feature(CPU_FTR_CAN_DOZE) || @@ -359,7 +314,4 @@ void __init setup_arch(char **cmdline_p) if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab); paging_init(); - - /* this is for modules since _machine can be a define -- Cort */ - ppc_md.ppc_machine = _machine; } diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 5b63a861ef43..6aea1fb74b69 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -95,11 +95,6 @@ int dcache_bsize; int icache_bsize; int ucache_bsize; -/* The main machine-dep calls structure - */ -struct machdep_calls ppc_md; -EXPORT_SYMBOL(ppc_md); - #ifdef CONFIG_MAGIC_SYSRQ unsigned long SYSRQ_KEY; #endif /* CONFIG_MAGIC_SYSRQ */ @@ -160,32 +155,6 @@ early_param("smt-enabled", early_smt_enabled); #define check_smt_enabled() #endif /* CONFIG_SMP */ -extern struct machdep_calls pSeries_md; -extern struct machdep_calls pmac_md; -extern struct machdep_calls maple_md; -extern struct machdep_calls cell_md; -extern struct machdep_calls iseries_md; - -/* Ultimately, stuff them in an elf section like initcalls... */ -static struct machdep_calls __initdata *machines[] = { -#ifdef CONFIG_PPC_PSERIES - &pSeries_md, -#endif /* CONFIG_PPC_PSERIES */ -#ifdef CONFIG_PPC_PMAC - &pmac_md, -#endif /* CONFIG_PPC_PMAC */ -#ifdef CONFIG_PPC_MAPLE - &maple_md, -#endif /* CONFIG_PPC_MAPLE */ -#ifdef CONFIG_PPC_CELL - &cell_md, -#endif -#ifdef CONFIG_PPC_ISERIES - &iseries_md, -#endif - NULL -}; - /* * Early initialization entry point. This is called by head.S * with MMU translation disabled. We rely on the "feature" of @@ -207,12 +176,10 @@ static struct machdep_calls __initdata *machines[] = { void __init early_setup(unsigned long dt_ptr) { - static struct machdep_calls **mach; - /* Enable early debugging if any specified (see udbg.h) */ udbg_early_init(); - DBG(" -> early_setup()\n"); + DBG(" -> early_setup(), dt_ptr: 0x%lx\n", dt_ptr); /* * Do early initializations using the flattened device @@ -229,22 +196,8 @@ void __init early_setup(unsigned long dt_ptr) get_paca()->stab_real = __pa((u64)&initial_stab); get_paca()->stab_addr = (u64)&initial_stab; - /* - * Iterate all ppc_md structures until we find the proper - * one for the current machine type - */ - DBG("Probing machine type for platform %x...\n", _machine); - - for (mach = machines; *mach; mach++) { - if ((*mach)->probe(_machine)) - break; - } - /* What can we do if we didn't find ? */ - if (*mach == NULL) { - DBG("No suitable machine found !\n"); - for (;;); - } - ppc_md = **mach; + /* Probe the machine type */ + probe_machine(); #ifdef CONFIG_CRASH_DUMP kdump_setup(); @@ -346,7 +299,7 @@ static void __init initialize_cache_info(void) const char *dc, *ic; /* Then read cache informations */ - if (_machine == PLATFORM_POWERMAC) { + if (machine_is(powermac)) { dc = "d-cache-block-size"; ic = "i-cache-block-size"; } else { @@ -490,7 +443,6 @@ void __init setup_system(void) printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size); printk("ppc64_interrupt_controller = 0x%ld\n", ppc64_interrupt_controller); - printk("platform = 0x%x\n", _machine); printk("physicalMemorySize = 0x%lx\n", lmb_phys_mem_size()); printk("ppc64_caches.dcache_line_size = 0x%x\n", ppc64_caches.dline_size); diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 98660aedeeb7..27600c9432bc 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -97,7 +97,6 @@ static DEFINE_SPINLOCK(die_lock); int die(const char *str, struct pt_regs *regs, long err) { static int die_counter, crash_dump_start = 0; - int nl = 0; if (debugger(regs)) return 1; @@ -106,7 +105,7 @@ int die(const char *str, struct pt_regs *regs, long err) spin_lock_irq(&die_lock); bust_spinlocks(1); #ifdef CONFIG_PMAC_BACKLIGHT - if (_machine == _MACH_Pmac) { + if (machine_is(powermac)) { set_backlight_enable(1); set_backlight_level(BACKLIGHT_MAX); } @@ -114,46 +113,18 @@ int die(const char *str, struct pt_regs *regs, long err) printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter); #ifdef CONFIG_PREEMPT printk("PREEMPT "); - nl = 1; #endif #ifdef CONFIG_SMP printk("SMP NR_CPUS=%d ", NR_CPUS); - nl = 1; #endif #ifdef CONFIG_DEBUG_PAGEALLOC printk("DEBUG_PAGEALLOC "); - nl = 1; #endif #ifdef CONFIG_NUMA printk("NUMA "); - nl = 1; #endif -#ifdef CONFIG_PPC64 - switch (_machine) { - case PLATFORM_PSERIES: - printk("PSERIES "); - nl = 1; - break; - case PLATFORM_PSERIES_LPAR: - printk("PSERIES LPAR "); - nl = 1; - break; - case PLATFORM_ISERIES_LPAR: - printk("ISERIES LPAR "); - nl = 1; - break; - case PLATFORM_POWERMAC: - printk("POWERMAC "); - nl = 1; - break; - case PLATFORM_CELL: - printk("CELL "); - nl = 1; - break; - } -#endif - if (nl) - printk("\n"); + printk("%s\n", ppc_md.name ? "" : ppc_md.name); + print_modules(); show_regs(regs); bust_spinlocks(0); diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index ec8370368423..573afb68d69e 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -667,7 +668,13 @@ void __init vdso_init(void) vdso_data->version.major = SYSTEMCFG_MAJOR; vdso_data->version.minor = SYSTEMCFG_MINOR; vdso_data->processor = mfspr(SPRN_PVR); - vdso_data->platform = _machine; + /* + * Fake the old platform number for pSeries and iSeries and add + * in LPAR bit if necessary + */ + vdso_data->platform = machine_is(iseries) ? 0x200 : 0x100; + if (firmware_has_feature(FW_FEATURE_LPAR)) + vdso_data->platform |= 1; vdso_data->physicalMemorySize = lmb_phys_mem_size(); vdso_data->dcache_size = ppc64_caches.dsize; vdso_data->dcache_line_size = ppc64_caches.dline_size; diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index 7fa7b15fd8e6..fe79c2584cb0 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S @@ -1,9 +1,11 @@ #include #ifdef CONFIG_PPC64 #include +#define PROVIDE32(x) PROVIDE(__unused__##x) #else #define PAGE_SIZE 4096 #define KERNELBASE CONFIG_KERNEL_START +#define PROVIDE32(x) PROVIDE(x) #endif #include @@ -18,43 +20,42 @@ jiffies = jiffies_64 + 4; #endif SECTIONS { - /* Sections to be discarded. */ - /DISCARD/ : { - *(.exitcall.exit) - *(.exit.data) - } - - . = KERNELBASE; - - /* Read-only sections, merged into text segment: */ - .text : { - *(.text .text.*) - SCHED_TEXT - LOCK_TEXT - KPROBES_TEXT - *(.fixup) -#ifdef CONFIG_PPC32 - *(.got1) - __got2_start = .; - *(.got2) - __got2_end = .; -#else - . = ALIGN(PAGE_SIZE); - _etext = .; -#endif - } -#ifdef CONFIG_PPC32 - _etext = .; - PROVIDE (etext = .); + /* Sections to be discarded. */ + /DISCARD/ : { + *(.exitcall.exit) + *(.exit.data) + } - RODATA - .fini : { *(.fini) } =0 - .ctors : { *(.ctors) } - .dtors : { *(.dtors) } + . = KERNELBASE; - .fixup : { *(.fixup) } -#endif +/* + * Text, read only data and other permanent read-only sections + */ + + /* Text and gots */ + .text : { + *(.text .text.*) + SCHED_TEXT + LOCK_TEXT + KPROBES_TEXT + *(.fixup) +#ifdef CONFIG_PPC32 + *(.got1) + __got2_start = .; + *(.got2) + __got2_end = .; +#endif /* CONFIG_PPC32 */ + + . = ALIGN(PAGE_SIZE); + _etext = .; + PROVIDE32 (etext = .); + } + + /* Read-only data */ + RODATA + + /* Exception & bug tables */ __ex_table : { __start___ex_table = .; *(__ex_table) @@ -67,192 +68,172 @@ SECTIONS __stop___bug_table = .; } -#ifdef CONFIG_PPC64 +/* + * Init sections discarded at runtime + */ + . = ALIGN(PAGE_SIZE); + __init_begin = .; + + .init.text : { + _sinittext = .; + *(.init.text) + _einittext = .; + } + + /* .exit.text is discarded at runtime, not link time, + * to deal with references from __bug_table + */ + .exit.text : { *(.exit.text) } + + .init.data : { + *(.init.data); + __vtop_table_begin = .; + *(.vtop_fixup); + __vtop_table_end = .; + __ptov_table_begin = .; + *(.ptov_fixup); + __ptov_table_end = .; + } + + . = ALIGN(16); + .init.setup : { + __setup_start = .; + *(.init.setup) + __setup_end = .; + } + + .initcall.init : { + __initcall_start = .; + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + __initcall_end = .; + } + + .con_initcall.init : { + __con_initcall_start = .; + *(.con_initcall.init) + __con_initcall_end = .; + } + + SECURITY_INIT + + . = ALIGN(8); __ftr_fixup : { __start___ftr_fixup = .; *(__ftr_fixup) __stop___ftr_fixup = .; } - RODATA -#endif + . = ALIGN(PAGE_SIZE); + .init.ramfs : { + __initramfs_start = .; + *(.init.ramfs) + __initramfs_end = .; + } #ifdef CONFIG_PPC32 - /* Read-write section, merged into data segment: */ - . = ALIGN(PAGE_SIZE); - _sdata = .; - .data : - { - *(.data) - *(.data1) - *(.sdata) - *(.sdata2) - *(.got.plt) *(.got) - *(.dynamic) - CONSTRUCTORS - } - - . = ALIGN(PAGE_SIZE); - __nosave_begin = .; - .data_nosave : { *(.data.nosave) } - . = ALIGN(PAGE_SIZE); - __nosave_end = .; - - . = ALIGN(32); - .data.cacheline_aligned : { *(.data.cacheline_aligned) } - - _edata = .; - PROVIDE (edata = .); - - . = ALIGN(8192); - .data.init_task : { *(.data.init_task) } + . = ALIGN(32); +#else + . = ALIGN(128); #endif + .data.percpu : { + __per_cpu_start = .; + *(.data.percpu) + __per_cpu_end = .; + } - /* will be freed after init */ - . = ALIGN(PAGE_SIZE); - __init_begin = .; - .init.text : { - _sinittext = .; - *(.init.text) - _einittext = .; - } -#ifdef CONFIG_PPC32 - /* .exit.text is discarded at runtime, not link time, - to deal with references from __bug_table */ - .exit.text : { *(.exit.text) } -#endif - .init.data : { - *(.init.data); - __vtop_table_begin = .; - *(.vtop_fixup); - __vtop_table_end = .; - __ptov_table_begin = .; - *(.ptov_fixup); - __ptov_table_end = .; - } - - . = ALIGN(16); - .init.setup : { - __setup_start = .; - *(.init.setup) - __setup_end = .; - } - - .initcall.init : { - __initcall_start = .; - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) - __initcall_end = .; - } - - .con_initcall.init : { - __con_initcall_start = .; - *(.con_initcall.init) - __con_initcall_end = .; - } - - SECURITY_INIT + . = ALIGN(8); + .machine.desc : { + __machine_desc_start = . ; + *(.machine.desc) + __machine_desc_end = . ; + } + + /* freed after init ends here */ + . = ALIGN(PAGE_SIZE); + __init_end = .; + +/* + * And now the various read/write data + */ + + . = ALIGN(PAGE_SIZE); + _sdata = .; #ifdef CONFIG_PPC32 - __start___ftr_fixup = .; - __ftr_fixup : { *(__ftr_fixup) } - __stop___ftr_fixup = .; + .data : + { + *(.data) + *(.sdata) + *(.got.plt) *(.got) + } #else - . = ALIGN(PAGE_SIZE); - .init.ramfs : { - __initramfs_start = .; - *(.init.ramfs) - __initramfs_end = .; - } -#endif + .data : { + *(.data .data.rel* .toc1) + *(.branch_lt) + } -#ifdef CONFIG_PPC32 - . = ALIGN(32); + .opd : { + *(.opd) + } + + .got : { + __toc_start = .; + *(.got) + *(.toc) + } #endif - .data.percpu : { - __per_cpu_start = .; - *(.data.percpu) - __per_cpu_end = .; - } - . = ALIGN(PAGE_SIZE); -#ifdef CONFIG_PPC64 - . = ALIGN(16384); - __init_end = .; - /* freed after init ends here */ - - /* Read/write sections */ - . = ALIGN(PAGE_SIZE); - . = ALIGN(16384); - _sdata = .; - /* The initial task and kernel stack */ - .data.init_task : { - *(.data.init_task) - } - - . = ALIGN(PAGE_SIZE); - .data.page_aligned : { - *(.data.page_aligned) - } - - .data.cacheline_aligned : { - *(.data.cacheline_aligned) - } - - .data : { - *(.data .data.rel* .toc1) - *(.branch_lt) - } - - .opd : { - *(.opd) - } - - .got : { - __toc_start = .; - *(.got) - *(.toc) - . = ALIGN(PAGE_SIZE); - _edata = .; - } - - . = ALIGN(PAGE_SIZE); + . = ALIGN(PAGE_SIZE); + _edata = .; + PROVIDE32 (edata = .); + + /* The initial task and kernel stack */ +#ifdef CONFIG_PPC32 + . = ALIGN(8192); #else - __initramfs_start = .; - .init.ramfs : { - *(.init.ramfs) - } - __initramfs_end = .; + . = ALIGN(16384); +#endif + .data.init_task : { + *(.data.init_task) + } - . = ALIGN(4096); - __init_end = .; + . = ALIGN(PAGE_SIZE); + .data.page_aligned : { + *(.data.page_aligned) + } - . = ALIGN(4096); - _sextratext = .; - _eextratext = .; + .data.cacheline_aligned : { + *(.data.cacheline_aligned) + } - __bss_start = .; -#endif + . = ALIGN(PAGE_SIZE); + __data_nosave : { + __nosave_begin = .; + *(.data.nosave) + . = ALIGN(PAGE_SIZE); + __nosave_end = .; + } - .bss : { - __bss_start = .; - *(.sbss) *(.scommon) - *(.dynbss) - *(.bss) - *(COMMON) - __bss_stop = .; - } +/* + * And finally the bss + */ + + .bss : { + __bss_start = .; + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + __bss_stop = .; + } -#ifdef CONFIG_PPC64 - . = ALIGN(PAGE_SIZE); -#endif - _end = . ; -#ifdef CONFIG_PPC32 - PROVIDE (end = .); -#endif + . = ALIGN(PAGE_SIZE); + _end = . ; + PROVIDE32 (end = .); } diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 89b35c181314..c006d9039633 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -167,7 +167,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, * normal insert callback here. */ #ifdef CONFIG_PPC_ISERIES - if (_machine == PLATFORM_ISERIES_LPAR) + if (machine_is(iseries)) ret = iSeries_hpte_insert(hpteg, va, paddr, tmp_mode, @@ -176,7 +176,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, else #endif #ifdef CONFIG_PPC_PSERIES - if (_machine & PLATFORM_LPAR) + if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR)) ret = pSeries_lpar_hpte_insert(hpteg, va, paddr, tmp_mode, @@ -295,8 +295,7 @@ static void __init htab_init_page_sizes(void) * Not in the device-tree, let's fallback on known size * list for 16M capable GP & GR */ - if ((_machine != PLATFORM_ISERIES_LPAR) && - cpu_has_feature(CPU_FTR_16M_PAGE)) + if (cpu_has_feature(CPU_FTR_16M_PAGE) && !machine_is(iseries)) memcpy(mmu_psize_defs, mmu_psize_defaults_gp, sizeof(mmu_psize_defaults_gp)); found: diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index fec8e65b36ea..dac5d0365fde 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -195,9 +195,13 @@ static void __init cell_init_early(void) } -static int __init cell_probe(int platform) +static int __init cell_probe(void) { - if (platform != PLATFORM_CELL) + /* XXX This is temporary, the Cell maintainer will come up with + * more appropriate detection logic + */ + unsigned long root = of_get_flat_dt_root(); + if (!of_flat_dt_is_compatible(root, "IBM,CPBW-1.0")) return 0; return 1; @@ -212,7 +216,8 @@ static int cell_check_legacy_ioport(unsigned int baseport) return -ENODEV; } -struct machdep_calls __initdata cell_md = { +define_machine(cell) { + .name = "Cell", .probe = cell_probe, .setup_arch = cell_setup_arch, .init_early = cell_init_early, diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 9c718bb2305e..23a201718704 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -292,6 +292,10 @@ void __init chrp_setup_arch(void) pci_create_OF_bus_map(); +#ifdef CONFIG_SMP + smp_ops = &chrp_smp_ops; +#endif /* CONFIG_SMP */ + /* * Print the banner, then scroll down so boot progress * can be printed. -- Cort @@ -506,8 +510,15 @@ chrp_init2(void) ppc_md.progress(" Have fun! ", 0x7777); } -void __init chrp_init(void) +static int __init chrp_probe(void) { + char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(), + "device_type", NULL); + if (dtype == NULL) + return 0; + if (strcmp(dtype, "chrp")) + return 0; + ISA_DMA_THRESHOLD = ~0L; DMA_MODE_READ = 0x44; DMA_MODE_WRITE = 0x48; diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 155aa690e4bb..6ce8a404ba6b 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -675,9 +675,10 @@ static void iseries_dedicated_idle(void) void __init iSeries_init_IRQ(void) { } #endif -static int __init iseries_probe(int platform) +static int __init iseries_probe(void) { - if (PLATFORM_ISERIES_LPAR != platform) + unsigned long root = of_get_flat_dt_root(); + if (!of_flat_dt_is_compatible(root, "IBM,iSeries")) return 0; powerpc_firmware_features |= FW_FEATURE_ISERIES; @@ -686,7 +687,8 @@ static int __init iseries_probe(int platform) return 1; } -struct machdep_calls __initdata iseries_md = { +define_machine(iseries) { + .name = "iSeries", .setup_arch = iSeries_setup_arch, .show_cpuinfo = iSeries_show_cpuinfo, .init_IRQ = iSeries_init_IRQ, @@ -930,7 +932,6 @@ void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) /* /chosen */ dt_start_node(dt, "chosen"); - dt_prop_u32(dt, "linux,platform", PLATFORM_ISERIES_LPAR); dt_prop_str(dt, "bootargs", cmd_line); if (cmd_mem_limit) dt_prop_u64(dt, "linux,memory-limit", cmd_mem_limit); diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index 137d6063182b..24c0aef4ea39 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c @@ -259,9 +259,10 @@ static void __init maple_progress(char *s, unsigned short hex) /* * Called very early, MMU is off, device-tree isn't unflattened */ -static int __init maple_probe(int platform) +static int __init maple_probe(void) { - if (platform != PLATFORM_MAPLE) + unsigned long root = of_get_flat_dt_root(); + if (!of_flat_dt_is_compatible(root, "Momentum,Maple")) return 0; /* * On U3, the DART (iommu) must be allocated now since it @@ -274,7 +275,8 @@ static int __init maple_probe(int platform) return 1; } -struct machdep_calls __initdata maple_md = { +define_machine(maple_md) { + .name = "Maple", .probe = maple_probe, .setup_arch = maple_setup_arch, .init_early = maple_init_early, diff --git a/arch/powerpc/platforms/powermac/bootx_init.c b/arch/powerpc/platforms/powermac/bootx_init.c index a94571be65ca..eacbfd9beabc 100644 --- a/arch/powerpc/platforms/powermac/bootx_init.c +++ b/arch/powerpc/platforms/powermac/bootx_init.c @@ -161,9 +161,7 @@ static void __init bootx_dt_add_prop(char *name, void *data, int size, static void __init bootx_add_chosen_props(unsigned long base, unsigned long *mem_end) { - u32 val = _MACH_Pmac; - - bootx_dt_add_prop("linux,platform", &val, 4, mem_end); + u32 val; if (bootx_info->kernelParamsOffset) { char *args = (char *)((unsigned long)bootx_info) + diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index e49eddd5042d..a5063cd675c5 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c @@ -2951,7 +2951,7 @@ static void *pmac_early_vresume_data; void pmac_set_early_video_resume(void (*proc)(void *data), void *data) { - if (_machine != _MACH_Pmac) + if (!machine_is(powermac)) return; preempt_disable(); pmac_early_vresume_proc = proc; diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c index 87eb6bb7f0e7..e14f9ac55cf4 100644 --- a/arch/powerpc/platforms/powermac/low_i2c.c +++ b/arch/powerpc/platforms/powermac/low_i2c.c @@ -1457,6 +1457,9 @@ int __init pmac_i2c_init(void) return 0; i2c_inited = 1; + if (!machine_is(powermac)) + return 0; + /* Probe keywest-i2c busses */ kw_i2c_probe(); diff --git a/arch/powerpc/platforms/powermac/nvram.c b/arch/powerpc/platforms/powermac/nvram.c index 3aa3477b86f7..262f967b880a 100644 --- a/arch/powerpc/platforms/powermac/nvram.c +++ b/arch/powerpc/platforms/powermac/nvram.c @@ -597,7 +597,7 @@ int __init pmac_nvram_init(void) } #ifdef CONFIG_PPC32 - if (_machine == _MACH_chrp && nvram_naddrs == 1) { + if (machine_is(chrp) && nvram_naddrs == 1) { nvram_data = ioremap(r1.start, s1); nvram_mult = 1; ppc_md.nvram_read_val = direct_nvram_read_byte; diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index de3f30e6b333..f5d8d15d74fa 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c @@ -1201,7 +1201,7 @@ void __init pmac_pcibios_after_init(void) #ifdef CONFIG_PPC32 void pmac_pci_fixup_cardbus(struct pci_dev* dev) { - if (_machine != _MACH_Pmac) + if (!machine_is(powermac)) return; /* * Fix the interrupt routing on the various cardbus bridges @@ -1244,8 +1244,9 @@ void pmac_pci_fixup_pciata(struct pci_dev* dev) * On PowerMacs, we try to switch any PCI ATA controller to * fully native mode */ - if (_machine != _MACH_Pmac) + if (!machine_is(powermac)) return; + /* Some controllers don't have the class IDE */ if (dev->vendor == PCI_VENDOR_ID_PROMISE) switch(dev->device) { diff --git a/arch/powerpc/platforms/powermac/pfunc_base.c b/arch/powerpc/platforms/powermac/pfunc_base.c index 9b7150f10414..a3bd3e728fa3 100644 --- a/arch/powerpc/platforms/powermac/pfunc_base.c +++ b/arch/powerpc/platforms/powermac/pfunc_base.c @@ -336,6 +336,8 @@ int __init pmac_pfunc_base_install(void) return 0; pfbase_inited = 1; + if (!machine_is(powermac)) + return 0; DBG("Installing base platform functions...\n"); diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index c2696d00672a..4d15e396655c 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -350,6 +350,13 @@ static void __init pmac_setup_arch(void) smp_ops = &psurge_smp_ops; #endif #endif /* CONFIG_SMP */ + +#ifdef CONFIG_ADB + if (strstr(cmd_line, "adb_sync")) { + extern int __adb_probe_sync; + __adb_probe_sync = 1; + } +#endif /* CONFIG_ADB */ } char *bootpath; @@ -576,30 +583,6 @@ pmac_halt(void) pmac_power_off(); } -#ifdef CONFIG_PPC32 -void __init pmac_init(void) -{ - /* isa_io_base gets set in pmac_pci_init */ - isa_mem_base = PMAC_ISA_MEM_BASE; - pci_dram_offset = PMAC_PCI_DRAM_OFFSET; - ISA_DMA_THRESHOLD = ~0L; - DMA_MODE_READ = 1; - DMA_MODE_WRITE = 2; - - ppc_md = pmac_md; - -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) -#ifdef CONFIG_BLK_DEV_IDE_PMAC - ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports; - ppc_ide_md.default_io_base = pmac_ide_get_base; -#endif /* CONFIG_BLK_DEV_IDE_PMAC */ -#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */ - - if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0); - -} -#endif - /* * Early initialization. */ @@ -646,6 +629,12 @@ static int __init pmac_declare_of_platform_devices(void) { struct device_node *np; + if (machine_is(chrp)) + return -1; + + if (!machine_is(powermac)) + return 0; + np = of_find_node_by_name(NULL, "valkyrie"); if (np) of_platform_device_create(np, "valkyrie", NULL); @@ -666,12 +655,15 @@ device_initcall(pmac_declare_of_platform_devices); /* * Called very early, MMU is off, device-tree isn't unflattened */ -static int __init pmac_probe(int platform) +static int __init pmac_probe(void) { -#ifdef CONFIG_PPC64 - if (platform != PLATFORM_POWERMAC) + unsigned long root = of_get_flat_dt_root(); + + if (!of_flat_dt_is_compatible(root, "Power Macintosh") && + !of_flat_dt_is_compatible(root, "MacRISC")) return 0; +#ifdef CONFIG_PPC64 /* * On U3, the DART (iommu) must be allocated now since it * has an impact on htab_initialize (due to the large page it @@ -681,6 +673,23 @@ static int __init pmac_probe(int platform) alloc_dart_table(); #endif +#ifdef CONFIG_PPC32 + /* isa_io_base gets set in pmac_pci_init */ + isa_mem_base = PMAC_ISA_MEM_BASE; + pci_dram_offset = PMAC_PCI_DRAM_OFFSET; + ISA_DMA_THRESHOLD = ~0L; + DMA_MODE_READ = 1; + DMA_MODE_WRITE = 2; + +#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) +#ifdef CONFIG_BLK_DEV_IDE_PMAC + ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports; + ppc_ide_md.default_io_base = pmac_ide_get_base; +#endif /* CONFIG_BLK_DEV_IDE_PMAC */ +#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */ + +#endif /* CONFIG_PPC32 */ + #ifdef CONFIG_PMAC_SMU /* * SMU based G5s need some memory below 2Gb, at least the current @@ -709,10 +718,8 @@ static int pmac_pci_probe_mode(struct pci_bus *bus) } #endif -struct machdep_calls __initdata pmac_md = { -#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC64) - .cpu_die = generic_mach_cpu_die, -#endif +define_machine(powermac) { + .name = "PowerMac", .probe = pmac_probe, .setup_arch = pmac_setup_arch, .init_early = pmac_init_early, @@ -746,4 +753,7 @@ struct machdep_calls __initdata pmac_md = { .pcibios_after_init = pmac_pcibios_after_init, .phys_mem_access_prot = pci_phys_mem_access_prot, #endif +#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC64) + .cpu_die = generic_mach_cpu_die, +#endif }; diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c index 5d9afa1fa02d..890758aa9667 100644 --- a/arch/powerpc/platforms/powermac/time.c +++ b/arch/powerpc/platforms/powermac/time.c @@ -336,10 +336,10 @@ static struct pmu_sleep_notifier time_sleep_notifier = { */ void __init pmac_calibrate_decr(void) { -#ifdef CONFIG_PM +#if defined(CONFIG_PM) && defined(CONFIG_ADB_PMU) /* XXX why here? */ pmu_register_sleep_notifier(&time_sleep_notifier); -#endif /* CONFIG_PM */ +#endif generic_calibrate_decr(); diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 2ab9dcdfb415..9b2b1cb117b3 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c @@ -1018,7 +1018,7 @@ static int __init eeh_init_proc(void) { struct proc_dir_entry *e; - if (platform_is_pseries()) { + if (machine_is(pseries)) { e = create_proc_entry("ppc64/eeh", 0, NULL); if (e) e->proc_fops = &proc_eeh_operations; diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c index 946ad59e3352..e97e67f5e079 100644 --- a/arch/powerpc/platforms/pseries/pci.c +++ b/arch/powerpc/platforms/pseries/pci.c @@ -120,7 +120,7 @@ static void fixup_winbond_82c105(struct pci_dev* dev) int i; unsigned int reg; - if (!platform_is_pseries()) + if (!machine_is(pseries)) return; printk("Using INTC for W82c105 IDE controller.\n"); diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index b3c2dcb1e4f0..6bfacc217085 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c @@ -28,6 +28,7 @@ #include #include #include +#include static struct pci_bus * find_bus_among_children(struct pci_bus *bus, diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 86cfa6ecdcf3..9a4b592e40bc 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c @@ -17,8 +17,9 @@ #include #include -#include +#include #include +#include @@ -508,7 +509,7 @@ static int proc_ppc64_create_ofdt(void) { struct proc_dir_entry *ent; - if (!platform_is_pseries()) + if (!machine_is(pseries)) return 0; ent = create_proc_entry("ppc64/ofdt", S_IWUSR, NULL); diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c index a6f628d4c9dc..fcc4d561a236 100644 --- a/arch/powerpc/platforms/pseries/rtasd.c +++ b/arch/powerpc/platforms/pseries/rtasd.c @@ -27,6 +27,7 @@ #include #include #include +#include #if 0 #define DEBUG(A...) printk(KERN_ERR A) @@ -481,7 +482,7 @@ static int __init rtas_init(void) { struct proc_dir_entry *entry; - if (!platform_is_pseries()) + if (!machine_is(pseries)) return 0; /* No RTAS */ diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 1b0c4c034a26..b2fbf8ba8fbb 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -372,24 +372,42 @@ static int pSeries_check_legacy_ioport(unsigned int baseport) /* * Called very early, MMU is off, device-tree isn't unflattened */ -extern struct machdep_calls pSeries_md; -static int __init pSeries_probe(int platform) +static int __init pSeries_probe_hypertas(unsigned long node, + const char *uname, int depth, + void *data) { - if (platform != PLATFORM_PSERIES && - platform != PLATFORM_PSERIES_LPAR) + if (depth != 1 || + (strcmp(uname, "rtas") != 0 && strcmp(uname, "rtas@0") != 0)) + return 0; + + if (of_get_flat_dt_prop(node, "ibm,hypertas-functions", NULL) != NULL) + powerpc_firmware_features |= FW_FEATURE_LPAR; + + return 1; +} + +static int __init pSeries_probe(void) +{ + char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(), + "device_type", NULL); + if (dtype == NULL) + return 0; + if (strcmp(dtype, "chrp")) return 0; - /* if we have some ppc_md fixups for LPAR to do, do - * it here ... - */ + DBG("pSeries detected, looking for LPAR capability...\n"); - if (platform == PLATFORM_PSERIES_LPAR) - powerpc_firmware_features |= FW_FEATURE_LPAR; + /* Now try to figure out if we are running on LPAR */ + of_scan_flat_dt(pSeries_probe_hypertas, NULL); + + DBG("Machine is%s LPAR !\n", + (powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not"); return 1; } + DECLARE_PER_CPU(unsigned long, smt_snooze_delay); static void pseries_dedicated_idle_sleep(void) @@ -501,7 +519,8 @@ static void pseries_kexec_cpu_down(int crash_shutdown, int secondary) } #endif -struct machdep_calls __initdata pSeries_md = { +define_machine(pseries) { + .name = "pSeries", .probe = pSeries_probe, .setup_arch = pSeries_setup_arch, .init_early = pSeries_init_early, -- cgit v1.2.2 From 4dc12ec7e26f287e33065e803bc0aede4c1dbdf3 Mon Sep 17 00:00:00 2001 From: Matt Mackall Date: Tue, 28 Mar 2006 01:56:03 -0800 Subject: [PATCH] RTC: Remove RTC UIP synchronization on CHRP (arch/powerpc) Signed-off-by: Matt Mackall Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/platforms/chrp/time.c | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c index 12c6f689b1aa..7d7889026936 100644 --- a/arch/powerpc/platforms/chrp/time.c +++ b/arch/powerpc/platforms/chrp/time.c @@ -120,33 +120,15 @@ int chrp_set_rtc_time(struct rtc_time *tmarg) void chrp_get_rtc_time(struct rtc_time *tm) { unsigned int year, mon, day, hour, min, sec; - int uip, i; - /* The Linux interpretation of the CMOS clock register contents: - * When the Update-In-Progress (UIP) flag goes from 1 to 0, the - * RTC registers show the second which has precisely just started. - * Let's hope other operating systems interpret the RTC the same way. - */ - - /* Since the UIP flag is set for about 2.2 ms and the clock - * is typically written with a precision of 1 jiffy, trying - * to obtain a precision better than a few milliseconds is - * an illusion. Only consistency is interesting, this also - * allows to use the routine for /dev/rtc without a potential - * 1 second kernel busy loop triggered by any reader of /dev/rtc. - */ - - for ( i = 0; i<1000000; i++) { - uip = chrp_cmos_clock_read(RTC_FREQ_SELECT); + do { sec = chrp_cmos_clock_read(RTC_SECONDS); min = chrp_cmos_clock_read(RTC_MINUTES); hour = chrp_cmos_clock_read(RTC_HOURS); day = chrp_cmos_clock_read(RTC_DAY_OF_MONTH); mon = chrp_cmos_clock_read(RTC_MONTH); year = chrp_cmos_clock_read(RTC_YEAR); - uip |= chrp_cmos_clock_read(RTC_FREQ_SELECT); - if ((uip & RTC_UIP)==0) break; - } + } while (sec != chrp_cmos_clock_read(RTC_SECONDS)); if (!(chrp_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { BCD_TO_BIN(sec); -- cgit v1.2.2 From 6f0d7bd6a14dcf5b258cfd809143c50e4897902b Mon Sep 17 00:00:00 2001 From: Matt Mackall Date: Tue, 28 Mar 2006 01:56:04 -0800 Subject: [PATCH] RTC: Remove RTC UIP synchronization on PPC Maple Signed-off-by: Matt Mackall Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/platforms/maple/time.c | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/maple/time.c b/arch/powerpc/platforms/maple/time.c index 5e6981d17379..b9a2b3d4bf33 100644 --- a/arch/powerpc/platforms/maple/time.c +++ b/arch/powerpc/platforms/maple/time.c @@ -60,34 +60,14 @@ static void maple_clock_write(unsigned long val, int addr) void maple_get_rtc_time(struct rtc_time *tm) { - int uip, i; - - /* The Linux interpretation of the CMOS clock register contents: - * When the Update-In-Progress (UIP) flag goes from 1 to 0, the - * RTC registers show the second which has precisely just started. - * Let's hope other operating systems interpret the RTC the same way. - */ - - /* Since the UIP flag is set for about 2.2 ms and the clock - * is typically written with a precision of 1 jiffy, trying - * to obtain a precision better than a few milliseconds is - * an illusion. Only consistency is interesting, this also - * allows to use the routine for /dev/rtc without a potential - * 1 second kernel busy loop triggered by any reader of /dev/rtc. - */ - - for (i = 0; i<1000000; i++) { - uip = maple_clock_read(RTC_FREQ_SELECT); + do { tm->tm_sec = maple_clock_read(RTC_SECONDS); tm->tm_min = maple_clock_read(RTC_MINUTES); tm->tm_hour = maple_clock_read(RTC_HOURS); tm->tm_mday = maple_clock_read(RTC_DAY_OF_MONTH); tm->tm_mon = maple_clock_read(RTC_MONTH); tm->tm_year = maple_clock_read(RTC_YEAR); - uip |= maple_clock_read(RTC_FREQ_SELECT); - if ((uip & RTC_UIP)==0) - break; - } + } while (tm->tm_sec != maple_clock_read(RTC_SECONDS)); if (!(maple_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { -- cgit v1.2.2 From 99ac48f54a91d02140c497edc31dc57d4bc5c85d Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Tue, 28 Mar 2006 01:56:41 -0800 Subject: [PATCH] mark f_ops const in the inode Mark the f_ops members of inodes as const, as well as fix the ripple-through this causes by places that copy this f_ops and then "do stuff" with it. Signed-off-by: Arjan van de Ven Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/platforms/cell/spufs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index b3962c3a0348..5be40aa483fd 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -103,7 +103,7 @@ spufs_setattr(struct dentry *dentry, struct iattr *attr) static int spufs_new_file(struct super_block *sb, struct dentry *dentry, - struct file_operations *fops, int mode, + const struct file_operations *fops, int mode, struct spu_context *ctx) { static struct inode_operations spufs_file_iops = { -- cgit v1.2.2 From bab70a4af737f623de5b034976a311055308ab86 Mon Sep 17 00:00:00 2001 From: Eugene Surovegin Date: Tue, 28 Mar 2006 10:13:12 -0800 Subject: [PATCH] lock PTE before updating it in 440/BookE page fault handler Fix 44x and BookE page fault handler to correctly lock PTE before trying to pte_update() it, otherwise this PTE might be swapped out after pte_present() check but before pte_uptdate() call, resulting in corrupted PTE. This can happen with enabled preemption and low memory condition. Signed-off-by: Eugene Surovegin Signed-off-by: Paul Mackerras --- arch/powerpc/mm/fault.c | 30 +++++++++++++++++------------- arch/powerpc/mm/pgtable_32.c | 6 ++++-- 2 files changed, 21 insertions(+), 15 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index ec4adcb4bc28..5aea0909a5ec 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -267,25 +267,29 @@ good_area: #endif #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) pte_t *ptep; + pmd_t *pmdp; /* Since 4xx/Book-E supports per-page execute permission, * we lazily flush dcache to icache. */ ptep = NULL; - if (get_pteptr(mm, address, &ptep) && pte_present(*ptep)) { - struct page *page = pte_page(*ptep); - - if (! test_bit(PG_arch_1, &page->flags)) { - flush_dcache_icache_page(page); - set_bit(PG_arch_1, &page->flags); + if (get_pteptr(mm, address, &ptep, &pmdp)) { + spinlock_t *ptl = pte_lockptr(mm, pmdp); + spin_lock(ptl); + if (pte_present(*ptep)) { + struct page *page = pte_page(*ptep); + + if (!test_bit(PG_arch_1, &page->flags)) { + flush_dcache_icache_page(page); + set_bit(PG_arch_1, &page->flags); + } + pte_update(ptep, 0, _PAGE_HWEXEC); + _tlbie(address); + pte_unmap_unlock(ptep, ptl); + up_read(&mm->mmap_sem); + return 0; } - pte_update(ptep, 0, _PAGE_HWEXEC); - _tlbie(address); - pte_unmap(ptep); - up_read(&mm->mmap_sem); - return 0; + pte_unmap_unlock(ptep, ptl); } - if (ptep != NULL) - pte_unmap(ptep); #endif /* a write */ } else if (is_write) { diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index d296eb6b4545..90628601fac7 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c @@ -372,7 +372,7 @@ void __init io_block_mapping(unsigned long virt, phys_addr_t phys, * the PTE pointer is unmodified if PTE is not found. */ int -get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep) +get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep, pmd_t **pmdp) { pgd_t *pgd; pmd_t *pmd; @@ -387,6 +387,8 @@ get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep) if (pte) { retval = 1; *ptep = pte; + if (pmdp) + *pmdp = pmd; /* XXX caller needs to do pte_unmap, yuck */ } } @@ -424,7 +426,7 @@ unsigned long iopa(unsigned long addr) mm = &init_mm; pa = 0; - if (get_pteptr(mm, addr, &pte)) { + if (get_pteptr(mm, addr, &pte, NULL)) { pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK); pte_unmap(pte); } -- cgit v1.2.2 From 0e5519548fdc8eadc3eacb49b1908d44d347fb2b Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Tue, 28 Mar 2006 14:50:51 -0800 Subject: [PATCH] for_each_possible_cpu: powerpc for_each_cpu() actually iterates across all possible CPUs. We've had mistakes in the past where people were using for_each_cpu() where they should have been iterating across only online or present CPUs. This is inefficient and possibly buggy. We're renaming for_each_cpu() to for_each_possible_cpu() to avoid this in the future. This patch replaces for_each_cpu with for_each_possible_cpu. Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/irq.c | 2 +- arch/powerpc/kernel/lparcfg.c | 4 ++-- arch/powerpc/kernel/rtas.c | 4 ++-- arch/powerpc/kernel/setup-common.c | 2 +- arch/powerpc/kernel/setup_32.c | 2 +- arch/powerpc/kernel/setup_64.c | 6 +++--- arch/powerpc/kernel/smp.c | 2 +- arch/powerpc/kernel/sysfs.c | 6 +++--- arch/powerpc/kernel/time.c | 4 ++-- arch/powerpc/mm/stab.c | 2 +- arch/powerpc/platforms/cell/interrupt.c | 2 +- arch/powerpc/platforms/cell/pervasive.c | 2 +- arch/powerpc/platforms/pseries/xics.c | 2 +- 13 files changed, 20 insertions(+), 20 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 771a59cbd213..bb5c9501234c 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -379,7 +379,7 @@ void irq_ctx_init(void) struct thread_info *tp; int i; - for_each_cpu(i) { + for_each_possible_cpu(i) { memset((void *)softirq_ctx[i], 0, THREAD_SIZE); tp = softirq_ctx[i]; tp->cpu = i; diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index e789fef4eb8a..1b73508ecb2b 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c @@ -56,7 +56,7 @@ static unsigned long get_purr(void) unsigned long sum_purr = 0; int cpu; - for_each_cpu(cpu) { + for_each_possible_cpu(cpu) { sum_purr += lppaca[cpu].emulated_time_base; #ifdef PURR_DEBUG @@ -222,7 +222,7 @@ static unsigned long get_purr(void) int cpu; struct cpu_usage *cu; - for_each_cpu(cpu) { + for_each_possible_cpu(cpu) { cu = &per_cpu(cpu_usage_array, cpu); sum_purr += cu->current_tb; } diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 4b78ee0e5867..06636c927a7e 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -593,7 +593,7 @@ static void rtas_percpu_suspend_me(void *info) data->waiting = 0; data->args->args[data->args->nargs] = rtas_call(ibm_suspend_me_token, 0, 1, NULL); - for_each_cpu(i) + for_each_possible_cpu(i) plpar_hcall_norets(H_PROD,i); } else { data->waiting = -EBUSY; @@ -626,7 +626,7 @@ static int rtas_ibm_suspend_me(struct rtas_args *args) /* Prod each CPU. This won't hurt, and will wake * anyone we successfully put to sleep with H_Join */ - for_each_cpu(i) + for_each_possible_cpu(i) plpar_hcall_norets(H_PROD, i); return data.waiting; diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 3473cb9cb0ab..c607f3b9ca17 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -431,7 +431,7 @@ void __init smp_setup_cpu_maps(void) /* * Do the sibling map; assume only two threads per processor. */ - for_each_cpu(cpu) { + for_each_possible_cpu(cpu) { cpu_set(cpu, cpu_sibling_map[cpu]); if (cpu_has_feature(CPU_FTR_SMT)) cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]); diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index ae9c33d70731..a72bf5dceeee 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -226,7 +226,7 @@ int __init ppc_init(void) if ( ppc_md.progress ) ppc_md.progress(" ", 0xffff); /* register CPU devices */ - for_each_cpu(i) + for_each_possible_cpu(i) register_cpu(&cpu_devices[i], i, NULL); /* call platform init */ diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 05b152299396..59aa92cd6fa4 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -474,7 +474,7 @@ static void __init irqstack_early_init(void) * interrupt stacks must be under 256MB, we cannot afford to take * SLB misses on them. */ - for_each_cpu(i) { + for_each_possible_cpu(i) { softirq_ctx[i] = (struct thread_info *) __va(lmb_alloc_base(THREAD_SIZE, THREAD_SIZE, 0x10000000)); @@ -507,7 +507,7 @@ static void __init emergency_stack_init(void) */ limit = min(0x10000000UL, lmb.rmo_size); - for_each_cpu(i) + for_each_possible_cpu(i) paca[i].emergency_sp = __va(lmb_alloc_base(HW_PAGE_SIZE, 128, limit)) + HW_PAGE_SIZE; } @@ -624,7 +624,7 @@ void __init setup_per_cpu_areas(void) size = PERCPU_ENOUGH_ROOM; #endif - for_each_cpu(i) { + for_each_possible_cpu(i) { ptr = alloc_bootmem_node(NODE_DATA(cpu_to_node(i)), size); if (!ptr) panic("Cannot allocate cpu data for CPU %d\n", i); diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 805eaedbc308..530f7dba0bd2 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -362,7 +362,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) smp_space_timers(max_cpus); - for_each_cpu(cpu) + for_each_possible_cpu(cpu) if (cpu != boot_cpuid) smp_create_idle(cpu); } diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index aca2f09cd842..73560ef6f802 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -74,7 +74,7 @@ static int __init smt_setup(void) val = (unsigned int *)get_property(options, "ibm,smt-snooze-delay", NULL); if (!smt_snooze_cmdline && val) { - for_each_cpu(cpu) + for_each_possible_cpu(cpu) per_cpu(smt_snooze_delay, cpu) = *val; } @@ -93,7 +93,7 @@ static int __init setup_smt_snooze_delay(char *str) smt_snooze_cmdline = 1; if (get_option(&str, &snooze)) { - for_each_cpu(cpu) + for_each_possible_cpu(cpu) per_cpu(smt_snooze_delay, cpu) = snooze; } @@ -347,7 +347,7 @@ static int __init topology_init(void) register_cpu_notifier(&sysfs_cpu_nb); - for_each_cpu(cpu) { + for_each_possible_cpu(cpu) { struct cpu *c = &per_cpu(cpu_devices, cpu); #ifdef CONFIG_NUMA diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 4a27218a086c..24e3ad756de0 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -261,7 +261,7 @@ void snapshot_timebases(void) if (!cpu_has_feature(CPU_FTR_PURR)) return; - for_each_cpu(cpu) + for_each_possible_cpu(cpu) spin_lock_init(&per_cpu(cpu_purr_data, cpu).lock); on_each_cpu(snapshot_tb_and_purr, NULL, 0, 1); } @@ -751,7 +751,7 @@ void __init smp_space_timers(unsigned int max_cpus) * systems works better if the two threads' timebase interrupts * are staggered by half a jiffy with respect to each other. */ - for_each_cpu(i) { + for_each_possible_cpu(i) { if (i == boot_cpuid) continue; if (i == (boot_cpuid ^ 1)) diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c index 91d25fb27f89..4a9291d9fef8 100644 --- a/arch/powerpc/mm/stab.c +++ b/arch/powerpc/mm/stab.c @@ -239,7 +239,7 @@ void stabs_alloc(void) if (cpu_has_feature(CPU_FTR_SLB)) return; - for_each_cpu(cpu) { + for_each_possible_cpu(cpu) { unsigned long newstab; if (cpu == 0) diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index ae62f5d5c31b..978be1c30c1b 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -364,7 +364,7 @@ void iic_init_IRQ(void) setup_iic_hardcoded(); irq_offset = 0; - for_each_cpu(cpu) { + for_each_possible_cpu(cpu) { iic = &per_cpu(iic, cpu); if (iic->regs) out_be64(&iic->regs->prio, 0xff); diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c index 58baeb52f6fc..7eed8c624517 100644 --- a/arch/powerpc/platforms/cell/pervasive.c +++ b/arch/powerpc/platforms/cell/pervasive.c @@ -217,7 +217,7 @@ void __init cell_pervasive_init(void) if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO)) return; - for_each_cpu(cpu) { + for_each_possible_cpu(cpu) { p = &cbe_pervasive[cpu]; ret = cbe_find_pmd_mmio(cpu, p); if (ret) diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index c60d3ff25a2f..4864cb32be25 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -541,7 +541,7 @@ nextnode: ops = &pSeriesLP_ops; else { #ifdef CONFIG_SMP - for_each_cpu(i) { + for_each_possible_cpu(i) { int hard_id; /* FIXME: Do this dynamically! --RR */ -- cgit v1.2.2 From 6c6bd754bf43d59756f094de144ecac239629dda Mon Sep 17 00:00:00 2001 From: Brian Rogan Date: Mon, 27 Mar 2006 11:57:01 +1100 Subject: [PATCH] powerpc: Add oprofile calltrace support Add oprofile calltrace support to powerpc. Disable spinlock backtracing now we can use calltrace info. (Updated to work on both 32bit and 64bit by me). Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/oprofile/Makefile | 2 +- arch/powerpc/oprofile/backtrace.c | 126 ++++++++++++++++++++++++++++++++ arch/powerpc/oprofile/common.c | 4 +- arch/powerpc/oprofile/op_model_power4.c | 2 +- 4 files changed, 130 insertions(+), 4 deletions(-) create mode 100644 arch/powerpc/oprofile/backtrace.c (limited to 'arch/powerpc') diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile index 554cd7c75321..f5f9859a8338 100644 --- a/arch/powerpc/oprofile/Makefile +++ b/arch/powerpc/oprofile/Makefile @@ -6,7 +6,7 @@ DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \ oprofilefs.o oprofile_stats.o \ timer_int.o ) -oprofile-y := $(DRIVER_OBJS) common.o +oprofile-y := $(DRIVER_OBJS) common.o backtrace.o oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o oprofile-$(CONFIG_PPC32) += op_model_7450.o diff --git a/arch/powerpc/oprofile/backtrace.c b/arch/powerpc/oprofile/backtrace.c new file mode 100644 index 000000000000..75f57bc96b40 --- /dev/null +++ b/arch/powerpc/oprofile/backtrace.c @@ -0,0 +1,126 @@ +/** + * Copyright (C) 2005 Brian Rogan , IBM + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. +**/ + +#include +#include +#include +#include + +#define STACK_SP(STACK) *(STACK) + +#define STACK_LR64(STACK) *((unsigned long *)(STACK) + 2) +#define STACK_LR32(STACK) *((unsigned int *)(STACK) + 1) + +#ifdef CONFIG_PPC64 +#define STACK_LR(STACK) STACK_LR64(STACK) +#else +#define STACK_LR(STACK) STACK_LR32(STACK) +#endif + +static unsigned int user_getsp32(unsigned int sp, int is_first) +{ + unsigned int stack_frame[2]; + + if (!access_ok(VERIFY_READ, sp, sizeof(stack_frame))) + return 0; + + /* + * The most likely reason for this is that we returned -EFAULT, + * which means that we've done all that we can do from + * interrupt context. + */ + if (__copy_from_user_inatomic(stack_frame, (void *)(long)sp, + sizeof(stack_frame))) + return 0; + + if (!is_first) + oprofile_add_trace(STACK_LR32(stack_frame)); + + /* + * We do not enforce increasing stack addresses here because + * we may transition to a different stack, eg a signal handler. + */ + return STACK_SP(stack_frame); +} + +#ifdef CONFIG_PPC64 +static unsigned long user_getsp64(unsigned long sp, int is_first) +{ + unsigned long stack_frame[3]; + + if (!access_ok(VERIFY_READ, sp, sizeof(stack_frame))) + return 0; + + if (__copy_from_user_inatomic(stack_frame, (void *)sp, + sizeof(stack_frame))) + return 0; + + if (!is_first) + oprofile_add_trace(STACK_LR64(stack_frame)); + + return STACK_SP(stack_frame); +} +#endif + +static unsigned long kernel_getsp(unsigned long sp, int is_first) +{ + unsigned long *stack_frame = (unsigned long *)sp; + + if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD)) + return 0; + + if (!is_first) + oprofile_add_trace(STACK_LR(stack_frame)); + + /* + * We do not enforce increasing stack addresses here because + * we might be transitioning from an interrupt stack to a kernel + * stack. validate_sp() is designed to understand this, so just + * use it. + */ + return STACK_SP(stack_frame); +} + +void op_powerpc_backtrace(struct pt_regs * const regs, unsigned int depth) +{ + unsigned long sp = regs->gpr[1]; + int first_frame = 1; + + /* We ditch the top stackframe so need to loop through an extra time */ + depth += 1; + + if (!user_mode(regs)) { + while (depth--) { + sp = kernel_getsp(sp, first_frame); + if (!sp) + break; + first_frame = 0; + } + } else { +#ifdef CONFIG_PPC64 + if (!test_thread_flag(TIF_32BIT)) { + while (depth--) { + sp = user_getsp64(sp, first_frame); + if (!sp) + break; + first_frame = 0; + } + + return; + } +#endif + + while (depth--) { + sp = user_getsp32(sp, first_frame); + if (!sp) + break; + first_frame = 0; + } + } +} diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c index cc2535be3a73..2b9143b0f6ba 100644 --- a/arch/powerpc/oprofile/common.c +++ b/arch/powerpc/oprofile/common.c @@ -126,8 +126,7 @@ static int op_powerpc_create_files(struct super_block *sb, struct dentry *root) sys.enable_kernel = 1; sys.enable_user = 1; #ifdef CONFIG_PPC64 - /* Turn on backtracing through spinlocks by default */ - sys.backtrace_spinlocks = 1; + sys.backtrace_spinlocks = 0; #endif return 0; @@ -168,6 +167,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) ops->shutdown = op_powerpc_shutdown; ops->start = op_powerpc_start; ops->stop = op_powerpc_stop; + ops->backtrace = op_powerpc_backtrace; printk(KERN_INFO "oprofile: using %s performance monitoring.\n", ops->cpu_type); diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c index 4b06e53eb9b4..38db2efef3bc 100644 --- a/arch/powerpc/oprofile/op_model_power4.c +++ b/arch/powerpc/oprofile/op_model_power4.c @@ -293,7 +293,7 @@ static void power4_handle_interrupt(struct pt_regs *regs, val = ctr_read(i); if (val < 0) { if (oprofile_running && ctr[i].enabled) { - oprofile_add_pc(pc, is_kernel, i); + oprofile_add_ext_sample(pc, regs, i, is_kernel); ctr_write(i, reset_value[i]); } else { ctr_write(i, 0); -- cgit v1.2.2 From fa465f8c7008c6cab32b05f3f1af57f7c86e8873 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 27 Mar 2006 12:03:17 +1100 Subject: [PATCH] powerpc: Add oprofile calltrace support to all powerpc cpus Add calltrace support for other powerpc cpus. Tested on 7450. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/oprofile/op_model_7450.c | 4 ++-- arch/powerpc/oprofile/op_model_fsl_booke.c | 4 ++-- arch/powerpc/oprofile/op_model_rs64.c | 5 ++++- 3 files changed, 8 insertions(+), 5 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/oprofile/op_model_7450.c b/arch/powerpc/oprofile/op_model_7450.c index 32abfdbb0eb1..e0491c3c71f1 100644 --- a/arch/powerpc/oprofile/op_model_7450.c +++ b/arch/powerpc/oprofile/op_model_7450.c @@ -176,13 +176,13 @@ static void fsl7450_handle_interrupt(struct pt_regs *regs, mtmsr(mfmsr() | MSR_PMM); pc = mfspr(SPRN_SIAR); - is_kernel = (pc >= KERNELBASE); + is_kernel = is_kernel_addr(pc); for (i = 0; i < NUM_CTRS; ++i) { val = ctr_read(i); if (val < 0) { if (oprofile_running && ctr[i].enabled) { - oprofile_add_pc(pc, is_kernel, i); + oprofile_add_ext_sample(pc, regs, i, is_kernel); ctr_write(i, reset_value[i]); } else { ctr_write(i, 0); diff --git a/arch/powerpc/oprofile/op_model_fsl_booke.c b/arch/powerpc/oprofile/op_model_fsl_booke.c index 26539cda6023..93d63e62662f 100644 --- a/arch/powerpc/oprofile/op_model_fsl_booke.c +++ b/arch/powerpc/oprofile/op_model_fsl_booke.c @@ -154,13 +154,13 @@ static void fsl_booke_handle_interrupt(struct pt_regs *regs, mtmsr(mfmsr() | MSR_PMM); pc = regs->nip; - is_kernel = (pc >= KERNELBASE); + is_kernel = is_kernel_addr(pc); for (i = 0; i < num_counters; ++i) { val = ctr_read(i); if (val < 0) { if (oprofile_running && ctr[i].enabled) { - oprofile_add_pc(pc, is_kernel, i); + oprofile_add_ext_sample(pc, regs, i, is_kernel); ctr_write(i, reset_value[i]); } else { ctr_write(i, 0); diff --git a/arch/powerpc/oprofile/op_model_rs64.c b/arch/powerpc/oprofile/op_model_rs64.c index 5c909ee609fe..042f8f4867ad 100644 --- a/arch/powerpc/oprofile/op_model_rs64.c +++ b/arch/powerpc/oprofile/op_model_rs64.c @@ -175,10 +175,13 @@ static void rs64_handle_interrupt(struct pt_regs *regs, struct op_counter_config *ctr) { unsigned int mmcr0; + int is_kernel; int val; int i; unsigned long pc = mfspr(SPRN_SIAR); + is_kernel = is_kernel_addr(pc); + /* set the PMM bit (see comment below) */ mtmsrd(mfmsr() | MSR_PMM); @@ -186,7 +189,7 @@ static void rs64_handle_interrupt(struct pt_regs *regs, val = ctr_read(i); if (val < 0) { if (ctr[i].enabled) { - oprofile_add_pc(pc, is_kernel_addr(pc), i); + oprofile_add_ext_sample(pc, regs, i, is_kernel); ctr_write(i, reset_value[i]); } else { ctr_write(i, 0); -- cgit v1.2.2 From 15e812ad849e142e3dfc984d33c4d8042389f148 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 27 Mar 2006 12:00:45 +1100 Subject: [PATCH] powerpc: Remove oprofile spinlock backtrace code Remove oprofile spinlock backtrace code now we have proper calltrace support. Also make MMCRA sihv and sipr bits a variable since they may change in future cpus. Finally, MMCRA should be a 64bit quantity. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/oprofile/common.c | 7 ------ arch/powerpc/oprofile/op_model_power4.c | 43 +++++++-------------------------- 2 files changed, 9 insertions(+), 41 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c index 2b9143b0f6ba..5b1de7e8041e 100644 --- a/arch/powerpc/oprofile/common.c +++ b/arch/powerpc/oprofile/common.c @@ -117,17 +117,10 @@ static int op_powerpc_create_files(struct super_block *sb, struct dentry *root) oprofilefs_create_ulong(sb, root, "enable_kernel", &sys.enable_kernel); oprofilefs_create_ulong(sb, root, "enable_user", &sys.enable_user); -#ifdef CONFIG_PPC64 - oprofilefs_create_ulong(sb, root, "backtrace_spinlocks", - &sys.backtrace_spinlocks); -#endif /* Default to tracing both kernel and user */ sys.enable_kernel = 1; sys.enable_user = 1; -#ifdef CONFIG_PPC64 - sys.backtrace_spinlocks = 0; -#endif return 0; } diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c index 38db2efef3bc..4c2beab1fdc1 100644 --- a/arch/powerpc/oprofile/op_model_power4.c +++ b/arch/powerpc/oprofile/op_model_power4.c @@ -25,18 +25,14 @@ static unsigned long reset_value[OP_MAX_COUNTER]; static int oprofile_running; static int mmcra_has_sihv; +/* Unfortunately these bits vary between CPUs */ +static unsigned long mmcra_sihv = MMCRA_SIHV; +static unsigned long mmcra_sipr = MMCRA_SIPR; /* mmcr values are set in power4_reg_setup, used in power4_cpu_setup */ static u32 mmcr0_val; static u64 mmcr1_val; -static u32 mmcra_val; - -/* - * Since we do not have an NMI, backtracing through spinlocks is - * only a best guess. In light of this, allow it to be disabled at - * runtime. - */ -static int backtrace_spinlocks; +static u64 mmcra_val; static void power4_reg_setup(struct op_counter_config *ctr, struct op_system_config *sys, @@ -63,8 +59,6 @@ static void power4_reg_setup(struct op_counter_config *ctr, mmcr1_val = sys->mmcr1; mmcra_val = sys->mmcra; - backtrace_spinlocks = sys->backtrace_spinlocks; - for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) reset_value[i] = 0x80000000UL - ctr[i].count; @@ -197,25 +191,6 @@ static void __attribute_used__ kernel_unknown_bucket(void) { } -static unsigned long check_spinlock_pc(struct pt_regs *regs, - unsigned long profile_pc) -{ - unsigned long pc = instruction_pointer(regs); - - /* - * If both the SIAR (sampled instruction) and the perfmon exception - * occurred in a spinlock region then we account the sample to the - * calling function. This isnt 100% correct, we really need soft - * IRQ disable so we always get the perfmon exception at the - * point at which the SIAR is set. - */ - if (backtrace_spinlocks && in_lock_functions(pc) && - in_lock_functions(profile_pc)) - return regs->link; - else - return profile_pc; -} - /* * On GQ and newer the MMCRA stores the HV and PR bits at the time * the SIAR was sampled. We use that to work out if the SIAR was sampled in @@ -228,17 +203,17 @@ static unsigned long get_pc(struct pt_regs *regs) /* Cant do much about it */ if (!mmcra_has_sihv) - return check_spinlock_pc(regs, pc); + return pc; mmcra = mfspr(SPRN_MMCRA); /* Were we in the hypervisor? */ - if (firmware_has_feature(FW_FEATURE_LPAR) && (mmcra & MMCRA_SIHV)) + if (firmware_has_feature(FW_FEATURE_LPAR) && (mmcra & mmcra_sihv)) /* function descriptor madness */ return *((unsigned long *)hypervisor_bucket); /* We were in userspace, nothing to do */ - if (mmcra & MMCRA_SIPR) + if (mmcra & mmcra_sipr) return pc; #ifdef CONFIG_PPC_RTAS @@ -257,7 +232,7 @@ static unsigned long get_pc(struct pt_regs *regs) /* function descriptor madness */ return *((unsigned long *)kernel_unknown_bucket); - return check_spinlock_pc(regs, pc); + return pc; } static int get_kernel(unsigned long pc) @@ -268,7 +243,7 @@ static int get_kernel(unsigned long pc) is_kernel = is_kernel_addr(pc); } else { unsigned long mmcra = mfspr(SPRN_MMCRA); - is_kernel = ((mmcra & MMCRA_SIPR) == 0); + is_kernel = ((mmcra & mmcra_sipr) == 0); } return is_kernel; -- cgit v1.2.2 From da2e9e1ff40c863a12803c32209baaded3512433 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 31 Mar 2006 02:30:28 -0800 Subject: [PATCH] Mark unwind info for signal trampolines in vDSOs Mark unwind info for signal trampolines using the new S augmentation flag introduced in: http://gcc.gnu.org/PR26208. GCC 4.2 (or patched earlier GCC) will be able to special case unwinding through frames right above signal trampolines. As the augmentations start with z flag and S is at the very end of the augmentation string, older GCCs will just skip the S flag as unknown (that's why an augmentation flag was chosen over say a new CFA opcode). Signed-off-by: Jakub Jelinek Cc: Andi Kleen Cc: Paul Mackerras Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/kernel/vdso32/sigtramp.S | 2 +- arch/powerpc/kernel/vdso64/sigtramp.S | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/vdso32/sigtramp.S b/arch/powerpc/kernel/vdso32/sigtramp.S index e04642781917..0c6a37b29dde 100644 --- a/arch/powerpc/kernel/vdso32/sigtramp.S +++ b/arch/powerpc/kernel/vdso32/sigtramp.S @@ -261,7 +261,7 @@ V_FUNCTION_END(__kernel_sigtramp_rt32) .Lcie_start: .long 0 /* CIE ID */ .byte 1 /* Version number */ - .string "zR" /* NUL-terminated augmentation string */ + .string "zRS" /* NUL-terminated augmentation string */ .uleb128 4 /* Code alignment factor */ .sleb128 -4 /* Data alignment factor */ .byte 67 /* Return address register column, ap */ diff --git a/arch/powerpc/kernel/vdso64/sigtramp.S b/arch/powerpc/kernel/vdso64/sigtramp.S index 31b604ab56de..7479edb101b8 100644 --- a/arch/powerpc/kernel/vdso64/sigtramp.S +++ b/arch/powerpc/kernel/vdso64/sigtramp.S @@ -263,7 +263,7 @@ V_FUNCTION_END(__kernel_sigtramp_rt64) .Lcie_start: .long 0 /* CIE ID */ .byte 1 /* Version number */ - .string "zR" /* NUL-terminated augmentation string */ + .string "zRS" /* NUL-terminated augmentation string */ .uleb128 4 /* Code alignment factor */ .sleb128 -8 /* Data alignment factor */ .byte 67 /* Return address register column, ap */ -- cgit v1.2.2 From 9b41046cd0ee0a57f849d6e1363f7933e363cca9 Mon Sep 17 00:00:00 2001 From: OGAWA Hirofumi Date: Fri, 31 Mar 2006 02:30:33 -0800 Subject: [PATCH] Don't pass boot parameters to argv_init[] The boot cmdline is parsed in parse_early_param() and parse_args(,unknown_bootoption). And __setup() is used in obsolete_checksetup(). start_kernel() -> parse_args() -> unknown_bootoption() -> obsolete_checksetup() If __setup()'s callback (->setup_func()) returns 1 in obsolete_checksetup(), obsolete_checksetup() thinks a parameter was handled. If ->setup_func() returns 0, obsolete_checksetup() tries other ->setup_func(). If all ->setup_func() that matched a parameter returns 0, a parameter is seted to argv_init[]. Then, when runing /sbin/init or init=app, argv_init[] is passed to the app. If the app doesn't ignore those arguments, it will warning and exit. This patch fixes a wrong usage of it, however fixes obvious one only. Signed-off-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/kernel/crash_dump.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c index 211d72653ea6..764d07329716 100644 --- a/arch/powerpc/kernel/crash_dump.c +++ b/arch/powerpc/kernel/crash_dump.c @@ -61,7 +61,7 @@ static int __init parse_elfcorehdr(char *p) if (p) elfcorehdr_addr = memparse(p, &p); - return 0; + return 1; } __setup("elfcorehdr=", parse_elfcorehdr); #endif @@ -71,7 +71,7 @@ static int __init parse_savemaxmem(char *p) if (p) saved_max_pfn = (memparse(p, &p) >> PAGE_SHIFT) - 1; - return 0; + return 1; } __setup("savemaxmem=", parse_savemaxmem); -- cgit v1.2.2 From 0cb3463f04e771869f481e2dd44f66419e850586 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 31 Mar 2006 02:32:07 -0800 Subject: [PATCH] unexport get_wchan The only user of get_wchan is the proc fs - and proc can't be built modular. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/kernel/process.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 706090c99f47..2dd47d2dd998 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -834,7 +834,6 @@ unsigned long get_wchan(struct task_struct *p) } while (count++ < 16); return 0; } -EXPORT_SYMBOL(get_wchan); static int kstack_depth_to_print = 64; -- cgit v1.2.2