Commit 8e4a8959 authored by David Mosberger's avatar David Mosberger

Sync up with Linus's tree and resolve conflicts in perfmon.c.

parents c39e9205 5bedd81b
IRQ affinity on IA64 platforms
------------------------------
07.01.2002, Erich Focht <efocht@ess.nec.de>
By writing to /proc/irq/IRQ#/smp_affinity the interrupt routing can be
controlled. The behavior on IA64 platforms is slightly different from
that described in Documentation/IRQ-affinity.txt for i386 systems.
Because of the usage of SAPIC mode and physical destination mode the
IRQ target is one particular CPU and cannot be a mask of several
CPUs. Only the first non-zero bit is taken into account.
Usage examples:
The target CPU has to be specified as a hexadecimal CPU mask. The
first non-zero bit is the selected CPU. This format has been kept for
compatibility reasons with i386.
Set the delivery mode of interrupt 41 to fixed and route the
interrupts to CPU #3 (logical CPU number) (2^3=0x08):
echo "8" >/proc/irq/41/smp_affinity
Set the default route for IRQ number 41 to CPU 6 in lowest priority
delivery mode (redirectable):
echo "r 40" >/proc/irq/41/smp_affinity
The output of the command
cat /proc/irq/IRQ#/smp_affinity
gives the target CPU mask for the specified interrupt vector. If the CPU
mask is preceeded by the character "r", the interrupt is redirectable
(i.e. lowest priority mode routing is used), otherwise its route is
fixed.
Initialization and default behavior:
If the platform features IRQ redirection (info provided by SAL) all
IO-SAPIC interrupts are initialized with CPU#0 as their default target
and the routing is the so called "lowest priority mode" (actually
fixed SAPIC mode with hint). The XTP chipset registers are used as hints
for the IRQ routing. Currently in Linux XTP registers can have three
values:
- minimal for an idle task,
- normal if any other task runs,
- maximal if the CPU is going to be switched off.
The IRQ is routed to the CPU with lowest XTP register value, the
search begins at the default CPU. Therefore most of the interrupts
will be handled by CPU #0.
If the platform doesn't feature interrupt redirection IOSAPIC fixed
routing is used. The target CPUs are distributed in a round robin
manner. IRQs will be routed only to the selected target CPUs. Check
with
cat /proc/interrupts
Comments:
On large (multi-node) systems it is recommended to route the IRQs to
the node to which the corresponding device is connected.
For systems like the NEC AzusA we get IRQ node-affinity for free. This
is because usually the chipsets on each node redirect the interrupts
only to their own CPUs (as they cannot see the XTP registers on the
other nodes).
......@@ -245,14 +245,14 @@ MRPROPER_DIRS = \
include arch/$(ARCH)/Makefile
export CPPFLAGS CFLAGS AFLAGS
export CPPFLAGS CFLAGS CFLAGS_KERNEL AFLAGS AFLAGS_KERNEL
export NETWORKS DRIVERS LIBS HEAD LDFLAGS LINKFLAGS MAKEBOOT ASFLAGS
.S.s:
$(CPP) $(AFLAGS) -traditional -o $*.s $<
$(CPP) $(AFLAGS) $(AFLAGS_KERNEL) -traditional -o $*.s $<
.S.o:
$(CC) $(AFLAGS) -traditional -c -o $*.o $<
$(CC) $(AFLAGS) $(AFLAGS_KERNEL) -traditional -c -o $*.o $<
Version: dummy
@rm -f include/linux/compile.h
......
......@@ -25,7 +25,7 @@ CFLAGS_KERNEL := -mconstant-gp
GCC_VERSION=$(shell $(CROSS_COMPILE)$(HOSTCC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f1 -d'.')
ifneq ($(GCC_VERSION),2)
CFLAGS += -frename-registers --param max-inline-insns=400
CFLAGS += -frename-registers --param max-inline-insns=2000
endif
ifeq ($(CONFIG_ITANIUM_BSTEP_SPECIFIC),y)
......@@ -58,7 +58,7 @@ ifdef CONFIG_IA64_SGI_SN
CFLAGS += -DBRINGUP
SUBDIRS := arch/$(ARCH)/sn/kernel \
arch/$(ARCH)/sn/io \
arch/$(ARCH)/sn/fprom \
arch/$(ARCH)/sn/fakeprom \
$(SUBDIRS)
CORE_FILES := arch/$(ARCH)/sn/kernel/sn.o \
arch/$(ARCH)/sn/io/sgiio.o \
......
......@@ -119,6 +119,7 @@ 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
......@@ -230,7 +231,7 @@ if [ "$CONFIG_IA64_HP_SIM" != "n" -o "$CONFIG_IA64_GENERIC" != "n" ]; then
mainmenu_option next_comment
comment 'Simulated drivers'
tristate 'Simulated Ethernet ' CONFIG_SIMETH
bool 'Simulated Ethernet ' CONFIG_SIMETH
bool 'Simulated serial driver support' CONFIG_SIM_SERIAL
if [ "$CONFIG_SCSI" != "n" ]; then
bool 'Simulated SCSI disk' CONFIG_SCSI_SIM
......@@ -252,13 +253,20 @@ if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then
bool ' Disable VHPT' CONFIG_DISABLE_VHPT
bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ
# early printk is currently broken for SMP: the secondary processors get stuck...
# bool ' Early printk support (requires VGA!)' CONFIG_IA64_EARLY_PRINTK
bool ' Early printk support (requires VGA!)' CONFIG_IA64_EARLY_PRINTK
bool ' Debug memory allocations' CONFIG_DEBUG_SLAB
bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK
bool ' Turn on compare-and-exchange bug checking (slow!)' CONFIG_IA64_DEBUG_CMPXCHG
bool ' Turn on irq debug checks (slow!)' CONFIG_IA64_DEBUG_IRQ
bool ' Built-in Kernel Debugger support' CONFIG_KDB
dep_tristate ' KDB modules' CONFIG_KDB_MODULES $CONFIG_KDB
if [ "$CONFIG_KDB" = "y" ]; then
bool ' KDB off by default' CONFIG_KDB_OFF
comment ' Load all symbols for debugging is required for KDB'
define_bool CONFIG_KALLSYMS y
else
bool ' Load all symbols for debugging' CONFIG_KALLSYMS
fi
fi
endmenu
......@@ -33,6 +33,7 @@
* is sufficient (the IDE driver will autodetect the drive geometry).
*/
char drive_info[4*16];
extern int pcat_compat;
unsigned char aux_device_present = 0xaa; /* XXX remove this when legacy I/O is gone */
......@@ -81,13 +82,19 @@ dig_setup (char **cmdline_p)
screen_info.orig_video_ega_bx = 3; /* XXX fake */
}
void
void __init
dig_irq_init (void)
{
if (pcat_compat) {
/*
* Disable the compatibility mode interrupts (8259 style), needs IN/OUT support
* enabled.
*/
printk("%s: Disabling PC-AT compatible 8259 interrupts\n", __FUNCTION__);
outb(0xff, 0xA1);
outb(0xff, 0x21);
} else {
printk("%s: System doesn't have PC-AT compatible dual-8259 setup. "
"Nothing to be done\n", __FUNCTION__);
}
}
/*
* Platform dependent support for HP simulator.
*
* Copyright (C) 1998, 1999 Hewlett-Packard Co
* Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 1998, 1999, 2002 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 1999 Vijay Chander <vijay@engr.sgi.com>
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/tty.h>
#include <linux/kdev_t.h>
#include <linux/console.h>
......@@ -57,5 +60,5 @@ simcons_write (struct console *cons, const char *buf, unsigned count)
static kdev_t
simcons_console_device (struct console *c)
{
return MKDEV(TTY_MAJOR, 64 + c->index);
return mk_kdev(TTY_MAJOR, 64 + c->index);
}
......@@ -142,10 +142,11 @@ ia64_elf32_init (struct pt_regs *regs)
/*
* Setup GDTD. Note: GDTD is the descrambled version of the pseudo-descriptor
* format defined by Figure 3-11 "Pseudo-Descriptor Format" in the IA-32
* architecture manual.
* architecture manual. Also note that the only fields that are not ignored are
* `base', `limit', 'G', `P' (must be 1) and `S' (must be 0).
*/
regs->r31 = IA32_SEG_UNSCRAMBLE(IA32_SEG_DESCRIPTOR(IA32_GDT_OFFSET, IA32_PAGE_SIZE - 1, 0,
0, 0, 0, 0, 0, 0));
regs->r31 = IA32_SEG_UNSCRAMBLE(IA32_SEG_DESCRIPTOR(IA32_GDT_OFFSET, IA32_PAGE_SIZE - 1,
0, 0, 0, 1, 0, 0, 0));
/* Setup the segment selectors */
regs->r16 = (__USER_DS << 16) | __USER_DS; /* ES == DS, GS, FS are zero */
regs->r17 = (__USER_DS << 16) | __USER_CS; /* SS, CS; ia32_load_state() sets TSS and LDT */
......@@ -206,6 +207,7 @@ elf32_set_personality (void)
set_personality(PER_LINUX32);
current->thread.map_base = IA32_PAGE_OFFSET/3;
current->thread.task_size = IA32_PAGE_OFFSET; /* use what Linux/x86 uses... */
current->thread.flags |= IA64_THREAD_XSTACK; /* data must be executable */
set_fs(USER_DS); /* set addr limit for new TASK_SIZE */
}
......
......@@ -37,7 +37,7 @@ ENTRY(ia32_clone)
mov loc1=r16 // save ar.pfs across do_fork
.body
zxt4 out1=in1 // newsp
mov out3=0 // stacksize
mov out3=16 // stacksize (compensates for 16-byte scratch area)
adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = &regs
zxt4 out0=in0 // out0 = clone_flags
br.call.sptk.many rp=do_fork
......@@ -98,7 +98,7 @@ GLOBAL_ENTRY(ia32_ret_from_clone)
ld8 r2=[r2]
;;
mov r8=0
tbit.nz p6,p0=r2,PT_TRACESYS_BIT
tbit.nz p6,p0=r2,PT_SYSCALLTRACE_BIT
(p6) br.cond.spnt .ia32_strace_check_retval
;; // prevent RAW on r8
END(ia32_ret_from_clone)
......@@ -220,7 +220,7 @@ ia32_syscall_table:
data8 sys32_pipe
data8 sys32_times
data8 sys32_ni_syscall /* old prof syscall holder */
data8 sys_brk /* 45 */
data8 sys32_brk /* 45 */
data8 sys_setgid /* 16-bit version */
data8 sys_getgid /* 16-bit version */
data8 sys32_signal
......
......@@ -3,12 +3,14 @@
*
* Copyright (C) 2000 VA Linux Co
* Copyright (C) 2000 Don Dugger <n0ano@valinux.com>
* Copyright (C) 2001 Hewlett-Packard Co
* Copyright (C) 2001-2002 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
*/
#include <linux/types.h>
#include <linux/dirent.h>
#include <linux/fs.h> /* argh, msdos_fs.h isn't self-contained... */
#include <linux/msdos_fs.h>
#include <linux/mtio.h>
#include <linux/ncp_fs.h>
......@@ -79,6 +81,38 @@ sys32_ioctl (unsigned int fd, unsigned int cmd, unsigned int arg)
return ret;
}
case IOCTL_NR(SIOCGIFCONF):
{
struct ifconf32 {
int ifc_len;
unsigned int ifc_ptr;
} ifconf32;
struct ifconf ifconf;
int i, n;
char *p32, *p64;
char buf[32]; /* sizeof IA32 ifreq structure */
if (copy_from_user(&ifconf32, P(arg), sizeof(ifconf32)))
return -EFAULT;
ifconf.ifc_len = ifconf32.ifc_len;
ifconf.ifc_req = P(ifconf32.ifc_ptr);
ret = DO_IOCTL(fd, SIOCGIFCONF, &ifconf);
ifconf32.ifc_len = ifconf.ifc_len;
if (copy_to_user(P(arg), &ifconf32, sizeof(ifconf32)))
return -EFAULT;
n = ifconf.ifc_len / sizeof(struct ifreq);
p32 = P(ifconf32.ifc_ptr);
p64 = P(ifconf32.ifc_ptr);
for (i = 0; i < n; i++) {
if (copy_from_user(buf, p64, sizeof(struct ifreq)))
return -EFAULT;
if (copy_to_user(p32, buf, sizeof(buf)))
return -EFAULT;
p32 += sizeof(buf);
p64 += sizeof(struct ifreq);
}
return ret;
}
case IOCTL_NR(DRM_IOCTL_VERSION):
{
......
/*
* IA32 Architecture-specific signal handling support.
*
* Copyright (C) 1999, 2001 Hewlett-Packard Co
* Copyright (C) 1999, 2001-2002 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 1999 Arun Sharma <arun.sharma@intel.com>
* Copyright (C) 2000 VA Linux Co
......@@ -522,6 +522,7 @@ get_sigframe (struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
static int
setup_frame_ia32 (int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs)
{
struct exec_domain *ed = current_thread_info()->exec_domain;
struct sigframe_ia32 *frame;
int err = 0;
......@@ -530,12 +531,8 @@ setup_frame_ia32 (int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;
err |= __put_user((current->exec_domain
&& current->exec_domain->signal_invmap
&& sig < 32
? (int)(current->exec_domain->signal_invmap[sig])
: sig),
&frame->sig);
err |= __put_user((ed && ed->signal_invmap && sig < 32
? (int)(ed->signal_invmap[sig]) : sig), &frame->sig);
err |= setup_sigcontext_ia32(&frame->sc, &frame->fpstate, regs, set->sig[0]);
......@@ -590,6 +587,7 @@ static int
setup_rt_frame_ia32 (int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs * regs)
{
struct exec_domain *ed = current_thread_info()->exec_domain;
struct rt_sigframe_ia32 *frame;
int err = 0;
......@@ -598,12 +596,8 @@ setup_rt_frame_ia32 (int sig, struct k_sigaction *ka, siginfo_t *info,
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;
err |= __put_user((current->exec_domain
&& current->exec_domain->signal_invmap
&& sig < 32
? current->exec_domain->signal_invmap[sig]
: sig),
&frame->sig);
err |= __put_user((ed && ed->signal_invmap
&& sig < 32 ? ed->signal_invmap[sig] : sig), &frame->sig);
err |= __put_user((long)&frame->info, &frame->pinfo);
err |= __put_user((long)&frame->uc, &frame->puc);
err |= copy_siginfo_to_user32(&frame->info, info);
......
......@@ -3,7 +3,7 @@
*
* Copyright (C) 1999 Arun Sharma <arun.sharma@intel.com>
* Copyright (C) 2000 Asit K. Mallick <asit.k.mallick@intel.com>
* Copyright (C) 2001 Hewlett-Packard Co
* Copyright (C) 2001-2002 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
*
* 06/16/00 A. Mallick added csd/ssd/tssd for ia32 thread context
......@@ -153,9 +153,11 @@ ia32_gdt_init (void)
/* We never change the TSS and LDT descriptors, so we can share them across all CPUs. */
ldt_size = PAGE_ALIGN(IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE);
for (nr = 0; nr < NR_CPUS; ++nr) {
ia32_gdt[_TSS(nr)] = IA32_SEG_DESCRIPTOR(IA32_TSS_OFFSET, 235,
ia32_gdt[_TSS(nr) >> IA32_SEGSEL_INDEX_SHIFT]
= IA32_SEG_DESCRIPTOR(IA32_TSS_OFFSET, 235,
0xb, 0, 3, 1, 1, 1, 0);
ia32_gdt[_LDT(nr)] = IA32_SEG_DESCRIPTOR(IA32_LDT_OFFSET, ldt_size - 1,
ia32_gdt[_LDT(nr) >> IA32_SEGSEL_INDEX_SHIFT]
= IA32_SEG_DESCRIPTOR(IA32_LDT_OFFSET, ldt_size - 1,
0x2, 0, 3, 1, 1, 1, 0);
}
}
......@@ -172,6 +174,10 @@ ia32_bad_interrupt (unsigned long int_num, struct pt_regs *regs)
siginfo.si_signo = SIGTRAP;
siginfo.si_errno = int_num; /* XXX is it OK to abuse si_errno like this? */
siginfo.si_flags = 0;
siginfo.si_isr = 0;
siginfo.si_addr = 0;
siginfo.si_imm = 0;
siginfo.si_code = TRAP_BRKPT;
force_sig_info(SIGTRAP, &siginfo, current);
}
......
......@@ -2,7 +2,7 @@
* IA-32 exception handlers
*
* Copyright (C) 2000 Asit K. Mallick <asit.k.mallick@intel.com>
* Copyright (C) 2001 Hewlett-Packard Co
* Copyright (C) 2001-2002 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
*
* 06/16/00 A. Mallick added siginfo for most cases (close to IA32)
......@@ -40,7 +40,11 @@ ia32_exception (struct pt_regs *regs, unsigned long isr)
{
struct siginfo siginfo;
/* initialize these fields to avoid leaking kernel bits to user space: */
siginfo.si_errno = 0;
siginfo.si_flags = 0;
siginfo.si_isr = 0;
siginfo.si_imm = 0;
switch ((isr >> 16) & 0xff) {
case 1:
case 2:
......@@ -103,6 +107,8 @@ ia32_exception (struct pt_regs *regs, unsigned long isr)
* and it will suffer the consequences since we won't be able to
* fully reproduce the context of the exception
*/
siginfo.si_isr = isr;
siginfo.si_flags = __ISR_VALID;
switch(((~fcr) & (fsr & 0x3f)) | (fsr & 0x240)) {
case 0x000:
default:
......
......@@ -6,7 +6,7 @@
* Copyright (C) 1999 Arun Sharma <arun.sharma@intel.com>
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
* Copyright (C) 2000-2001 Hewlett-Packard Co
* Copyright (C) 2000-2002 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
*
* These routines maintain argument size conversion between 32bit and 64bit
......@@ -74,6 +74,9 @@
#define PAGE_START(addr) ((addr) & PAGE_MASK)
#define PAGE_OFF(addr) ((addr) & ~PAGE_MASK)
#define high2lowuid(uid) ((uid) > 65535 ? 65534 : (uid))
#define high2lowgid(gid) ((gid) > 65535 ? 65534 : (gid))
extern asmlinkage long sys_execve (char *, char **, char **, struct pt_regs *);
extern asmlinkage long sys_mprotect (unsigned long, size_t, unsigned long);
extern asmlinkage long sys_munmap (unsigned long, size_t);
......@@ -82,6 +85,7 @@ extern unsigned long arch_get_unmapped_area (struct file *, unsigned long, unsig
/* forward declaration: */
asmlinkage long sys32_mprotect (unsigned int, unsigned int, int);
asmlinkage unsigned long sys_brk(unsigned long);
/*
* Anything that modifies or inspects ia32 user virtual memory must hold this semaphore
......@@ -400,7 +404,7 @@ emulate_mmap (struct file *file, unsigned long start, unsigned long len, int pro
return -EINVAL;
}
if (!(prot & PROT_WRITE) && sys_mprotect(pstart, pend - pstart, prot) < 0)
return EINVAL;
return -EINVAL;
}
return start;
}
......@@ -2578,6 +2582,7 @@ sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
default:
return -EINVAL;
}
return -EINVAL;
}
/*
......@@ -3783,6 +3788,19 @@ sys32_personality (unsigned int personality)
return ret;
}
asmlinkage unsigned long
sys32_brk (unsigned int brk)
{
unsigned long ret, obrk;
struct mm_struct *mm = current->mm;
obrk = mm->brk;
ret = sys_brk(brk);
if (ret < obrk)
clear_user((void *) ret, PAGE_ALIGN(ret) - ret);
return ret;
}
#ifdef NOTYET /* UNTESTED FOR IA64 FROM HERE DOWN */
struct ncp_mount_data32 {
......
......@@ -5,11 +5,11 @@
* 'IA-64 Extensions to ACPI Specification' Revision 0.6
*
* Copyright (C) 1999 VA Linux Systems
* Copyright (C) 1999,2000 Walt Drummond <drummond@valinux.com>
* Copyright (C) 2000 Hewlett-Packard Co.
* Copyright (C) 2000 David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 1999, 2000 Walt Drummond <drummond@valinux.com>
* Copyright (C) 2000, 2002 Hewlett-Packard Co.
* David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 2000 Intel Corp.
* Copyright (C) 2000,2001 J.I. Lee <jung-ik.lee@intel.com>
* Copyright (C) 2000, 2001 J.I. Lee <jung-ik.lee@intel.com>
* ACPI based kernel configuration manager.
* ACPI 2.0 & IA64 ext 0.71
*/
......@@ -44,6 +44,8 @@ int platform_irq_list[ACPI_MAX_PLATFORM_IRQS];
int __initdata available_cpus;
int __initdata total_cpus;
int __initdata pcat_compat;
void (*pm_idle) (void);
void (*pm_power_off) (void);
......@@ -293,6 +295,16 @@ acpi20_parse_madt (acpi_madt_t *madt)
} else
printk("Lapic address set to default 0x%lx\n", ipi_base_addr);
/*
* The PCAT_COMPAT flag indicates that the system has a dual-8259 compatible
* setup.
*/
#ifdef CONFIG_ITANIUM
pcat_compat = 1; /* fw on some Itanium systems is broken... */
#else
pcat_compat = (madt->flags & MADT_PCAT_COMPAT);
#endif
p = (char *) (madt + 1);
end = p + (madt->header.length - sizeof(acpi_madt_t));
......@@ -319,17 +331,7 @@ acpi20_parse_madt (acpi_madt_t *madt)
case ACPI20_ENTRY_IO_SAPIC:
iosapic = (acpi_entry_iosapic_t *) p;
if (iosapic_init)
/*
* The PCAT_COMPAT flag indicates that the system has a
* dual-8259 compatible setup.
*/
iosapic_init(iosapic->address, iosapic->irq_base,
#ifdef CONFIG_ITANIUM
1 /* fw on some Itanium systems is broken... */
#else
(madt->flags & MADT_PCAT_COMPAT)
#endif
);
iosapic_init(iosapic->address, iosapic->irq_base, pcat_compat);
break;
case ACPI20_ENTRY_PLATFORM_INT_SOURCE:
......@@ -401,7 +403,7 @@ acpi20_parse (acpi20_rsdp_t *rsdp20)
# ifdef CONFIG_ACPI
acpi_xsdt_t *xsdt;
acpi_desc_table_hdr_t *hdrp;
acpi_madt_t *madt;
acpi_madt_t *madt = NULL;
int tables, i;
if (strncmp(rsdp20->signature, ACPI_RSDP_SIG, ACPI_RSDP_SIG_LEN)) {
......
......@@ -2,6 +2,9 @@
* Emulation of the "brl" instruction for IA64 processors that
* don't support it in hardware.
* Author: Stephan Zeisset, Intel Corp. <Stephan.Zeisset@intel.com>
*
* 02/22/02 D. Mosberger Clear si_flgs, si_isr, and si_imm to avoid
* leaking kernel bits.
*/
#include <linux/kernel.h>
......@@ -195,6 +198,9 @@ ia64_emulate_brl (struct pt_regs *regs, unsigned long ar_ec)
printk("Woah! Unimplemented Instruction Address Trap!\n");
siginfo.si_signo = SIGILL;
siginfo.si_errno = 0;
siginfo.si_flags = 0;
siginfo.si_isr = 0;
siginfo.si_imm = 0;
siginfo.si_code = ILL_BADIADDR;
force_sig_info(SIGILL, &siginfo, current);
} else if (ia64_psr(regs)->tb) {
......@@ -205,6 +211,10 @@ ia64_emulate_brl (struct pt_regs *regs, unsigned long ar_ec)
siginfo.si_signo = SIGTRAP;
siginfo.si_errno = 0;
siginfo.si_code = TRAP_BRANCH;
siginfo.si_flags = 0;
siginfo.si_isr = 0;
siginfo.si_addr = 0;
siginfo.si_imm = 0;
force_sig_info(SIGTRAP, &siginfo, current);
} else if (ia64_psr(regs)->ss) {
/*
......@@ -214,6 +224,10 @@ ia64_emulate_brl (struct pt_regs *regs, unsigned long ar_ec)
siginfo.si_signo = SIGTRAP;
siginfo.si_errno = 0;
siginfo.si_code = TRAP_TRACE;
siginfo.si_flags = 0;
siginfo.si_isr = 0;
siginfo.si_addr = 0;
siginfo.si_imm = 0;
force_sig_info(SIGTRAP, &siginfo, current);
}
return rv;
......
......@@ -29,6 +29,11 @@
*
* Changelog:
*
* 12 Feb 2002 - Matt Domsch <Matt_Domsch@dell.com>
* use list_for_each_safe when deleting vars.
* remove ifdef CONFIG_SMP around include <linux/smp.h>
* v0.04 release to linux-ia64@linuxia64.org
*
* 20 April 2001 - Matt Domsch <Matt_Domsch@dell.com>
* Moved vars from /proc/efi to /proc/efi/vars, and made
* efi.c own the /proc/efi directory.
......@@ -56,18 +61,16 @@
#include <linux/sched.h> /* for capable() */
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/smp.h>
#include <asm/efi.h>
#include <asm/uaccess.h>
#ifdef CONFIG_SMP
#include <linux/smp.h>
#endif
MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>");
MODULE_DESCRIPTION("/proc interface to EFI Variables");
MODULE_LICENSE("GPL");
#define EFIVARS_VERSION "0.03 2001-Apr-20"
#define EFIVARS_VERSION "0.04 2002-Feb-12"
static int
efivar_read(char *page, char **start, off_t off,
......@@ -265,7 +268,7 @@ efivar_write(struct file *file, const char *buffer,
{
unsigned long strsize1, strsize2;
int found=0;
struct list_head *pos;
struct list_head *pos, *n;
unsigned long size = sizeof(efi_variable_t);
efi_status_t status;
efivar_entry_t *efivar = data, *search_efivar = NULL;
......@@ -297,7 +300,7 @@ efivar_write(struct file *file, const char *buffer,
This allows any properly formatted data structure to
be written to any of the files in /proc/efi/vars and it will work.
*/
list_for_each(pos, &efivar_list) {
list_for_each_safe(pos, n, &efivar_list) {
search_efivar = efivar_entry(pos);
strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024);
strsize2 = utf8_strsize(var_data->VariableName, 1024);
......@@ -413,12 +416,12 @@ efivars_init(void)
static void __exit
efivars_exit(void)
{
struct list_head *pos;
struct list_head *pos, *n;
efivar_entry_t *efivar;
spin_lock(&efivars_lock);
list_for_each(pos, &efivar_list) {
list_for_each_safe(pos, n, &efivar_list) {
efivar = efivar_entry(pos);
remove_proc_entry(efivar->entry->name, efi_vars_dir);
list_del(&efivar->list);
......
......@@ -3,7 +3,7 @@
*
* Kernel entry points.
*
* Copyright (C) 1998-2001 Hewlett-Packard Co
* Copyright (C) 1998-2002 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 1999 VA Linux Systems
* Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
......@@ -30,14 +30,15 @@
#include <linux/config.h>
#include <asm/asmmacro.h>
#include <asm/cache.h>
#include <asm/errno.h>
#include <asm/kregs.h>
#include <asm/offsets.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
#include <asm/thread_info.h>
#include <asm/unistd.h>
#include <asm/asmmacro.h>
#include <asm/pgtable.h>
#include "minstate.h"
......@@ -115,7 +116,7 @@ GLOBAL_ENTRY(sys_clone)
mov loc1=r16 // save ar.pfs across do_fork
.body
mov out1=in1
mov out3=0
mov out3=16 // stacksize (compensates for 16-byte scratch area)
adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = &regs
mov out0=in0 // out0 = clone_flags
br.call.sptk.many rp=do_fork
......@@ -128,6 +129,9 @@ END(sys_clone)
/*
* prev_task <- ia64_switch_to(struct task_struct *next)
* With Ingo's new scheduler, interrupts are disabled when this routine gets
* called. The code starting at .map relies on this. The rest of the code
* doesn't care about the interrupt masking status.
*/
GLOBAL_ENTRY(ia64_switch_to)
.prologue
......@@ -158,10 +162,8 @@ GLOBAL_ENTRY(ia64_switch_to)
(p6) srlz.d
ld8 sp=[r21] // load kernel stack pointer of new task
mov IA64_KR(CURRENT)=r20 // update "current" application register
mov r8=r13 // return pointer to previously running task
mov r13=in0 // set "current" pointer
;;
(p6) ssm psr.i // renable psr.i AFTER the ic bit is serialized
DO_LOAD_SWITCH_STACK
#ifdef CONFIG_SMP
......@@ -170,7 +172,7 @@ GLOBAL_ENTRY(ia64_switch_to)
br.ret.sptk.many rp // boogie on out in new context
.map:
rsm psr.i | psr.ic
rsm psr.ic // interrupts (psr.i) are already disabled here
movl r25=PAGE_KERNEL
;;
srlz.d
......@@ -433,7 +435,7 @@ GLOBAL_ENTRY(invoke_syscall_trace)
.body
mov loc2=b6
;;
#error br.call.sptk.many rp=syscall_trace
br.call.sptk.many rp=syscall_trace
.ret3: mov rp=loc0
mov ar.pfs=loc1
mov b6=loc2
......@@ -454,7 +456,7 @@ END(invoke_syscall_trace)
GLOBAL_ENTRY(ia64_trace_syscall)
PT_REGS_UNWIND_INFO(0)
#error br.call.sptk.many rp=invoke_syscall_trace // give parent a chance to catch syscall args
br.call.sptk.many rp=invoke_syscall_trace // give parent a chance to catch syscall args
.ret6: br.call.sptk.many rp=b6 // do the syscall
strace_check_retval:
cmp.lt p6,p0=r8,r0 // syscall failed?
......@@ -467,7 +469,7 @@ strace_save_retval:
.mem.offset 0,0; st8.spill [r2]=r8 // store return value in slot for r8
.mem.offset 8,0; st8.spill [r3]=r10 // clear error indication in slot for r10
ia64_strace_leave_kernel:
#error br.call.sptk.many rp=invoke_syscall_trace // give parent a chance to catch return value
br.call.sptk.many rp=invoke_syscall_trace // give parent a chance to catch return value
.rety: br.cond.sptk ia64_leave_kernel
strace_error:
......@@ -491,12 +493,12 @@ GLOBAL_ENTRY(ia64_ret_from_clone)
*/
br.call.sptk.many rp=ia64_invoke_schedule_tail
.ret8:
adds r2=IA64_TASK_PTRACE_OFFSET,r13
adds r2=TI_FLAGS+IA64_TASK_SIZE,r13
;;
ld8 r2=[r2]
ld4 r2=[r2]
;;
mov r8=0
tbit.nz p6,p0=r2,PT_TRACESYS_BIT
tbit.nz p6,p0=r2,TIF_SYSCALL_TRACE
(p6) br.cond.spnt strace_check_retval
;; // added stop bits to prevent r8 dependency
END(ia64_ret_from_clone)
......@@ -516,50 +518,29 @@ END(ia64_ret_from_syscall)
// fall through
GLOBAL_ENTRY(ia64_leave_kernel)
PT_REGS_UNWIND_INFO(0)
lfetch.fault [sp]
movl r14=.restart
;;
mov.ret.sptk rp=r14,.restart
.restart:
adds r17=IA64_TASK_NEED_RESCHED_OFFSET,r13
adds r18=IA64_TASK_SIGPENDING_OFFSET,r13
#ifdef CONFIG_PERFMON
adds r19=IA64_TASK_PFM_MUST_BLOCK_OFFSET,r13
#endif
;;
#ifdef CONFIG_PERFMON
(pUser) ld8 r19=[r19] // load current->thread.pfm_must_block
#endif
#error (pUser) ld8 r17=[r17] // load current->need_resched
#error (pUser) ld4 r18=[r18] // load current->sigpending
// work.need_resched etc. mustn't get changed by this CPU before it returns to userspace:
(pUser) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUser
(pUser) rsm psr.i
;;
#ifdef CONFIG_PERFMON
(pUser) cmp.ne.unc p9,p0=r19,r0 // current->thread.pfm_must_block != 0?
#endif
#error (pUser) cmp.ne.unc p7,p0=r17,r0 // current->need_resched != 0?
#errror (pUser) cmp.ne.unc p8,p0=r18,r0 // current->sigpending != 0?
(pUser) adds r17=TI_FLAGS+IA64_TASK_SIZE,r13
;;
.work_processed:
(p6) ld4 r18=[r17] // load current_thread_info()->flags
adds r2=PT(R8)+16,r12
adds r3=PT(R9)+16,r12
#ifdef CONFIG_PERFMON
(p9) br.call.spnt.many b7=pfm_block_on_overflow
#endif
#if __GNUC__ < 3
(p7) br.call.spnt.many b7=invoke_schedule
#else
(p7) br.call.spnt.many b7=schedule
#endif
(p8) br.call.spnt.many b7=handle_signal_delivery // check & deliver pending signals
;;
// start restoring the state saved on the kernel stack (struct pt_regs):
ld8.fill r8=[r2],16
ld8.fill r9=[r3],16
(p6) and r19=TIF_WORK_MASK,r18 // any work other than TIF_SYSCALL_TRACE?
;;
ld8.fill r10=[r2],16
ld8.fill r11=[r3],16
(p6) cmp4.ne.unc p6,p0=r19, r0 // any special work pending?
;;
ld8.fill r16=[r2],16
ld8.fill r17=[r3],16
(p6) br.cond.spnt .work_pending
;;
ld8.fill r18=[r2],16
ld8.fill r19=[r3],16
......@@ -582,7 +563,7 @@ GLOBAL_ENTRY(ia64_leave_kernel)
ld8.fill r30=[r2],16
ld8.fill r31=[r3],16
;;
rsm psr.i | psr.ic // initiate turning off of interrupts & interruption collection
rsm psr.i | psr.ic // initiate turning off of interrupt and interruption collection
invala // invalidate ALAT
;;
ld8 r1=[r2],16 // ar.ccv
......@@ -601,7 +582,7 @@ GLOBAL_ENTRY(ia64_leave_kernel)
mov ar.fpsr=r13
mov b0=r14
;;
srlz.i // ensure interrupts & interruption collection are off
srlz.i // ensure interruption collection is off
mov b7=r15
;;
bsw.0 // switch back to bank 0
......@@ -729,6 +710,25 @@ skip_rbs_switch:
mov ar.unat=rARUNAT
mov pr=rARPR,-1
rfi
.work_pending:
tbit.z p6,p0=r18,TIF_NEED_RESCHED // current_thread_info()->need_resched==0?
(p6) br.cond.sptk.few .notify
#if __GNUC__ < 3
br.call.spnt.many rp=invoke_schedule
#else
br.call.spnt.many rp=schedule
#endif
.ret9: cmp.eq p6,p0=r0,r0 // p6 <- 1
rsm psr.i
;;
adds r17=TI_FLAGS+IA64_TASK_SIZE,r13
br.cond.sptk.many .work_processed // re-check
.notify:
br.call.spnt.many rp=notify_resume_user
.ret10: cmp.ne p6,p0=r0,r0 // p6 <- 0
br.cond.sptk.many .work_processed // don't re-check
END(ia64_leave_kernel)
ENTRY(handle_syscall_error)
......@@ -802,7 +802,7 @@ END(invoke_schedule)
* be set up by the caller. We declare 8 input registers so the system call
* args get preserved, in case we need to restart a system call.
*/
ENTRY(handle_signal_delivery)
ENTRY(notify_resume_user)
.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs in case of syscall restart!
mov r9=ar.unat
......@@ -816,17 +816,17 @@ ENTRY(handle_signal_delivery)
.spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!)
st8 [sp]=r9,-16 // allocate space for ar.unat and save it
.body
#error br.call.sptk.many rp=ia64_do_signal
br.call.sptk.many rp=do_notify_resume_user
.ret15: .restore sp
adds sp=16,sp // pop scratch stack space
;;
ld8 r9=[sp] // load new unat from sw->caller_unat
ld8 r9=[sp] // load new unat from sigscratch->scratch_unat
mov rp=loc0
;;
mov ar.unat=r9
mov ar.pfs=loc1
br.ret.sptk.many rp
END(handle_signal_delivery)
END(do_notify_resume_user)
GLOBAL_ENTRY(sys_rt_sigsuspend)
.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
......@@ -1033,9 +1033,9 @@ sys_call_table:
data8 sys_syslog
data8 sys_setitimer
data8 sys_getitimer
data8 ia64_oldstat // 1120
data8 ia64_oldlstat
data8 ia64_oldfstat
data8 ia64_ni_syscall // 1120 /* was: ia64_oldstat */
data8 ia64_ni_syscall /* was: ia64_oldlstat */
data8 ia64_ni_syscall /* was: ia64_oldfstat */
data8 sys_vhangup
data8 sys_lchown
data8 sys_vm86 // 1125
......@@ -1130,19 +1130,23 @@ sys_call_table:
data8 sys_getdents64
data8 sys_getunwind // 1215
data8 sys_readahead
data8 sys_setxattr
data8 sys_lsetxattr
data8 sys_fsetxattr
data8 sys_getxattr // 1220
data8 sys_lgetxattr
data8 sys_fgetxattr
data8 sys_listxattr
data8 sys_llistxattr
data8 sys_flistxattr // 1225
data8 sys_removexattr
data8 sys_lremovexattr
data8 sys_fremovexattr
#if 0
data8 sys_tkill
#else
data8 ia64_ni_syscall
data8 ia64_ni_syscall
data8 ia64_ni_syscall // 1220
data8 ia64_ni_syscall
data8 ia64_ni_syscall
data8 ia64_ni_syscall
data8 ia64_ni_syscall
data8 ia64_ni_syscall // 1225
data8 ia64_ni_syscall
data8 ia64_ni_syscall
data8 ia64_ni_syscall
data8 ia64_ni_syscall
#endif
data8 ia64_ni_syscall // 1230
data8 ia64_ni_syscall
data8 ia64_ni_syscall
......
......@@ -90,7 +90,7 @@ GLOBAL_ENTRY(ia64_sigtramp)
(p8) br.cond.spnt setup_rbs // yup -> (clobbers r14, r15, and r16)
back_from_setup_rbs:
.save ar.pfs, r8
.spillreg ar.pfs, r8
alloc r8=ar.pfs,0,0,3,0 // get CFM0, EC0, and CPL0 into r8
ld8 out0=[base0],16 // load arg0 (signum)
adds base1=(ARG1_OFF-(RBS_BASE_OFF+SIGCONTEXT_OFF)),base1
......
......@@ -127,23 +127,21 @@ start_ap:
#ifdef CONFIG_SMP
/*
* Find the init_task for the currently booting CPU. At poweron, and in
* UP mode, cpucount is 0.
* UP mode, task_for_booting_cpu is NULL.
*/
movl r3=cpucount
movl r3=task_for_booting_cpu
;;
ld4 r3=[r3] // r3 <- smp_processor_id()
movl r2=init_tasks
ld8 r3=[r3]
movl r2=init_thread_union
;;
shladd r2=r3,3,r2
cmp.eq isBP,isAP=r3,r0
;;
ld8 r2=[r2]
(isAP) mov r2=r3
#else
mov r3=0
movl r2=init_task_union
;;
movl r2=init_thread_union
cmp.eq isBP,isAP=r0,r0
#endif
cmp4.ne isAP,isBP=r3,r0
;; // RAW on r2
;;
extr r3=r2,0,61 // r3 == phys addr of task struct
mov r16=KERNEL_TR_PAGE_NUM
;;
......@@ -180,10 +178,12 @@ start_ap:
.rodata
alive_msg:
stringz "I'm alive and well\n"
alive_msg_end:
.previous
alloc r2=ar.pfs,0,0,2,0
movl out0=alive_msg
movl out1=alive_msg_end-alive_msg-1
;;
br.call.sptk.many rp=early_printk
1: // force new bundle
......
......@@ -24,6 +24,7 @@ EXPORT_SYMBOL(strnlen);
EXPORT_SYMBOL(strrchr);
EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(strtok);
EXPORT_SYMBOL(strpbrk);
#include <linux/irq.h>
EXPORT_SYMBOL(isa_irq_to_vector_map);
......
......@@ -2,8 +2,8 @@
* This is where we statically allocate and initialize the initial
* task.
*
* Copyright (C) 1999 Hewlett-Packard Co
* Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 1999, 2002 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
*/
#include <linux/init.h>
......@@ -22,10 +22,20 @@ struct mm_struct init_mm = INIT_MM(init_mm);
/*
* Initial task structure.
*
* We need to make sure that this is page aligned due to the way
* process stacks are handled. This is done by having a special
* "init_task" linker map entry..
* We need to make sure that this is properly aligned due to the way process stacks are
* handled. This is done by having a special ".data.init_task" section...
*/
union task_union init_task_union
__attribute__((section("init_task"))) =
{ INIT_TASK(init_task_union.task) };
#define init_thread_info init_thread_union.s.thread_info
union init_thread {
struct {
struct task_struct task;
struct thread_info thread_info;
} s;
unsigned long stack[KERNEL_STACK_SIZE/sizeof (unsigned long)];
} init_thread_union __attribute__((section(".data.init_task"))) = {{
task: INIT_TASK(init_thread_union.s.task),
thread_info: INIT_THREAD_INFO(init_thread_union.s.thread_info)
}};
asm (".global init_task; init_task = init_thread_union");
This diff is collapsed.
......@@ -161,7 +161,7 @@ int show_interrupts(struct seq_file *p, void *v)
for (action=action->next; action; action = action->next)
seq_printf(p, ", %s", action->name);
seq_putc('\n');
seq_putc(p, '\n');
}
seq_puts(p, "NMI: ");
for (j = 0; j < smp_num_cpus; j++)
......@@ -287,10 +287,11 @@ static inline void wait_on_irq(void)
* already executing in one..
*/
if (!irqs_running())
if (local_bh_count() || !spin_is_locked(&global_bh_lock))
if (really_local_bh_count() || !spin_is_locked(&global_bh_lock))
break;
/* Duh, we have to loop. Release the lock to avoid deadlocks */
smp_mb__before_clear_bit(); /* need barrier before releasing lock... */
clear_bit(0,&global_irq_lock);
for (;;) {
......@@ -305,7 +306,7 @@ static inline void wait_on_irq(void)
continue;
if (global_irq_lock)
continue;
if (!local_bh_count() && spin_is_locked(&global_bh_lock))
if (!really_local_bh_count() && spin_is_locked(&global_bh_lock))
continue;
if (!test_and_set_bit(0,&global_irq_lock))
break;
......@@ -378,14 +379,14 @@ void __global_cli(void)
__save_flags(flags);
if (flags & IA64_PSR_I) {
__cli();
if (!local_irq_count())
if (!really_local_irq_count())
get_irqlock();
}
#else
__save_flags(flags);
if (flags & (1 << EFLAGS_IF_SHIFT)) {
__cli();
if (!local_irq_count())
if (!really_local_irq_count())
get_irqlock();
}
#endif
......@@ -393,7 +394,7 @@ void __global_cli(void)
void __global_sti(void)
{
if (!local_irq_count())
if (!really_local_irq_count())
release_irqlock(smp_processor_id());
__sti();
}
......@@ -422,7 +423,7 @@ unsigned long __global_save_flags(void)
retval = 2 + local_enabled;
/* check for global flags if we're not in an interrupt */
if (!local_irq_count()) {
if (!really_local_irq_count()) {
if (local_enabled)
retval = 1;
if (global_irq_holder == cpu)
......@@ -529,7 +530,7 @@ void disable_irq(unsigned int irq)
disable_irq_nosync(irq);
#ifdef CONFIG_SMP
if (!local_irq_count()) {
if (!really_local_irq_count()) {
do {
barrier();
} while (irq_desc(irq)->status & IRQ_INPROGRESS);
......@@ -1009,6 +1010,11 @@ int setup_irq(unsigned int irq, struct irqaction * new)
rand_initialize_irq(irq);
}
if (new->flags & SA_PERCPU_IRQ) {
desc->status |= IRQ_PER_CPU;
desc->handler = &irq_type_ia64_lsapic;
}
/*
* The following block of code has to be executed atomically
*/
......@@ -1089,13 +1095,25 @@ static unsigned int parse_hex_value (const char *buffer,
static struct proc_dir_entry * smp_affinity_entry [NR_IRQS];
static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL };
static char irq_redir [NR_IRQS]; // = { [0 ... NR_IRQS-1] = 1 };
void set_irq_affinity_info(int irq, int hwid, int redir)
{
unsigned long mask = 1UL<<cpu_logical_id(hwid);
if (irq >= 0 && irq < NR_IRQS) {
irq_affinity[irq] = mask;
irq_redir[irq] = (char) (redir & 0xff);
}
}
static int irq_affinity_read_proc (char *page, char **start, off_t off,
int count, int *eof, void *data)
{
if (count < HEX_DIGITS+1)
if (count < HEX_DIGITS+3)
return -EINVAL;
return sprintf (page, "%08lx\n", irq_affinity[(long)data]);
return sprintf (page, "%s%08lx\n", irq_redir[(long)data] ? "r " : "",
irq_affinity[(long)data]);
}
static int irq_affinity_write_proc (struct file *file, const char *buffer,
......@@ -1103,11 +1121,20 @@ static int irq_affinity_write_proc (struct file *file, const char *buffer,
{
int irq = (long) data, full_count = count, err;
unsigned long new_value;
const char *buf = buffer;
int redir;
if (!irq_desc(irq)->handler->set_affinity)
return -EIO;
err = parse_hex_value(buffer, count, &new_value);
if (buf[0] == 'r' || buf[0] == 'R') {
++buf;
while (*buf == ' ') ++buf;
redir = 1;
} else
redir = 0;
err = parse_hex_value(buf, count, &new_value);
/*
* Do not allow disabling IRQs completely - it's a too easy
......@@ -1117,8 +1144,7 @@ static int irq_affinity_write_proc (struct file *file, const char *buffer,
if (!(new_value & cpu_online_map))
return -EINVAL;
irq_affinity[irq] = new_value;
irq_desc(irq)->handler->set_affinity(irq, new_value);
irq_desc(irq)->handler->set_affinity(irq | (redir?(1<<31):0), new_value);
return full_count;
}
......
......@@ -43,6 +43,7 @@
#include <asm/processor.h>
#include <asm/ptrace.h>
#include <asm/system.h>
#include <asm/thread_info.h>
#include <asm/unistd.h>
#if 1
......@@ -275,6 +276,7 @@ ENTRY(alt_itlb_miss)
mov r16=cr.ifa // get address that caused the TLB miss
movl r17=PAGE_KERNEL
mov r21=cr.ipsr
movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
mov r31=pr
;;
#ifdef CONFIG_DISABLE_VHPT
......@@ -289,12 +291,12 @@ ENTRY(alt_itlb_miss)
(p8) br.cond.dptk itlb_fault
#endif
extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl
and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
shr.u r18=r16,57 // move address bit 61 to bit 4
dep r19=0,r16,IA64_MAX_PHYS_BITS,(64-IA64_MAX_PHYS_BITS) // clear ed & reserved bits
;;
andcm r18=0x10,r18 // bit 4=~address-bit(61)
cmp.ne p8,p0=r0,r23 // psr.cpl != 0?
dep r19=r17,r19,0,12 // insert PTE control bits into r19
or r19=r17,r19 // insert PTE control bits into r19
;;
or r19=r19,r18 // set bit 4 (uncached) if the access was to region 6
(p8) br.cond.spnt page_fault
......@@ -312,6 +314,7 @@ ENTRY(alt_dtlb_miss)
mov r16=cr.ifa // get address that caused the TLB miss
movl r17=PAGE_KERNEL
mov r20=cr.isr
movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
mov r21=cr.ipsr
mov r31=pr
;;
......@@ -328,15 +331,15 @@ ENTRY(alt_dtlb_miss)
#endif
extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl
tbit.nz p6,p7=r20,IA64_ISR_SP_BIT // is speculation bit on?
and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
shr.u r18=r16,57 // move address bit 61 to bit 4
dep r19=0,r16,IA64_MAX_PHYS_BITS,(64-IA64_MAX_PHYS_BITS) // clear ed & reserved bits
;;
andcm r18=0x10,r18 // bit 4=~address-bit(61)
cmp.ne p8,p0=r0,r23
(p8) br.cond.spnt page_fault
dep r21=-1,r21,IA64_PSR_ED_BIT,1
dep r19=r17,r19,0,12 // insert PTE control bits into r19
or r19=r19,r17 // insert PTE control bits into r19
;;
or r19=r19,r18 // set bit 4 (uncached) if the access was to region 6
(p6) mov cr.ipsr=r21
......@@ -654,16 +657,16 @@ ENTRY(break_fault)
ld8 r16=[r16] // load address of syscall entry point
mov rp=r15 // set the real return addr
;;
ld8 r2=[r2] // r2 = current->ptrace
mov b6=r16
// arrange things so we skip over break instruction when returning:
adds r16=16,sp // get pointer to cr_ipsr
adds r17=24,sp // get pointer to cr_iip
add r2=TI_FLAGS+IA64_TASK_SIZE,r13
;;
ld8 r18=[r16] // fetch cr_ipsr
tbit.z p8,p0=r2,PT_TRACESYS_BIT // (current->ptrace & PF_TRACESYS) == 0?
ld4 r2=[r2] // r2 = current_thread_info()->flags
;;
ld8 r19=[r17] // fetch cr_iip
extr.u r20=r18,41,2 // extract ei field
......@@ -676,6 +679,7 @@ ENTRY(break_fault)
;;
(p6) st8 [r17]=r19 // store new cr.iip if cr.isr.ei wrapped around
dep r18=r20,r18,41,2 // insert new ei into cr.isr
tbit.z p8,p0=r2,TIF_SYSCALL_TRACE
;;
st8 [r16]=r18 // store new value for cr.isr
......@@ -855,16 +859,16 @@ ENTRY(dispatch_to_ia32_handler)
ld4 out5=[r14],8 // r13 == ebp
;;
ld4 out3=[r14],8 // r14 == esi
adds r2=IA64_TASK_PTRACE_OFFSET,r13 // r2 = &current->ptrace
adds r2=TI_FLAGS+IA64_TASK_SIZE,r13
;;
ld4 out4=[r14] // r15 == edi
movl r16=ia32_syscall_table
;;
(p6) shladd r16=r8,3,r16 // force ni_syscall if not valid syscall number
ld8 r2=[r2] // r2 = current->ptrace
ld4 r2=[r2] // r2 = current_thread_info()->flags
;;
ld8 r16=[r16]
tbit.z p8,p0=r2,PT_TRACESYS_BIT // (current->ptrace & PT_TRACESYS) == 0?
tbit.z p8,p0=r2,TIF_SYSCALL_TRACE
;;
mov b6=r16
movl r15=ia32_ret_from_syscall
......
This diff is collapsed.
......@@ -7,6 +7,12 @@
// 00/03/29 cfleck Added code to save INIT handoff state in pt_regs format, switch to temp
// kstack, switch modes, jump to C INIT handler
//
// 02/01/04 J.Hall <jenna.s.hall@intel.com>
// Before entering virtual mode code:
// 1. Check for TLB CPU error
// 2. Restore current thread pointer to kr6
// 3. Move stack ptr 16 bytes to conform to C calling convention
//
#include <linux/config.h>
#include <asm/asmmacro.h>
......@@ -21,6 +27,17 @@
*/
#define MINSTATE_PHYS /* Make sure stack access is physical for MINSTATE */
/*
* Needed for ia64_sal call
*/
#define SAL_GET_STATE_INFO 0x01000001
/*
* Needed for return context to SAL
*/
#define IA64_MCA_SAME_CONTEXT 0x0
#define IA64_MCA_COLD_BOOT -2
#include "minstate.h"
/*
......@@ -40,10 +57,12 @@
st8 [_tmp]=r9,0x08;; \
st8 [_tmp]=r10,0x08;; \
st8 [_tmp]=r11,0x08;; \
st8 [_tmp]=r12,0x08;;
st8 [_tmp]=r12,0x08
/*
* OS_MCA_TO_SAL_HANDOFF_STATE (SAL 3.0 spec)
* (p6) is executed if we never entered virtual mode (TLB error)
* (p7) is executed if we entered virtual mode as expected (normal case)
* 1. GR8 = OS_MCA return status
* 2. GR9 = SAL GP (physical)
* 3. GR10 = 0/1 returning same/new context
......@@ -51,15 +70,21 @@
* returns ptr to SAL rtn save loc in _tmp
*/
#define OS_MCA_TO_SAL_HANDOFF_STATE_RESTORE(_tmp) \
movl _tmp=ia64_os_to_sal_handoff_state;; \
DATA_VA_TO_PA(_tmp);; \
ld8 r8=[_tmp],0x08;; \
ld8 r9=[_tmp],0x08;; \
ld8 r10=[_tmp],0x08;; \
ld8 r22=[_tmp],0x08;; \
movl _tmp=ia64_sal_to_os_handoff_state;; \
(p6) movl _tmp=ia64_sal_to_os_handoff_state;; \
(p7) movl _tmp=ia64_os_to_sal_handoff_state;; \
DATA_VA_TO_PA(_tmp);; \
add _tmp=0x28,_tmp;; // point to SAL rtn save location
(p6) movl r8=IA64_MCA_COLD_BOOT; \
(p6) movl r10=IA64_MCA_SAME_CONTEXT; \
(p6) add _tmp=0x18,_tmp;; \
(p6) ld8 r9=[_tmp],0x10; \
(p6) movl r22=ia64_mca_min_state_save_info;; \
(p7) ld8 r8=[_tmp],0x08;; \
(p7) ld8 r9=[_tmp],0x08;; \
(p7) ld8 r10=[_tmp],0x08;; \
(p7) ld8 r22=[_tmp],0x08;; \
DATA_VA_TO_PA(r22)
// now _tmp is pointing to SAL rtn save location
.global ia64_os_mca_dispatch
.global ia64_os_mca_dispatch_end
......@@ -70,6 +95,9 @@
.global ia64_mca_stackframe
.global ia64_mca_bspstore
.global ia64_init_stack
.global ia64_mca_sal_data_area
.global ia64_tlb_functional
.global ia64_mca_min_state_save_info
.text
.align 16
......@@ -90,9 +118,9 @@ ia64_os_mca_dispatch:
// for ia64_mca_sal_to_os_state_t has been
// defined in include/asm/mca.h
SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(r2)
;;
// LOG PROCESSOR STATE INFO FROM HERE ON..
;;
begin_os_mca_dump:
br ia64_os_mca_proc_state_dump;;
......@@ -104,12 +132,20 @@ ia64_os_mca_done_dump:
movl r3=ia64_mca_stackframe;; // save stack frame to memory in r3
DATA_VA_TO_PA(r3);;
rse_switch_context(r6,r3,r2);; // RSC management in this new context
movl r12=ia64_mca_stack;;
mov r2=8*1024;; // stack size must be same as c array
movl r12=ia64_mca_stack
mov r2=8*1024;; // stack size must be same as C array
add r12=r2,r12;; // stack base @ bottom of array
adds r12=-16,r12;; // allow 16 bytes of scratch
// (C calling convention)
DATA_VA_TO_PA(r12);;
// Enter virtual mode from physical mode
// Check to see if the MCA resulted from a TLB error
begin_tlb_error_check:
br ia64_os_mca_tlb_error_check;;
done_tlb_error_check:
// If TLB is functional, enter virtual mode from physical mode
VIRTUAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_begin, r4)
ia64_os_mca_virtual_begin:
......@@ -144,9 +180,12 @@ begin_os_mca_restore:
br ia64_os_mca_proc_state_restore;;
ia64_os_mca_done_restore:
;;
movl r3=ia64_tlb_functional;;
DATA_VA_TO_PA(r3);;
ld8 r3=[r3];;
cmp.eq p6,p7=r0,r3;;
OS_MCA_TO_SAL_HANDOFF_STATE_RESTORE(r2);;
// branch back to SALE_CHECK
OS_MCA_TO_SAL_HANDOFF_STATE_RESTORE(r2)
ld8 r3=[r2];;
mov b0=r3;; // SAL_CHECK return address
br b0
......@@ -405,7 +444,7 @@ ia64_os_mca_proc_state_restore:
movl r2=ia64_mca_proc_state_dump // Convert virtual address
;; // of OS state dump area
DATA_VA_TO_PA(r2) // to physical address
;;
restore_GRs: // restore bank-1 GRs 16-31
bsw.1;;
add r3=16*8,r2;; // to get to NaT of GR 16-31
......@@ -621,6 +660,80 @@ end_os_mca_restore:
//EndStub//////////////////////////////////////////////////////////////////////
//++
// Name:
// ia64_os_mca_tlb_error_check()
//
// Stub Description:
//
// This stub checks to see if the MCA resulted from a TLB error
//
//--
ia64_os_mca_tlb_error_check:
// Retrieve sal data structure for uncorrected MCA
// Make the ia64_sal_get_state_info() call
movl r4=ia64_mca_sal_data_area;;
movl r7=ia64_sal;;
mov r6=r1 // save gp
DATA_VA_TO_PA(r4) // convert to physical address
DATA_VA_TO_PA(r7);; // convert to physical address
ld8 r7=[r7] // get addr of pdesc from ia64_sal
movl r3=SAL_GET_STATE_INFO;;
DATA_VA_TO_PA(r7);; // convert to physical address
ld8 r8=[r7],8;; // get pdesc function pointer
DATA_VA_TO_PA(r8) // convert to physical address
ld8 r1=[r7];; // set new (ia64_sal) gp
DATA_VA_TO_PA(r1) // convert to physical address
mov b6=r8
alloc r5=ar.pfs,8,0,8,0;; // allocate stack frame for SAL call
mov out0=r3 // which SAL proc to call
mov out1=r0 // error type == MCA
mov out2=r0 // null arg
mov out3=r4 // data copy area
mov out4=r0 // null arg
mov out5=r0 // null arg
mov out6=r0 // null arg
mov out7=r0;; // null arg
br.call.sptk.few b0=b6;;
mov r1=r6 // restore gp
mov ar.pfs=r5;; // restore ar.pfs
movl r6=ia64_tlb_functional;;
DATA_VA_TO_PA(r6) // needed later
cmp.eq p6,p7=r0,r8;; // check SAL call return address
(p7) st8 [r6]=r0 // clear tlb_functional flag
(p7) br tlb_failure // error; return to SAL
// examine processor error log for type of error
add r4=40+24,r4;; // parse past record header (length=40)
// and section header (length=24)
ld4 r4=[r4] // get valid field of processor log
mov r5=0xf00;;
and r5=r4,r5;; // read bits 8-11 of valid field
// to determine if we have a TLB error
movl r3=0x1
cmp.eq p6,p7=r0,r5;;
// if no TLB failure, set tlb_functional flag
(p6) st8 [r6]=r3
// else clear flag
(p7) st8 [r6]=r0
// if no TLB failure, continue with normal virtual mode logging
(p6) br done_tlb_error_check
// else no point in entering virtual mode for logging
tlb_failure:
br ia64_os_mca_virtual_end
//EndStub//////////////////////////////////////////////////////////////////////
// ok, the issue here is that we need to save state information so
// it can be useable by the kernel debugger and show regs routines.
// In order to do this, our best bet is save the current state (plus
......@@ -633,7 +746,7 @@ end_os_mca_restore:
// This has been defined for registration purposes with SAL
// as a part of ia64_mca_init.
//
// When we get here, the follow registers have been
// When we get here, the following registers have been
// set by the SAL for our use
//
// 1. GR1 = OS INIT GP
......@@ -649,42 +762,10 @@ end_os_mca_restore:
GLOBAL_ENTRY(ia64_monarch_init_handler)
#if defined(CONFIG_SMP) && defined(SAL_MPINIT_WORKAROUND)
//
// work around SAL bug that sends all processors to monarch entry
//
mov r17=cr.lid
// XXX fix me: this is wrong: hard_smp_processor_id() is a pair of lid/eid
movl r18=ia64_cpu_to_sapicid
;;
dep r18=0,r18,61,3 // convert to physical address
;;
shr.u r17=r17,16
ld4 r18=[r18] // get the BSP ID
;;
dep r17=0,r17,16,48
;;
cmp4.ne p6,p0=r17,r18 // Am I the BSP ?
(p6) br.cond.spnt slave_init_spin_me
;;
#endif
//
// ok, the first thing we do is stash the information
// the SAL passed to os
//
_tmp = r2
movl _tmp=ia64_sal_to_os_handoff_state
;;
dep _tmp=0,_tmp, 61, 3 // get physical address
// stash the information the SAL passed to os
SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(r2)
;;
st8 [_tmp]=r1,0x08;;
st8 [_tmp]=r8,0x08;;
st8 [_tmp]=r9,0x08;;
st8 [_tmp]=r10,0x08;;
st8 [_tmp]=r11,0x08;;
st8 [_tmp]=r12,0x08;;
// now we want to save information so we can dump registers
SAVE_MIN_WITH_COVER
......@@ -698,9 +779,7 @@ _tmp = r2
// ok, enough should be saved at this point to be dangerous, and supply
// information for a dump
// We need to switch to Virtual mode before hitting the C functions.
//
//
//
movl r2=IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|IA64_PSR_BN
mov r3=psr // get the current psr, minimum enabled at this point
;;
......@@ -717,7 +796,7 @@ IVirtual_Switch:
//
// We should now be running virtual
//
// Lets call the C handler to get the rest of the state info
// Let's call the C handler to get the rest of the state info
//
alloc r14=ar.pfs,0,0,1,0 // now it's safe (must be first in insn group!)
;; //
......
......@@ -92,7 +92,6 @@
*
* Assumed state upon entry:
* psr.ic: off
* psr.dt: off
* r31: contains saved predicates (pr)
*
* Upon exit, the state is as follows:
......@@ -186,7 +185,6 @@
*
* Assumed state upon entry:
* psr.ic: on
* psr.dt: on
* r2: points to &pt_regs.r16
* r3: points to &pt_regs.r17
*/
......
......@@ -724,7 +724,7 @@ tr_info(char *page)
status = ia64_pal_tr_read(j, i, tr_buffer, &tr_valid);
if (status != 0) {
printk(__FUNCTION__ " pal call failed on tr[%d:%d]=%ld\n", i, j, status);
printk("palinfo: pal call failed on tr[%d:%d]=%ld\n", i, j, status);
continue;
}
......@@ -842,9 +842,8 @@ static void
palinfo_smp_call(void *info)
{
palinfo_smp_data_t *data = (palinfo_smp_data_t *)info;
/* printk(__FUNCTION__" called on CPU %d\n", smp_processor_id());*/
if (data == NULL) {
printk(KERN_ERR __FUNCTION__" data pointer is NULL\n");
printk("%s palinfo: data pointer is NULL\n", KERN_ERR);
data->ret = 0; /* no output */
return;
}
......@@ -868,11 +867,10 @@ int palinfo_handle_smp(pal_func_cpu_u_t *f, char *page)
ptr.page = page;
ptr.ret = 0; /* just in case */
/*printk(__FUNCTION__" calling CPU %d from CPU %d for function %d\n", f->req_cpu,smp_processor_id(), f->func_id);*/
/* will send IPI to other CPU and wait for completion of remote call */
if ((ret=smp_call_function_single(f->req_cpu, palinfo_smp_call, &ptr, 0, 1))) {
printk(__FUNCTION__" remote CPU call from %d to %d on function %d: error %d\n", smp_processor_id(), f->req_cpu, f->func_id, ret);
printk("palinfo: remote CPU call from %d to %d on function %d: error %d\n", smp_processor_id(), f->req_cpu, f->func_id, ret);
return 0;
}
return ptr.ret;
......@@ -881,7 +879,7 @@ int palinfo_handle_smp(pal_func_cpu_u_t *f, char *page)
static
int palinfo_handle_smp(pal_func_cpu_u_t *f, char *page)
{
printk(__FUNCTION__" should not be called with non SMP kernel\n");
printk("palinfo: should not be called with non SMP kernel\n");
return 0;
}
#endif /* CONFIG_SMP */
......
This diff is collapsed.
/*
* Architecture-specific setup.
*
* Copyright (C) 1998-2001 Hewlett-Packard Co
* Copyright (C) 1998-2001 David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 1998-2002 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
*/
#define __KERNEL_SYSCALLS__ /* see <asm/unistd.h> */
#include <linux/config.h>
......@@ -12,14 +12,17 @@
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/personality.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/stddef.h>
#include <linux/thread_info.h>
#include <linux/unistd.h>
#include <asm/delay.h>
#include <asm/efi.h>
#include <asm/elf.h>
#include <asm/perfmon.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
......@@ -28,6 +31,16 @@
#include <asm/unwind.h>
#include <asm/user.h>
#ifdef CONFIG_IA64_SGI_SN
#include <asm/sn/idle.h>
#endif
#ifdef CONFIG_PERFMON
# include <asm/perfmon.h>
#endif
#include "sigframe.h"
static void
do_show_stack (struct unw_frame_info *info, void *arg)
{
......@@ -45,6 +58,15 @@ do_show_stack (struct unw_frame_info *info, void *arg)
} while (unw_unwind(info) >= 0);
}
void
show_trace_task (struct task_struct *task)
{
struct unw_frame_info info;
unw_init_from_blocked_task(&info, task);
do_show_stack(&info, 0);
}
void
show_stack (struct task_struct *task)
{
......@@ -90,8 +112,8 @@ show_regs (struct pt_regs *regs)
printk("r26 : %016lx r27 : %016lx r28 : %016lx\n", regs->r26, regs->r27, regs->r28);
printk("r29 : %016lx r30 : %016lx r31 : %016lx\n", regs->r29, regs->r30, regs->r31);
/* print the stacked registers if cr.ifs is valid: */
if (regs->cr_ifs & 0x8000000000000000) {
if (user_mode(regs)) {
/* print the stacked registers */
unsigned long val, sof, *bsp, ndirty;
int i, is_nat = 0;
......@@ -103,32 +125,61 @@ show_regs (struct pt_regs *regs)
printk("r%-3u:%c%016lx%s", 32 + i, is_nat ? '*' : ' ', val,
((i == sof - 1) || (i % 3) == 2) ? "\n" : " ");
}
}
if (!user_mode(regs))
} else
show_stack(0);
}
void
do_notify_resume_user (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
{
#ifdef CONFIG_PERFMON
if (current->thread.pfm_ovfl_block_reset)
pfm_ovfl_block_reset();
#endif
/* deal with pending signal delivery */
if (test_thread_flag(TIF_SIGPENDING))
ia64_do_signal(oldset, scr, in_syscall);
}
/*
* We use this if we don't have any better idle routine..
*/
static void
default_idle (void)
{
/* may want to do PAL_LIGHT_HALT here... */
}
void __attribute__((noreturn))
cpu_idle (void *unused)
{
/* endless idle loop with no priority at all */
init_idle();
current->nice = 20;
while (1) {
#ifdef CONFIG_SMP
if (!need_resched())
min_xtp();
#endif
while (!need_resched())
continue;
while (!need_resched()) {
#ifdef CONFIG_IA64_SGI_SN
snidle();
#endif
if (pm_idle)
(*pm_idle)();
else
default_idle();
}
#ifdef CONFIG_IA64_SGI_SN
snidleoff();
#endif
#ifdef CONFIG_SMP
normal_xtp();
#endif
schedule();
check_pgt_cache();
if (pm_idle)
(*pm_idle)();
}
}
......@@ -137,10 +188,14 @@ ia64_save_extra (struct task_struct *task)
{
if ((task->thread.flags & IA64_THREAD_DBG_VALID) != 0)
ia64_save_debug_regs(&task->thread.dbr[0]);
#ifdef CONFIG_PERFMON
if ((task->thread.flags & IA64_THREAD_PM_VALID) != 0)
pfm_save_regs(task);
if (local_cpu_data->pfm_syst_wide) pfm_syst_wide_update_task(task, 0);
#endif
if (IS_IA32_PROCESS(ia64_task_regs(task)))
ia32_save_state(task);
}
......@@ -150,10 +205,14 @@ ia64_load_extra (struct task_struct *task)
{
if ((task->thread.flags & IA64_THREAD_DBG_VALID) != 0)
ia64_load_debug_regs(&task->thread.dbr[0]);
#ifdef CONFIG_PERFMON
if ((task->thread.flags & IA64_THREAD_PM_VALID) != 0)
pfm_load_regs(task);
if (local_cpu_data->pfm_syst_wide) pfm_syst_wide_update_task(task, 1);
#endif
if (IS_IA32_PROCESS(ia64_task_regs(task)))
ia32_load_state(task);
}
......@@ -233,7 +292,7 @@ copy_thread (int nr, unsigned long clone_flags,
if (user_mode(child_ptregs)) {
if (user_stack_base) {
child_ptregs->r12 = user_stack_base + user_stack_size;
child_ptregs->r12 = user_stack_base + user_stack_size - 16;
child_ptregs->ar_bspstore = user_stack_base;
child_ptregs->ar_rnat = 0;
child_ptregs->loadrs = 0;
......@@ -286,9 +345,15 @@ copy_thread (int nr, unsigned long clone_flags,
if (IS_IA32_PROCESS(ia64_task_regs(current)))
ia32_save_state(p);
#endif
#ifdef CONFIG_PERFMON
if (p->thread.pfm_context)
retval = pfm_inherit(p, child_ptregs);
/*
* reset notifiers and owner check (may not have a perfmon context)
*/
atomic_set(&p->thread.pfm_notifiers_check, 0);
atomic_set(&p->thread.pfm_owners_check, 0);
if (current->thread.pfm_context) retval = pfm_inherit(p, child_ptregs);
#endif
return retval;
}
......@@ -412,6 +477,16 @@ sys_execve (char *filename, char **argv, char **envp, struct pt_regs *regs)
return error;
}
void
ia64_set_personality (struct elf64_hdr *elf_ex, int ibcs2_interpreter)
{
set_personality(PER_LINUX);
if (elf_ex->e_flags & EF_IA_64_LINUX_EXECUTABLE_STACK)
current->thread.flags |= IA64_THREAD_XSTACK;
else
current->thread.flags &= ~IA64_THREAD_XSTACK;
}
pid_t
kernel_thread (int (*fn)(void *), void *arg, unsigned long flags)
{
......@@ -443,15 +518,15 @@ flush_thread (void)
#ifdef CONFIG_PERFMON
/*
* By the time we get here, the task is detached from the tasklist. This is important
* because it means that no other tasks can ever find it as a notifiied task, therfore
* there is no race condition between this code and let's say a pfm_context_create().
* Conversely, the pfm_cleanup_notifiers() cannot try to access a task's pfm context if
* this other task is in the middle of its own pfm_context_exit() because it would alreayd
* be out of the task list. Note that this case is very unlikely between a direct child
* and its parents (if it is the notified process) because of the way the exit is notified
* via SIGCHLD.
* by the time we get here, the task is detached from the tasklist. This is important
* because it means that no other tasks can ever find it as a notified task, therfore there
* is no race condition between this code and let's say a pfm_context_create().
* Conversely, the pfm_cleanup_notifiers() cannot try to access a task's pfm context if this
* other task is in the middle of its own pfm_context_exit() because it would already be out of
* the task list. Note that this case is very unlikely between a direct child and its parents
* (if it is the notified process) because of the way the exit is notified via SIGCHLD.
*/
void
release_thread (struct task_struct *task)
{
......@@ -460,6 +535,12 @@ release_thread (struct task_struct *task)
if (atomic_read(&task->thread.pfm_notifiers_check) > 0)
pfm_cleanup_notifiers(task);
if (atomic_read(&task->thread.pfm_owners_check) > 0)
pfm_cleanup_owners(task);
if (task->thread.pfm_smpl_buf_list)
pfm_cleanup_smpl_buf(task);
}
#endif
......@@ -475,21 +556,13 @@ exit_thread (void)
ia64_set_fpu_owner(0);
#endif
#ifdef CONFIG_PERFMON
/* stop monitoring */
if ((current->thread.flags & IA64_THREAD_PM_VALID) != 0) {
/*
* we cannot rely on switch_to() to save the PMU
* context for the last time. There is a possible race
* condition in SMP mode between the child and the
* parent. by explicitly saving the PMU context here
* we garantee no race. this call we also stop
* monitoring
*/
/* if needed, stop monitoring and flush state to perfmon context */
if (current->thread.pfm_context)
pfm_flush_regs(current);
/*
* make sure that switch_to() will not save context again
*/
current->thread.flags &= ~IA64_THREAD_PM_VALID;
/* free debug register resources */
if ((current->thread.flags & IA64_THREAD_DBG_VALID) != 0) {
pfm_release_debug_registers(current);
}
#endif
}
......@@ -571,3 +644,29 @@ machine_power_off (void)
pm_power_off();
machine_halt();
}
void __init
init_task_struct_cache (void)
{
}
struct task_struct *
dup_task_struct(struct task_struct *orig)
{
struct task_struct *tsk;
tsk = __get_free_pages(GFP_KERNEL, KERNEL_STACK_SIZE_ORDER);
if (!tsk)
return NULL;
memcpy(tsk, orig, sizeof(struct task_struct) + sizeof(struct thread_info));
tsk->thread_info = (struct thread_info *) ((char *) tsk + IA64_TASK_SIZE);
atomic_set(&tsk->usage, 1);
return tsk;
}
void
__put_task_struct (struct task_struct *tsk)
{
free_pages((unsigned long) tsk, KERNEL_STACK_SIZE_ORDER);
}
This diff is collapsed.
......@@ -18,7 +18,8 @@
#include <asm/sal.h>
#include <asm/pal.h>
spinlock_t sal_lock = SPIN_LOCK_UNLOCKED;
spinlock_t sal_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED;
unsigned long sal_platform_features;
static struct {
void *addr; /* function entry point */
......@@ -152,12 +153,12 @@ ia64_sal_init (struct ia64_sal_systab *systab)
case SAL_DESC_PLATFORM_FEATURE:
{
struct ia64_sal_desc_platform_feature *pf = (void *) p;
sal_platform_features = pf->feature_mask;
printk("SAL: Platform features ");
if (pf->feature_mask & (1 << 0))
if (pf->feature_mask & IA64_SAL_PLATFORM_FEATURE_BUS_LOCK)
printk("BusLock ");
if (pf->feature_mask & (1 << 1)) {
if (pf->feature_mask & IA64_SAL_PLATFORM_FEATURE_IRQ_REDIR_HINT) {
printk("IRQ_Redirection ");
#ifdef CONFIG_SMP
if (no_int_routing)
......@@ -166,7 +167,7 @@ ia64_sal_init (struct ia64_sal_systab *systab)
smp_int_redirect |= SMP_IRQ_REDIRECTION;
#endif
}
if (pf->feature_mask & (1 << 2)) {
if (pf->feature_mask & IA64_SAL_PLATFORM_FEATURE_IPI_REDIR_HINT) {
printk("IPI_Redirection ");
#ifdef CONFIG_SMP
if (no_int_routing)
......@@ -175,6 +176,8 @@ ia64_sal_init (struct ia64_sal_systab *systab)
smp_int_redirect |= SMP_IPI_REDIRECTION;
#endif
}
if (pf->feature_mask & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)
printk("ITC_Drift ");
printk("\n");
break;
}
......
/*
* salinfo.c
*
* Creates entries in /proc/sal for various system features.
*
* Copyright (c) 2001 Silicon Graphics, Inc. All rights reserved.
*
* 10/30/2001 jbarnes@sgi.com copied much of Stephane's palinfo
* code to create this file
*/
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/module.h>
#include <asm/sal.h>
MODULE_AUTHOR("Jesse Barnes <jbarnes@sgi.com>");
MODULE_DESCRIPTION("/proc interface to IA-64 SAL features");
MODULE_LICENSE("GPL");
static int salinfo_read(char *page, char **start, off_t off, int count, int *eof, void *data);
typedef struct {
const char *name; /* name of the proc entry */
unsigned long feature; /* feature bit */
struct proc_dir_entry *entry; /* registered entry (removal) */
} salinfo_entry_t;
/*
* List {name,feature} pairs for every entry in /proc/sal/<feature>
* that this module exports
*/
static salinfo_entry_t salinfo_entries[]={
{ "bus_lock", IA64_SAL_PLATFORM_FEATURE_BUS_LOCK, },
{ "irq_redirection", IA64_SAL_PLATFORM_FEATURE_IRQ_REDIR_HINT, },
{ "ipi_redirection", IA64_SAL_PLATFORM_FEATURE_IPI_REDIR_HINT, },
{ "itc_drift", IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT, },
};
#define NR_SALINFO_ENTRIES (sizeof(salinfo_entries)/sizeof(salinfo_entry_t))
/*
* One for each feature and one more for the directory entry...
*/
static struct proc_dir_entry *salinfo_proc_entries[NR_SALINFO_ENTRIES + 1];
static int __init
salinfo_init(void)
{
struct proc_dir_entry *salinfo_dir; /* /proc/sal dir entry */
struct proc_dir_entry **sdir = salinfo_proc_entries; /* keeps track of every entry */
int i;
salinfo_dir = proc_mkdir("sal", NULL);
for (i=0; i < NR_SALINFO_ENTRIES; i++) {
/* pass the feature bit in question as misc data */
*sdir++ = create_proc_read_entry (salinfo_entries[i].name, 0, salinfo_dir,
salinfo_read, (void *)salinfo_entries[i].feature);
}
*sdir++ = salinfo_dir;
return 0;
}
static void __exit
salinfo_exit(void)
{
int i = 0;
for (i = 0; i < NR_SALINFO_ENTRIES ; i++) {
if (salinfo_proc_entries[i])
remove_proc_entry (salinfo_proc_entries[i]->name, NULL);
}
}
/*
* 'data' contains an integer that corresponds to the feature we're
* testing
*/
static int
salinfo_read(char *page, char **start, off_t off, int count, int *eof, void *data)
{
int len = 0;
MOD_INC_USE_COUNT;
len = sprintf(page, (sal_platform_features & (unsigned long)data) ? "1\n" : "0\n");
if (len <= off+count) *eof = 1;
*start = page + off;
len -= off;
if (len>count) len = count;
if (len<0) len = 0;
MOD_DEC_USE_COUNT;
return len;
}
module_init(salinfo_init);
module_exit(salinfo_exit);
......@@ -3,7 +3,7 @@
*
* Copyright (C) 1998-2001 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 1998, 1999, 2001 Stephane Eranian <eranian@hpl.hp.com>
* Stephane Eranian <eranian@hpl.hp.com>
* Copyright (C) 2000, Rohit Seth <rohit.seth@intel.com>
* Copyright (C) 1999 VA Linux Systems
* Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
......@@ -20,6 +20,7 @@
#include <linux/init.h>
#include <linux/bootmem.h>
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/reboot.h>
......@@ -27,7 +28,7 @@
#include <linux/seq_file.h>
#include <linux/string.h>
#include <linux/threads.h>
#include <linux/console.h>
#include <linux/tty.h>
#include <asm/acpi-ext.h>
#include <asm/ia32.h>
......@@ -147,6 +148,10 @@ free_available_memory (unsigned long start, unsigned long end, void *arg)
}
/*
* Find a place to put the bootmap and return its starting address in bootmap_start.
* This address must be page-aligned.
*/
static int
find_bootmap_location (unsigned long start, unsigned long end, void *arg)
{
......@@ -165,7 +170,7 @@ find_bootmap_location (unsigned long start, unsigned long end, void *arg)
for (i = 0; i < num_rsvd_regions; i++) {
range_start = MAX(start, free_start);
range_end = MIN(end, rsvd_region[i].start);
range_end = MIN(end, rsvd_region[i].start & PAGE_MASK);
if (range_end <= range_start) continue; /* skip over empty range */
......@@ -177,7 +182,7 @@ find_bootmap_location (unsigned long start, unsigned long end, void *arg)
/* nothing more available in this segment */
if (range_end == end) return 0;
free_start = rsvd_region[i].end;
free_start = PAGE_ALIGN(rsvd_region[i].end);
}
return 0;
}
......@@ -306,6 +311,10 @@ setup_arch (char **cmdline_p)
/* process SAL system table: */
ia64_sal_init(efi.sal_systab);
#ifdef CONFIG_IA64_GENERIC
machvec_init(acpi_get_sysname());
#endif
/*
* Set `iobase' to the appropriate address in region 6
* (uncached access range)
......@@ -332,10 +341,6 @@ setup_arch (char **cmdline_p)
cpu_init(); /* initialize the bootstrap CPU */
#ifdef CONFIG_IA64_GENERIC
machvec_init(acpi_get_sysname());
#endif
if (efi.acpi20) {
/* Parse the ACPI 2.0 tables */
acpi20_parse(efi.acpi20);
......@@ -371,17 +376,14 @@ show_cpuinfo (struct seq_file *m, void *v)
{
#ifdef CONFIG_SMP
# define lpj c->loops_per_jiffy
# define cpunum c->cpu
#else
# define lpj loops_per_jiffy
# define cpunum 0
#endif
char family[32], features[128], *cp;
struct cpuinfo_ia64 *c = v;
unsigned long mask, cpu = c - cpu_data(0);
#ifdef CONFIG_SMP
if (!(cpu_online_map & (1 << cpu)))
return 0;
#endif
unsigned long mask;
mask = c->features;
......@@ -403,7 +405,7 @@ show_cpuinfo (struct seq_file *m, void *v)
sprintf(cp, " 0x%lx", mask);
seq_printf(m,
"processor : %lu\n"
"processor : %d\n"
"vendor : %s\n"
"arch : IA-64\n"
"family : %s\n"
......@@ -416,7 +418,7 @@ show_cpuinfo (struct seq_file *m, void *v)
"cpu MHz : %lu.%06lu\n"
"itc MHz : %lu.%06lu\n"
"BogoMIPS : %lu.%02lu\n\n",
cpu, c->vendor, family, c->model, c->revision, c->archrev,
cpunum, c->vendor, family, c->model, c->revision, c->archrev,
features, c->ppn, c->number,
c->proc_freq / 1000000, c->proc_freq % 1000000,
c->itc_freq / 1000000, c->itc_freq % 1000000,
......@@ -427,6 +429,10 @@ show_cpuinfo (struct seq_file *m, void *v)
static void *
c_start (struct seq_file *m, loff_t *pos)
{
#ifdef CONFIG_SMP
while (*pos < NR_CPUS && !(cpu_online_map & (1 << *pos)))
++*pos;
#endif
return *pos < NR_CPUS ? cpu_data(*pos) : NULL;
}
......@@ -483,6 +489,9 @@ identify_cpu (struct cpuinfo_ia64 *c)
cpuid.bits[i] = ia64_get_cpuid(i);
memcpy(c->vendor, cpuid.field.vendor, 16);
#ifdef CONFIG_SMP
c->cpu = smp_processor_id();
#endif
c->ppn = cpuid.field.ppn;
c->number = cpuid.field.number;
c->revision = cpuid.field.revision;
......@@ -534,7 +543,7 @@ cpu_init (void)
= alloc_bootmem_pages_node(NODE_DATA(numa_node_id()),
sizeof(struct cpuinfo_ia64));
for (cpu = 1; cpu < NR_CPUS; ++cpu)
memcpy(my_cpu_data->cpu_data[cpu]->cpu_data_ptrs,
memcpy(my_cpu_data->cpu_data[cpu]->cpu_data,
my_cpu_data->cpu_data, sizeof(my_cpu_data->cpu_data));
} else {
order = get_order(sizeof(struct cpuinfo_ia64));
......@@ -577,6 +586,8 @@ cpu_init (void)
atomic_inc(&init_mm.mm_count);
current->active_mm = &init_mm;
if (current->mm)
BUG();
ia64_mmu_init(my_cpu_data);
......@@ -616,4 +627,6 @@ cpu_init (void)
num_phys_stacked = 96;
}
local_cpu_data->phys_stacked_size_p8 = num_phys_stacked*8 + 8;
platform_cpu_init();
}
......@@ -21,3 +21,5 @@ struct sigframe {
struct siginfo info;
struct sigcontext sc;
};
extern long ia64_do_signal (sigset_t *, struct sigscratch *, long);
/*
* Architecture-specific signal handling support.
*
* Copyright (C) 1999-2001 Hewlett-Packard Co
* Copyright (C) 1999-2002 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
*
* Derived from i386 and Alpha versions.
......@@ -17,6 +17,8 @@
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/stddef.h>
#include <linux/tty.h>
#include <linux/binfmts.h>
#include <linux/unistd.h>
#include <linux/wait.h>
......@@ -39,8 +41,6 @@
# define GET_SIGSET(k,u) __get_user((k)->sig[0], &(u)->sig[0])
#endif
extern long ia64_do_signal (sigset_t *, struct sigscratch *, long); /* forward decl */
long
ia64_rt_sigsuspend (sigset_t *uset, size_t sigsetsize, struct sigscratch *scr)
{
......@@ -160,6 +160,7 @@ copy_siginfo_to_user (siginfo_t *to, siginfo_t *from)
err |= __put_user((short)from->si_code, &to->si_code);
switch (from->si_code >> 16) {
case __SI_FAULT >> 16:
err |= __put_user(from->si_flags, &to->si_flags);
err |= __put_user(from->si_isr, &to->si_isr);
case __SI_POLL >> 16:
err |= __put_user(from->si_addr, &to->si_addr);
......@@ -172,7 +173,12 @@ copy_siginfo_to_user (siginfo_t *to, siginfo_t *from)
case __SI_PROF >> 16:
err |= __put_user(from->si_uid, &to->si_uid);
err |= __put_user(from->si_pid, &to->si_pid);
err |= __put_user(from->si_pfm_ovfl, &to->si_pfm_ovfl);
if (from->si_code == PROF_OVFL) {
err |= __put_user(from->si_pfm_ovfl[0], &to->si_pfm_ovfl[0]);
err |= __put_user(from->si_pfm_ovfl[1], &to->si_pfm_ovfl[1]);
err |= __put_user(from->si_pfm_ovfl[2], &to->si_pfm_ovfl[2]);
err |= __put_user(from->si_pfm_ovfl[3], &to->si_pfm_ovfl[3]);
}
break;
default:
err |= __put_user(from->si_uid, &to->si_uid);
......@@ -239,7 +245,7 @@ ia64_rt_sigreturn (struct sigscratch *scr)
* could be corrupted.
*/
retval = (long) &ia64_leave_kernel;
if (current->ptrace & PT_TRACESYS)
if (test_thread_flag(TIF_SYSCALL_TRACE))
/*
* strace expects to be notified after sigreturn returns even though the
* context to which we return may not be in the middle of a syscall.
......
......@@ -29,6 +29,7 @@
#include <linux/smp.h>
#include <linux/kernel_stat.h>
#include <linux/mm.h>
#include <linux/cache.h>
#include <linux/delay.h>
#include <linux/cache.h>
......@@ -38,7 +39,6 @@
#include <asm/delay.h>
#include <asm/efi.h>
#include <asm/machvec.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/page.h>
......@@ -51,14 +51,19 @@
#include <asm/unistd.h>
#include <asm/mca.h>
/* The 'big kernel lock' */
spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
/*
* The Big Kernel Lock. It's not supposed to be used for performance critical stuff
* anymore. But we still need to align it because certain workloads are still affected by
* it. For example, llseek() and various other filesystem related routines still use the
* BKL.
*/
spinlock_t kernel_flag __cacheline_aligned = SPIN_LOCK_UNLOCKED;
/*
* Structure and data for smp_call_function(). This is designed to minimise static memory
* requirements. It also looks cleaner.
*/
static spinlock_t call_lock = SPIN_LOCK_UNLOCKED;
static spinlock_t call_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED;
struct call_data_struct {
void (*func) (void *info);
......@@ -70,8 +75,12 @@ struct call_data_struct {
static volatile struct call_data_struct *call_data;
static spinlock_t migration_lock = SPIN_LOCK_UNLOCKED;
static task_t *migrating_task;
#define IPI_CALL_FUNC 0
#define IPI_CPU_STOP 1
#define IPI_MIGRATE_TASK 2
static void
stop_this_cpu (void)
......@@ -121,8 +130,10 @@ handle_IPI (int irq, void *dev_id, struct pt_regs *regs)
mb();
atomic_inc(&data->started);
/* At this point the structure may be gone unless wait is true. */
/*
* At this point the structure may be gone unless
* wait is true.
*/
(*func)(info);
/* Notify the sending CPU that the task is done. */
......@@ -132,6 +143,14 @@ handle_IPI (int irq, void *dev_id, struct pt_regs *regs)
}
break;
case IPI_MIGRATE_TASK:
{
task_t *p = migrating_task;
spin_unlock(&migration_lock);
sched_task_migrated(p);
}
break;
case IPI_CPU_STOP:
stop_this_cpu();
break;
......@@ -139,9 +158,8 @@ handle_IPI (int irq, void *dev_id, struct pt_regs *regs)
default:
printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n", this_cpu, which);
break;
} /* Switch */
}
} while (ops);
mb(); /* Order data access and bit testing. */
}
}
......@@ -185,10 +203,25 @@ smp_send_reschedule (int cpu)
platform_send_ipi(cpu, IA64_IPI_RESCHEDULE, IA64_IPI_DM_INT, 0);
}
/*
* This function sends a reschedule IPI to all (other) CPUs. This should only be used if
* some 'global' task became runnable, such as a RT task, that must be handled now. The
* first CPU that manages to grab the task will run it.
*/
void
smp_send_reschedule_all (void)
{
int i;
for (i = 0; i < smp_num_cpus; i++)
if (i != smp_processor_id())
smp_send_reschedule(i);
}
void
smp_flush_tlb_all (void)
{
smp_call_function ((void (*)(void *))__flush_tlb_all,0,1,1);
smp_call_function((void (*)(void *))__flush_tlb_all, 0, 1, 1);
__flush_tlb_all();
}
......@@ -317,6 +350,15 @@ smp_send_stop (void)
smp_num_cpus = 1;
}
void
smp_migrate_task (int cpu, task_t *p)
{
/* The target CPU will unlock the migration spinlock: */
spin_lock(&migration_lock);
migrating_task = p;
send_IPI_single(cpu, IPI_MIGRATE_TASK);
}
int __init
setup_profiling_timer (unsigned int multiplier)
{
......
......@@ -70,6 +70,7 @@ extern void __init calibrate_delay(void);
extern void start_ap(void);
int cpucount;
task_t *task_for_booting_cpu;
/* Setup configured maximum number of CPUs to activate */
static int max_cpus = -1;
......@@ -378,7 +379,7 @@ start_secondary (void *unused)
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();
......@@ -416,13 +417,13 @@ do_boot_cpu (int sapicid)
if (!idle)
panic("No idle process for CPU %d", cpu);
idle->processor = cpu;
init_idle(idle, cpu);
ia64_cpu_to_sapicid[cpu] = sapicid;
idle->cpus_runnable = 1 << cpu; /* we schedule the first task manually */
del_from_runqueue(idle);
unhash_process(idle);
init_tasks[cpu] = idle;
task_for_booting_cpu = idle;
Dprintk("Sending wakeup vector %u to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid);
......@@ -451,6 +452,17 @@ do_boot_cpu (int sapicid)
}
}
unsigned long cache_decay_ticks; /* # of ticks an idle task is considered cache-hot */
static void
smp_tune_scheduling (void)
{
cache_decay_ticks = 10; /* XXX base this on PAL info and cache-bandwidth estimate */
printk("task migration cache decay timeout: %ld msecs.\n",
(cache_decay_ticks + 1) * 1000 / HZ);
}
/*
* Cycle through the APs sending Wakeup IPIs to boot each.
*/
......@@ -480,9 +492,9 @@ smp_boot_cpus (void)
printk("Boot processor id 0x%x/0x%x\n", 0, boot_cpu_id);
global_irq_holder = 0;
current->processor = 0;
init_idle();
global_irq_holder = NO_PROC_ID;
current_thread_info()->cpu = 0;
smp_tune_scheduling();
/*
* If SMP should be disabled, then really disable it!
......
......@@ -2,8 +2,8 @@
* This file contains various system calls that have different calling
* conventions on different platforms.
*
* Copyright (C) 1999-2000 Hewlett-Packard Co
* Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 1999-2000, 2002 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
*/
#include <linux/config.h>
#include <linux/errno.h>
......@@ -201,15 +201,13 @@ do_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, un
if (len == 0)
goto out;
/* don't permit mappings into unmapped space or the virtual page table of a region: */
/*
* Don't permit mappings into unmapped space, the virtual page table of a region,
* or across a region boundary. Note: RGN_MAP_LIMIT is equal to 2^n-PAGE_SIZE
* (for some integer n <= 61) and len > 0.
*/
roff = rgn_offset(addr);
if ((len | roff | (roff + len)) >= RGN_MAP_LIMIT) {
addr = -EINVAL;
goto out;
}
/* don't permit mappings that would cross a region boundary: */
if (rgn_index(addr) != rgn_index(addr + len)) {
if ((len > RGN_MAP_LIMIT) || (roff > (RGN_MAP_LIMIT - len))) {
addr = -EINVAL;
goto out;
}
......@@ -276,74 +274,6 @@ ia64_create_module (const char *name_user, size_t size, long arg2, long arg3,
return addr;
}
#if 1
/*
* This is here for a while to keep compatibillity with the old stat()
* call - it will be removed later once everybody migrates to the new
* kernel stat structure that matches the glibc one - Jes
*/
static int
cp_ia64_old_stat (struct kstat *stat, struct ia64_oldstat *statbuf)
{
struct ia64_oldstat tmp;
unsigned int blocks, indirect;
memset(&tmp, 0, sizeof(tmp));
tmp.st_dev = stat->dev;
tmp.st_ino = stat->ino;
tmp.st_mode = stat->mode;
tmp.st_nlink = stat->nlink;
SET_STAT_UID(tmp, stat->uid);
SET_STAT_GID(tmp, stat->gid);
tmp.st_rdev = stat->rdev;
tmp.st_size = stat->size;
tmp.st_atime = stat->atime;
tmp.st_mtime = stat->mtime;
tmp.st_ctime = stat->ctime;
tmp.st_blocks = stat->i_blocks;
tmp.st_blksize = stat->i_blksize;
return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
}
asmlinkage long
ia64_oldstat (char *filename, struct ia64_oldstat *statbuf)
{
struct kstat stat;
int error = vfs_stat(filename, &stat);
if (!error)
error = cp_ia64_old_stat(&stat, statbuf);
return error;
}
asmlinkage long
ia64_oldlstat (char *filename, struct ia64_oldstat *statbuf)
{
struct kstat stat;
int error = vfs_lstat(filename, &stat);
if (!error)
error = cp_ia64_old_stat(&stat, statbuf);
return error;
}
asmlinkage long
ia64_oldfstat (unsigned int fd, struct ia64_oldstat *statbuf)
{
struct kstat stat;
int error = vfs_fstat(fd, &stat);
if (!error)
error = cp_ia64_old_stat(&stat, statbuf);
return error;
}
#endif
#ifndef CONFIG_PCI
asmlinkage long
......
/*
* Architecture-specific trap handling.
*
* Copyright (C) 1998-2001 Hewlett-Packard Co
* Copyright (C) 1998-2002 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
*
* 05/12/00 grao <goutham.rao@intel.com> : added isr in siginfo for SIGFPE
......@@ -32,6 +32,7 @@ register double f30 asm ("f30"); register double f31 asm ("f31");
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/vt_kern.h> /* For unblank_screen() */
#include <asm/hardirq.h>
......@@ -133,6 +134,8 @@ ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
/* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */
siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
siginfo.si_imm = break_num;
siginfo.si_flags = 0; /* clear __ISR_VALID */
siginfo.si_isr = 0;
switch (break_num) {
case 0: /* unknown error */
......@@ -352,6 +355,8 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr)
siginfo.si_code = FPE_FLTDIV;
}
siginfo.si_isr = isr;
siginfo.si_flags = __ISR_VALID;
siginfo.si_imm = 0;
force_sig_info(SIGFPE, &siginfo, current);
}
} else {
......@@ -372,6 +377,8 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr)
siginfo.si_code = FPE_FLTRES;
}
siginfo.si_isr = isr;
siginfo.si_flags = __ISR_VALID;
siginfo.si_imm = 0;
force_sig_info(SIGFPE, &siginfo, current);
}
}
......@@ -490,6 +497,8 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
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(SIGILL, &siginfo, current);
return;
}
......@@ -517,6 +526,10 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
}
siginfo.si_signo = SIGTRAP;
siginfo.si_errno = 0;
siginfo.si_flags = 0;
siginfo.si_isr = 0;
siginfo.si_addr = 0;
siginfo.si_imm = 0;
force_sig_info(SIGTRAP, &siginfo, current);
return;
......@@ -528,6 +541,9 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
siginfo.si_errno = 0;
siginfo.si_code = FPE_FLTINV;
siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
siginfo.si_flags = __ISR_VALID;
siginfo.si_isr = isr;
siginfo.si_imm = 0;
force_sig_info(SIGFPE, &siginfo, current);
}
return;
......@@ -537,6 +553,9 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
siginfo.si_signo = SIGILL;
siginfo.si_code = ILL_BADIADDR;
siginfo.si_errno = 0;
siginfo.si_flags = 0;
siginfo.si_isr = 0;
siginfo.si_imm = 0;
siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
force_sig_info(SIGILL, &siginfo, current);
return;
......
/*
* Architecture-specific unaligned trap handling.
*
* Copyright (C) 1999-2001 Hewlett-Packard Co
* Copyright (C) 1999-2000 Stephane Eranian <eranian@hpl.hp.com>
* Copyright (C) 2001 David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 1999-2002 Hewlett-Packard Co
* Stephane Eranian <eranian@hpl.hp.com>
* David Mosberger-Tang <davidm@hpl.hp.com>
*
* 2001/10/11 Fix unaligned access to rotating registers in s/w pipelined loops.
* 2001/08/13 Correct size of extended floats (float_fsz) from 16 to 10 bytes.
......@@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/smp_lock.h>
#include <linux/tty.h>
#include <asm/uaccess.h>
#include <asm/rse.h>
......@@ -23,7 +24,7 @@ extern void die_if_kernel(char *str, struct pt_regs *regs, long err) __attribute
#undef DEBUG_UNALIGNED_TRAP
#ifdef DEBUG_UNALIGNED_TRAP
# define DPRINT(a...) do { printk("%s.%u: ", __FUNCTION__, __LINE__); printk (a); } while (0)
# define DPRINT(a...) do { printk("%s %u: ", __FUNCTION__, __LINE__); printk (a); } while (0)
# define DDUMP(str,vp,len) dump(str, vp, len)
static void
......@@ -650,7 +651,7 @@ emulate_load_updates (update_t type, load_store_t ld, struct pt_regs *regs, unsi
* just in case.
*/
if (ld.x6_op == 1 || ld.x6_op == 3) {
printk(KERN_ERR __FUNCTION__": register update on speculative load, error\n");
printk("%s %s: register update on speculative load, error\n", KERN_ERR, __FUNCTION__);
die_if_kernel("unaligned reference on specualtive load with register update\n",
regs, 30);
}
......@@ -1080,8 +1081,8 @@ emulate_load_floatpair (unsigned long ifa, load_store_t ld, struct pt_regs *regs
* For this reason we keep this sanity check
*/
if (ld.x6_op == 1 || ld.x6_op == 3)
printk(KERN_ERR __FUNCTION__": register update on speculative load pair, "
"error\n");
printk("%s %s: register update on speculative load pair, "
"error\n",KERN_ERR, __FUNCTION__);
setreg(ld.r3, ifa, 0, regs);
}
......@@ -1488,6 +1489,9 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
si.si_errno = 0;
si.si_code = BUS_ADRALN;
si.si_addr = (void *) ifa;
si.si_flags = 0;
si.si_isr = 0;
si.si_imm = 0;
force_sig_info(SIGBUS, &si, current);
goto done;
}
/*
* Copyright (C) 1999-2001 Hewlett-Packard Co
* Copyright (C) 1999-2001 David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 1999-2002 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
*/
/*
* This file implements call frame unwind support for the Linux
......@@ -72,6 +72,8 @@
#define alloc_reg_state() kmalloc(sizeof(struct unw_state_record), GFP_ATOMIC)
#define free_reg_state(usr) kfree(usr)
#define alloc_labeled_state() kmalloc(sizeof(struct unw_labeled_state), GFP_ATOMIC)
#define free_labeled_state(usr) kfree(usr)
typedef unsigned long unw_word;
typedef unsigned char unw_hash_index_t;
......@@ -521,7 +523,7 @@ unw_access_pr (struct unw_frame_info *info, unsigned long *val, int write)
}
/* Unwind decoder routines */
/* Routines to manipulate the state stack. */
static inline void
push (struct unw_state_record *sr)
......@@ -534,24 +536,60 @@ push (struct unw_state_record *sr)
return;
}
memcpy(rs, &sr->curr, sizeof(*rs));
rs->next = sr->stack;
sr->stack = rs;
sr->curr.next = rs;
}
static void
pop (struct unw_state_record *sr)
{
struct unw_reg_state *rs;
struct unw_reg_state *rs = sr->curr.next;
if (!sr->stack) {
printk ("unwind: stack underflow!\n");
if (!rs) {
printk("unwind: stack underflow!\n");
return;
}
rs = sr->stack;
sr->stack = rs->next;
memcpy(&sr->curr, rs, sizeof(*rs));
free_reg_state(rs);
}
/* Make a copy of the state stack. Non-recursive to avoid stack overflows. */
static struct unw_reg_state *
dup_state_stack (struct unw_reg_state *rs)
{
struct unw_reg_state *copy, *prev = NULL, *first = NULL;
while (rs) {
copy = alloc_reg_state();
if (!copy) {
printk ("unwind.dup_state_stack: out of memory\n");
return NULL;
}
memcpy(copy, rs, sizeof(*copy));
if (first)
prev->next = copy;
else
first = copy;
rs = rs->next;
prev = copy;
}
return first;
}
/* Free all stacked register states (but not RS itself). */
static void
free_state_stack (struct unw_reg_state *rs)
{
struct unw_reg_state *p, *next;
for (p = rs->next; p != NULL; p = next) {
next = p->next;
free_reg_state(p);
}
rs->next = NULL;
}
/* Unwind decoder routines */
static enum unw_register_index __attribute__((const))
decode_abreg (unsigned char abreg, int memory)
{
......@@ -689,7 +727,7 @@ desc_prologue (int body, unw_word rlen, unsigned char mask, unsigned char grsave
sr->first_region = 0;
/* check if we're done: */
if (body && sr->when_target < sr->region_start + sr->region_len) {
if (sr->when_target < sr->region_start + sr->region_len) {
sr->done = 1;
return;
}
......@@ -902,31 +940,36 @@ desc_epilogue (unw_word t, unw_word ecount, struct unw_state_record *sr)
static inline void
desc_copy_state (unw_word label, struct unw_state_record *sr)
{
struct unw_reg_state *rs;
struct unw_labeled_state *ls;
for (rs = sr->reg_state_list; rs; rs = rs->next) {
if (rs->label == label) {
memcpy (&sr->curr, rs, sizeof(sr->curr));
for (ls = sr->labeled_states; ls; ls = ls->next) {
if (ls->label == label) {
free_state_stack(&sr->curr);
memcpy(&sr->curr, &ls->saved_state, sizeof(sr->curr));
sr->curr.next = dup_state_stack(ls->saved_state.next);
return;
}
}
printk("unwind: failed to find state labelled 0x%lx\n", label);
printk("unwind: failed to find state labeled 0x%lx\n", label);
}
static inline void
desc_label_state (unw_word label, struct unw_state_record *sr)
{
struct unw_reg_state *rs;
struct unw_labeled_state *ls;
rs = alloc_reg_state();
if (!rs) {
printk("unwind: cannot stack!\n");
ls = alloc_labeled_state();
if (!ls) {
printk("unwind.desc_label_state(): out of memory\n");
return;
}
memcpy(rs, &sr->curr, sizeof(*rs));
rs->label = label;
rs->next = sr->reg_state_list;
sr->reg_state_list = rs;
ls->label = label;
memcpy(&ls->saved_state, &sr->curr, sizeof(ls->saved_state));
ls->saved_state.next = dup_state_stack(sr->curr.next);
/* insert into list of labeled states: */
ls->next = sr->labeled_states;
sr->labeled_states = ls;
}
/*
......@@ -1378,6 +1421,8 @@ lookup (struct unw_table *table, unsigned long rel_ip)
else
break;
}
if (rel_ip < e->start_offset || rel_ip >= e->end_offset)
return NULL;
return e;
}
......@@ -1388,9 +1433,9 @@ lookup (struct unw_table *table, unsigned long rel_ip)
static inline struct unw_script *
build_script (struct unw_frame_info *info)
{
struct unw_reg_state *rs, *next;
const struct unw_table_entry *e = 0;
struct unw_script *script = 0;
struct unw_labeled_state *ls, *next;
unsigned long ip = info->ip;
struct unw_state_record sr;
struct unw_table *table;
......@@ -1535,15 +1580,15 @@ build_script (struct unw_frame_info *info)
for (i = UNW_REG_BSP; i < UNW_NUM_REGS; ++i)
compile_reg(&sr, i, script);
/* free labelled register states & stack: */
/* free labeled register states & stack: */
STAT(parse_start = ia64_get_itc());
for (rs = sr.reg_state_list; rs; rs = next) {
next = rs->next;
free_reg_state(rs);
for (ls = sr.labeled_states; ls; ls = next) {
next = ls->next;
free_state_stack(&ls->saved_state);
free_labeled_state(ls);
}
while (sr.stack)
pop(&sr);
free_state_stack(&sr.curr);
STAT(unw.stat.script.parse_time += ia64_get_itc() - parse_start);
script_finalize(script, &sr);
......
/*
* Copyright (C) 2000 Hewlett-Packard Co
* Copyright (C) 2000 David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 2000, 2002 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
*
* Kernel unwind support.
*/
......@@ -85,6 +85,17 @@ struct unw_reg_info {
int when; /* when the register gets saved */
};
struct unw_reg_state {
struct unw_reg_state *next; /* next (outer) element on state stack */
struct unw_reg_info reg[UNW_NUM_REGS]; /* register save locations */
};
struct unw_labeled_state {
struct unw_labeled_state *next; /* next labeled state (or NULL) */
unsigned long label; /* label for this state */
struct unw_reg_state saved_state;
};
struct unw_state_record {
unsigned int first_region : 1; /* is this the first region? */
unsigned int done : 1; /* are we done scanning descriptors? */
......@@ -105,11 +116,8 @@ struct unw_state_record {
u8 gr_save_loc; /* next general register to use for saving a register */
u8 return_link_reg; /* branch register in which the return link is passed */
struct unw_reg_state {
struct unw_reg_state *next;
unsigned long label; /* label of this state record */
struct unw_reg_info reg[UNW_NUM_REGS];
} curr, *stack, *reg_state_list;
struct unw_labeled_state *labeled_states; /* list of all labeled states */
struct unw_reg_state curr; /* current state */
};
enum unw_nat_type {
......@@ -139,7 +147,7 @@ struct unw_insn {
};
/*
* Preserved general static registers (r2-r5) give rise to two script
* Preserved general static registers (r4-r7) give rise to two script
* instructions; everything else yields at most one instruction; at
* the end of the script, the psp gets popped, accounting for one more
* instruction.
......
/*
*
* Optimized function to clear a page of memory.
*
* Inputs:
* in0: address of page
*
* Output:
* none
*
* Copyright (C) 1999-2001 Hewlett-Packard Co
* Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
* Copyright (C) 1999-2001 David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 1999-2002 Hewlett-Packard Co
* Stephane Eranian <eranian@hpl.hp.com>
* David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 2002 Ken Chen <kenneth.w.chen@intel.com>
*
* 1/06/01 davidm Tuned for Itanium.
* 2/12/02 kchen Tuned for both Itanium and McKinley
* 3/08/02 davidm Some more tweaking
*/
#include <linux/config.h>
#include <asm/asmmacro.h>
#include <asm/page.h>
#ifdef CONFIG_ITANIUM
# define L3_LINE_SIZE 64 // Itanium L3 line size
# define PREFETCH_LINES 9 // magic number
#else
# define L3_LINE_SIZE 128 // McKinley L3 line size
# define PREFETCH_LINES 7 // magic number
#endif
#define saved_lc r2
#define dst0 in0
#define dst_fetch r3
#define dst1 r8
#define dst2 r9
#define dst3 r10
#define dst_fetch r11
#define dst4 r11
#define dst_last r31
GLOBAL_ENTRY(clear_page)
.prologue
.regstk 1,0,0,0
mov r16 = PAGE_SIZE/64-1 // -1 = repeat/until
;;
mov r16 = PAGE_SIZE/L3_LINE_SIZE-1 // main loop count, -1=repeat/until
.save ar.lc, saved_lc
mov saved_lc = ar.lc
.body
mov ar.lc = r16
adds dst1 = 16, dst0
adds dst2 = 32, dst0
adds dst3 = 48, dst0
adds dst_fetch = 512, dst0
mov ar.lc = (PREFETCH_LINES - 1)
mov dst_fetch = in0
adds dst1 = 16, in0
adds dst2 = 32, in0
;;
.fetch: stf.spill.nta [dst_fetch] = f0, L3_LINE_SIZE
adds dst3 = 48, in0 // executing this multiple times is harmless
br.cloop.sptk.few .fetch
;;
addl dst_last = (PAGE_SIZE - PREFETCH_LINES*L3_LINE_SIZE), dst_fetch
mov ar.lc = r16 // one L3 line per iteration
adds dst4 = 64, in0
;;
#ifdef CONFIG_ITANIUM
// Optimized for Itanium
1: stf.spill.nta [dst1] = f0, 64
stf.spill.nta [dst2] = f0, 64
cmp.lt p8,p0=dst_fetch, dst_last
;;
#else
// Optimized for McKinley
1: stf.spill.nta [dst1] = f0, 64
stf.spill.nta [dst2] = f0, 64
stf.spill.nta [dst3] = f0, 64
stf.spill.nta [dst4] = f0, 128
cmp.lt p8,p0=dst_fetch, dst_last
;;
1: stf.spill.nta [dst0] = f0, 64
stf.spill.nta [dst1] = f0, 64
stf.spill.nta [dst2] = f0, 64
#endif
stf.spill.nta [dst3] = f0, 64
lfetch [dst_fetch], 64
br.cloop.dptk.few 1b
(p8) stf.spill.nta [dst_fetch] = f0, L3_LINE_SIZE
br.cloop.sptk.few 1b
;;
mov ar.lc = r2 // restore lc
mov ar.lc = saved_lc // restore lc
br.ret.sptk.many rp
END(clear_page)
......@@ -9,8 +9,8 @@
* no return value
*
* Copyright (C) 1999, 2001 Hewlett-Packard Co
* Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
* Copyright (C) 2001 David Mosberger <davidm@hpl.hp.com>
* Stephane Eranian <eranian@hpl.hp.com>
* David Mosberger <davidm@hpl.hp.com>
*
* 4/06/01 davidm Tuned to make it perform well both for cached and uncached copies.
*/
......
......@@ -27,10 +27,19 @@
#define ALIGN(val, align) ((unsigned long) \
(((unsigned long) (val) + ((align) - 1)) & ~((align) - 1)))
#define SG_ENT_VIRT_ADDRESS(sg) ((sg)->address ? (sg)->address \
: page_address((sg)->page) + (sg)->offset)
#define OFFSET(val,align) ((unsigned long) \
( (val) & ( (align) - 1)))
#define SG_ENT_VIRT_ADDRESS(sg) (page_address((sg)->page) + (sg)->offset)
#define SG_ENT_PHYS_ADDRESS(SG) virt_to_phys(SG_ENT_VIRT_ADDRESS(SG))
/*
* Maximum allowable number of contiguous slabs to map,
* must be a power of 2. What is the appropriate value ?
* The complexity of {map,unmap}_single is linearly dependent on this value.
*/
#define IO_TLB_SEGSIZE 128
/*
* log of the size of each IO TLB slab. The number of slabs is command line controllable.
*/
......@@ -69,10 +78,15 @@ static int __init
setup_io_tlb_npages (char *str)
{
io_tlb_nslabs = simple_strtoul(str, NULL, 0) << (PAGE_SHIFT - IO_TLB_SHIFT);
/* avoid tail segment of size < IO_TLB_SEGSIZE */
io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE);
return 1;
}
__setup("swiotlb=", setup_io_tlb_npages);
/*
* Statically reserve bounce buffer space and initialize bounce buffer data structures for
* the software IO TLB used to implement the PCI DMA API.
......@@ -92,12 +106,12 @@ swiotlb_init (void)
/*
* Allocate and initialize the free list array. This array is used
* to find contiguous free memory regions of size 2^IO_TLB_SHIFT between
* io_tlb_start and io_tlb_end.
* to find contiguous free memory regions of size up to IO_TLB_SEGSIZE
* between io_tlb_start and io_tlb_end.
*/
io_tlb_list = alloc_bootmem(io_tlb_nslabs * sizeof(int));
for (i = 0; i < io_tlb_nslabs; i++)
io_tlb_list[i] = io_tlb_nslabs - i;
io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE);
io_tlb_index = 0;
io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(char *));
......@@ -124,7 +138,7 @@ map_single (struct pci_dev *hwdev, char *buffer, size_t size, int direction)
if (size > (1 << PAGE_SHIFT))
stride = (1 << (PAGE_SHIFT - IO_TLB_SHIFT));
else
stride = nslots;
stride = 1;
if (!nslots)
BUG();
......@@ -151,7 +165,8 @@ map_single (struct pci_dev *hwdev, char *buffer, size_t size, int direction)
for (i = index; i < index + nslots; i++)
io_tlb_list[i] = 0;
for (i = index - 1; (i >= 0) && io_tlb_list[i]; i--)
for (i = index - 1; (OFFSET(i, IO_TLB_SEGSIZE) != IO_TLB_SEGSIZE -1)
&& io_tlb_list[i]; i--)
io_tlb_list[i] = ++count;
dma_addr = io_tlb_start + (index << IO_TLB_SHIFT);
......@@ -217,7 +232,8 @@ unmap_single (struct pci_dev *hwdev, char *dma_addr, size_t size, int direction)
*/
spin_lock_irqsave(&io_tlb_lock, flags);
{
int count = ((index + nslots) < io_tlb_nslabs ? io_tlb_list[index + nslots] : 0);
int count = ((index + nslots) < ALIGN(index + 1, IO_TLB_SEGSIZE) ?
io_tlb_list[index + nslots] : 0);
/*
* Step 1: return the slots to the free list, merging the slots with
* superceeding slots
......@@ -228,7 +244,8 @@ unmap_single (struct pci_dev *hwdev, char *dma_addr, size_t size, int direction)
* Step 2: merge the returned slots with the preceeding slots, if
* available (non zero)
*/
for (i = index - 1; (i >= 0) && io_tlb_list[i]; i--)
for (i = index - 1; (OFFSET(i, IO_TLB_SEGSIZE) != IO_TLB_SEGSIZE -1) &&
io_tlb_list[i]; i--)
io_tlb_list[i] = ++count;
}
spin_unlock_irqrestore(&io_tlb_lock, flags);
......@@ -405,11 +422,9 @@ swiotlb_map_sg (struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int d
for (i = 0; i < nelems; i++, sg++) {
sg->orig_address = SG_ENT_VIRT_ADDRESS(sg);
if ((SG_ENT_PHYS_ADDRESS(sg) & ~hwdev->dma_mask) != 0) {
addr = map_single(hwdev, sg->address, sg->length, direction);
if (sg->address)
sg->address = addr;
else
addr = map_single(hwdev, sg->orig_address, sg->length, direction);
sg->page = virt_to_page(addr);
sg->offset = (u64) addr & ~PAGE_MASK;
}
}
return nelems;
......@@ -430,12 +445,10 @@ swiotlb_unmap_sg (struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int
for (i = 0; i < nelems; i++, sg++)
if (sg->orig_address != SG_ENT_VIRT_ADDRESS(sg)) {
unmap_single(hwdev, SG_ENT_VIRT_ADDRESS(sg), sg->length, direction);
if (sg->address)
sg->address = sg->orig_address;
else
sg->page = virt_to_page(sg->orig_address);
sg->offset = (u64) sg->orig_address & ~PAGE_MASK;
} else if (direction == PCI_DMA_FROMDEVICE)
mark_clean(sg->address, sg->length);
mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->length);
}
/*
......
/*
* Kernel exception handling table support. Derived from arch/alpha/mm/extable.c.
*
* Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co
* Copyright (C) 1998, 1999, 2001 David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 1998, 1999, 2001-2002 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
*/
#include <linux/config.h>
......@@ -55,10 +55,12 @@ search_exception_table (unsigned long addr)
struct module *mp;
/* The kernel is the last "module" -- no need to treat it special. */
for (mp = module_list; mp ; mp = mp->next) {
for (mp = module_list; mp; mp = mp->next) {
if (!mp->ex_table_start)
continue;
archdata = (struct archdata *) mp->archdata_start;
if (!archdata)
continue;
entry = search_one_table(mp->ex_table_start, mp->ex_table_end - 1,
addr, (unsigned long) archdata->gp);
if (entry) {
......
/*
* MMU fault handling support.
*
* Copyright (C) 1998-2001 Hewlett-Packard Co
* Copyright (C) 1998-2002 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
*/
#include <linux/sched.h>
......@@ -96,7 +96,7 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
* sure we exit gracefully rather than endlessly redo the
* fault.
*/
switch (handle_mm_fault(mm, vma, address, mask)) {
switch (handle_mm_fault(mm, vma, address, (mask & VM_WRITE) != 0)) {
case 1:
++current->min_flt;
break;
......@@ -151,6 +151,8 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
si.si_errno = 0;
si.si_code = code;
si.si_addr = (void *) address;
si.si_isr = isr;
si.si_flags = __ISR_VALID;
force_sig_info(signal, &si, current);
return;
}
......@@ -194,9 +196,7 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
out_of_memory:
up_read(&mm->mmap_sem);
if (current->pid == 1) {
current->policy |= SCHED_YIELD;
schedule();
down_read(&mm->mmap_sem);
yield();
goto survive;
}
printk("VM: killing process %s\n", current->comm);
......
/*
* Initialize MMU support.
*
* Copyright (C) 1998-2001 Hewlett-Packard Co
* Copyright (C) 1998-2001 David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 1998-2002 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
*/
#include <linux/config.h>
#include <linux/kernel.h>
......@@ -14,6 +14,7 @@
#include <linux/slab.h>
#include <linux/swap.h>
#include <asm/a.out.h>
#include <asm/bitops.h>
#include <asm/dma.h>
#include <asm/efi.h>
......@@ -37,10 +38,15 @@ unsigned long MAX_DMA_ADDRESS = PAGE_OFFSET + 0x100000000UL;
static unsigned long totalram_pages;
static int pgt_cache_water[2] = { 25, 50 };
int
do_check_pgt_cache (int low, int high)
check_pgt_cache (void)
{
int freed = 0;
int low, high, freed = 0;
low = pgt_cache_water[0];
high = pgt_cache_water[1];
if (pgtable_cache_size > high) {
do {
......@@ -48,8 +54,6 @@ do_check_pgt_cache (int low, int high)
free_page((unsigned long)pgd_alloc_one_fast(0)), ++freed;
if (pmd_quicklist)
free_page((unsigned long)pmd_alloc_one_fast(0, 0)), ++freed;
if (pte_quicklist)
free_page((unsigned long)pte_alloc_one_fast(0, 0)), ++freed;
} while (pgtable_cache_size > low);
}
return freed;
......@@ -243,15 +247,16 @@ put_gate_page (struct page *page, unsigned long address)
pmd = pmd_alloc(&init_mm, pgd, address);
if (!pmd)
goto out;
pte = pte_alloc(&init_mm, pmd, address);
pte = pte_alloc_map(&init_mm, pmd, address);
if (!pte)
goto out;
if (!pte_none(*pte)) {
pte_ERROR(*pte);
pte_unmap(pte);
goto out;
}
flush_page_to_ram(page);
set_pte(pte, mk_pte(page, PAGE_GATE));
pte_unmap(pte);
}
out: spin_unlock(&init_mm.page_table_lock);
/* no need for flush_tlb */
......
#
# ia64/sn/Makefile
#
# Copyright (C) 1999 Silicon Graphics, Inc.
# Copyright (C) Srinivasa Thirumalachar (sprasad@engr.sgi.com)
#
EXTRA_CFLAGS := -DSN -DLANGUAGE_C=1 -D_LANGUAGE_C=1 -I. -DBRINGUP \
-DDIRECT_L1_CONSOLE -DNUMA_BASE -DSIMULATED_KLGRAPH \
-DNUMA_MIGR_CONTROL -DLITTLE_ENDIAN -DREAL_HARDWARE \
-DNEW_INTERRUPTS
all: sn.a
O_TARGET = sn.a
obj-y = sn1/sn1.a
clean::
include $(TOPDIR)/Rules.make
This diff is collapsed.
This diff is collapsed.
#
# Automatically generated make config: don't edit
#
#
# Code maturity level options
#
# CONFIG_EXPERIMENTAL is not set
#
# Loadable module support
#
# CONFIG_MODULES is not set
#
# General setup
#
CONFIG_IA64=y
# CONFIG_ISA is not set
# CONFIG_EISA is not set
# CONFIG_MCA is not set
# CONFIG_SBUS is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
CONFIG_ACPI=y
CONFIG_ACPI_EFI=y
CONFIG_ACPI_INTERPRETER=y
CONFIG_ACPI_KERNEL_CONFIG=y
CONFIG_ITANIUM=y
# CONFIG_MCKINLEY is not set
# CONFIG_IA64_GENERIC is not set
CONFIG_IA64_DIG=y
# CONFIG_IA64_HP_SIM is not set
# CONFIG_IA64_SGI_SN1 is not set
# CONFIG_IA64_SGI_SN2 is not set
# CONFIG_IA64_PAGE_SIZE_4KB is not set
# CONFIG_IA64_PAGE_SIZE_8KB is not set
CONFIG_IA64_PAGE_SIZE_16KB=y
# CONFIG_IA64_PAGE_SIZE_64KB is not set
CONFIG_IA64_BRL_EMU=y
CONFIG_ITANIUM_BSTEP_SPECIFIC=y
CONFIG_IA64_L1_CACHE_SHIFT=6
# CONFIG_NUMA is not set
# CONFIG_IA64_MCA is not set
CONFIG_PM=y
CONFIG_IA64_HAVE_SYNCRONIZED_ITC=y
# CONFIG_DEVFS_FS is not set
CONFIG_KCORE_ELF=y
CONFIG_SMP=y
# CONFIG_IA32_SUPPORT is not set
# CONFIG_PERFMON is not set
# CONFIG_IA64_PALINFO is not set
# CONFIG_EFI_VARS is not set
# CONFIG_NET is not set
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_SYSCTL is not set
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_ACPI_DEBUG is not set
# CONFIG_ACPI_BUSMGR is not set
# CONFIG_ACPI_SYS is not set
# CONFIG_ACPI_CPU is not set
# CONFIG_ACPI_BUTTON is not set
# CONFIG_ACPI_AC is not set
# CONFIG_ACPI_EC is not set
# CONFIG_ACPI_CMBATT is not set
# CONFIG_ACPI_THERMAL is not set
CONFIG_PCI=y
# CONFIG_PCI_NAMES is not set
# CONFIG_HOTPLUG is not set
# CONFIG_PCMCIA is not set
#
# Parallel port support
#
# CONFIG_PARPORT is not set
#
# Memory Technology Devices (MTD)
#
# CONFIG_MTD is not set
#
# Plug and Play configuration
#
# CONFIG_PNP is not set
# CONFIG_ISAPNP is not set
#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XD is not set
# CONFIG_PARIDE is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
# CONFIG_BLK_DEV_INITRD is not set
#
# I2O device support
#
# CONFIG_I2O is not set
# CONFIG_I2O_PCI is not set
# CONFIG_I2O_BLOCK is not set
# CONFIG_I2O_SCSI is not set
# CONFIG_I2O_PROC is not set
#
# Multi-device support (RAID and LVM)
#
# CONFIG_MD is not set
# CONFIG_BLK_DEV_MD is not set
# CONFIG_MD_LINEAR is not set
# CONFIG_MD_RAID0 is not set
# CONFIG_MD_RAID1 is not set
# CONFIG_MD_RAID5 is not set
# CONFIG_MD_MULTIPATH is not set
# CONFIG_BLK_DEV_LVM is not set
#
# ATA/IDE/MFM/RLL support
#
CONFIG_IDE=y
#
# IDE, ATA and ATAPI Block devices
#
CONFIG_BLK_DEV_IDE=y
#
# Please see Documentation/ide.txt for help/info on IDE drives
#
# CONFIG_BLK_DEV_HD_IDE is not set
# CONFIG_BLK_DEV_HD is not set
CONFIG_BLK_DEV_IDEDISK=y
# CONFIG_IDEDISK_MULTI_MODE is not set
# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
# CONFIG_BLK_DEV_IDEDISK_IBM is not set
# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
# CONFIG_BLK_DEV_IDEDISK_WD is not set
# CONFIG_BLK_DEV_COMMERIAL is not set
# CONFIG_BLK_DEV_TIVO is not set
# CONFIG_BLK_DEV_IDECS is not set
# CONFIG_BLK_DEV_IDECD is not set
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_BLK_DEV_IDESCSI is not set
#
# IDE chipset support/bugfixes
#
# CONFIG_BLK_DEV_CMD640 is not set
# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
# CONFIG_BLK_DEV_ISAPNP is not set
# CONFIG_BLK_DEV_RZ1000 is not set
# CONFIG_BLK_DEV_IDEPCI is not set
# CONFIG_IDE_CHIPSETS is not set
# CONFIG_IDEDMA_AUTO is not set
# CONFIG_DMA_NONPCI is not set
# CONFIG_BLK_DEV_IDE_MODES is not set
# CONFIG_BLK_DEV_ATARAID is not set
# CONFIG_BLK_DEV_ATARAID_PDC is not set
# CONFIG_BLK_DEV_ATARAID_HPT is not set
#
# Alternate 1394 support
#
# CONFIG_X1394 is not set
#
# Alternate SCSI support
#
# CONFIG_XSCSI is not set
#
# SCSI support
#
# CONFIG_SCSI is not set
#
# Amateur Radio support
#
# CONFIG_HAMRADIO is not set
#
# ISDN subsystem
#
# CONFIG_ISDN is not set
#
# CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
#
# CONFIG_CD_NO_IDESCSI is not set
#
# Input core support
#
# CONFIG_INPUT is not set
# CONFIG_INPUT_KEYBDEV is not set
# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_JOYDEV is not set
# CONFIG_INPUT_EVDEV is not set
#
# Character devices
#
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
# CONFIG_SERIAL is not set
# CONFIG_SERIAL_EXTENDED is not set
# CONFIG_SERIAL_NONSTANDARD is not set
CONFIG_UNIX98_PTYS=y
CONFIG_UNIX98_PTY_COUNT=256
#
# I2C support
#
# CONFIG_I2C is not set
#
# Mice
#
# CONFIG_BUSMOUSE is not set
# CONFIG_MOUSE is not set
#
# Joysticks
#
# CONFIG_INPUT_GAMEPORT is not set
#
# Input core support is needed for gameports
#
#
# Input core support is needed for joysticks
#
# CONFIG_QIC02_TAPE is not set
#
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
# CONFIG_INTEL_RNG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
# CONFIG_EFI_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
#
# Ftape, the floppy tape device driver
#
# CONFIG_FTAPE is not set
# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_MWAVE is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
#
# File systems
#
# CONFIG_QUOTA is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_REISERFS_CHECK is not set
# CONFIG_ADFS_FS is not set
# CONFIG_ADFS_FS_RW is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_FAT_FS is not set
# CONFIG_MSDOS_FS is not set
# CONFIG_UMSDOS_FS is not set
# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_JFFS_FS is not set
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
CONFIG_TMPFS=y
# CONFIG_RAMFS is not set
# CONFIG_ISO9660_FS is not set
# CONFIG_JOLIET is not set
# CONFIG_MINIX_FS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
# CONFIG_DEVFS_MOUNT is not set
# CONFIG_DEVFS_DEBUG is not set
CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_QNX4FS_RW is not set
# CONFIG_ROMFS_FS is not set
CONFIG_EXT2_FS=y
# CONFIG_SYSV_FS is not set
# CONFIG_UDF_FS is not set
# CONFIG_UDF_RW is not set
# CONFIG_UFS_FS is not set
# CONFIG_UFS_FS_WRITE is not set
# CONFIG_XFS_SUPPORT is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_SMB_FS is not set
#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
# CONFIG_SMB_NLS is not set
# CONFIG_NLS is not set
#
# Console drivers
#
CONFIG_VGA_CONSOLE=y
#
# Frame-buffer support
#
# CONFIG_FB is not set
#
# Sound
#
# CONFIG_SOUND is not set
#
# USB support
#
# CONFIG_USB is not set
#
# USB Controllers
#
# CONFIG_USB_UHCI is not set
# CONFIG_USB_UHCI_ALT is not set
# CONFIG_USB_OHCI is not set
#
# USB Device Class drivers
#
# CONFIG_USB_AUDIO is not set
# CONFIG_USB_BLUETOOTH is not set
# CONFIG_USB_STORAGE is not set
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_HP8200e is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_JUMPSHOT is not set
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
#
# USB Human Interface Devices (HID)
#
#
# Input core support is needed for USB HID
#
#
# USB Imaging devices
#
# CONFIG_USB_DC2XX is not set
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_SCANNER is not set
# CONFIG_USB_MICROTEK is not set
# CONFIG_USB_HPUSBSCSI is not set
#
# USB Multimedia devices
#
#
# Video4Linux support is needed for USB Multimedia device support
#
#
# USB Network adaptors
#
#
# Networking support is needed for USB Networking device support
#
#
# USB port drivers
#
# CONFIG_USB_USS720 is not set
#
# USB Serial Converter support
#
# CONFIG_USB_SERIAL is not set
# CONFIG_USB_SERIAL_GENERIC is not set
# CONFIG_USB_SERIAL_BELKIN is not set
# CONFIG_USB_SERIAL_WHITEHEAT is not set
# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
# CONFIG_USB_SERIAL_EMPEG is not set
# CONFIG_USB_SERIAL_FTDI_SIO is not set
# CONFIG_USB_SERIAL_VISOR is not set
# CONFIG_USB_SERIAL_IR is not set
# CONFIG_USB_SERIAL_EDGEPORT is not set
# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
# CONFIG_USB_SERIAL_KEYSPAN is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
# CONFIG_USB_SERIAL_MCT_U232 is not set
# CONFIG_USB_SERIAL_PL2303 is not set
# CONFIG_USB_SERIAL_CYBERJACK is not set
# CONFIG_USB_SERIAL_XIRCOM is not set
# CONFIG_USB_SERIAL_OMNINET is not set
#
# USB Miscellaneous drivers
#
# CONFIG_USB_RIO500 is not set
#
# Kernel hacking
#
CONFIG_DEBUG_KERNEL=y
CONFIG_IA64_PRINT_HAZARDS=y
# CONFIG_DISABLE_VHPT is not set
CONFIG_MAGIC_SYSRQ=y
CONFIG_IA64_EARLY_PRINTK=y
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_IA64_DEBUG_CMPXCHG is not set
# CONFIG_IA64_DEBUG_IRQ is not set
# CONFIG_KDB is not set
# CONFIG_KDB_MODULES is not set
# CONFIG_KALLSYMS is not set
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.
......@@ -3,8 +3,7 @@
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
# Copyright (C) 2000 Silicon Graphics, Inc.
# Copyright (C) Jack Steiner (steiner@sgi.com)
# Copyright (c) 2000-2001 Silicon Graphics, Inc. All rights reserved.
#
TOPDIR=../../../..
......@@ -12,18 +11,16 @@ HPATH = $(TOPDIR)/include
LIB = ../../lib/lib.a
OBJ=fpromasm.o main.o fw-emu.o fpmem.o
OBJ=fpromasm.o main.o fw-emu.o fpmem.o klgraph_init.o
obj-y=fprom
fprom: $(OBJ)
$(LD) -static -Tfprom.lds -o fprom $(OBJ) $(LIB)
comma := ,
.S.o:
$(CC) -D__ASSEMBLY__ $(AFLAGS) $(AFLAGS_KERNEL) -c -o $*.o $<
.c.o:
$(CC) $(CFLAGS) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_KERNEL) -c -o $*.o $<
$(CC) $(CFLAGS) $(CFLAGS_KERNEL) -c -o $*.o $<
clean:
rm -f *.o fprom
......
This diff is collapsed.
......@@ -4,15 +4,16 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2000 Silicon Graphics, Inc.
* Copyright (C) 2000 by Jack Steiner (steiner@sgi.com)
* Copyright (C) 2000-2001 Silicon Graphics, Inc. All rights reserved.
*/
#include <linux/config.h>
#include <linux/types.h>
#include <asm/bitops.h>
extern void klgraph_init(void);
void bedrock_init(int);
void synergy_init(int, int);
void sys_fw_init (const char *args, int arglen, int bsp);
......@@ -32,6 +33,8 @@ fmain(int lid, int bsp) {
* First lets figure out who we are. This is done from the
* LID passed to us.
*/
#ifdef CONFIG_IA64_SGI_SN1
nasid = (lid>>24);
syn = (lid>>17)&1;
cpu = (lid>>16)&1;
......@@ -44,6 +47,11 @@ fmain(int lid, int bsp) {
test_and_set_bit(syn+2, &nasidmaster[nasid]);
} else
while (get_bit(syn+2, &nasidmaster[nasid]) == 0);
#else
nasid = (lid>>16)&0xfff;
cpu = (lid>>28)&3;
syn = 0;
#endif
/*
* Now pick a nasid master to initialize Bedrock registers.
......@@ -72,6 +80,13 @@ void
bedrock_init(int nasid)
{
nasid = nasid; /* to quiet gcc */
#if 0
/*
* Undef if you need fprom to generate a 1 node klgraph
* information .. only works for 1 node for nasid 0.
*/
klgraph_init();
#endif
}
......
/*
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2000 Silicon Graphics, Inc.
* Copyright (C) 2000 by Jack Steiner (steiner@sgi.com)
*/
#include <asm/sn/mmzone_sn1.h>
typedef struct sn_memmap_s
{
short nasid ;
short cpuconfig;
node_memmap_t node_memmap ;
} sn_memmap_t ;
typedef struct sn_config_s
{
int cpus;
int nodes;
sn_memmap_t memmap[1]; /* start of array */
} sn_config_t;
extern void build_init(unsigned long);
extern int build_efi_memmap(void *, int);
extern int GetNumNodes(void);
extern int GetNumCpus(void);
extern int IsCpuPresent(int, int);
extern int GetNasid(int);
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.
......@@ -4,8 +4,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc.
* Copyright (C) 2000 by Colin Ngam
* Copyright (C) 1992 - 1997, 2000-2001 Silicon Graphics, Inc. All rights reserved.
*/
#include <linux/types.h>
......@@ -14,6 +13,7 @@
#include <linux/devfs_fs_kernel.h>
#include <asm/sn/sgi.h>
#include <asm/io.h>
#include <asm/sn/io.h>
#include <asm/sn/iograph.h>
#include <asm/sn/invent.h>
#include <asm/sn/hcl.h>
......
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.
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.
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.
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.
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.
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.
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