Commit 177b0888 authored by Linus Torvalds's avatar Linus Torvalds

Merge http://lia64.bkbits.net/to-linus-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 0fc27e84 c78a7e90
...@@ -13,7 +13,7 @@ AWK := awk ...@@ -13,7 +13,7 @@ AWK := awk
export AWK export AWK
OBJCOPYFLAGS := --strip-all OBJCOPYFLAGS := --strip-all
LDFLAGS_vmlinux := -static -T arch/$(ARCH)/vmlinux.lds LDFLAGS_vmlinux := -static -T arch/$(ARCH)/vmlinux.lds
AFLAGS_KERNEL := -mconstant-gp AFLAGS_KERNEL := -mconstant-gp
EXTRA = EXTRA =
...@@ -26,7 +26,7 @@ CFLAGS_KERNEL := -mconstant-gp ...@@ -26,7 +26,7 @@ CFLAGS_KERNEL := -mconstant-gp
GCC_VERSION=$(shell $(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f1 -d'.') GCC_VERSION=$(shell $(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f1 -d'.')
ifneq ($(GCC_VERSION),2) ifneq ($(GCC_VERSION),2)
CFLAGS += -frename-registers --param max-inline-insns=2000 CFLAGS += -frename-registers --param max-inline-insns=5000
endif endif
ifeq ($(CONFIG_ITANIUM_BSTEP_SPECIFIC),y) ifeq ($(CONFIG_ITANIUM_BSTEP_SPECIFIC),y)
......
...@@ -12,8 +12,10 @@ LINKFLAGS = -static -T bootloader.lds ...@@ -12,8 +12,10 @@ LINKFLAGS = -static -T bootloader.lds
OBJECTS = bootloader.o OBJECTS = bootloader.o
targets-$(CONFIG_IA64_HP_SIM) += bootloader targets-$(CONFIG_IA64_HP_SIM) += bootloader
targets-$(CONFIG_IA64_GENERIC) += bootloader targets-$(CONFIG_IA64_GENERIC) += bootloader
CFLAGS := $(CFLAGS) $(CFLAGS_KERNEL)
all: $(targets-y) all: $(targets-y)
......
...@@ -64,12 +64,13 @@ if [ "$CONFIG_MCKINLEY" = "y" ]; then ...@@ -64,12 +64,13 @@ if [ "$CONFIG_MCKINLEY" = "y" ]; then
fi fi
fi fi
if [ "$CONFIG_IA64_GENERIC" = "y" -o "$CONFIG_IA64_DIG" = "y" -o "$CONFIG_IA64_HP_ZX1" = "y" ]; then if [ "$CONFIG_IA64_GENERIC" = "y" -o "$CONFIG_IA64_DIG" = "y" -o "$CONFIG_IA64_HP_ZX1" = "y" ];
then
bool ' Enable IA-64 Machine Check Abort' CONFIG_IA64_MCA bool ' Enable IA-64 Machine Check Abort' CONFIG_IA64_MCA
define_bool CONFIG_PM y define_bool CONFIG_PM y
fi fi
if [ "$CONFIG_IA64_SGI_SN1" = "y" -o "$CONFIG_IA64_SGI_SN2" = "y" ]; then if [ "$CONFIG_IA64_SGI_SN1" = "y" -o "$CONFIG_IA64_SGI_SN2" = "y" ]; then
define_bool CONFIG_IA64_SGI_SN y define_bool CONFIG_IA64_SGI_SN y
bool ' Enable extra debugging code' CONFIG_IA64_SGI_SN_DEBUG bool ' Enable extra debugging code' CONFIG_IA64_SGI_SN_DEBUG
bool ' Enable SGI Medusa Simulator Support' CONFIG_IA64_SGI_SN_SIM bool ' Enable SGI Medusa Simulator Support' CONFIG_IA64_SGI_SN_SIM
...@@ -99,21 +100,20 @@ tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF ...@@ -99,21 +100,20 @@ tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
source drivers/acpi/Config.in
source drivers/acpi/Config.in bool 'PCI support' CONFIG_PCI
source drivers/pci/Config.in
bool 'PCI support' CONFIG_PCI bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG
source drivers/pci/Config.in if [ "$CONFIG_HOTPLUG" = "y" ]; then
source drivers/hotplug/Config.in
bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG source drivers/pcmcia/Config.in
if [ "$CONFIG_HOTPLUG" = "y" ]; then else
source drivers/pcmcia/Config.in define_bool CONFIG_PCMCIA n
else fi
define_bool CONFIG_PCMCIA n
fi
source drivers/parport/Config.in
source drivers/parport/Config.in
fi # !HP_SIM fi # !HP_SIM
endmenu endmenu
...@@ -123,39 +123,26 @@ if [ "$CONFIG_NET" = "y" ]; then ...@@ -123,39 +123,26 @@ if [ "$CONFIG_NET" = "y" ]; then
fi fi
if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
source drivers/mtd/Config.in
source drivers/pnp/Config.in
source drivers/block/Config.in
source drivers/ieee1394/Config.in
source drivers/message/i2o/Config.in
source drivers/md/Config.in
source drivers/message/fusion/Config.in
source drivers/mtd/Config.in mainmenu_option next_comment
source drivers/pnp/Config.in comment 'ATA/ATAPI/MFM/RLL support'
source drivers/block/Config.in
source drivers/ieee1394/Config.in
source drivers/message/i2o/Config.in
source drivers/md/Config.in
source drivers/message/fusion/Config.in
mainmenu_option next_comment
comment 'ATA/ATAPI/MFM/RLL support'
tristate 'ATA/ATAPI/MFM/RLL support' CONFIG_IDE
if [ "$CONFIG_IDE" != "n" ]; then
source drivers/ide/Config.in
else
define_bool CONFIG_BLK_DEV_HD n
fi
endmenu
else # ! HP_SIM tristate 'ATA/ATAPI/MFM/RLL support' CONFIG_IDE
mainmenu_option next_comment
comment 'Block devices'
tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET
tristate 'RAM disk support' CONFIG_BLK_DEV_RAM if [ "$CONFIG_IDE" != "n" ]; then
if [ "$CONFIG_BLK_DEV_RAM" = "y" -o "$CONFIG_BLK_DEV_RAM" = "m" ]; then source drivers/ide/Config.in
int ' Default RAM disk size' CONFIG_BLK_DEV_RAM_SIZE 4096 else
define_bool CONFIG_BLK_DEV_HD n
fi
endmenu
fi fi
endmenu
fi # !HP_SIM
mainmenu_option next_comment mainmenu_option next_comment
comment 'SCSI support' comment 'SCSI support'
...@@ -168,80 +155,83 @@ fi ...@@ -168,80 +155,83 @@ fi
endmenu endmenu
if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
if [ "$CONFIG_NET" = "y" ]; then
mainmenu_option next_comment
comment 'Network device support'
bool 'Network device support' CONFIG_NETDEVICES
if [ "$CONFIG_NETDEVICES" = "y" ]; then
source drivers/net/Config.in
fi
endmenu
fi
source net/ax25/Config.in
source drivers/isdn/Config.in
if [ "$CONFIG_NET" = "y" ]; then
mainmenu_option next_comment mainmenu_option next_comment
comment 'Network device support' comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)'
bool 'Network device support' CONFIG_NETDEVICES bool 'Support non-SCSI/IDE/ATAPI CDROM drives' CONFIG_CD_NO_IDESCSI
if [ "$CONFIG_NETDEVICES" = "y" ]; then if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
source drivers/net/Config.in source drivers/cdrom/Config.in
fi fi
endmenu endmenu
fi
source net/ax25/Config.in #
# input before char - char/joystick depends on it. As does USB.
#
source drivers/input/Config.in
source drivers/char/Config.in
source drivers/isdn/Config.in #source drivers/misc/Config.in
mainmenu_option next_comment source drivers/media/Config.in
comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)' else # HP_SIM
bool 'Support non-SCSI/IDE/ATAPI CDROM drives' CONFIG_CD_NO_IDESCSI
if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
source drivers/cdrom/Config.in
fi
endmenu
fi # !HP_SIM
#
# input before char - char/joystick depends on it. As does USB.
#
source drivers/input/Config.in
source drivers/char/Config.in
#source drivers/misc/Config.in
source drivers/media/Config.in
source fs/Config.in
if [ "$CONFIG_VT" = "y" ]; then
mainmenu_option next_comment mainmenu_option next_comment
comment 'Console drivers' comment 'Block devices'
bool 'VGA text console' CONFIG_VGA_CONSOLE tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
source drivers/video/Config.in dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET
if [ "$CONFIG_FB" = "y" ]; then
define_bool CONFIG_PCI_CONSOLE y tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
if [ "$CONFIG_BLK_DEV_RAM" = "y" -o "$CONFIG_BLK_DEV_RAM" = "m" ]; then
int ' Default RAM disk size' CONFIG_BLK_DEV_RAM_SIZE 4096
fi fi
endmenu endmenu
fi fi # HP_SIM
if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
mainmenu_option next_comment source fs/Config.in
comment 'Sound'
tristate 'Sound card support' CONFIG_SOUND
if [ "$CONFIG_SOUND" != "n" ]; then
source sound/Config.in
fi
endmenu
source drivers/usb/Config.in if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
if [ "$CONFIG_VT" = "y" ]; then
mainmenu_option next_comment
comment 'Console drivers'
bool 'VGA text console' CONFIG_VGA_CONSOLE
source drivers/video/Config.in
if [ "$CONFIG_FB" = "y" ]; then
define_bool CONFIG_PCI_CONSOLE y
fi
endmenu
fi
source lib/Config.in mainmenu_option next_comment
comment 'Sound'
source net/bluetooth/Config.in tristate 'Sound card support' CONFIG_SOUND
if [ "$CONFIG_SOUND" != "n" ]; then
source sound/Config.in
fi
endmenu
source drivers/usb/Config.in
source lib/Config.in
source net/bluetooth/Config.in
fi # !HP_SIM fi # !HP_SIM
if [ "$CONFIG_IA64_HP_SIM" != "n" -o "$CONFIG_IA64_GENERIC" != "n" ]; then if [ "$CONFIG_IA64_HP_SIM" != "n" -o "$CONFIG_IA64_GENERIC" != "n" ]; then
source arch/ia64/hp/Config.in source arch/ia64/hp/sim/Config.in
fi fi
mainmenu_option next_comment mainmenu_option next_comment
comment 'Kernel hacking' comment 'Kernel hacking'
...@@ -255,7 +245,14 @@ if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then ...@@ -255,7 +245,14 @@ if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then
bool ' Disable VHPT' CONFIG_DISABLE_VHPT bool ' Disable VHPT' CONFIG_DISABLE_VHPT
bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ
bool ' Early printk support (requires VGA!)' CONFIG_IA64_EARLY_PRINTK bool ' Early printk support' CONFIG_IA64_EARLY_PRINTK
if [ "$CONFIG_IA64_EARLY_PRINTK" != "n" ]; then
bool ' Early printk on MMIO serial port' CONFIG_IA64_EARLY_PRINTK_UART
if [ "$CONFIG_IA64_EARLY_PRINTK_UART" != "n" ]; then
hex ' UART MMIO base address' CONFIG_IA64_EARLY_PRINTK_UART_BASE ff5e0000
fi
bool ' Early printk on VGA' CONFIG_IA64_EARLY_PRINTK_VGA
fi
bool ' Debug memory allocations' CONFIG_DEBUG_SLAB bool ' Debug memory allocations' CONFIG_DEBUG_SLAB
bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK
bool ' Turn on compare-and-exchange bug checking (slow!)' CONFIG_IA64_DEBUG_CMPXCHG bool ' Turn on compare-and-exchange bug checking (slow!)' CONFIG_IA64_DEBUG_CMPXCHG
......
This diff is collapsed.
...@@ -30,12 +30,12 @@ static void simcons_write (struct console *, const char *, unsigned); ...@@ -30,12 +30,12 @@ static void simcons_write (struct console *, const char *, unsigned);
static kdev_t simcons_console_device (struct console *); static kdev_t simcons_console_device (struct console *);
struct console hpsim_cons = { struct console hpsim_cons = {
name: "simcons", .name = "simcons",
write: simcons_write, .write = simcons_write,
device: simcons_console_device, .device = simcons_console_device,
setup: simcons_init, .setup = simcons_init,
flags: CON_PRINTBUFFER, .flags = CON_PRINTBUFFER,
index: -1, .index = -1,
}; };
static int static int
......
...@@ -22,14 +22,14 @@ hpsim_irq_noop (unsigned int irq) ...@@ -22,14 +22,14 @@ hpsim_irq_noop (unsigned int irq)
} }
static struct hw_interrupt_type irq_type_hp_sim = { static struct hw_interrupt_type irq_type_hp_sim = {
typename: "hpsim", .typename = "hpsim",
startup: hpsim_irq_startup, .startup = hpsim_irq_startup,
shutdown: hpsim_irq_noop, .shutdown = hpsim_irq_noop,
enable: hpsim_irq_noop, .enable = hpsim_irq_noop,
disable: hpsim_irq_noop, .disable = hpsim_irq_noop,
ack: hpsim_irq_noop, .ack = hpsim_irq_noop,
end: hpsim_irq_noop, .end = hpsim_irq_noop,
set_affinity: (void (*)(unsigned int, unsigned long)) hpsim_irq_noop, .set_affinity = (void (*)(unsigned int, unsigned long)) hpsim_irq_noop,
}; };
void __init void __init
......
/* /*
* Platform dependent support for HP simulator. * Platform dependent support for HP simulator.
* *
* Copyright (C) 1998, 1999 Hewlett-Packard Co * Copyright (C) 1998, 1999, 2002 Hewlett-Packard Co
* Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com> * David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 1999 Vijay Chander <vijay@engr.sgi.com> * Copyright (C) 1999 Vijay Chander <vijay@engr.sgi.com>
*/ */
#include <linux/console.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/kdev_t.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/major.h>
#include <linux/param.h> #include <linux/param.h>
#include <linux/root_dev.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/kdev_t.h>
#include <linux/console.h>
#include <linux/root_dev.h>
#include <asm/delay.h> #include <asm/delay.h>
#include <asm/irq.h> #include <asm/irq.h>
...@@ -55,5 +56,5 @@ hpsim_setup (char **cmdline_p) ...@@ -55,5 +56,5 @@ hpsim_setup (char **cmdline_p)
{ {
ROOT_DEV = Root_SDA1; /* default to first SCSI drive */ ROOT_DEV = Root_SDA1; /* default to first SCSI drive */
register_console (&hpsim_cons); register_console(&hpsim_cons);
} }
...@@ -62,7 +62,9 @@ struct disk_stat { ...@@ -62,7 +62,9 @@ struct disk_stat {
extern long ia64_ssc (long arg0, long arg1, long arg2, long arg3, int nr); extern long ia64_ssc (long arg0, long arg1, long arg2, long arg3, int nr);
static int desc[8] = { -1, -1, -1, -1, -1, -1, -1, -1 }; static int desc[16] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};
static struct queue_entry { static struct queue_entry {
Scsi_Cmnd *sc; Scsi_Cmnd *sc;
...@@ -148,9 +150,9 @@ simscsi_biosparam (Disk *disk, struct block_device *n, int ip[]) ...@@ -148,9 +150,9 @@ simscsi_biosparam (Disk *disk, struct block_device *n, int ip[])
{ {
int size = disk->capacity; int size = disk->capacity;
ip[0] = 64; ip[0] = 64; /* heads */
ip[1] = 32; ip[1] = 32; /* sectors */
ip[2] = size >> 11; ip[2] = size >> 11; /* cylinders */
return 0; return 0;
} }
...@@ -229,6 +231,29 @@ simscsi_readwrite6 (Scsi_Cmnd *sc, int mode) ...@@ -229,6 +231,29 @@ simscsi_readwrite6 (Scsi_Cmnd *sc, int mode)
simscsi_readwrite(sc, mode, offset, sc->cmnd[4]*512); simscsi_readwrite(sc, mode, offset, sc->cmnd[4]*512);
} }
static size_t
simscsi_get_disk_size (int fd)
{
struct disk_stat stat;
size_t bit, sectors = 0;
struct disk_req req;
char buf[512];
/*
* This is a bit kludgey: the simulator doesn't provide a direct way of determining
* the disk size, so we do a binary search, assuming a maximum disk size of 4GB.
*/
for (bit = (4UL << 30)/512; bit != 0; bit >>= 1) {
req.addr = __pa(&buf);
req.len = sizeof(buf);
ia64_ssc(fd, 1, __pa(&req), ((sectors | bit) - 1)*512, SSC_READ);
stat.fd = fd;
ia64_ssc(__pa(&stat), 0, 0, 0, SSC_WAIT_COMPLETION);
if (stat.count == sizeof(buf))
sectors |= bit;
}
return sectors - 1; /* return last valid sector number */
}
static void static void
simscsi_readwrite10 (Scsi_Cmnd *sc, int mode) simscsi_readwrite10 (Scsi_Cmnd *sc, int mode)
...@@ -247,6 +272,7 @@ int ...@@ -247,6 +272,7 @@ int
simscsi_queuecommand (Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *)) simscsi_queuecommand (Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *))
{ {
char fname[MAX_ROOT_LEN+16]; char fname[MAX_ROOT_LEN+16];
size_t disk_size;
char *buf; char *buf;
#if DEBUG_SIMSCSI #if DEBUG_SIMSCSI
register long sp asm ("sp"); register long sp asm ("sp");
...@@ -258,15 +284,15 @@ simscsi_queuecommand (Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *)) ...@@ -258,15 +284,15 @@ simscsi_queuecommand (Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *))
sc->result = DID_BAD_TARGET << 16; sc->result = DID_BAD_TARGET << 16;
sc->scsi_done = done; sc->scsi_done = done;
if (sc->target <= 7 && sc->lun == 0) { if (sc->target <= 15 && sc->lun == 0) {
switch (sc->cmnd[0]) { switch (sc->cmnd[0]) {
case INQUIRY: case INQUIRY:
if (sc->request_bufflen < 35) { if (sc->request_bufflen < 35) {
break; break;
} }
sprintf (fname, "%s%c", simscsi_root, 'a' + sc->target); sprintf (fname, "%s%c", simscsi_root, 'a' + sc->target);
desc[sc->target] = ia64_ssc (__pa(fname), SSC_READ_ACCESS|SSC_WRITE_ACCESS, desc[sc->target] = ia64_ssc(__pa(fname), SSC_READ_ACCESS|SSC_WRITE_ACCESS,
0, 0, SSC_OPEN); 0, 0, SSC_OPEN);
if (desc[sc->target] < 0) { if (desc[sc->target] < 0) {
/* disk doesn't exist... */ /* disk doesn't exist... */
break; break;
...@@ -319,11 +345,13 @@ simscsi_queuecommand (Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *)) ...@@ -319,11 +345,13 @@ simscsi_queuecommand (Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *))
} }
buf = sc->request_buffer; buf = sc->request_buffer;
disk_size = simscsi_get_disk_size(desc[sc->target]);
/* pretend to be a 1GB disk (partition table contains real stuff): */ /* pretend to be a 1GB disk (partition table contains real stuff): */
buf[0] = 0x00; buf[0] = (disk_size >> 24) & 0xff;
buf[1] = 0x1f; buf[1] = (disk_size >> 16) & 0xff;
buf[2] = 0xff; buf[2] = (disk_size >> 8) & 0xff;
buf[3] = 0xff; buf[3] = (disk_size >> 0) & 0xff;
/* set block size of 512 bytes: */ /* set block size of 512 bytes: */
buf[4] = 0; buf[4] = 0;
buf[5] = 0; buf[5] = 0;
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
* *
* 02/04/00 D. Mosberger Merged in serial.c bug fixes in rs_close(). * 02/04/00 D. Mosberger Merged in serial.c bug fixes in rs_close().
* 02/25/00 D. Mosberger Synced up with 2.3.99pre-5 version of serial.c. * 02/25/00 D. Mosberger Synced up with 2.3.99pre-5 version of serial.c.
* 07/30/02 D. Mosberger Replace sti()/cli() with explicit spinlocks & local irq masking
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -31,6 +32,7 @@ ...@@ -31,6 +32,7 @@
#include <linux/serialP.h> #include <linux/serialP.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/hw_irq.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#ifdef CONFIG_KDB #ifdef CONFIG_KDB
...@@ -61,6 +63,7 @@ extern void ia64_ssc_connect_irq (long intr, long irq); ...@@ -61,6 +63,7 @@ extern void ia64_ssc_connect_irq (long intr, long irq);
static char *serial_name = "SimSerial driver"; static char *serial_name = "SimSerial driver";
static char *serial_version = "0.6"; static char *serial_version = "0.6";
static spinlock_t serial_lock = SPIN_LOCK_UNLOCKED;
/* /*
* This has been extracted from asm/serial.h. We need one eventually but * This has been extracted from asm/serial.h. We need one eventually but
...@@ -232,14 +235,14 @@ static void rs_put_char(struct tty_struct *tty, unsigned char ch) ...@@ -232,14 +235,14 @@ static void rs_put_char(struct tty_struct *tty, unsigned char ch)
if (!tty || !info->xmit.buf) return; if (!tty || !info->xmit.buf) return;
save_flags(flags); cli(); spin_lock_irqsave(&serial_lock, flags);
if (CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) == 0) { if (CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) == 0) {
restore_flags(flags); spin_unlock_irqrestore(&serial_lock, flags);
return; return;
} }
info->xmit.buf[info->xmit.head] = ch; info->xmit.buf[info->xmit.head] = ch;
info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1); info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1);
restore_flags(flags); spin_unlock_irqrestore(&serial_lock, flags);
} }
static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done) static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done)
...@@ -247,7 +250,7 @@ static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done) ...@@ -247,7 +250,7 @@ static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done)
int count; int count;
unsigned long flags; unsigned long flags;
save_flags(flags); cli(); spin_lock_irqsave(&serial_lock, flags);
if (info->x_char) { if (info->x_char) {
char c = info->x_char; char c = info->x_char;
...@@ -290,7 +293,7 @@ static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done) ...@@ -290,7 +293,7 @@ static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done)
info->xmit.tail += count; info->xmit.tail += count;
} }
out: out:
restore_flags(flags); spin_unlock_irqrestore(&serial_lock, flags);
} }
static void rs_flush_chars(struct tty_struct *tty) static void rs_flush_chars(struct tty_struct *tty)
...@@ -314,7 +317,6 @@ static int rs_write(struct tty_struct * tty, int from_user, ...@@ -314,7 +317,6 @@ static int rs_write(struct tty_struct * tty, int from_user,
if (!tty || !info->xmit.buf || !tmp_buf) return 0; if (!tty || !info->xmit.buf || !tmp_buf) return 0;
save_flags(flags);
if (from_user) { if (from_user) {
down(&tmp_buf_sem); down(&tmp_buf_sem);
while (1) { while (1) {
...@@ -331,21 +333,26 @@ static int rs_write(struct tty_struct * tty, int from_user, ...@@ -331,21 +333,26 @@ static int rs_write(struct tty_struct * tty, int from_user,
ret = -EFAULT; ret = -EFAULT;
break; break;
} }
cli();
c1 = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); spin_lock_irqsave(&serial_lock, flags);
if (c1 < c) {
c = c1; c1 = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail,
memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c); SERIAL_XMIT_SIZE);
info->xmit.head = ((info->xmit.head + c) & if (c1 < c)
(SERIAL_XMIT_SIZE-1)); c = c1;
restore_flags(flags); memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c);
info->xmit.head = ((info->xmit.head + c) &
(SERIAL_XMIT_SIZE-1));
}
spin_unlock_irqrestore(&serial_lock, flags);
buf += c; buf += c;
count -= c; count -= c;
ret += c; ret += c;
} }
up(&tmp_buf_sem); up(&tmp_buf_sem);
} else { } else {
cli(); spin_lock_irqsave(&serial_lock, flags);
while (1) { while (1) {
c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
if (count < c) if (count < c)
...@@ -360,7 +367,7 @@ static int rs_write(struct tty_struct * tty, int from_user, ...@@ -360,7 +367,7 @@ static int rs_write(struct tty_struct * tty, int from_user,
count -= c; count -= c;
ret += c; ret += c;
} }
restore_flags(flags); spin_unlock_irqrestore(&serial_lock, flags);
} }
/* /*
* Hey, we transmit directly from here in our case * Hey, we transmit directly from here in our case
...@@ -391,9 +398,9 @@ static void rs_flush_buffer(struct tty_struct *tty) ...@@ -391,9 +398,9 @@ static void rs_flush_buffer(struct tty_struct *tty)
struct async_struct *info = (struct async_struct *)tty->driver_data; struct async_struct *info = (struct async_struct *)tty->driver_data;
unsigned long flags; unsigned long flags;
save_flags(flags); cli(); spin_lock_irqsave(&serial_lock, flags);
info->xmit.head = info->xmit.tail = 0; info->xmit.head = info->xmit.tail = 0;
restore_flags(flags); spin_unlock_irqrestore(&serial_lock, flags);
wake_up_interruptible(&tty->write_wait); wake_up_interruptible(&tty->write_wait);
...@@ -566,44 +573,45 @@ static void shutdown(struct async_struct * info) ...@@ -566,44 +573,45 @@ static void shutdown(struct async_struct * info)
state->irq); state->irq);
#endif #endif
save_flags(flags); cli(); /* Disable interrupts */ spin_lock_irqsave(&serial_lock, flags);
{
/*
* First unlink the serial port from the IRQ chain...
*/
if (info->next_port)
info->next_port->prev_port = info->prev_port;
if (info->prev_port)
info->prev_port->next_port = info->next_port;
else
IRQ_ports[state->irq] = info->next_port;
/* /*
* First unlink the serial port from the IRQ chain... * Free the IRQ, if necessary
*/ */
if (info->next_port) if (state->irq && (!IRQ_ports[state->irq] ||
info->next_port->prev_port = info->prev_port; !IRQ_ports[state->irq]->next_port)) {
if (info->prev_port) if (IRQ_ports[state->irq]) {
info->prev_port->next_port = info->next_port; free_irq(state->irq, NULL);
else retval = request_irq(state->irq, rs_interrupt_single,
IRQ_ports[state->irq] = info->next_port; IRQ_T(info), "serial", NULL);
if (retval)
printk("serial shutdown: request_irq: error %d"
" Couldn't reacquire IRQ.\n", retval);
} else
free_irq(state->irq, NULL);
}
/* if (info->xmit.buf) {
* Free the IRQ, if necessary free_page((unsigned long) info->xmit.buf);
*/ info->xmit.buf = 0;
if (state->irq && (!IRQ_ports[state->irq] || }
!IRQ_ports[state->irq]->next_port)) {
if (IRQ_ports[state->irq]) {
free_irq(state->irq, NULL);
retval = request_irq(state->irq, rs_interrupt_single,
IRQ_T(info), "serial", NULL);
if (retval) if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags);
printk("serial shutdown: request_irq: error %d"
" Couldn't reacquire IRQ.\n", retval);
} else
free_irq(state->irq, NULL);
}
if (info->xmit.buf) { info->flags &= ~ASYNC_INITIALIZED;
free_page((unsigned long) info->xmit.buf);
info->xmit.buf = 0;
} }
spin_unlock_irqrestore(&serial_lock, flags);
if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags);
info->flags &= ~ASYNC_INITIALIZED;
restore_flags(flags);
} }
/* /*
...@@ -626,14 +634,13 @@ static void rs_close(struct tty_struct *tty, struct file * filp) ...@@ -626,14 +634,13 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
state = info->state; state = info->state;
save_flags(flags); cli(); spin_lock_irqsave(&serial_lock, flags);
if (tty_hung_up_p(filp)) { if (tty_hung_up_p(filp)) {
#ifdef SIMSERIAL_DEBUG #ifdef SIMSERIAL_DEBUG
printk("rs_close: hung_up\n"); printk("rs_close: hung_up\n");
#endif #endif
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
restore_flags(flags); spin_unlock_irqrestore(&serial_lock, flags);
return; return;
} }
#ifdef SIMSERIAL_DEBUG #ifdef SIMSERIAL_DEBUG
...@@ -658,11 +665,11 @@ static void rs_close(struct tty_struct *tty, struct file * filp) ...@@ -658,11 +665,11 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
} }
if (state->count) { if (state->count) {
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
restore_flags(flags); spin_unlock_irqrestore(&serial_lock, flags);
return; return;
} }
info->flags |= ASYNC_CLOSING; info->flags |= ASYNC_CLOSING;
restore_flags(flags); spin_unlock_irqrestore(&serial_lock, flags);
/* /*
* Now we wait for the transmit buffer to clear; and we notify * Now we wait for the transmit buffer to clear; and we notify
...@@ -770,7 +777,7 @@ startup(struct async_struct *info) ...@@ -770,7 +777,7 @@ startup(struct async_struct *info)
if (!page) if (!page)
return -ENOMEM; return -ENOMEM;
save_flags(flags); cli(); spin_lock_irqsave(&serial_lock, flags);
if (info->flags & ASYNC_INITIALIZED) { if (info->flags & ASYNC_INITIALIZED) {
free_page(page); free_page(page);
...@@ -851,11 +858,11 @@ startup(struct async_struct *info) ...@@ -851,11 +858,11 @@ startup(struct async_struct *info)
} }
info->flags |= ASYNC_INITIALIZED; info->flags |= ASYNC_INITIALIZED;
restore_flags(flags); spin_unlock_irqrestore(&serial_lock, flags);
return 0; return 0;
errout: errout:
restore_flags(flags); spin_unlock_irqrestore(&serial_lock, flags);
return retval; return retval;
} }
......
#define MACHVEC_PLATFORM_NAME hpzx1 #define MACHVEC_PLATFORM_NAME hpzx1
#include <asm/machvec_init.h> #include <asm/machvec_init.h>
#define MACHVEC_PLATFORM_NAME hpzx1
#include <asm/machvec_init.h>
This diff is collapsed.
...@@ -67,7 +67,7 @@ ia32_install_shared_page (struct vm_area_struct *vma, unsigned long address, int ...@@ -67,7 +67,7 @@ ia32_install_shared_page (struct vm_area_struct *vma, unsigned long address, int
} }
static struct vm_operations_struct ia32_shared_page_vm_ops = { static struct vm_operations_struct ia32_shared_page_vm_ops = {
nopage: ia32_install_shared_page .nopage =ia32_install_shared_page
}; };
void void
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#include <asm/ia32.h> #include <asm/ia32.h>
#include <../drivers/char/drm/drm.h> #include <../drivers/char/drm/drm.h>
#include <../drivers/char/drm/mga_drm.h>
#include <../drivers/char/drm/i810_drm.h>
#define IOCTL_NR(a) ((a) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) #define IOCTL_NR(a) ((a) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
......
This diff is collapsed.
...@@ -125,9 +125,79 @@ efi_gettimeofday (struct timeval *tv) ...@@ -125,9 +125,79 @@ efi_gettimeofday (struct timeval *tv)
tv->tv_usec = tm.nanosecond / 1000; tv->tv_usec = tm.nanosecond / 1000;
} }
static int
is_available_memory (efi_memory_desc_t *md)
{
if (!(md->attribute & EFI_MEMORY_WB))
return 0;
switch (md->type) {
case EFI_LOADER_CODE:
case EFI_LOADER_DATA:
case EFI_BOOT_SERVICES_CODE:
case EFI_BOOT_SERVICES_DATA:
case EFI_CONVENTIONAL_MEMORY:
return 1;
}
return 0;
}
/*
* Trim descriptor MD so its starts at address START_ADDR. If the descriptor covers
* memory that is normally available to the kernel, issue a warning that some memory
* is being ignored.
*/
static void
trim_bottom (efi_memory_desc_t *md, u64 start_addr)
{
u64 num_skipped_pages;
if (md->phys_addr >= start_addr || !md->num_pages)
return;
num_skipped_pages = (start_addr - md->phys_addr) >> EFI_PAGE_SHIFT;
if (num_skipped_pages > md->num_pages)
num_skipped_pages = md->num_pages;
if (is_available_memory(md))
printk(KERN_NOTICE "efi.%s: ignoring %luKB of memory at 0x%lx due to granule hole "
"at 0x%lx\n", __FUNCTION__,
(num_skipped_pages << EFI_PAGE_SHIFT) >> 10,
md->phys_addr, start_addr - IA64_GRANULE_SIZE);
/*
* NOTE: Don't set md->phys_addr to START_ADDR because that could cause the memory
* descriptor list to become unsorted. In such a case, md->num_pages will be
* zero, so the Right Thing will happen.
*/
md->phys_addr += num_skipped_pages << EFI_PAGE_SHIFT;
md->num_pages -= num_skipped_pages;
}
static void
trim_top (efi_memory_desc_t *md, u64 end_addr)
{
u64 num_dropped_pages, md_end_addr;
md_end_addr = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
if (md_end_addr <= end_addr || !md->num_pages)
return;
num_dropped_pages = (md_end_addr - end_addr) >> EFI_PAGE_SHIFT;
if (num_dropped_pages > md->num_pages)
num_dropped_pages = md->num_pages;
if (is_available_memory(md))
printk(KERN_NOTICE "efi.%s: ignoring %luKB of memory at 0x%lx due to granule hole "
"at 0x%lx\n", __FUNCTION__,
(num_dropped_pages << EFI_PAGE_SHIFT) >> 10,
md->phys_addr, end_addr);
md->num_pages -= num_dropped_pages;
}
/* /*
* Walks the EFI memory map and calls CALLBACK once for each EFI * Walks the EFI memory map and calls CALLBACK once for each EFI memory descriptor that
* memory descriptor that has memory that is available for OS use. * has memory that is available for OS use.
*/ */
void void
efi_memmap_walk (efi_freemem_callback_t callback, void *arg) efi_memmap_walk (efi_freemem_callback_t callback, void *arg)
...@@ -137,9 +207,9 @@ efi_memmap_walk (efi_freemem_callback_t callback, void *arg) ...@@ -137,9 +207,9 @@ efi_memmap_walk (efi_freemem_callback_t callback, void *arg)
u64 start; u64 start;
u64 end; u64 end;
} prev, curr; } prev, curr;
void *efi_map_start, *efi_map_end, *p; void *efi_map_start, *efi_map_end, *p, *q;
efi_memory_desc_t *md; efi_memory_desc_t *md, *check_md;
u64 efi_desc_size, start, end; u64 efi_desc_size, start, end, granule_addr, first_non_wb_addr = 0;
efi_map_start = __va(ia64_boot_param->efi_memmap); efi_map_start = __va(ia64_boot_param->efi_memmap);
efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
...@@ -147,24 +217,56 @@ efi_memmap_walk (efi_freemem_callback_t callback, void *arg) ...@@ -147,24 +217,56 @@ efi_memmap_walk (efi_freemem_callback_t callback, void *arg)
for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
md = p; md = p;
switch (md->type) {
case EFI_LOADER_CODE: /* skip over non-WB memory descriptors; that's all we're interested in... */
case EFI_LOADER_DATA: if (!(md->attribute & EFI_MEMORY_WB))
case EFI_BOOT_SERVICES_CODE: continue;
case EFI_BOOT_SERVICES_DATA:
case EFI_CONVENTIONAL_MEMORY: if (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) > first_non_wb_addr) {
if (!(md->attribute & EFI_MEMORY_WB)) /*
continue; * Search for the next run of contiguous WB memory. Start search
* at first granule boundary covered by md.
*/
granule_addr = ((md->phys_addr + IA64_GRANULE_SIZE - 1)
& -IA64_GRANULE_SIZE);
first_non_wb_addr = granule_addr;
for (q = p; q < efi_map_end; q += efi_desc_size) {
check_md = q;
if (check_md->attribute & EFI_MEMORY_WB)
trim_bottom(md, granule_addr);
if (check_md->phys_addr < granule_addr)
continue;
if (!(check_md->attribute & EFI_MEMORY_WB))
break; /* hit a non-WB region; stop search */
if (check_md->phys_addr != first_non_wb_addr)
break; /* hit a memory hole; stop search */
first_non_wb_addr += check_md->num_pages << EFI_PAGE_SHIFT;
}
/* round it down to the previous granule-boundary: */
first_non_wb_addr &= -IA64_GRANULE_SIZE;
if (!(first_non_wb_addr > granule_addr))
continue; /* couldn't find enough contiguous memory */
}
/* BUG_ON((md->phys_addr >> IA64_GRANULE_SHIFT) < first_non_wb_addr); */
trim_top(md, first_non_wb_addr);
if (is_available_memory(md)) {
if (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) > mem_limit) { if (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) > mem_limit) {
if (md->phys_addr > mem_limit) if (md->phys_addr > mem_limit)
continue; continue;
md->num_pages = (mem_limit - md->phys_addr) >> EFI_PAGE_SHIFT; md->num_pages = (mem_limit - md->phys_addr) >> EFI_PAGE_SHIFT;
} }
if (md->num_pages == 0) {
printk("efi_memmap_walk: ignoring empty region at 0x%lx", if (md->num_pages == 0)
md->phys_addr);
continue; continue;
}
curr.start = PAGE_OFFSET + md->phys_addr; curr.start = PAGE_OFFSET + md->phys_addr;
curr.end = curr.start + (md->num_pages << EFI_PAGE_SHIFT); curr.end = curr.start + (md->num_pages << EFI_PAGE_SHIFT);
...@@ -187,10 +289,6 @@ efi_memmap_walk (efi_freemem_callback_t callback, void *arg) ...@@ -187,10 +289,6 @@ efi_memmap_walk (efi_freemem_callback_t callback, void *arg)
prev = curr; prev = curr;
} }
} }
break;
default:
continue;
} }
} }
if (prev_valid) { if (prev_valid) {
...@@ -268,8 +366,9 @@ efi_map_pal_code (void) ...@@ -268,8 +366,9 @@ efi_map_pal_code (void)
*/ */
psr = ia64_clear_ic(); psr = ia64_clear_ic();
ia64_itr(0x1, IA64_TR_PALCODE, vaddr & mask, ia64_itr(0x1, IA64_TR_PALCODE, vaddr & mask,
pte_val(pfn_pte(md->phys_addr >> PAGE_SHIFT, PAGE_KERNEL)), IA64_GRANULE_SHIFT); pte_val(pfn_pte(md->phys_addr >> PAGE_SHIFT, PAGE_KERNEL)),
ia64_set_psr(psr); IA64_GRANULE_SHIFT);
ia64_set_psr(psr); /* restore psr */
ia64_srlz_i(); ia64_srlz_i();
} }
} }
...@@ -347,6 +446,9 @@ efi_init (void) ...@@ -347,6 +446,9 @@ efi_init (void)
} else if (efi_guidcmp(config_tables[i].guid, SAL_SYSTEM_TABLE_GUID) == 0) { } else if (efi_guidcmp(config_tables[i].guid, SAL_SYSTEM_TABLE_GUID) == 0) {
efi.sal_systab = __va(config_tables[i].table); efi.sal_systab = __va(config_tables[i].table);
printk(" SALsystab=0x%lx", config_tables[i].table); printk(" SALsystab=0x%lx", config_tables[i].table);
} else if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) {
efi.hcdp = __va(config_tables[i].table);
printk(" HCDP=0x%lx", config_tables[i].table);
} }
} }
printk("\n"); printk("\n");
...@@ -376,7 +478,7 @@ efi_init (void) ...@@ -376,7 +478,7 @@ efi_init (void)
md = p; md = p;
printk("mem%02u: type=%u, attr=0x%lx, range=[0x%016lx-0x%016lx) (%luMB)\n", printk("mem%02u: type=%u, attr=0x%lx, range=[0x%016lx-0x%016lx) (%luMB)\n",
i, md->type, md->attribute, md->phys_addr, i, md->type, md->attribute, md->phys_addr,
md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1, md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT),
md->num_pages >> (20 - EFI_PAGE_SHIFT)); md->num_pages >> (20 - EFI_PAGE_SHIFT));
} }
} }
......
...@@ -175,6 +175,7 @@ GLOBAL_ENTRY(ia64_switch_to) ...@@ -175,6 +175,7 @@ GLOBAL_ENTRY(ia64_switch_to)
(p6) srlz.d (p6) srlz.d
ld8 sp=[r21] // load kernel stack pointer of new task ld8 sp=[r21] // load kernel stack pointer of new task
mov IA64_KR(CURRENT)=r20 // update "current" application register mov IA64_KR(CURRENT)=r20 // update "current" application register
mov r8=r13 // return pointer to previously running task
mov r13=in0 // set "current" pointer mov r13=in0 // set "current" pointer
;; ;;
DO_LOAD_SWITCH_STACK DO_LOAD_SWITCH_STACK
......
...@@ -88,12 +88,6 @@ EXPORT_SYMBOL(ia64_cpu_to_sapicid); ...@@ -88,12 +88,6 @@ EXPORT_SYMBOL(ia64_cpu_to_sapicid);
#include <asm/smplock.h> #include <asm/smplock.h>
EXPORT_SYMBOL(kernel_flag); EXPORT_SYMBOL(kernel_flag);
/* #include <asm/system.h> */
EXPORT_SYMBOL(__global_sti);
EXPORT_SYMBOL(__global_cli);
EXPORT_SYMBOL(__global_save_flags);
EXPORT_SYMBOL(__global_restore_flags);
#else /* !CONFIG_SMP */ #else /* !CONFIG_SMP */
EXPORT_SYMBOL(__flush_tlb_all); EXPORT_SYMBOL(__flush_tlb_all);
......
...@@ -34,8 +34,8 @@ union init_thread { ...@@ -34,8 +34,8 @@ union init_thread {
} s; } s;
unsigned long stack[KERNEL_STACK_SIZE/sizeof (unsigned long)]; unsigned long stack[KERNEL_STACK_SIZE/sizeof (unsigned long)];
} init_thread_union __attribute__((section(".data.init_task"))) = {{ } init_thread_union __attribute__((section(".data.init_task"))) = {{
task: INIT_TASK(init_thread_union.s.task), .task = INIT_TASK(init_thread_union.s.task),
thread_info: INIT_THREAD_INFO(init_thread_union.s.thread_info) .thread_info = INIT_THREAD_INFO(init_thread_union.s.thread_info)
}}; }};
asm (".global init_task; init_task = init_thread_union"); asm (".global init_task; init_task = init_thread_union");
...@@ -88,7 +88,7 @@ static struct { ...@@ -88,7 +88,7 @@ static struct {
static struct iosapic_irq { static struct iosapic_irq {
char *addr; /* base address of IOSAPIC */ char *addr; /* base address of IOSAPIC */
unsigned char base_irq; /* first irq assigned to this IOSAPIC */ unsigned int base_irq; /* first irq assigned to this IOSAPIC */
char pin; /* IOSAPIC pin (-1 => not an IOSAPIC irq) */ char pin; /* IOSAPIC pin (-1 => not an IOSAPIC irq) */
unsigned char dmode : 3; /* delivery mode (see iosapic.h) */ unsigned char dmode : 3; /* delivery mode (see iosapic.h) */
unsigned char polarity : 1; /* interrupt polarity (see iosapic.h) */ unsigned char polarity : 1; /* interrupt polarity (see iosapic.h) */
...@@ -97,9 +97,9 @@ static struct iosapic_irq { ...@@ -97,9 +97,9 @@ static struct iosapic_irq {
static struct iosapic { static struct iosapic {
char *addr; /* base address of IOSAPIC */ char *addr; /* base address of IOSAPIC */
unsigned char pcat_compat; /* 8259 compatibility flag */ unsigned int base_irq; /* first irq assigned to this IOSAPIC */
unsigned char base_irq; /* first irq assigned to this IOSAPIC */
unsigned short max_pin; /* max input pin supported in this IOSAPIC */ unsigned short max_pin; /* max input pin supported in this IOSAPIC */
unsigned char pcat_compat; /* 8259 compatibility flag */
} iosapic_lists[256] __initdata; } iosapic_lists[256] __initdata;
static int num_iosapic = 0; static int num_iosapic = 0;
...@@ -160,6 +160,10 @@ set_rte (unsigned int vector, unsigned long dest) ...@@ -160,6 +160,10 @@ set_rte (unsigned int vector, unsigned long dest)
int pin; int pin;
char redir; char redir;
#ifdef DEBUG_IRQ_ROUTING
printk(KERN_DEBUG "set_rte: routing vector 0x%02x to 0x%lx\n", vector, dest);
#endif
pin = iosapic_irq[vector].pin; pin = iosapic_irq[vector].pin;
if (pin < 0) if (pin < 0)
return; /* not an IOSAPIC interrupt */ return; /* not an IOSAPIC interrupt */
...@@ -322,14 +326,14 @@ iosapic_end_level_irq (unsigned int irq) ...@@ -322,14 +326,14 @@ iosapic_end_level_irq (unsigned int irq)
#define iosapic_ack_level_irq nop #define iosapic_ack_level_irq nop
struct hw_interrupt_type irq_type_iosapic_level = { struct hw_interrupt_type irq_type_iosapic_level = {
typename: "IO-SAPIC-level", .typename = "IO-SAPIC-level",
startup: iosapic_startup_level_irq, .startup = iosapic_startup_level_irq,
shutdown: iosapic_shutdown_level_irq, .shutdown = iosapic_shutdown_level_irq,
enable: iosapic_enable_level_irq, .enable = iosapic_enable_level_irq,
disable: iosapic_disable_level_irq, .disable = iosapic_disable_level_irq,
ack: iosapic_ack_level_irq, .ack = iosapic_ack_level_irq,
end: iosapic_end_level_irq, .end = iosapic_end_level_irq,
set_affinity: iosapic_set_affinity .set_affinity = iosapic_set_affinity
}; };
/* /*
...@@ -366,14 +370,14 @@ iosapic_ack_edge_irq (unsigned int irq) ...@@ -366,14 +370,14 @@ iosapic_ack_edge_irq (unsigned int irq)
#define iosapic_end_edge_irq nop #define iosapic_end_edge_irq nop
struct hw_interrupt_type irq_type_iosapic_edge = { struct hw_interrupt_type irq_type_iosapic_edge = {
typename: "IO-SAPIC-edge", .typename = "IO-SAPIC-edge",
startup: iosapic_startup_edge_irq, .startup = iosapic_startup_edge_irq,
shutdown: iosapic_disable_edge_irq, .shutdown = iosapic_disable_edge_irq,
enable: iosapic_enable_edge_irq, .enable = iosapic_enable_edge_irq,
disable: iosapic_disable_edge_irq, .disable = iosapic_disable_edge_irq,
ack: iosapic_ack_edge_irq, .ack = iosapic_ack_edge_irq,
end: iosapic_end_edge_irq, .end = iosapic_end_edge_irq,
set_affinity: iosapic_set_affinity .set_affinity = iosapic_set_affinity
}; };
unsigned int unsigned int
...@@ -406,7 +410,7 @@ iosapic_reassign_vector (int vector) ...@@ -406,7 +410,7 @@ iosapic_reassign_vector (int vector)
|| iosapic_irq[vector].polarity || iosapic_irq[vector].trigger) || iosapic_irq[vector].polarity || iosapic_irq[vector].trigger)
{ {
new_vector = ia64_alloc_irq(); new_vector = ia64_alloc_irq();
printk("Reassigning Vector 0x%x to 0x%x\n", vector, new_vector); printk("Reassigning vector 0x%x to 0x%x\n", vector, new_vector);
memcpy (&iosapic_irq[new_vector], &iosapic_irq[vector], memcpy (&iosapic_irq[new_vector], &iosapic_irq[vector],
sizeof(struct iosapic_irq)); sizeof(struct iosapic_irq));
memset (&iosapic_irq[vector], 0, sizeof(struct iosapic_irq)); memset (&iosapic_irq[vector], 0, sizeof(struct iosapic_irq));
...@@ -422,6 +426,7 @@ register_irq (u32 global_vector, int vector, int pin, unsigned char delivery, ...@@ -422,6 +426,7 @@ register_irq (u32 global_vector, int vector, int pin, unsigned char delivery,
irq_desc_t *idesc; irq_desc_t *idesc;
struct hw_interrupt_type *irq_type; struct hw_interrupt_type *irq_type;
gsi_to_vector(global_vector) = vector;
iosapic_irq[vector].pin = pin; iosapic_irq[vector].pin = pin;
iosapic_irq[vector].polarity = polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW; iosapic_irq[vector].polarity = polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW;
iosapic_irq[vector].dmode = delivery; iosapic_irq[vector].dmode = delivery;
...@@ -640,7 +645,7 @@ iosapic_init_pci_irq (void) ...@@ -640,7 +645,7 @@ iosapic_init_pci_irq (void)
unsigned int irq; unsigned int irq;
char *addr; char *addr;
if (0 != acpi_get_prt(&pci_irq.route, &pci_irq.num_routes)) if (acpi_get_prt(&pci_irq.route, &pci_irq.num_routes))
return; return;
for (i = 0; i < pci_irq.num_routes; i++) { for (i = 0; i < pci_irq.num_routes; i++) {
...@@ -679,11 +684,10 @@ iosapic_init_pci_irq (void) ...@@ -679,11 +684,10 @@ iosapic_init_pci_irq (void)
pci_irq.route[i].bus, pci_irq.route[i].pci_id>>16, pci_irq.route[i].pin, pci_irq.route[i].bus, pci_irq.route[i].pci_id>>16, pci_irq.route[i].pin,
iosapic_irq[vector].base_irq + iosapic_irq[vector].pin, vector); iosapic_irq[vector].base_irq + iosapic_irq[vector].pin, vector);
#endif #endif
/* /*
* Forget not to program the IOSAPIC RTE per ACPI _PRT * NOTE: The IOSAPIC RTE will be programmed in iosapic_pci_fixup(). It
* needs to be done there to ensure PCI hotplug works right.
*/ */
set_rte(vector, (ia64_get_lid() >> 16) & 0xffff);
} }
} }
...@@ -757,10 +761,11 @@ iosapic_pci_fixup (int phase) ...@@ -757,10 +761,11 @@ iosapic_pci_fixup (int phase)
if (!(smp_int_redirect & SMP_IRQ_REDIRECTION)) { if (!(smp_int_redirect & SMP_IRQ_REDIRECTION)) {
static int cpu_index = 0; static int cpu_index = 0;
set_rte(vector, cpu_physical_id(cpu_index) & 0xffff); while (!cpu_online(cpu_index))
if (++cpu_index >= NR_CPUS)
cpu_index = 0;
for (cpu_index++; !cpu_online(cpu_index % NR_CPUS); cpu_index++); set_rte(vector, cpu_physical_id(cpu_index) & 0xffff);
cpu_index %= NR_CPUS;
} else { } else {
/* /*
* Direct the interrupt vector to the current cpu, * Direct the interrupt vector to the current cpu,
......
This diff is collapsed.
...@@ -36,6 +36,10 @@ ...@@ -36,6 +36,10 @@
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/system.h> #include <asm/system.h>
#ifdef CONFIG_PERFMON
# include <asm/perfmon.h>
#endif
#define IRQ_DEBUG 0 #define IRQ_DEBUG 0
/* default base addr of IPI table */ /* default base addr of IPI table */
...@@ -50,6 +54,11 @@ __u8 isa_irq_to_vector_map[16] = { ...@@ -50,6 +54,11 @@ __u8 isa_irq_to_vector_map[16] = {
0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21
}; };
/*
* GSI to IA-64 vector translation table.
*/
__u8 gsi_to_vector_map[255];
int int
ia64_alloc_irq (void) ia64_alloc_irq (void)
{ {
...@@ -144,9 +153,9 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs) ...@@ -144,9 +153,9 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs)
extern void handle_IPI (int irq, void *dev_id, struct pt_regs *regs); extern void handle_IPI (int irq, void *dev_id, struct pt_regs *regs);
static struct irqaction ipi_irqaction = { static struct irqaction ipi_irqaction = {
handler: handle_IPI, .handler = handle_IPI,
flags: SA_INTERRUPT, .flags = SA_INTERRUPT,
name: "IPI" .name = "IPI"
}; };
#endif #endif
...@@ -172,6 +181,9 @@ init_IRQ (void) ...@@ -172,6 +181,9 @@ init_IRQ (void)
register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL); register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
register_percpu_irq(IA64_IPI_VECTOR, &ipi_irqaction); register_percpu_irq(IA64_IPI_VECTOR, &ipi_irqaction);
#endif
#ifdef CONFIG_PERFMON
perfmon_init_percpu();
#endif #endif
platform_irq_init(); platform_irq_init();
} }
......
...@@ -27,12 +27,12 @@ lsapic_noop (unsigned int irq) ...@@ -27,12 +27,12 @@ lsapic_noop (unsigned int irq)
} }
struct hw_interrupt_type irq_type_ia64_lsapic = { struct hw_interrupt_type irq_type_ia64_lsapic = {
typename: "LSAPIC", .typename = "LSAPIC",
startup: lsapic_noop_startup, .startup = lsapic_noop_startup,
shutdown: lsapic_noop, .shutdown = lsapic_noop,
enable: lsapic_noop, .enable = lsapic_noop,
disable: lsapic_noop, .disable = lsapic_noop,
ack: lsapic_noop, .ack = lsapic_noop,
end: lsapic_noop, .end = lsapic_noop,
set_affinity: (void (*)(unsigned int, unsigned long)) lsapic_noop .set_affinity = (void (*)(unsigned int, unsigned long)) lsapic_noop
}; };
...@@ -11,13 +11,16 @@ ...@@ -11,13 +11,16 @@
struct ia64_machine_vector ia64_mv; struct ia64_machine_vector ia64_mv;
/* /*
* Most platforms use this routine for mapping page frame addresses * Most platforms use this routine for mapping page frame addresses into a memory map
* into a memory map index. * index.
*
* Note: we can't use __pa() because map_nr_dense(X) MUST map to something >= max_mapnr if
* X is outside the identity mapped kernel space.
*/ */
unsigned long unsigned long
map_nr_dense (unsigned long addr) map_nr_dense (unsigned long addr)
{ {
return MAP_NR_DENSE(addr); return (addr - PAGE_OFFSET) >> PAGE_SHIFT;
} }
static struct ia64_machine_vector * static struct ia64_machine_vector *
......
...@@ -82,27 +82,27 @@ extern void ia64_slave_init_handler (void); ...@@ -82,27 +82,27 @@ extern void ia64_slave_init_handler (void);
extern struct hw_interrupt_type irq_type_iosapic_level; extern struct hw_interrupt_type irq_type_iosapic_level;
static struct irqaction cmci_irqaction = { static struct irqaction cmci_irqaction = {
handler: ia64_mca_cmc_int_handler, .handler = ia64_mca_cmc_int_handler,
flags: SA_INTERRUPT, .flags = SA_INTERRUPT,
name: "cmc_hndlr" .name = "cmc_hndlr"
}; };
static struct irqaction mca_rdzv_irqaction = { static struct irqaction mca_rdzv_irqaction = {
handler: ia64_mca_rendez_int_handler, .handler = ia64_mca_rendez_int_handler,
flags: SA_INTERRUPT, .flags = SA_INTERRUPT,
name: "mca_rdzv" .name = "mca_rdzv"
}; };
static struct irqaction mca_wkup_irqaction = { static struct irqaction mca_wkup_irqaction = {
handler: ia64_mca_wakeup_int_handler, .handler = ia64_mca_wakeup_int_handler,
flags: SA_INTERRUPT, .flags = SA_INTERRUPT,
name: "mca_wkup" .name = "mca_wkup"
}; };
static struct irqaction mca_cpe_irqaction = { static struct irqaction mca_cpe_irqaction = {
handler: ia64_mca_cpe_int_handler, .handler = ia64_mca_cpe_int_handler,
flags: SA_INTERRUPT, .flags = SA_INTERRUPT,
name: "cpe_hndlr" .name = "cpe_hndlr"
}; };
/* /*
...@@ -626,9 +626,12 @@ ia64_mca_wakeup_all(void) ...@@ -626,9 +626,12 @@ ia64_mca_wakeup_all(void)
void void
ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *ptregs) ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *ptregs)
{ {
int flags, cpu = 0; unsigned long flags;
int cpu = 0;
/* Mask all interrupts */ /* Mask all interrupts */
save_and_cli(flags); #warning XXX fix me: this used to be: save_and_cli(flags);
local_irq_save(flags);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
cpu = cpu_logical_id(hard_smp_processor_id()); cpu = cpu_logical_id(hard_smp_processor_id());
...@@ -646,7 +649,7 @@ ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *ptregs) ...@@ -646,7 +649,7 @@ ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *ptregs)
ia64_mca_wakeup_ipi_wait(); ia64_mca_wakeup_ipi_wait();
/* Enable all interrupts */ /* Enable all interrupts */
restore_flags(flags); local_irq_restore(flags);
} }
......
...@@ -684,9 +684,9 @@ ia64_os_mca_tlb_error_check: ...@@ -684,9 +684,9 @@ ia64_os_mca_tlb_error_check:
movl r3=SAL_GET_STATE_INFO;; movl r3=SAL_GET_STATE_INFO;;
DATA_VA_TO_PA(r7);; // convert to physical address DATA_VA_TO_PA(r7);; // convert to physical address
ld8 r8=[r7],8;; // get pdesc function pointer ld8 r8=[r7],8;; // get pdesc function pointer
DATA_VA_TO_PA(r8) // convert to physical address dep r8=0,r8,61,3;; // convert SAL VA to PA
ld8 r1=[r7];; // set new (ia64_sal) gp ld8 r1=[r7];; // set new (ia64_sal) gp
DATA_VA_TO_PA(r1) // convert to physical address dep r1=0,r1,61,3;; // convert SAL VA to PA
mov b6=r8 mov b6=r8
alloc r5=ar.pfs,8,0,8,0;; // allocate stack frame for SAL call alloc r5=ar.pfs,8,0,8,0;; // allocate stack frame for SAL call
......
...@@ -165,7 +165,7 @@ struct pci_ops pci_sal_ops = { ...@@ -165,7 +165,7 @@ struct pci_ops pci_sal_ops = {
*/ */
struct pci_bus * struct pci_bus *
pcibios_scan_root(int seg, int bus) pcibios_scan_root(int bus)
{ {
struct list_head *list = NULL; struct list_head *list = NULL;
struct pci_bus *pci_bus = NULL; struct pci_bus *pci_bus = NULL;
...@@ -174,12 +174,12 @@ pcibios_scan_root(int seg, int bus) ...@@ -174,12 +174,12 @@ pcibios_scan_root(int seg, int bus)
pci_bus = pci_bus_b(list); pci_bus = pci_bus_b(list);
if (pci_bus->number == bus) { if (pci_bus->number == bus) {
/* Already scanned */ /* Already scanned */
printk("PCI: Bus (%02x:%02x) already probed\n", seg, bus); printk("PCI: Bus (%02x) already probed\n", bus);
return pci_bus; return pci_bus;
} }
} }
printk("PCI: Probing PCI hardware on bus (%02x:%02x)\n", seg, bus); printk("PCI: Probing PCI hardware on bus (%02x)\n", bus);
return pci_scan_bus(bus, pci_root_ops, NULL); return pci_scan_bus(bus, pci_root_ops, NULL);
} }
...@@ -265,12 +265,37 @@ pcibios_fixup_pbus_ranges (struct pci_bus * bus, struct pbus_set_ranges_data * r ...@@ -265,12 +265,37 @@ pcibios_fixup_pbus_ranges (struct pci_bus * bus, struct pbus_set_ranges_data * r
int int
pcibios_enable_device (struct pci_dev *dev) pcibios_enable_device (struct pci_dev *dev)
{ {
u16 cmd, old_cmd;
int idx;
struct resource *r;
if (!dev) if (!dev)
return -EINVAL; return -EINVAL;
/* Not needed, since we enable all devices at startup. */ pci_read_config_word(dev, PCI_COMMAND, &cmd);
old_cmd = cmd;
for (idx=0; idx<6; idx++) {
r = &dev->resource[idx];
if (!r->start && r->end) {
printk(KERN_ERR
"PCI: Device %s not available because of resource collisions\n",
dev->slot_name);
return -EINVAL;
}
if (r->flags & IORESOURCE_IO)
cmd |= PCI_COMMAND_IO;
if (r->flags & IORESOURCE_MEM)
cmd |= PCI_COMMAND_MEMORY;
}
if (dev->resource[PCI_ROM_RESOURCE].start)
cmd |= PCI_COMMAND_MEMORY;
if (cmd != old_cmd) {
printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd);
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
printk(KERN_INFO "PCI: Found IRQ %d for device %s\n", dev->irq, dev->slot_name); printk(KERN_INFO "PCI: Found IRQ %d for device %s\n", dev->irq, dev->slot_name);
return 0; return 0;
} }
......
...@@ -106,6 +106,12 @@ ...@@ -106,6 +106,12 @@
#define PFM_REG_RETFLAG_SET(flags, val) do { flags &= ~PFM_REG_RETFL_MASK; flags |= (val); } while(0) #define PFM_REG_RETFLAG_SET(flags, val) do { flags &= ~PFM_REG_RETFL_MASK; flags |= (val); } while(0)
#ifdef CONFIG_SMP
#define cpu_is_online(i) (cpu_online_map & (1UL << i))
#else
#define cpu_is_online(i) (i==0)
#endif
/* /*
* debugging * debugging
*/ */
...@@ -277,8 +283,8 @@ typedef struct { ...@@ -277,8 +283,8 @@ typedef struct {
typedef struct { typedef struct {
pfm_pmu_reg_type_t type; pfm_pmu_reg_type_t type;
int pm_pos; int pm_pos;
int (*read_check)(struct task_struct *task, unsigned int cnum, unsigned long *val); int (*read_check)(struct task_struct *task, unsigned int cnum, unsigned long *val, struct pt_regs *regs);
int (*write_check)(struct task_struct *task, unsigned int cnum, unsigned long *val); int (*write_check)(struct task_struct *task, unsigned int cnum, unsigned long *val, struct pt_regs *regs);
unsigned long dep_pmd[4]; unsigned long dep_pmd[4];
unsigned long dep_pmc[4]; unsigned long dep_pmc[4];
} pfm_reg_desc_t; } pfm_reg_desc_t;
...@@ -396,7 +402,7 @@ static unsigned long reset_pmcs[IA64_NUM_PMC_REGS]; /* contains PAL reset values ...@@ -396,7 +402,7 @@ static unsigned long reset_pmcs[IA64_NUM_PMC_REGS]; /* contains PAL reset values
static void pfm_vm_close(struct vm_area_struct * area); static void pfm_vm_close(struct vm_area_struct * area);
static struct vm_operations_struct pfm_vm_ops={ static struct vm_operations_struct pfm_vm_ops={
close: pfm_vm_close .close = pfm_vm_close
}; };
/* /*
...@@ -902,8 +908,8 @@ pfx_is_sane(struct task_struct *task, pfarg_context_t *pfx) ...@@ -902,8 +908,8 @@ pfx_is_sane(struct task_struct *task, pfarg_context_t *pfx)
/* /*
* and it must be a valid CPU * and it must be a valid CPU
*/ */
cpu = ffs(pfx->ctx_cpu_mask); cpu = ffz(~pfx->ctx_cpu_mask);
if (!cpu_online(cpu)) { if (cpu_is_online(cpu) == 0) {
DBprintk(("CPU%d is not online\n", cpu)); DBprintk(("CPU%d is not online\n", cpu));
return -EINVAL; return -EINVAL;
} }
...@@ -925,11 +931,12 @@ pfx_is_sane(struct task_struct *task, pfarg_context_t *pfx) ...@@ -925,11 +931,12 @@ pfx_is_sane(struct task_struct *task, pfarg_context_t *pfx)
DBprintk(("must have notify_pid when blocking for [%d]\n", task->pid)); DBprintk(("must have notify_pid when blocking for [%d]\n", task->pid));
return -EINVAL; return -EINVAL;
} }
#if 0
if ((ctx_flags & PFM_FL_NOTIFY_BLOCK) && pfx->ctx_notify_pid == task->pid) { if ((ctx_flags & PFM_FL_NOTIFY_BLOCK) && pfx->ctx_notify_pid == task->pid) {
DBprintk(("cannot notify self when blocking for [%d]\n", task->pid)); DBprintk(("cannot notify self when blocking for [%d]\n", task->pid));
return -EINVAL; return -EINVAL;
} }
#endif
} }
/* probably more to add here */ /* probably more to add here */
...@@ -968,7 +975,7 @@ pfm_context_create(struct task_struct *task, pfm_context_t *ctx, void *req, int ...@@ -968,7 +975,7 @@ pfm_context_create(struct task_struct *task, pfm_context_t *ctx, void *req, int
if (ctx_flags & PFM_FL_SYSTEM_WIDE) { if (ctx_flags & PFM_FL_SYSTEM_WIDE) {
/* at this point, we know there is at least one bit set */ /* at this point, we know there is at least one bit set */
cpu = ffs(tmp.ctx_cpu_mask) - 1; cpu = ffz(~tmp.ctx_cpu_mask);
DBprintk(("requesting CPU%d currently on CPU%d\n",cpu, smp_processor_id())); DBprintk(("requesting CPU%d currently on CPU%d\n",cpu, smp_processor_id()));
...@@ -1280,7 +1287,7 @@ pfm_write_pmcs(struct task_struct *task, pfm_context_t *ctx, void *arg, int coun ...@@ -1280,7 +1287,7 @@ pfm_write_pmcs(struct task_struct *task, pfm_context_t *ctx, void *arg, int coun
/* /*
* execute write checker, if any * execute write checker, if any
*/ */
if (PMC_WR_FUNC(cnum)) ret = PMC_WR_FUNC(cnum)(task, cnum, &tmp.reg_value); if (PMC_WR_FUNC(cnum)) ret = PMC_WR_FUNC(cnum)(task, cnum, &tmp.reg_value, regs);
abort_mission: abort_mission:
if (ret == -EINVAL) reg_retval = PFM_REG_RETFL_EINVAL; if (ret == -EINVAL) reg_retval = PFM_REG_RETFL_EINVAL;
...@@ -1371,7 +1378,7 @@ pfm_write_pmds(struct task_struct *task, pfm_context_t *ctx, void *arg, int coun ...@@ -1371,7 +1378,7 @@ pfm_write_pmds(struct task_struct *task, pfm_context_t *ctx, void *arg, int coun
/* /*
* execute write checker, if any * execute write checker, if any
*/ */
if (PMD_WR_FUNC(cnum)) ret = PMD_WR_FUNC(cnum)(task, cnum, &tmp.reg_value); if (PMD_WR_FUNC(cnum)) ret = PMD_WR_FUNC(cnum)(task, cnum, &tmp.reg_value, regs);
abort_mission: abort_mission:
if (ret == -EINVAL) reg_retval = PFM_REG_RETFL_EINVAL; if (ret == -EINVAL) reg_retval = PFM_REG_RETFL_EINVAL;
...@@ -1394,6 +1401,8 @@ pfm_write_pmds(struct task_struct *task, pfm_context_t *ctx, void *arg, int coun ...@@ -1394,6 +1401,8 @@ pfm_write_pmds(struct task_struct *task, pfm_context_t *ctx, void *arg, int coun
/* keep track of what we use */ /* keep track of what we use */
CTX_USED_PMD(ctx, pmu_conf.pmd_desc[(cnum)].dep_pmd[0]); CTX_USED_PMD(ctx, pmu_conf.pmd_desc[(cnum)].dep_pmd[0]);
/* mark this register as used as well */
CTX_USED_PMD(ctx, RDEP(cnum));
/* writes to unimplemented part is ignored, so this is safe */ /* writes to unimplemented part is ignored, so this is safe */
ia64_set_pmd(cnum, tmp.reg_value & pmu_conf.perf_ovfl_val); ia64_set_pmd(cnum, tmp.reg_value & pmu_conf.perf_ovfl_val);
...@@ -1438,7 +1447,7 @@ pfm_read_pmds(struct task_struct *task, pfm_context_t *ctx, void *arg, int count ...@@ -1438,7 +1447,7 @@ pfm_read_pmds(struct task_struct *task, pfm_context_t *ctx, void *arg, int count
DBprintk(("ctx_last_cpu=%d for [%d]\n", atomic_read(&ctx->ctx_last_cpu), task->pid)); DBprintk(("ctx_last_cpu=%d for [%d]\n", atomic_read(&ctx->ctx_last_cpu), task->pid));
for (i = 0; i < count; i++, req++) { for (i = 0; i < count; i++, req++) {
unsigned long reg_val = ~0UL, ctx_val = ~0UL; unsigned long ctx_val = ~0UL;
if (copy_from_user(&tmp, req, sizeof(tmp))) return -EFAULT; if (copy_from_user(&tmp, req, sizeof(tmp))) return -EFAULT;
...@@ -1462,7 +1471,7 @@ pfm_read_pmds(struct task_struct *task, pfm_context_t *ctx, void *arg, int count ...@@ -1462,7 +1471,7 @@ pfm_read_pmds(struct task_struct *task, pfm_context_t *ctx, void *arg, int count
*/ */
if (atomic_read(&ctx->ctx_last_cpu) == smp_processor_id()){ if (atomic_read(&ctx->ctx_last_cpu) == smp_processor_id()){
ia64_srlz_d(); ia64_srlz_d();
val = reg_val = ia64_get_pmd(cnum); val = ia64_get_pmd(cnum);
DBprintk(("reading pmd[%u]=0x%lx from hw\n", cnum, val)); DBprintk(("reading pmd[%u]=0x%lx from hw\n", cnum, val));
} else { } else {
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
...@@ -1484,7 +1493,7 @@ pfm_read_pmds(struct task_struct *task, pfm_context_t *ctx, void *arg, int count ...@@ -1484,7 +1493,7 @@ pfm_read_pmds(struct task_struct *task, pfm_context_t *ctx, void *arg, int count
} }
#endif #endif
/* context has been saved */ /* context has been saved */
val = reg_val = th->pmd[cnum]; val = th->pmd[cnum];
} }
if (PMD_IS_COUNTING(cnum)) { if (PMD_IS_COUNTING(cnum)) {
/* /*
...@@ -1493,9 +1502,7 @@ pfm_read_pmds(struct task_struct *task, pfm_context_t *ctx, void *arg, int count ...@@ -1493,9 +1502,7 @@ pfm_read_pmds(struct task_struct *task, pfm_context_t *ctx, void *arg, int count
val &= pmu_conf.perf_ovfl_val; val &= pmu_conf.perf_ovfl_val;
val += ctx_val = ctx->ctx_soft_pmds[cnum].val; val += ctx_val = ctx->ctx_soft_pmds[cnum].val;
} else { }
val = reg_val = ia64_get_pmd(cnum);
}
tmp.reg_value = val; tmp.reg_value = val;
...@@ -1503,14 +1510,13 @@ pfm_read_pmds(struct task_struct *task, pfm_context_t *ctx, void *arg, int count ...@@ -1503,14 +1510,13 @@ pfm_read_pmds(struct task_struct *task, pfm_context_t *ctx, void *arg, int count
* execute read checker, if any * execute read checker, if any
*/ */
if (PMD_RD_FUNC(cnum)) { if (PMD_RD_FUNC(cnum)) {
ret = PMD_RD_FUNC(cnum)(task, cnum, &tmp.reg_value); ret = PMD_RD_FUNC(cnum)(task, cnum, &tmp.reg_value, regs);
} }
PFM_REG_RETFLAG_SET(tmp.reg_flags, ret); PFM_REG_RETFLAG_SET(tmp.reg_flags, ret);
DBprintk(("read pmd[%u] ret=%d soft_pmd=0x%lx reg=0x%lx pmc=0x%lx\n", DBprintk(("read pmd[%u] ret=%d value=0x%lx pmc=0x%lx\n",
cnum, ret, ctx_val, reg_val, cnum, ret, val, ia64_get_pmc(cnum)));
ia64_get_pmc(cnum)));
if (copy_to_user(req, &tmp, sizeof(tmp))) return -EFAULT; if (copy_to_user(req, &tmp, sizeof(tmp))) return -EFAULT;
} }
...@@ -1553,15 +1559,11 @@ pfm_use_debug_registers(struct task_struct *task) ...@@ -1553,15 +1559,11 @@ pfm_use_debug_registers(struct task_struct *task)
*/ */
if (ctx && ctx->ctx_fl_using_dbreg == 1) return -1; if (ctx && ctx->ctx_fl_using_dbreg == 1) return -1;
/*
* XXX: not pretty
*/
LOCK_PFS(); LOCK_PFS();
/* /*
* We only allow the use of debug registers when there is no system * We cannot allow setting breakpoints when system wide monitoring
* wide monitoring * sessions are using the debug registers.
* XXX: we could relax this by
*/ */
if (pfm_sessions.pfs_sys_use_dbregs> 0) if (pfm_sessions.pfs_sys_use_dbregs> 0)
ret = -1; ret = -1;
...@@ -1921,7 +1923,6 @@ typedef union { ...@@ -1921,7 +1923,6 @@ typedef union {
dbr_mask_reg_t dbr; dbr_mask_reg_t dbr;
} dbreg_t; } dbreg_t;
static int static int
pfm_write_ibr_dbr(int mode, struct task_struct *task, void *arg, int count, struct pt_regs *regs) pfm_write_ibr_dbr(int mode, struct task_struct *task, void *arg, int count, struct pt_regs *regs)
{ {
...@@ -1963,8 +1964,8 @@ pfm_write_ibr_dbr(int mode, struct task_struct *task, void *arg, int count, stru ...@@ -1963,8 +1964,8 @@ pfm_write_ibr_dbr(int mode, struct task_struct *task, void *arg, int count, stru
if (ctx->ctx_fl_system) { if (ctx->ctx_fl_system) {
/* we mark ourselves as owner of the debug registers */ /* we mark ourselves as owner of the debug registers */
ctx->ctx_fl_using_dbreg = 1; ctx->ctx_fl_using_dbreg = 1;
} else { DBprintk(("system-wide setting fl_using_dbreg for [%d]\n", task->pid));
if (ctx->ctx_fl_using_dbreg == 0) { } else if (first_time) {
ret= -EBUSY; ret= -EBUSY;
if ((thread->flags & IA64_THREAD_DBG_VALID) != 0) { if ((thread->flags & IA64_THREAD_DBG_VALID) != 0) {
DBprintk(("debug registers already in use for [%d]\n", task->pid)); DBprintk(("debug registers already in use for [%d]\n", task->pid));
...@@ -1973,6 +1974,7 @@ pfm_write_ibr_dbr(int mode, struct task_struct *task, void *arg, int count, stru ...@@ -1973,6 +1974,7 @@ pfm_write_ibr_dbr(int mode, struct task_struct *task, void *arg, int count, stru
/* we mark ourselves as owner of the debug registers */ /* we mark ourselves as owner of the debug registers */
ctx->ctx_fl_using_dbreg = 1; ctx->ctx_fl_using_dbreg = 1;
DBprintk(("setting fl_using_dbreg for [%d]\n", task->pid));
/* /*
* Given debug registers cannot be used for both debugging * Given debug registers cannot be used for both debugging
* and performance monitoring at the same time, we reuse * and performance monitoring at the same time, we reuse
...@@ -1980,20 +1982,27 @@ pfm_write_ibr_dbr(int mode, struct task_struct *task, void *arg, int count, stru ...@@ -1980,20 +1982,27 @@ pfm_write_ibr_dbr(int mode, struct task_struct *task, void *arg, int count, stru
*/ */
memset(task->thread.dbr, 0, sizeof(task->thread.dbr)); memset(task->thread.dbr, 0, sizeof(task->thread.dbr));
memset(task->thread.ibr, 0, sizeof(task->thread.ibr)); memset(task->thread.ibr, 0, sizeof(task->thread.ibr));
}
/* if (first_time) {
* clear hardware registers to make sure we don't DBprintk(("[%d] clearing ibrs,dbrs\n", task->pid));
* pick up stale state /*
*/ * clear hardware registers to make sure we don't
for (i=0; i < pmu_conf.num_ibrs; i++) { * pick up stale state.
ia64_set_ibr(i, 0UL); *
} * for a system wide session, we do not use
ia64_srlz_i(); * thread.dbr, thread.ibr because this process
for (i=0; i < pmu_conf.num_dbrs; i++) { * never leaves the current CPU and the state
ia64_set_dbr(i, 0UL); * is shared by all processes running on it
} */
ia64_srlz_d(); for (i=0; i < pmu_conf.num_ibrs; i++) {
ia64_set_ibr(i, 0UL);
} }
ia64_srlz_i();
for (i=0; i < pmu_conf.num_dbrs; i++) {
ia64_set_dbr(i, 0UL);
}
ia64_srlz_d();
} }
ret = -EFAULT; ret = -EFAULT;
...@@ -2361,9 +2370,9 @@ sys_perfmonctl (pid_t pid, int cmd, void *arg, int count, long arg5, long arg6, ...@@ -2361,9 +2370,9 @@ sys_perfmonctl (pid_t pid, int cmd, void *arg, int count, long arg5, long arg6,
{ {
struct pt_regs *regs = (struct pt_regs *)&stack; struct pt_regs *regs = (struct pt_regs *)&stack;
struct task_struct *task = current; struct task_struct *task = current;
pfm_context_t *ctx = task->thread.pfm_context; pfm_context_t *ctx;
size_t sz; size_t sz;
int ret = -ESRCH, narg; int ret, narg;
/* /*
* reject any call if perfmon was disabled at initialization time * reject any call if perfmon was disabled at initialization time
...@@ -2393,6 +2402,8 @@ sys_perfmonctl (pid_t pid, int cmd, void *arg, int count, long arg5, long arg6, ...@@ -2393,6 +2402,8 @@ sys_perfmonctl (pid_t pid, int cmd, void *arg, int count, long arg5, long arg6,
if (pid != current->pid) { if (pid != current->pid) {
ret = -ESRCH;
read_lock(&tasklist_lock); read_lock(&tasklist_lock);
task = find_task_by_pid(pid); task = find_task_by_pid(pid);
...@@ -2407,10 +2418,11 @@ sys_perfmonctl (pid_t pid, int cmd, void *arg, int count, long arg5, long arg6, ...@@ -2407,10 +2418,11 @@ sys_perfmonctl (pid_t pid, int cmd, void *arg, int count, long arg5, long arg6,
ret = check_task_state(task); ret = check_task_state(task);
if (ret != 0) goto abort_call; if (ret != 0) goto abort_call;
} }
ctx = task->thread.pfm_context;
} }
} }
ctx = task->thread.pfm_context;
if (PFM_CMD_USE_CTX(cmd)) { if (PFM_CMD_USE_CTX(cmd)) {
ret = -EINVAL; ret = -EINVAL;
if (ctx == NULL) { if (ctx == NULL) {
...@@ -2953,11 +2965,6 @@ perfmon_interrupt (int irq, void *arg, struct pt_regs *regs) ...@@ -2953,11 +2965,6 @@ perfmon_interrupt (int irq, void *arg, struct pt_regs *regs)
static int static int
perfmon_proc_info(char *page) perfmon_proc_info(char *page)
{ {
#ifdef CONFIG_SMP
#define cpu_is_online(i) (cpu_online_map & (1UL << i))
#else
#define cpu_is_online(i) 1
#endif
char *p = page; char *p = page;
int i; int i;
...@@ -4118,9 +4125,9 @@ pfm_cleanup_notifiers(struct task_struct *task) ...@@ -4118,9 +4125,9 @@ pfm_cleanup_notifiers(struct task_struct *task)
} }
static struct irqaction perfmon_irqaction = { static struct irqaction perfmon_irqaction = {
handler: perfmon_interrupt, .handler = perfmon_interrupt,
flags: SA_INTERRUPT, .flags = SA_INTERRUPT,
name: "perfmon" .name = "perfmon"
}; };
...@@ -4150,11 +4157,6 @@ perfmon_init (void) ...@@ -4150,11 +4157,6 @@ perfmon_init (void)
pal_perf_mon_info_u_t pm_info; pal_perf_mon_info_u_t pm_info;
s64 status; s64 status;
register_percpu_irq(IA64_PERFMON_VECTOR, &perfmon_irqaction);
ia64_set_pmv(IA64_PERFMON_VECTOR);
ia64_srlz_d();
pmu_conf.pfm_is_disabled = 1; pmu_conf.pfm_is_disabled = 1;
printk("perfmon: version %u.%u (sampling format v%u.%u) IRQ %u\n", printk("perfmon: version %u.%u (sampling format v%u.%u) IRQ %u\n",
...@@ -4232,6 +4234,9 @@ __initcall(perfmon_init); ...@@ -4232,6 +4234,9 @@ __initcall(perfmon_init);
void void
perfmon_init_percpu (void) perfmon_init_percpu (void)
{ {
if (smp_processor_id() == 0)
register_percpu_irq(IA64_PERFMON_VECTOR, &perfmon_irqaction);
ia64_set_pmv(IA64_PERFMON_VECTOR); ia64_set_pmv(IA64_PERFMON_VECTOR);
ia64_srlz_d(); ia64_srlz_d();
} }
......
/*
* This file contains the Itanium PMU register description tables
* and pmc checker used by perfmon.c.
*
* Copyright (C) 2002 Hewlett Packard Co
* Stephane Eranian <eranian@hpl.hp.com>
*/
#define RDEP(x) (1UL<<(x))
#ifndef CONFIG_ITANIUM
#error "This file is only valid when CONFIG_ITANIUM is defined"
#endif
static int pfm_ita_pmc_check(struct task_struct *task, unsigned int cnum, unsigned long *val, struct pt_regs *regs);
static int pfm_write_ibr_dbr(int mode, struct task_struct *task, void *arg, int count, struct pt_regs *regs);
static pfm_reg_desc_t pmc_desc[256]={
/* pmc0 */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc1 */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc2 */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc3 */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc4 */ { PFM_REG_COUNTING, 6, NULL, NULL, {RDEP(4),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc5 */ { PFM_REG_COUNTING, 6, NULL, NULL, {RDEP(5),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc6 */ { PFM_REG_COUNTING, 6, NULL, NULL, {RDEP(6),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc7 */ { PFM_REG_COUNTING, 6, NULL, NULL, {RDEP(7),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc8 */ { PFM_REG_CONFIG, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc9 */ { PFM_REG_CONFIG, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc10 */ { PFM_REG_MONITOR, 6, NULL, NULL, {RDEP(0)|RDEP(1),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc11 */ { PFM_REG_MONITOR, 6, NULL, pfm_ita_pmc_check, {RDEP(2)|RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc12 */ { PFM_REG_MONITOR, 6, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc13 */ { PFM_REG_CONFIG, 0, NULL, pfm_ita_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
{ PFM_REG_NONE, 0, NULL, NULL, {0,}, {0,}}, /* end marker */
};
static pfm_reg_desc_t pmd_desc[256]={
/* pmd0 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(1),0UL, 0UL, 0UL}, {RDEP(10),0UL, 0UL, 0UL}},
/* pmd1 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(0),0UL, 0UL, 0UL}, {RDEP(10),0UL, 0UL, 0UL}},
/* pmd2 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}},
/* pmd3 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(2)|RDEP(17),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}},
/* pmd4 */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(4),0UL, 0UL, 0UL}},
/* pmd5 */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(5),0UL, 0UL, 0UL}},
/* pmd6 */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(6),0UL, 0UL, 0UL}},
/* pmd7 */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(7),0UL, 0UL, 0UL}},
/* pmd8 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
/* pmd9 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
/* pmd10 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
/* pmd11 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
/* pmd12 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
/* pmd13 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
/* pmd14 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
/* pmd15 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
/* pmd16 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
/* pmd17 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(2)|RDEP(3),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}},
{ PFM_REG_NONE, 0, NULL, NULL, {0,}, {0,}}, /* end marker */
};
static int
pfm_ita_pmc_check(struct task_struct *task, unsigned int cnum, unsigned long *val, struct pt_regs *regs)
{
pfm_context_t *ctx = task->thread.pfm_context;
int ret;
/*
* we must clear the (instruction) debug registers if pmc13.ta bit is cleared
* before they are written (fl_using_dbreg==0) to avoid picking up stale information.
*/
if (cnum == 13 && ((*val & 0x1) == 0UL) && ctx->ctx_fl_using_dbreg == 0) {
/* don't mix debug with perfmon */
if ((task->thread.flags & IA64_THREAD_DBG_VALID) != 0) return -EINVAL;
/*
* a count of 0 will mark the debug registers as in use and also
* ensure that they are properly cleared.
*/
ret = pfm_write_ibr_dbr(1, task, NULL, 0, regs);
if (ret) return ret;
}
/*
* we must clear the (data) debug registers if pmc11.pt bit is cleared
* before they are written (fl_using_dbreg==0) to avoid picking up stale information.
*/
if (cnum == 11 && ((*val >> 28)& 0x1) == 0 && ctx->ctx_fl_using_dbreg == 0) {
/* don't mix debug with perfmon */
if ((task->thread.flags & IA64_THREAD_DBG_VALID) != 0) return -EINVAL;
/*
* a count of 0 will mark the debug registers as in use and also
* ensure that they are properly cleared.
*/
ret = pfm_write_ibr_dbr(0, task, NULL, 0, regs);
if (ret) return ret;
}
return 0;
}
/*
* This file contains the McKinley PMU register description tables
* and pmc checker used by perfmon.c.
*
* Copyright (C) 2002 Hewlett Packard Co
* Stephane Eranian <eranian@hpl.hp.com>
*/
#define RDEP(x) (1UL<<(x))
#ifndef CONFIG_MCKINLEY
#error "This file is only valid when CONFIG_MCKINLEY is defined"
#endif
static int pfm_mck_pmc_check(struct task_struct *task, unsigned int cnum, unsigned long *val, struct pt_regs *regs);
static int pfm_write_ibr_dbr(int mode, struct task_struct *task, void *arg, int count, struct pt_regs *regs);
static pfm_reg_desc_t pmc_desc[256]={
/* pmc0 */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc1 */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc2 */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc3 */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc4 */ { PFM_REG_COUNTING, 6, NULL, pfm_mck_pmc_check, {RDEP(4),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc5 */ { PFM_REG_COUNTING, 6, NULL, NULL, {RDEP(5),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc6 */ { PFM_REG_COUNTING, 6, NULL, NULL, {RDEP(6),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc7 */ { PFM_REG_COUNTING, 6, NULL, NULL, {RDEP(7),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc8 */ { PFM_REG_CONFIG, 0, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc9 */ { PFM_REG_CONFIG, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc10 */ { PFM_REG_MONITOR, 4, NULL, NULL, {RDEP(0)|RDEP(1),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc11 */ { PFM_REG_MONITOR, 6, NULL, NULL, {RDEP(2)|RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc12 */ { PFM_REG_MONITOR, 6, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc13 */ { PFM_REG_CONFIG, 0, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc14 */ { PFM_REG_CONFIG, 0, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc15 */ { PFM_REG_CONFIG, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
{ PFM_REG_NONE, 0, NULL, NULL, {0,}, {0,}}, /* end marker */
};
static pfm_reg_desc_t pmd_desc[256]={
/* pmd0 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(1),0UL, 0UL, 0UL}, {RDEP(10),0UL, 0UL, 0UL}},
/* pmd1 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(0),0UL, 0UL, 0UL}, {RDEP(10),0UL, 0UL, 0UL}},
/* pmd2 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}},
/* pmd3 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(2)|RDEP(17),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}},
/* pmd4 */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(4),0UL, 0UL, 0UL}},
/* pmd5 */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(5),0UL, 0UL, 0UL}},
/* pmd6 */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(6),0UL, 0UL, 0UL}},
/* pmd7 */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(7),0UL, 0UL, 0UL}},
/* pmd8 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
/* pmd9 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
/* pmd10 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
/* pmd11 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
/* pmd12 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
/* pmd13 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
/* pmd14 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
/* pmd15 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
/* pmd16 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
/* pmd17 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(2)|RDEP(3),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}},
{ PFM_REG_NONE, 0, NULL, NULL, {0,}, {0,}}, /* end marker */
};
static int
pfm_mck_pmc_check(struct task_struct *task, unsigned int cnum, unsigned long *val, struct pt_regs *regs)
{
struct thread_struct *th = &task->thread;
pfm_context_t *ctx = task->thread.pfm_context;
int ret = 0, check_case1 = 0;
unsigned long val8 = 0, val14 = 0, val13 = 0;
/*
* we must clear the debug registers if any pmc13.ena_dbrpX bit is enabled
* before they are written (fl_using_dbreg==0) to avoid picking up stale information.
*/
if (cnum == 13 && (*val & (0xfUL << 45)) && ctx->ctx_fl_using_dbreg == 0) {
/* don't mix debug with perfmon */
if ((task->thread.flags & IA64_THREAD_DBG_VALID) != 0) return -EINVAL;
/*
* a count of 0 will mark the debug registers as in use and also
* ensure that they are properly cleared.
*/
ret = pfm_write_ibr_dbr(1, task, NULL, 0, regs);
if (ret) return ret;
}
/*
* we must clear the (instruction) debug registers if any pmc14.ibrpX bit is enabled
* before they are (fl_using_dbreg==0) to avoid picking up stale information.
*/
if (cnum == 14 && ((*val & 0x2222) != 0x2222) && ctx->ctx_fl_using_dbreg == 0) {
/* don't mix debug with perfmon */
if ((task->thread.flags & IA64_THREAD_DBG_VALID) != 0) return -EINVAL;
/*
* a count of 0 will mark the debug registers as in use and also
* ensure that they are properly cleared.
*/
ret = pfm_write_ibr_dbr(0, task, NULL, 0, regs);
if (ret) return ret;
}
switch(cnum) {
case 4: *val |= 1UL << 23; /* force power enable bit */
break;
case 8: val8 = *val;
val13 = th->pmc[13];
val14 = th->pmc[14];
check_case1 = 1;
break;
case 13: val8 = th->pmc[8];
val13 = *val;
val14 = th->pmc[14];
check_case1 = 1;
break;
case 14: val8 = th->pmc[13];
val13 = th->pmc[13];
val14 = *val;
check_case1 = 1;
break;
}
/* check illegal configuration which can produce inconsistencies in tagging
* i-side events in L1D and L2 caches
*/
if (check_case1) {
ret = ((val13 >> 45) & 0xf) == 0
&& ((val8 & 0x1) == 0)
&& ((((val14>>1) & 0x3) == 0x2 || ((val14>>1) & 0x3) == 0x0)
||(((val14>>4) & 0x3) == 0x2 || ((val14>>4) & 0x3) == 0x0));
if (ret) printk("perfmon: failure check_case1\n");
}
return ret ? -EINVAL : 0;
}
...@@ -325,6 +325,11 @@ copy_thread (int nr, unsigned long clone_flags, ...@@ -325,6 +325,11 @@ copy_thread (int nr, unsigned long clone_flags,
/* copy parts of thread_struct: */ /* copy parts of thread_struct: */
p->thread.ksp = (unsigned long) child_stack - 16; p->thread.ksp = (unsigned long) child_stack - 16;
/* stop some PSR bits from being inherited: */
child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET)
& ~IA64_PSR_BITS_TO_CLEAR);
/* /*
* NOTE: The calling convention considers all floating point * NOTE: The calling convention considers all floating point
* registers in the high partition (fph) to be scratch. Since * registers in the high partition (fph) to be scratch. Since
......
...@@ -347,6 +347,14 @@ setup_arch (char **cmdline_p) ...@@ -347,6 +347,14 @@ setup_arch (char **cmdline_p)
#ifdef CONFIG_ACPI_BOOT #ifdef CONFIG_ACPI_BOOT
acpi_boot_init(*cmdline_p); acpi_boot_init(*cmdline_p);
#endif #endif
#ifdef CONFIG_SERIAL_HCDP
if (efi.hcdp) {
void setup_serial_hcdp(void *);
/* Setup the serial ports described by HCDP */
setup_serial_hcdp(efi.hcdp);
}
#endif
#ifdef CONFIG_VT #ifdef CONFIG_VT
# if defined(CONFIG_DUMMY_CONSOLE) # if defined(CONFIG_DUMMY_CONSOLE)
conswitchp = &dummy_con; conswitchp = &dummy_con;
...@@ -436,7 +444,7 @@ static void * ...@@ -436,7 +444,7 @@ static void *
c_start (struct seq_file *m, loff_t *pos) c_start (struct seq_file *m, loff_t *pos)
{ {
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
while (*pos < NR_CPUS && !(cpu_online_map & (1 << *pos))) while (*pos < NR_CPUS && !(cpu_online_map & (1UL << *pos)))
++*pos; ++*pos;
#endif #endif
return *pos < NR_CPUS ? cpu_data(*pos) : NULL; return *pos < NR_CPUS ? cpu_data(*pos) : NULL;
...@@ -455,10 +463,10 @@ c_stop (struct seq_file *m, void *v) ...@@ -455,10 +463,10 @@ c_stop (struct seq_file *m, void *v)
} }
struct seq_operations cpuinfo_op = { struct seq_operations cpuinfo_op = {
start: c_start, .start = c_start,
next: c_next, .next = c_next,
stop: c_stop, .stop = c_stop,
show: show_cpuinfo .show = show_cpuinfo
}; };
void void
...@@ -542,7 +550,18 @@ cpu_init (void) ...@@ -542,7 +550,18 @@ cpu_init (void)
extern char __per_cpu_end[]; extern char __per_cpu_end[];
int cpu = smp_processor_id(); int cpu = smp_processor_id();
my_cpu_data = alloc_bootmem_pages(__per_cpu_end - __per_cpu_start); if (__per_cpu_end - __per_cpu_start > PAGE_SIZE)
panic("Per-cpu data area too big! (%Zu > %Zu)",
__per_cpu_end - __per_cpu_start, PAGE_SIZE);
/*
* On the BSP, the page allocator isn't initialized by the time we get here. On
* the APs, the bootmem allocator is no longer available...
*/
if (cpu == 0)
my_cpu_data = alloc_bootmem_pages(__per_cpu_end - __per_cpu_start);
else
my_cpu_data = (void *) get_free_page(GFP_KERNEL);
memcpy(my_cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start); memcpy(my_cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start);
__per_cpu_offset[cpu] = (char *) my_cpu_data - __per_cpu_start; __per_cpu_offset[cpu] = (char *) my_cpu_data - __per_cpu_start;
my_cpu_info = my_cpu_data + ((char *) &cpu_info - __per_cpu_start); my_cpu_info = my_cpu_data + ((char *) &cpu_info - __per_cpu_start);
......
...@@ -146,6 +146,7 @@ copy_siginfo_to_user (siginfo_t *to, siginfo_t *from) ...@@ -146,6 +146,7 @@ copy_siginfo_to_user (siginfo_t *to, siginfo_t *from)
if (from->si_code < 0) { if (from->si_code < 0) {
if (__copy_to_user(to, from, sizeof(siginfo_t))) if (__copy_to_user(to, from, sizeof(siginfo_t)))
return -EFAULT; return -EFAULT;
return 0;
} else { } else {
int err; int err;
......
/* /*
* SMP boot-related support * SMP boot-related support
* *
* Copyright (C) 2001 David Mosberger-Tang <davidm@hpl.hp.com> * Copyright (C) 1998-2002 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
* *
* 01/05/16 Rohit Seth <rohit.seth@intel.com> Moved SMP booting functions from smp.c to here. * 01/05/16 Rohit Seth <rohit.seth@intel.com> Moved SMP booting functions from smp.c to here.
* 01/04/27 David Mosberger <davidm@hpl.hp.com> Added ITC synching code. * 01/04/27 David Mosberger <davidm@hpl.hp.com> Added ITC synching code.
* 02/07/31 David Mosberger <davidm@hpl.hp.com> Switch over to hotplug-CPU boot-sequence.
* smp_boot_cpus()/smp_commence() is replaced by
* smp_prepare_cpus()/__cpu_up()/smp_cpus_done().
*/ */
...@@ -66,18 +70,16 @@ static volatile unsigned long go[SLAVE + 1]; ...@@ -66,18 +70,16 @@ static volatile unsigned long go[SLAVE + 1];
#define DEBUG_ITC_SYNC 0 #define DEBUG_ITC_SYNC 0
extern void __init calibrate_delay(void); extern void __init calibrate_delay (void);
extern void start_ap(void); extern void start_ap (void);
extern unsigned long ia64_iobase; extern unsigned long ia64_iobase;
int cpucount; int cpucount;
task_t *task_for_booting_cpu; task_t *task_for_booting_cpu;
/* Setup configured maximum number of CPUs to activate */
static int max_cpus = -1;
/* Bitmask of currently online CPUs */ /* Bitmask of currently online CPUs */
volatile unsigned long cpu_online_map; volatile unsigned long cpu_online_map;
unsigned long phys_cpu_present_map;
/* which logical CPU number maps to which CPU (physical APIC ID) */ /* which logical CPU number maps to which CPU (physical APIC ID) */
volatile int ia64_cpu_to_sapicid[NR_CPUS]; volatile int ia64_cpu_to_sapicid[NR_CPUS];
...@@ -86,44 +88,12 @@ static volatile unsigned long cpu_callin_map; ...@@ -86,44 +88,12 @@ static volatile unsigned long cpu_callin_map;
struct smp_boot_data smp_boot_data __initdata; struct smp_boot_data smp_boot_data __initdata;
/* Set when the idlers are all forked */
volatile int smp_threads_ready;
unsigned long ap_wakeup_vector = -1; /* External Int use to wakeup APs */ unsigned long ap_wakeup_vector = -1; /* External Int use to wakeup APs */
char __initdata no_int_routing; char __initdata no_int_routing;
unsigned char smp_int_redirect; /* are INT and IPI redirectable by the chipset? */ unsigned char smp_int_redirect; /* are INT and IPI redirectable by the chipset? */
/*
* Setup routine for controlling SMP activation
*
* Command-line option of "nosmp" or "maxcpus=0" will disable SMP
* activation entirely (the MPS table probe still happens, though).
*
* Command-line option of "maxcpus=<NUM>", where <NUM> is an integer
* greater than 0, limits the maximum number of CPUs activated in
* SMP mode to <NUM>.
*/
static int __init
nosmp (char *str)
{
max_cpus = 0;
return 1;
}
__setup("nosmp", nosmp);
static int __init
maxcpus (char *str)
{
get_option(&str, &max_cpus);
return 1;
}
__setup("maxcpus=", maxcpus);
static int __init static int __init
nointroute (char *str) nointroute (char *str)
{ {
...@@ -299,7 +269,7 @@ smp_setup_percpu_timer (void) ...@@ -299,7 +269,7 @@ smp_setup_percpu_timer (void)
static volatile atomic_t smp_commenced = ATOMIC_INIT(0); static volatile atomic_t smp_commenced = ATOMIC_INIT(0);
void __init static void __init
smp_commence (void) smp_commence (void)
{ {
/* /*
...@@ -308,7 +278,7 @@ smp_commence (void) ...@@ -308,7 +278,7 @@ smp_commence (void)
Dprintk("Setting commenced=1, go go go\n"); Dprintk("Setting commenced=1, go go go\n");
wmb(); wmb();
atomic_set(&smp_commenced,1); atomic_set(&smp_commenced, 1);
} }
...@@ -380,11 +350,7 @@ start_secondary (void *unused) ...@@ -380,11 +350,7 @@ start_secondary (void *unused)
efi_map_pal_code(); efi_map_pal_code();
cpu_init(); cpu_init();
smp_callin(); smp_callin();
Dprintk("CPU %d is set to go.\n", smp_processor_id());
while (!atomic_read(&smp_commenced))
cpu_relax();
Dprintk("CPU %d is starting idle.\n", smp_processor_id());
return cpu_idle(); return cpu_idle();
} }
...@@ -392,22 +358,20 @@ static struct task_struct * __init ...@@ -392,22 +358,20 @@ static struct task_struct * __init
fork_by_hand (void) fork_by_hand (void)
{ {
/* /*
* don't care about the eip and regs settings since * don't care about the eip and regs settings since we'll never reschedule the
* we'll never reschedule the forked task. * forked task.
*/ */
return do_fork(CLONE_VM|CLONE_IDLETASK, 0, 0, 0); return do_fork(CLONE_VM|CLONE_IDLETASK, 0, 0, 0);
} }
static void __init static int __init
do_boot_cpu (int sapicid) do_boot_cpu (int sapicid, int cpu)
{ {
struct task_struct *idle; struct task_struct *idle;
int timeout, cpu; int timeout;
cpu = ++cpucount;
/* /*
* We can't use kernel_thread since we must avoid to * We can't use kernel_thread since we must avoid to reschedule the child.
* reschedule the child.
*/ */
idle = fork_by_hand(); idle = fork_by_hand();
if (IS_ERR(idle)) if (IS_ERR(idle))
...@@ -419,13 +383,11 @@ do_boot_cpu (int sapicid) ...@@ -419,13 +383,11 @@ do_boot_cpu (int sapicid)
*/ */
init_idle(idle, cpu); init_idle(idle, cpu);
ia64_cpu_to_sapicid[cpu] = sapicid;
unhash_process(idle); unhash_process(idle);
task_for_booting_cpu = idle; task_for_booting_cpu = idle;
Dprintk("Sending wakeup vector %u to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid); Dprintk("Sending wakeup vector %lu to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid);
platform_send_ipi(cpu, ap_wakeup_vector, IA64_IPI_DM_INT, 0); platform_send_ipi(cpu, ap_wakeup_vector, IA64_IPI_DM_INT, 0);
...@@ -448,8 +410,10 @@ do_boot_cpu (int sapicid) ...@@ -448,8 +410,10 @@ do_boot_cpu (int sapicid)
} else { } else {
printk(KERN_ERR "Processor 0x%x/0x%x is stuck.\n", cpu, sapicid); printk(KERN_ERR "Processor 0x%x/0x%x is stuck.\n", cpu, sapicid);
ia64_cpu_to_sapicid[cpu] = -1; ia64_cpu_to_sapicid[cpu] = -1;
cpucount--; clear_bit(cpu, &cpu_online_map); /* was set in smp_callin() */
return -EINVAL;
} }
return 0;
} }
unsigned long cache_decay_ticks; /* # of ticks an idle task is considered cache-hot */ unsigned long cache_decay_ticks; /* # of ticks an idle task is considered cache-hot */
...@@ -463,22 +427,43 @@ smp_tune_scheduling (void) ...@@ -463,22 +427,43 @@ smp_tune_scheduling (void)
(cache_decay_ticks + 1) * 1000 / HZ); (cache_decay_ticks + 1) * 1000 / HZ);
} }
/*
* Initialize the logical CPU number to SAPICID mapping
*/
void __init
smp_build_cpu_map (void)
{
int sapicid, cpu, i;
int boot_cpu_id = hard_smp_processor_id();
for (cpu = 0; cpu < NR_CPUS; cpu++)
ia64_cpu_to_sapicid[cpu] = -1;
ia64_cpu_to_sapicid[0] = boot_cpu_id;
phys_cpu_present_map = 1;
for (cpu = 1, i = 0; i < smp_boot_data.cpu_count; i++) {
sapicid = smp_boot_data.cpu_phys_id[i];
if (sapicid == -1 || sapicid == boot_cpu_id)
continue;
phys_cpu_present_map |= (1 << cpu);
ia64_cpu_to_sapicid[cpu] = sapicid;
cpu++;
}
}
/* /*
* Cycle through the APs sending Wakeup IPIs to boot each. * Cycle through the APs sending Wakeup IPIs to boot each.
*/ */
void __init void __init
smp_boot_cpus (void) smp_prepare_cpus (unsigned int max_cpus)
{ {
int sapicid, cpu;
int boot_cpu_id = hard_smp_processor_id(); int boot_cpu_id = hard_smp_processor_id();
/* /*
* Initialize the logical to physical CPU number mapping * Initialize the per-CPU profiling counter/multiplier
* and the per-CPU profiling counter/multiplier
*/ */
for (cpu = 0; cpu < NR_CPUS; cpu++)
ia64_cpu_to_sapicid[cpu] = -1;
smp_setup_percpu_timer(); smp_setup_percpu_timer();
/* /*
...@@ -492,7 +477,6 @@ smp_boot_cpus (void) ...@@ -492,7 +477,6 @@ smp_boot_cpus (void)
printk("Boot processor id 0x%x/0x%x\n", 0, boot_cpu_id); printk("Boot processor id 0x%x/0x%x\n", 0, boot_cpu_id);
global_irq_holder = NO_PROC_ID;
current_thread_info()->cpu = 0; current_thread_info()->cpu = 0;
smp_tune_scheduling(); smp_tune_scheduling();
...@@ -501,55 +485,48 @@ smp_boot_cpus (void) ...@@ -501,55 +485,48 @@ smp_boot_cpus (void)
*/ */
if (!max_cpus || (max_cpus < -1)) { if (!max_cpus || (max_cpus < -1)) {
printk(KERN_INFO "SMP mode deactivated.\n"); printk(KERN_INFO "SMP mode deactivated.\n");
cpu_online_map = 1; cpu_online_map = phys_cpu_present_map = 1;
goto smp_done; return;
} }
if (max_cpus != -1) }
printk (KERN_INFO "Limiting CPUs to %d\n", max_cpus);
if (smp_boot_data.cpu_count > 1) { void
smp_cpus_done (unsigned int dummy)
{
int cpu;
unsigned long bogosum = 0;
printk(KERN_INFO "SMP: starting up secondaries.\n"); /*
* Allow the user to impress friends.
*/
for (cpu = 0; cpu < smp_boot_data.cpu_count; cpu++) { for (cpu = 0; cpu < NR_CPUS; cpu++)
/* if (cpu_online(cpu))
* Don't even attempt to start the boot CPU! bogosum += cpu_data(cpu)->loops_per_jiffy;
*/
sapicid = smp_boot_data.cpu_phys_id[cpu];
if ((sapicid == -1) || (sapicid == hard_smp_processor_id()))
continue;
if ((max_cpus > 0) && (cpucount + 1 >= max_cpus)) printk(KERN_INFO"Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
break; num_online_cpus(), bogosum/(500000/HZ), (bogosum/(5000/HZ))%100);
}
do_boot_cpu(sapicid); int __devinit
__cpu_up (unsigned int cpu)
{
int ret;
int sapicid;
/* sapicid = ia64_cpu_to_sapicid[cpu];
* Make sure we unmap all failed CPUs if (sapicid == -1)
*/ return -EINVAL;
if (ia64_cpu_to_sapicid[cpu] == -1)
printk("phys CPU#%d not responding - cannot use it.\n", cpu);
}
/* printk(KERN_INFO "Processor %d/%d is spinning up...\n", sapicid, cpu);
* Allow the user to impress friends.
*/ /* Processor goes to start_secondary(), sets online flag */
ret = do_boot_cpu(sapicid, cpu);
printk("Before bogomips.\n"); if (ret < 0)
if (!cpucount) { return ret;
printk(KERN_ERR "Error: only one processor found.\n");
} else { printk(KERN_INFO "Processor %d has spun up...\n", cpu);
unsigned long bogosum = 0; return 0;
for (cpu = 0; cpu < NR_CPUS; cpu++)
if (cpu_online_map & (1<<cpu))
bogosum += cpu_data(cpu)->loops_per_jiffy;
printk(KERN_INFO"Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
cpucount + 1, bogosum/(500000/HZ), (bogosum/(5000/HZ))%100);
}
}
smp_done:
;
} }
/* /*
...@@ -571,9 +548,6 @@ init_smp_config(void) ...@@ -571,9 +548,6 @@ init_smp_config(void)
ap_startup = (struct fptr *) start_ap; ap_startup = (struct fptr *) start_ap;
sal_ret = ia64_sal_set_vectors(SAL_VECTOR_OS_BOOT_RENDEZ, sal_ret = ia64_sal_set_vectors(SAL_VECTOR_OS_BOOT_RENDEZ,
__pa(ap_startup->fp), __pa(ap_startup->gp), 0, 0, 0, 0); __pa(ap_startup->fp), __pa(ap_startup->gp), 0, 0, 0, 0);
if (sal_ret < 0) { if (sal_ret < 0)
printk("SMP: Can't set SAL AP Boot Rendezvous: %s\n Forcing UP mode\n", printk("SMP: Can't set SAL AP Boot Rendezvous: %s\n", ia64_sal_strerror(sal_ret));
ia64_sal_strerror(sal_ret));
max_cpus = 0;
}
} }
...@@ -82,7 +82,6 @@ asmlinkage unsigned long ...@@ -82,7 +82,6 @@ asmlinkage unsigned long
ia64_shmat (int shmid, void *shmaddr, int shmflg, long arg3, long arg4, long arg5, long arg6, ia64_shmat (int shmid, void *shmaddr, int shmflg, long arg3, long arg4, long arg5, long arg6,
long arg7, long stack) long arg7, long stack)
{ {
extern int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr);
struct pt_regs *regs = (struct pt_regs *) &stack; struct pt_regs *regs = (struct pt_regs *) &stack;
unsigned long raddr; unsigned long raddr;
int retval; int retval;
...@@ -138,10 +137,6 @@ ia64_brk (unsigned long brk, long arg1, long arg2, long arg3, ...@@ -138,10 +137,6 @@ ia64_brk (unsigned long brk, long arg1, long arg2, long arg3,
if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE)) if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE))
goto out; goto out;
/* Check if we have enough memory.. */
if (!vm_enough_memory((newbrk-oldbrk) >> PAGE_SHIFT))
goto out;
/* Ok, looks good - let it rip. */ /* Ok, looks good - let it rip. */
if (do_brk(oldbrk, newbrk-oldbrk) != oldbrk) if (do_brk(oldbrk, newbrk-oldbrk) != oldbrk)
goto out; goto out;
......
...@@ -41,21 +41,22 @@ do_profile (unsigned long ip) ...@@ -41,21 +41,22 @@ do_profile (unsigned long ip)
extern unsigned long prof_cpu_mask; extern unsigned long prof_cpu_mask;
extern char _stext; extern char _stext;
if (!prof_buffer)
return;
if (!((1UL << smp_processor_id()) & prof_cpu_mask)) if (!((1UL << smp_processor_id()) & prof_cpu_mask))
return; return;
if (prof_buffer && current->pid) { ip -= (unsigned long) &_stext;
ip -= (unsigned long) &_stext; ip >>= prof_shift;
ip >>= prof_shift; /*
/* * Don't ignore out-of-bounds IP values silently, put them into the last
* Don't ignore out-of-bounds IP values silently, put them into the last * histogram slot, so if present, they will show up as a sharp peak.
* histogram slot, so if present, they will show up as a sharp peak. */
*/ if (ip > prof_len - 1)
if (ip > prof_len - 1) ip = prof_len - 1;
ip = prof_len - 1;
atomic_inc((atomic_t *) &prof_buffer[ip]); atomic_inc((atomic_t *) &prof_buffer[ip]);
}
} }
/* /*
...@@ -285,9 +286,9 @@ ia64_init_itm (void) ...@@ -285,9 +286,9 @@ ia64_init_itm (void)
} }
static struct irqaction timer_irqaction = { static struct irqaction timer_irqaction = {
handler: timer_interrupt, .handler = timer_interrupt,
flags: SA_INTERRUPT, .flags = SA_INTERRUPT,
name: "timer" .name = "timer"
}; };
void __init void __init
......
...@@ -49,10 +49,15 @@ static fpswa_interface_t *fpswa_interface; ...@@ -49,10 +49,15 @@ static fpswa_interface_t *fpswa_interface;
void __init void __init
trap_init (void) trap_init (void)
{ {
printk("fpswa interface at %lx\n", ia64_boot_param->fpswa); int major = 0, minor = 0;
if (ia64_boot_param->fpswa)
if (ia64_boot_param->fpswa) {
/* FPSWA fixup: make the interface pointer a kernel virtual address: */ /* FPSWA fixup: make the interface pointer a kernel virtual address: */
fpswa_interface = __va(ia64_boot_param->fpswa); fpswa_interface = __va(ia64_boot_param->fpswa);
major = fpswa_interface->revision & 0xffff;
minor = fpswa_interface->revision >> 16;
}
printk("fpswa interface at %lx (rev %d.%d)\n", ia64_boot_param->fpswa, major, minor);
} }
/* /*
...@@ -62,27 +67,26 @@ trap_init (void) ...@@ -62,27 +67,26 @@ trap_init (void)
void void
bust_spinlocks (int yes) bust_spinlocks (int yes)
{ {
int loglevel_save = console_loglevel;
spin_lock_init(&timerlist_lock); spin_lock_init(&timerlist_lock);
if (yes) { if (yes) {
oops_in_progress = 1; oops_in_progress = 1;
#ifdef CONFIG_SMP return;
global_irq_lock = 0; /* Many serial drivers do __global_cli() */ }
#endif
} else {
int loglevel_save = console_loglevel;
#ifdef CONFIG_VT #ifdef CONFIG_VT
unblank_screen(); unblank_screen();
#endif #endif
oops_in_progress = 0; oops_in_progress = 0;
/* /*
* OK, the message is on the console. Now we call printk() without * OK, the message is on the console. Now we call printk() without
* oops_in_progress set so that printk will give klogd a poke. Hold onto * oops_in_progress set so that printk will give klogd a poke. Hold onto
* your hats... * your hats...
*/ */
console_loglevel = 15; /* NMI oopser may have shut the console up */ console_loglevel = 15; /* NMI oopser may have shut the console up */
printk(" "); printk(" ");
console_loglevel = loglevel_save; console_loglevel = loglevel_save;
}
} }
void void
...@@ -93,9 +97,9 @@ die (const char *str, struct pt_regs *regs, long err) ...@@ -93,9 +97,9 @@ die (const char *str, struct pt_regs *regs, long err)
int lock_owner; int lock_owner;
int lock_owner_depth; int lock_owner_depth;
} die = { } die = {
lock: SPIN_LOCK_UNLOCKED, .lock = SPIN_LOCK_UNLOCKED,
lock_owner: -1, .lock_owner = -1,
lock_owner_depth: 0 .lock_owner_depth = 0
}; };
if (die.lock_owner != smp_processor_id()) { if (die.lock_owner != smp_processor_id()) {
...@@ -131,6 +135,8 @@ ia64_bad_break (unsigned long break_num, struct pt_regs *regs) ...@@ -131,6 +135,8 @@ ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
siginfo_t siginfo; siginfo_t siginfo;
int sig, code; int sig, code;
die_if_kernel("bad break", regs, break_num);
/* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */ /* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */
siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri); siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
siginfo.si_imm = break_num; siginfo.si_imm = break_num;
...@@ -247,10 +253,9 @@ disabled_fph_fault (struct pt_regs *regs) ...@@ -247,10 +253,9 @@ disabled_fph_fault (struct pt_regs *regs)
if (fpu_owner) if (fpu_owner)
ia64_flush_fph(fpu_owner); ia64_flush_fph(fpu_owner);
ia64_set_fpu_owner(current);
} }
#endif /* !CONFIG_SMP */ #endif /* !CONFIG_SMP */
ia64_set_fpu_owner(current);
if ((current->thread.flags & IA64_THREAD_FPH_VALID) != 0) { if ((current->thread.flags & IA64_THREAD_FPH_VALID) != 0) {
__ia64_load_fpu(current->thread.fph); __ia64_load_fpu(current->thread.fph);
psr->mfh = 0; psr->mfh = 0;
...@@ -435,7 +440,7 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, ...@@ -435,7 +440,7 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
unsigned long code, error = isr; unsigned long code, error = isr;
struct siginfo siginfo; struct siginfo siginfo;
char buf[128]; char buf[128];
int result; int result, sig;
static const char *reason[] = { static const char *reason[] = {
"IA-64 Illegal Operation fault", "IA-64 Illegal Operation fault",
"IA-64 Privileged Operation fault", "IA-64 Privileged Operation fault",
...@@ -479,6 +484,30 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, ...@@ -479,6 +484,30 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
break; break;
case 26: /* NaT Consumption */ case 26: /* NaT Consumption */
if (user_mode(regs)) {
if (((isr >> 4) & 0xf) == 2) {
/* NaT page consumption */
sig = SIGSEGV;
code = SEGV_ACCERR;
} else {
/* register NaT consumption */
sig = SIGILL;
code = ILL_ILLOPN;
}
siginfo.si_signo = sig;
siginfo.si_code = code;
siginfo.si_errno = 0;
siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
siginfo.si_imm = vector;
siginfo.si_flags = __ISR_VALID;
siginfo.si_isr = isr;
force_sig_info(sig, &siginfo, current);
return;
} else if (done_with_exception(regs))
return;
sprintf(buf, "NaT consumption");
break;
case 31: /* Unsupported Data Reference */ case 31: /* Unsupported Data Reference */
if (user_mode(regs)) { if (user_mode(regs)) {
siginfo.si_signo = SIGILL; siginfo.si_signo = SIGILL;
...@@ -491,7 +520,7 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, ...@@ -491,7 +520,7 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
force_sig_info(SIGILL, &siginfo, current); force_sig_info(SIGILL, &siginfo, current);
return; return;
} }
sprintf(buf, (vector == 26) ? "NaT consumption" : "Unsupported data reference"); sprintf(buf, "Unsupported data reference");
break; break;
case 29: /* Debug */ case 29: /* Debug */
...@@ -508,16 +537,15 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, ...@@ -508,16 +537,15 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
if (ia64_psr(regs)->is == 0) if (ia64_psr(regs)->is == 0)
ifa = regs->cr_iip; ifa = regs->cr_iip;
#endif #endif
siginfo.si_addr = (void *) ifa;
break; break;
case 35: siginfo.si_code = TRAP_BRANCH; break; case 35: siginfo.si_code = TRAP_BRANCH; ifa = 0; break;
case 36: siginfo.si_code = TRAP_TRACE; break; case 36: siginfo.si_code = TRAP_TRACE; ifa = 0; break;
} }
siginfo.si_signo = SIGTRAP; siginfo.si_signo = SIGTRAP;
siginfo.si_errno = 0; siginfo.si_errno = 0;
siginfo.si_flags = 0; siginfo.si_flags = 0;
siginfo.si_isr = 0; siginfo.si_isr = 0;
siginfo.si_addr = 0; siginfo.si_addr = (void *) ifa;
siginfo.si_imm = 0; siginfo.si_imm = 0;
force_sig_info(SIGTRAP, &siginfo, current); force_sig_info(SIGTRAP, &siginfo, current);
return; return;
......
...@@ -140,13 +140,13 @@ static struct { ...@@ -140,13 +140,13 @@ static struct {
} stat; } stat;
# endif # endif
} unw = { } unw = {
tables: &unw.kernel_table, .tables = &unw.kernel_table,
lock: SPIN_LOCK_UNLOCKED, .lock = SPIN_LOCK_UNLOCKED,
save_order: { .save_order = {
UNW_REG_RP, UNW_REG_PFS, UNW_REG_PSP, UNW_REG_PR, UNW_REG_RP, UNW_REG_PFS, UNW_REG_PSP, UNW_REG_PR,
UNW_REG_UNAT, UNW_REG_LC, UNW_REG_FPSR, UNW_REG_PRI_UNAT_GR UNW_REG_UNAT, UNW_REG_LC, UNW_REG_FPSR, UNW_REG_PRI_UNAT_GR
}, },
preg_index: { .preg_index = {
struct_offset(struct unw_frame_info, pri_unat_loc)/8, /* PRI_UNAT_GR */ struct_offset(struct unw_frame_info, pri_unat_loc)/8, /* PRI_UNAT_GR */
struct_offset(struct unw_frame_info, pri_unat_loc)/8, /* PRI_UNAT_MEM */ struct_offset(struct unw_frame_info, pri_unat_loc)/8, /* PRI_UNAT_MEM */
struct_offset(struct unw_frame_info, bsp_loc)/8, struct_offset(struct unw_frame_info, bsp_loc)/8,
...@@ -189,9 +189,9 @@ static struct { ...@@ -189,9 +189,9 @@ static struct {
struct_offset(struct unw_frame_info, fr_loc[30 - 16])/8, struct_offset(struct unw_frame_info, fr_loc[30 - 16])/8,
struct_offset(struct unw_frame_info, fr_loc[31 - 16])/8, struct_offset(struct unw_frame_info, fr_loc[31 - 16])/8,
}, },
hash : { [0 ... UNW_HASH_SIZE - 1] = -1 }, .hash = { [0 ... UNW_HASH_SIZE - 1] = -1 },
#if UNW_DEBUG #if UNW_DEBUG
preg_name: { .preg_name = {
"pri_unat_gr", "pri_unat_mem", "bsp", "bspstore", "ar.pfs", "ar.rnat", "psp", "rp", "pri_unat_gr", "pri_unat_mem", "bsp", "bspstore", "ar.pfs", "ar.rnat", "psp", "rp",
"r4", "r5", "r6", "r7", "r4", "r5", "r6", "r7",
"ar.unat", "pr", "ar.lc", "ar.fpsr", "ar.unat", "pr", "ar.lc", "ar.fpsr",
...@@ -634,8 +634,8 @@ alloc_spill_area (unsigned long *offp, unsigned long regsize, ...@@ -634,8 +634,8 @@ alloc_spill_area (unsigned long *offp, unsigned long regsize,
for (reg = hi; reg >= lo; --reg) { for (reg = hi; reg >= lo; --reg) {
if (reg->where == UNW_WHERE_SPILL_HOME) { if (reg->where == UNW_WHERE_SPILL_HOME) {
reg->where = UNW_WHERE_PSPREL; reg->where = UNW_WHERE_PSPREL;
reg->val = 0x10 - *offp; *offp -= regsize;
*offp += regsize; reg->val = *offp;
} }
} }
} }
...@@ -814,7 +814,8 @@ desc_frgr_mem (unsigned char grmask, unw_word frmask, struct unw_state_record *s ...@@ -814,7 +814,8 @@ desc_frgr_mem (unsigned char grmask, unw_word frmask, struct unw_state_record *s
} }
for (i = 0; i < 20; ++i) { for (i = 0; i < 20; ++i) {
if ((frmask & 1) != 0) { if ((frmask & 1) != 0) {
set_reg(sr->curr.reg + UNW_REG_F2 + i, UNW_WHERE_SPILL_HOME, int base = (i < 4) ? UNW_REG_F2 : UNW_REG_F16 - 4;
set_reg(sr->curr.reg + base + i, UNW_WHERE_SPILL_HOME,
sr->region_start + sr->region_len - 1, 0); sr->region_start + sr->region_len - 1, 0);
sr->any_spills = 1; sr->any_spills = 1;
} }
......
...@@ -6,43 +6,51 @@ L_TARGET = lib.a ...@@ -6,43 +6,51 @@ L_TARGET = lib.a
export-objs := swiotlb.o export-objs := swiotlb.o
obj-y := __divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \ obj-y := __divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \
__divdi3.o __udivdi3.o __moddi3.o __umoddi3.o \ __divdi3.o __udivdi3.o __moddi3.o __umoddi3.o \
checksum.o clear_page.o csum_partial_copy.o copy_page.o \ checksum.o clear_page.o csum_partial_copy.o copy_page.o \
copy_user.o clear_user.o strncpy_from_user.o strlen_user.o strnlen_user.o \ clear_user.o strncpy_from_user.o strlen_user.o strnlen_user.o \
flush.o io.o ip_fast_csum.o do_csum.o \ flush.o io.o ip_fast_csum.o do_csum.o \
memcpy.o memset.o strlen.o swiotlb.o memset.o strlen.o swiotlb.o
obj-$(CONFIG_ITANIUM) += copy_page.o obj-$(CONFIG_ITANIUM) += copy_page.o copy_user.o memcpy.o
obj-$(CONFIG_MCKINLEY) += copy_page_mck.o obj-$(CONFIG_MCKINLEY) += copy_page_mck.o memcpy_mck.o
IGNORE_FLAGS_OBJS = __divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \ IGNORE_FLAGS_OBJS = __divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \
__divdi3.o __udivdi3.o __moddi3.o __umoddi3.o __divdi3.o __udivdi3.o __moddi3.o __umoddi3.o
$(L_TARGET): $(obj-y) $(export-objs) include $(TOPDIR)/Rules.make
AFLAGS___divdi3.o =
AFLAGS___udivdi3.o = -DUNSIGNED
AFLAGS___moddi3.o = -DMODULO
AFLAGS___umoddi3.o = -DUNSIGNED -DMODULO
AFLAGS___divsi3.o =
AFLAGS___udivsi3.o = -DUNSIGNED
AFLAGS___modsi3.o = -DMODULO
AFLAGS___umodsi3.o = -DUNSIGNED -DMODULO
__divdi3.o: idiv64.S __divdi3.o: idiv64.S
$(CC) $(AFLAGS) -c -o $@ $< $(cmd_as_o_S)
__udivdi3.o: idiv64.S __udivdi3.o: idiv64.S
$(CC) $(AFLAGS) -c -DUNSIGNED -c -o $@ $< $(cmd_as_o_S)
__moddi3.o: idiv64.S __moddi3.o: idiv64.S
$(CC) $(AFLAGS) -c -DMODULO -c -o $@ $< $(cmd_as_o_S)
__umoddi3.o: idiv64.S __umoddi3.o: idiv64.S
$(CC) $(AFLAGS) -c -DMODULO -DUNSIGNED -c -o $@ $< $(cmd_as_o_S)
__divsi3.o: idiv32.S __divsi3.o: idiv32.S
$(CC) $(AFLAGS) -c -o $@ $< $(cmd_as_o_S)
__udivsi3.o: idiv32.S __udivsi3.o: idiv32.S
$(CC) $(AFLAGS) -c -DUNSIGNED -c -o $@ $< $(cmd_as_o_S)
__modsi3.o: idiv32.S __modsi3.o: idiv32.S
$(CC) $(AFLAGS) -c -DMODULO -c -o $@ $< $(cmd_as_o_S)
__umodsi3.o: idiv32.S __umodsi3.o: idiv32.S
$(CC) $(AFLAGS) -c -DMODULO -DUNSIGNED -c -o $@ $< $(cmd_as_o_S)
include $(TOPDIR)/Rules.make
...@@ -237,15 +237,17 @@ GLOBAL_ENTRY(__copy_user) ...@@ -237,15 +237,17 @@ GLOBAL_ENTRY(__copy_user)
.copy_user_bit##rshift: \ .copy_user_bit##rshift: \
1: \ 1: \
EX(.failure_out,(EPI) st8 [dst1]=tmp,8); \ EX(.failure_out,(EPI) st8 [dst1]=tmp,8); \
(EPI_1) shrp tmp=val1[PIPE_DEPTH-3],val1[PIPE_DEPTH-2],rshift; \ (EPI_1) shrp tmp=val1[PIPE_DEPTH-2],val1[PIPE_DEPTH-1],rshift; \
EX(3f,(p16) ld8 val1[0]=[src1],8); \ EX(3f,(p16) ld8 val1[1]=[src1],8); \
(p16) mov val1[0]=r0; \
br.ctop.dptk 1b; \ br.ctop.dptk 1b; \
;; \ ;; \
br.cond.sptk.many .diff_align_do_tail; \ br.cond.sptk.many .diff_align_do_tail; \
2: \ 2: \
(EPI) st8 [dst1]=tmp,8; \ (EPI) st8 [dst1]=tmp,8; \
(EPI_1) shrp tmp=val1[PIPE_DEPTH-3],val1[PIPE_DEPTH-2],rshift; \ (EPI_1) shrp tmp=val1[PIPE_DEPTH-2],val1[PIPE_DEPTH-1],rshift; \
3: \ 3: \
(p16) mov val1[1]=r0; \
(p16) mov val1[0]=r0; \ (p16) mov val1[0]=r0; \
br.ctop.dptk 2b; \ br.ctop.dptk 2b; \
;; \ ;; \
......
...@@ -87,6 +87,12 @@ ia64_outl (unsigned int val, unsigned long port) ...@@ -87,6 +87,12 @@ ia64_outl (unsigned int val, unsigned long port)
__ia64_outl(val, port); __ia64_outl(val, port);
} }
void
ia64_mmiob (void)
{
__ia64_mmiob();
}
/* define aliases: */ /* define aliases: */
asm (".global __ia64_inb, __ia64_inw, __ia64_inl"); asm (".global __ia64_inb, __ia64_inw, __ia64_inl");
...@@ -99,4 +105,7 @@ asm ("__ia64_outb = ia64_outb"); ...@@ -99,4 +105,7 @@ asm ("__ia64_outb = ia64_outb");
asm ("__ia64_outw = ia64_outw"); asm ("__ia64_outw = ia64_outw");
asm ("__ia64_outl = ia64_outl"); asm ("__ia64_outl = ia64_outl");
asm (".global __ia64_mmiob");
asm ("__ia64_mmiob = ia64_mmiob");
#endif /* CONFIG_IA64_GENERIC */ #endif /* CONFIG_IA64_GENERIC */
This diff is collapsed.
...@@ -415,18 +415,21 @@ int ...@@ -415,18 +415,21 @@ int
swiotlb_map_sg (struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int direction) swiotlb_map_sg (struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int direction)
{ {
void *addr; void *addr;
unsigned long pci_addr;
int i; int i;
if (direction == PCI_DMA_NONE) if (direction == PCI_DMA_NONE)
BUG(); BUG();
for (i = 0; i < nelems; i++, sg++) { for (i = 0; i < nelems; i++, sg++) {
sg->orig_address = SG_ENT_VIRT_ADDRESS(sg); addr = SG_ENT_VIRT_ADDRESS(sg);
if ((SG_ENT_PHYS_ADDRESS(sg) & ~hwdev->dma_mask) != 0) { pci_addr = virt_to_phys(addr);
addr = map_single(hwdev, sg->orig_address, sg->length, direction); if ((pci_addr & ~hwdev->dma_mask) != 0)
sg->page = virt_to_page(addr); sg->dma_address = (dma_addr_t)
sg->offset = (u64) addr & ~PAGE_MASK; map_single(hwdev, addr, sg->length, direction);
} else
sg->dma_address = pci_addr;
sg->dma_length = sg->length;
} }
return nelems; return nelems;
} }
...@@ -444,12 +447,10 @@ swiotlb_unmap_sg (struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int ...@@ -444,12 +447,10 @@ swiotlb_unmap_sg (struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int
BUG(); BUG();
for (i = 0; i < nelems; i++, sg++) for (i = 0; i < nelems; i++, sg++)
if (sg->orig_address != SG_ENT_VIRT_ADDRESS(sg)) { if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
unmap_single(hwdev, SG_ENT_VIRT_ADDRESS(sg), sg->length, direction); unmap_single(hwdev, (void *) sg->dma_address, sg->dma_length, direction);
sg->page = virt_to_page(sg->orig_address); else if (direction == PCI_DMA_FROMDEVICE)
sg->offset = (u64) sg->orig_address & ~PAGE_MASK; mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length);
} else if (direction == PCI_DMA_FROMDEVICE)
mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->length);
} }
/* /*
...@@ -468,14 +469,14 @@ swiotlb_sync_sg (struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int ...@@ -468,14 +469,14 @@ swiotlb_sync_sg (struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int
BUG(); BUG();
for (i = 0; i < nelems; i++, sg++) for (i = 0; i < nelems; i++, sg++)
if (sg->orig_address != SG_ENT_VIRT_ADDRESS(sg)) if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
sync_single(hwdev, SG_ENT_VIRT_ADDRESS(sg), sg->length, direction); sync_single(hwdev, (void *) sg->dma_address, sg->dma_length, direction);
} }
unsigned long unsigned long
swiotlb_dma_address (struct scatterlist *sg) swiotlb_dma_address (struct scatterlist *sg)
{ {
return SG_ENT_PHYS_ADDRESS(sg); return sg->dma_address;
} }
/* /*
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/personality.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/swap.h> #include <linux/swap.h>
...@@ -68,10 +69,9 @@ ia64_init_addr_space (void) ...@@ -68,10 +69,9 @@ ia64_init_addr_space (void)
struct vm_area_struct *vma; struct vm_area_struct *vma;
/* /*
* If we're out of memory and kmem_cache_alloc() returns NULL, * If we're out of memory and kmem_cache_alloc() returns NULL, we simply ignore
* we simply ignore the problem. When the process attempts to * the problem. When the process attempts to write to the register backing store
* write to the register backing store for the first time, it * for the first time, it will get a SEGFAULT in this case.
* will get a SEGFAULT in this case.
*/ */
vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
if (vma) { if (vma) {
...@@ -86,6 +86,19 @@ ia64_init_addr_space (void) ...@@ -86,6 +86,19 @@ ia64_init_addr_space (void)
vma->vm_private_data = NULL; vma->vm_private_data = NULL;
insert_vm_struct(current->mm, vma); insert_vm_struct(current->mm, vma);
} }
/* map NaT-page at address zero to speed up speculative dereferencing of NULL: */
if (!(current->personality & MMAP_PAGE_ZERO)) {
vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
if (vma) {
memset(vma, 0, sizeof(*vma));
vma->vm_mm = current->mm;
vma->vm_end = PAGE_SIZE;
vma->vm_page_prot = __pgprot(pgprot_val(PAGE_READONLY) | _PAGE_MA_NAT);
vma->vm_flags = VM_READ | VM_MAYREAD | VM_IO | VM_RESERVED;
insert_vm_struct(current->mm, vma);
}
}
} }
void void
...@@ -95,7 +108,7 @@ free_initmem (void) ...@@ -95,7 +108,7 @@ free_initmem (void)
addr = (unsigned long) &__init_begin; addr = (unsigned long) &__init_begin;
for (; addr < (unsigned long) &__init_end; addr += PAGE_SIZE) { for (; addr < (unsigned long) &__init_end; addr += PAGE_SIZE) {
clear_bit(PG_reserved, &virt_to_page(addr)->flags); ClearPageReserved(virt_to_page(addr));
set_page_count(virt_to_page(addr), 1); set_page_count(virt_to_page(addr), 1);
free_page(addr); free_page(addr);
++totalram_pages; ++totalram_pages;
...@@ -149,9 +162,9 @@ free_initrd_mem (unsigned long start, unsigned long end) ...@@ -149,9 +162,9 @@ free_initrd_mem (unsigned long start, unsigned long end)
if (!virt_addr_valid(start)) if (!virt_addr_valid(start))
continue; continue;
page = virt_to_page(start); page = virt_to_page(start);
clear_bit(PG_reserved, &page->flags); ClearPageReserved(page);
set_page_count(page, 1); set_page_count(page, 1);
__free_page(page); free_page(start);
++totalram_pages; ++totalram_pages;
} }
} }
......
...@@ -35,12 +35,14 @@ ...@@ -35,12 +35,14 @@
1 << _PAGE_SIZE_4K ) 1 << _PAGE_SIZE_4K )
struct ia64_ctx ia64_ctx = { struct ia64_ctx ia64_ctx = {
lock: SPIN_LOCK_UNLOCKED, .lock = SPIN_LOCK_UNLOCKED,
next: 1, .next = 1,
limit: (1 << 15) - 1, /* start out with the safe (architected) limit */ .limit = (1 << 15) - 1, /* start out with the safe (architected) limit */
max_ctx: ~0U .max_ctx = ~0U
}; };
u8 ia64_need_tlb_flush __per_cpu_data;
/* /*
* Acquire the ia64_ctx.lock before calling this function! * Acquire the ia64_ctx.lock before calling this function!
*/ */
...@@ -49,6 +51,7 @@ wrap_mmu_context (struct mm_struct *mm) ...@@ -49,6 +51,7 @@ wrap_mmu_context (struct mm_struct *mm)
{ {
unsigned long tsk_context, max_ctx = ia64_ctx.max_ctx; unsigned long tsk_context, max_ctx = ia64_ctx.max_ctx;
struct task_struct *tsk; struct task_struct *tsk;
int i;
if (ia64_ctx.next > max_ctx) if (ia64_ctx.next > max_ctx)
ia64_ctx.next = 300; /* skip daemons */ ia64_ctx.next = 300; /* skip daemons */
...@@ -77,7 +80,11 @@ wrap_mmu_context (struct mm_struct *mm) ...@@ -77,7 +80,11 @@ wrap_mmu_context (struct mm_struct *mm)
ia64_ctx.limit = tsk_context; ia64_ctx.limit = tsk_context;
} }
read_unlock(&tasklist_lock); read_unlock(&tasklist_lock);
flush_tlb_all(); /* can't call flush_tlb_all() here because of race condition with O(1) scheduler [EF] */
for (i = 0; i < NR_CPUS; ++i)
if (i != smp_processor_id())
per_cpu(ia64_need_tlb_flush, i) = 1;
__flush_tlb_all();
} }
void void
......
...@@ -279,9 +279,9 @@ static int ifconfig_net_ioctl(struct inode * inode, struct file * file, ...@@ -279,9 +279,9 @@ static int ifconfig_net_ioctl(struct inode * inode, struct file * file,
} }
struct file_operations ifconfig_net_fops = { struct file_operations ifconfig_net_fops = {
ioctl:ifconfig_net_ioctl, /* ioctl */ .ioctl =ifconfig_net_ioctl, /* ioctl */
open:ifconfig_net_open, /* open */ .open =ifconfig_net_open, /* open */
release:ifconfig_net_close /* release */ .release =ifconfig_net_close /* release */
}; };
......
...@@ -210,31 +210,31 @@ static void dump_allocations(struct list_head * dalp); ...@@ -210,31 +210,31 @@ static void dump_allocations(struct list_head * dalp);
/* file operations for each type of node */ /* file operations for each type of node */
static struct file_operations rom_fops = { static struct file_operations rom_fops = {
owner: THIS_MODULE, .owner = THIS_MODULE,
mmap: rom_mmap, .mmap = rom_mmap,
open: generic_open, .open = generic_open,
release: rom_release .release = rom_release
}; };
static struct file_operations base_fops = { static struct file_operations base_fops = {
owner: THIS_MODULE, .owner = THIS_MODULE,
mmap: base_mmap, .mmap = base_mmap,
open: generic_open .open = generic_open
}; };
static struct file_operations config_fops = { static struct file_operations config_fops = {
owner: THIS_MODULE, .owner = THIS_MODULE,
ioctl: config_ioctl, .ioctl = config_ioctl,
open: generic_open .open = generic_open
}; };
static struct file_operations dma_fops = { static struct file_operations dma_fops = {
owner: THIS_MODULE, .owner = THIS_MODULE,
ioctl: dma_ioctl, .ioctl = dma_ioctl,
mmap: dma_mmap, .mmap = dma_mmap,
open: generic_open .open = generic_open
}; };
......
...@@ -24,7 +24,7 @@ extern void hubni_error_handler(char *, int); /* huberror.c */ ...@@ -24,7 +24,7 @@ extern void hubni_error_handler(char *, int); /* huberror.c */
static int hubstats_ioctl(struct inode *, struct file *, unsigned int, unsigned long); static int hubstats_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
struct file_operations hub_mon_fops = { struct file_operations hub_mon_fops = {
ioctl: hubstats_ioctl, .ioctl = hubstats_ioctl,
}; };
#define HUB_CAPTURE_TICKS (2 * HZ) #define HUB_CAPTURE_TICKS (2 * HZ)
......
...@@ -307,22 +307,22 @@ extern void free_pciio_dmamap(pcibr_dmamap_t); ...@@ -307,22 +307,22 @@ extern void free_pciio_dmamap(pcibr_dmamap_t);
* appropriate function name below. * appropriate function name below.
*/ */
struct file_operations pcibr_fops = { struct file_operations pcibr_fops = {
owner: THIS_MODULE, .owner = THIS_MODULE,
llseek: NULL, .llseek = NULL,
read: NULL, .read = NULL,
write: NULL, .write = NULL,
readdir: NULL, .readdir = NULL,
poll: NULL, .poll = NULL,
ioctl: NULL, .ioctl = NULL,
mmap: NULL, .mmap = NULL,
open: NULL, .open = NULL,
flush: NULL, .flush = NULL,
release: NULL, .release = NULL,
fsync: NULL, .fsync = NULL,
fasync: NULL, .fasync = NULL,
lock: NULL, .lock = NULL,
readv: NULL, .readv = NULL,
writev: NULL .writev = NULL
}; };
extern devfs_handle_t hwgraph_root; extern devfs_handle_t hwgraph_root;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment