Commit 56d7957e authored by David Mosberger's avatar David Mosberger

ia64-patches

parent efe80e09
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).
......@@ -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)
{
/*
* Disable the compatibility mode interrupts (8259 style), needs IN/OUT support
* enabled.
*/
outb(0xff, 0xA1);
outb(0xff, 0x21);
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,10 +153,12 @@ 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,
0xb, 0, 3, 1, 1, 1, 0);
ia32_gdt[_LDT(nr)] = IA32_SEG_DESCRIPTOR(IA32_LDT_OFFSET, ldt_size - 1,
0x2, 0, 3, 1, 1, 1, 0);
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_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.
This diff is collapsed.
......@@ -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 */
......@@ -76,7 +77,7 @@ ia64_sal_strerror (long status)
return str;
}
static void __init
static void __init
ia64_sal_handler_init (void *entry_point, void *gpval)
{
/* fill in the SAL procedure descriptor and point ia64_sal to it: */
......@@ -102,7 +103,7 @@ ia64_sal_init (struct ia64_sal_systab *systab)
if (strncmp(systab->signature, "SST_", 4) != 0)
printk("bad signature in system table!");
/*
/*
* revisions are coded in BCD, so %x does the job for us
*/
printk("SAL v%x.%02x: oem=%.32s, product=%.32s\n",
......@@ -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,15 +167,17 @@ 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)
if (no_int_routing)
smp_int_redirect &= ~SMP_IPI_REDIRECTION;
else
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)
......@@ -98,51 +107,60 @@ handle_IPI (int irq, void *dev_id, struct pt_regs *regs)
mb(); /* Order interrupt and bit testing. */
while ((ops = xchg(pending_ipis, 0)) != 0) {
mb(); /* Order bit clearing and data access. */
do {
unsigned long which;
which = ffz(~ops);
ops &= ~(1 << which);
switch (which) {
case IPI_CALL_FUNC:
{
struct call_data_struct *data;
void (*func)(void *info);
void *info;
int wait;
/* release the 'pointer lock' */
data = (struct call_data_struct *) call_data;
func = data->func;
info = data->info;
wait = data->wait;
mb();
atomic_inc(&data->started);
/* At this point the structure may be gone unless wait is true. */
(*func)(info);
/* Notify the sending CPU that the task is done. */
mb();
if (wait)
atomic_inc(&data->finished);
mb(); /* Order bit clearing and data access. */
do {
unsigned long which;
which = ffz(~ops);
ops &= ~(1 << which);
switch (which) {
case IPI_CALL_FUNC:
{
struct call_data_struct *data;
void (*func)(void *info);
void *info;
int wait;
/* release the 'pointer lock' */
data = (struct call_data_struct *) call_data;
func = data->func;
info = data->info;
wait = data->wait;
mb();
atomic_inc(&data->started);
/*
* At this point the structure may be gone unless
* wait is true.
*/
(*func)(info);
/* Notify the sending CPU that the task is done. */
mb();
if (wait)
atomic_inc(&data->finished);
}
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;
default:
printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n", this_cpu, which);
break;
}
break;
case IPI_CPU_STOP:
stop_this_cpu();
break;
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. */
} 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.
*/
......@@ -470,8 +482,8 @@ smp_boot_cpus (void)
smp_setup_percpu_timer();
/*
* We have the boot CPU online for sure.
*/
* We have the boot CPU online for sure.
*/
set_bit(0, &cpu_online_map);
set_bit(0, &cpu_callin_map);
......@@ -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!
......@@ -493,7 +505,7 @@ smp_boot_cpus (void)
smp_num_cpus = 1;
goto smp_done;
}
if (max_cpus != -1)
if (max_cpus != -1)
printk (KERN_INFO "Limiting CPUs to %d\n", max_cpus);
if (smp_boot_data.cpu_count > 1) {
......
......@@ -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
sg->page = virt_to_page(addr);
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->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.
This diff is collapsed.
This diff is collapsed.
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_ITANIUM=y
# CONFIG_MCKINLEY is not set
# CONFIG_IA64_GENERIC is not set
# CONFIG_IA64_DIG is not set
CONFIG_IA64_HP_SIM=y
# 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_KCORE_ELF=y
# CONFIG_SMP is not set
# 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=y
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
#
# Networking options
#
# CONFIG_PACKET is not set
# CONFIG_NETLINK is not set
# CONFIG_NETFILTER is not set
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
# CONFIG_IP_PNP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
#
#
#
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_DECNET is not set
# CONFIG_BRIDGE is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
#
# Alternate 1394 support
#
# CONFIG_X1394 is not set
#
# Alternate SCSI support
#
# CONFIG_XSCSI is not set
#
# SCSI support
#
CONFIG_SCSI=y
#
# SCSI support type (disk, tape, CD-ROM)
#
CONFIG_BLK_DEV_SD=y
CONFIG_SD_EXTRA_DEVS=40
# CONFIG_CHR_DEV_ST is not set
# CONFIG_CHR_DEV_OSST is not set
# CONFIG_BLK_DEV_SR is not set
# CONFIG_CHR_DEV_SG is not set
#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
#
# CONFIG_SCSI_DEBUG_QUEUES is not set
# CONFIG_SCSI_MULTI_LUN is not set
CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
#
# SCSI low-level drivers
#
# CONFIG_SCSI_7000FASST is not set
# CONFIG_SCSI_ACARD is not set
# CONFIG_SCSI_AHA152X is not set
# CONFIG_SCSI_AHA1542 is not set
# CONFIG_SCSI_AHA1740 is not set
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_DPT_I2O is not set
# CONFIG_SCSI_ADVANSYS is not set
# CONFIG_SCSI_IN2000 is not set
# CONFIG_SCSI_AM53C974 is not set
# CONFIG_SCSI_MEGARAID is not set
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_DTC3280 is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_EATA_DMA is not set
# CONFIG_SCSI_EATA_PIO is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_GENERIC_NCR5380 is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_PPA is not set
# CONFIG_SCSI_IMM is not set
# CONFIG_SCSI_NCR53C406A is not set
# CONFIG_SCSI_NCR53C7xx is not set
# CONFIG_SCSI_PAS16 is not set
# CONFIG_SCSI_PCI2000 is not set
# CONFIG_SCSI_PCI2220I is not set
# CONFIG_SCSI_PSI240I is not set
# CONFIG_SCSI_QLOGIC_FAS is not set
# CONFIG_SCSI_SIM710 is not set
# CONFIG_SCSI_SYM53C416 is not set
# CONFIG_SCSI_T128 is not set
# CONFIG_SCSI_U14_34F 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
# CONFIG_PRINTER is not set
# CONFIG_PPDEV is not set
#
# 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=y
# 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
#
# Network File Systems
#
# CONFIG_CODA_FS is not set
# CONFIG_NFS_FS is not set
# CONFIG_NFS_V3 is not set
# CONFIG_ROOT_NFS is not set
# CONFIG_NFSD is not set
# CONFIG_NFSD_V3 is not set
# CONFIG_SUNRPC is not set
# CONFIG_LOCKD is not set
# CONFIG_SMB_FS is not set
# CONFIG_NCP_FS is not set
# CONFIG_NCPFS_PACKET_SIGNING is not set
# CONFIG_NCPFS_IOCTL_LOCKING is not set
# CONFIG_NCPFS_STRONG is not set
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
#
# 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
#
# Simulated drivers
#
CONFIG_SIMETH=y
CONFIG_SIM_SERIAL=y
CONFIG_SCSI_SIM=y
#
# 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.
......@@ -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.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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.
......@@ -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.
*/
/*
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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