Commit eaea39e2 authored by David Mosberger's avatar David Mosberger

Merge tiger.hpl.hp.com:/data1/bk/vanilla/linux-2.5

into tiger.hpl.hp.com:/data1/bk/lia64/to-linus-2.5
parents ecf2c214 4daa333c
...@@ -157,6 +157,11 @@ CONFIG_PCMCIA ...@@ -157,6 +157,11 @@ CONFIG_PCMCIA
and ds.o. If you want to compile it as a module, say M here and and ds.o. If you want to compile it as a module, say M here and
read <file:Documentation/modules.txt>. read <file:Documentation/modules.txt>.
CONFIG_KALLSYMS
Say Y here to let the kernel print out symbolic crash information and
symbolic stack backtraces. This increases the size of the kernel
somewhat, as all symbols have to be loaded into the kernel image.
CONFIG_KCORE_ELF CONFIG_KCORE_ELF
If you enabled support for /proc file system then the file If you enabled support for /proc file system then the file
/proc/kcore will contain the kernel core image. This can be used /proc/kcore will contain the kernel core image. This can be used
......
...@@ -33,26 +33,25 @@ ifeq ($(CONFIG_ITANIUM_BSTEP_SPECIFIC),y) ...@@ -33,26 +33,25 @@ ifeq ($(CONFIG_ITANIUM_BSTEP_SPECIFIC),y)
CFLAGS += -mb-step CFLAGS += -mb-step
endif endif
HEAD := arch/$(ARCH)/kernel/head.o arch/ia64/kernel/init_task.o HEAD := arch/$(ARCH)/kernel/head.o arch/$(ARCH)/kernel/init_task.o
core-$(CONFIG_IA64_GENERIC) += arch/$(ARCH)/hp/ arch/$(ARCH)/dig/ libs-y += arch/$(ARCH)/lib/
core-$(CONFIG_IA64_HP_SIM) += arch/$(ARCH)/hp/ core-y += arch/$(ARCH)/kernel/ arch/$(ARCH)/mm/
core-$(CONFIG_IA64_HP_ZX1) += arch/$(ARCH)/hp/ arch/$(ARCH)/dig/ core-$(CONFIG_IA32_SUPPORT) += arch/$(ARCH)/ia32/
core-$(CONFIG_IA64_SGI_SN) += arch/$(ARCH)/sn/kernel arch/$(ARCH)/sn/io
core-$(CONFIG_IA64_DIG) += arch/$(ARCH)/dig/ core-$(CONFIG_IA64_DIG) += arch/$(ARCH)/dig/
core-$(CONFIG_IA64_GENERIC) += arch/$(ARCH)/hp/ arch/$(ARCH)/dig/
core-$(CONFIG_IA64_HP_SIM) += arch/$(ARCH)/hp/
core-$(CONFIG_IA64_HP_ZX1) += arch/$(ARCH)/hp/ arch/$(ARCH)/dig/
core-$(CONFIG_IA64_SGI_SN) += arch/$(ARCH)/sn/kernel arch/$(ARCH)/sn/io \
arch/$(ARCH)/sn/fakeprom
drivers-$(CONFIG_PCI) += arch/$(ARCH)/pci/
drivers-$(CONFIG_IA64_HP_ZX1) += arch/$(ARCH)/hp/common/ arch/$(ARCH)/hp/zx1/
ifdef CONFIG_IA64_SGI_SN ifdef CONFIG_IA64_SGI_SN
CFLAGS += -DBRINGUP CFLAGS += -DBRINGUP
SUBDIRS += arch/$(ARCH)/sn/fakeprom SUBDIRS += arch/$(ARCH)/sn/fakeprom
endif endif
core-$(CONFIG_IA32_SUPPORT) += arch/$(ARCH)/ia32/
libs-y += arch/$(ARCH)/lib/
core-y += arch/$(ARCH)/kernel/ arch/$(ARCH)/mm/
drivers-$(CONFIG_PCI) += arch/$(ARCH)/pci/
drivers-$(CONFIG_IA64_HP_ZX1) += arch/$(ARCH)/hp/common/ arch/$(ARCH)/hp/zx1/
MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
compressed: vmlinux compressed: vmlinux
......
...@@ -267,6 +267,7 @@ choice 'Physical memory granularity' \ ...@@ -267,6 +267,7 @@ choice 'Physical memory granularity' \
bool 'Kernel debugging' CONFIG_DEBUG_KERNEL bool 'Kernel debugging' CONFIG_DEBUG_KERNEL
if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then
bool ' Load all symbols for debugging/kksymoops' CONFIG_KALLSYMS
bool ' Print possible IA64 hazards to console' CONFIG_IA64_PRINT_HAZARDS bool ' Print possible IA64 hazards to console' CONFIG_IA64_PRINT_HAZARDS
bool ' Disable VHPT' CONFIG_DISABLE_VHPT bool ' Disable VHPT' CONFIG_DISABLE_VHPT
bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ
......
This diff is collapsed.
...@@ -26,6 +26,12 @@ ...@@ -26,6 +26,12 @@
#include <linux/if_ppp.h> #include <linux/if_ppp.h>
#include <linux/ixjuser.h> #include <linux/ixjuser.h>
#include <linux/i2o-dev.h> #include <linux/i2o-dev.h>
#include <scsi/scsi.h>
/* Ugly hack. */
#undef __KERNEL__
#include <scsi/scsi_ioctl.h>
#define __KERNEL__
#include <scsi/sg.h>
#include <asm/ia32.h> #include <asm/ia32.h>
...@@ -60,6 +66,235 @@ put_dirent32 (struct dirent *d, struct linux32_dirent *d32) ...@@ -60,6 +66,235 @@ put_dirent32 (struct dirent *d, struct linux32_dirent *d32)
|| put_user(d->d_reclen, &d32->d_reclen) || put_user(d->d_reclen, &d32->d_reclen)
|| copy_to_user(d32->d_name, d->d_name, namelen + 1)); || copy_to_user(d32->d_name, d->d_name, namelen + 1));
} }
/*
* The transform code for the SG_IO ioctl was brazenly lifted from
* the Sparc64 port in the file `arch/sparc64/kernel/ioctl32.c'.
* Thanks to Jakub Jelinek & Eddie C. Dost.
*/
typedef struct sg_io_hdr32 {
int interface_id; /* [i] 'S' for SCSI generic (required) */
int dxfer_direction; /* [i] data transfer direction */
char cmd_len; /* [i] SCSI command length ( <= 16 bytes) */
char mx_sb_len; /* [i] max length to write to sbp */
short iovec_count; /* [i] 0 implies no scatter gather */
int dxfer_len; /* [i] byte count of data transfer */
int dxferp; /* [i], [*io] points to data transfer memory
or scatter gather list */
int cmdp; /* [i], [*i] points to command to perform */
int sbp; /* [i], [*o] points to sense_buffer memory */
int timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */
int flags; /* [i] 0 -> default, see SG_FLAG... */
int pack_id; /* [i->o] unused internally (normally) */
int usr_ptr; /* [i->o] unused internally */
char status; /* [o] scsi status */
char masked_status; /* [o] shifted, masked scsi status */
char msg_status; /* [o] messaging level data (optional) */
char sb_len_wr; /* [o] byte count actually written to sbp */
short host_status; /* [o] errors from host adapter */
short driver_status; /* [o] errors from software driver */
int resid; /* [o] dxfer_len - actual_transferred */
int duration; /* [o] time taken by cmd (unit: millisec) */
int info; /* [o] auxiliary information */
} sg_io_hdr32_t; /* 64 bytes long (on IA32) */
struct iovec32 { unsigned int iov_base; int iov_len; };
static int alloc_sg_iovec(sg_io_hdr_t *sgp, int uptr32)
{
struct iovec32 *uiov = (struct iovec32 *) P(uptr32);
sg_iovec_t *kiov;
int i;
sgp->dxferp = kmalloc(sgp->iovec_count *
sizeof(sg_iovec_t), GFP_KERNEL);
if (!sgp->dxferp)
return -ENOMEM;
memset(sgp->dxferp, 0,
sgp->iovec_count * sizeof(sg_iovec_t));
kiov = (sg_iovec_t *) sgp->dxferp;
for (i = 0; i < sgp->iovec_count; i++) {
int iov_base32;
if (__get_user(iov_base32, &uiov->iov_base) ||
__get_user(kiov->iov_len, &uiov->iov_len))
return -EFAULT;
kiov->iov_base = kmalloc(kiov->iov_len, GFP_KERNEL);
if (!kiov->iov_base)
return -ENOMEM;
if (copy_from_user(kiov->iov_base,
(void *) P(iov_base32),
kiov->iov_len))
return -EFAULT;
uiov++;
kiov++;
}
return 0;
}
static int copy_back_sg_iovec(sg_io_hdr_t *sgp, int uptr32)
{
struct iovec32 *uiov = (struct iovec32 *) P(uptr32);
sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp;
int i;
for (i = 0; i < sgp->iovec_count; i++) {
int iov_base32;
if (__get_user(iov_base32, &uiov->iov_base))
return -EFAULT;
if (copy_to_user((void *) P(iov_base32),
kiov->iov_base,
kiov->iov_len))
return -EFAULT;
uiov++;
kiov++;
}
return 0;
}
static void free_sg_iovec(sg_io_hdr_t *sgp)
{
sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp;
int i;
for (i = 0; i < sgp->iovec_count; i++) {
if (kiov->iov_base) {
kfree(kiov->iov_base);
kiov->iov_base = NULL;
}
kiov++;
}
kfree(sgp->dxferp);
sgp->dxferp = NULL;
}
static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
{
sg_io_hdr32_t *sg_io32;
sg_io_hdr_t sg_io64;
int dxferp32, cmdp32, sbp32;
mm_segment_t old_fs;
int err = 0;
sg_io32 = (sg_io_hdr32_t *)arg;
err = __get_user(sg_io64.interface_id, &sg_io32->interface_id);
err |= __get_user(sg_io64.dxfer_direction, &sg_io32->dxfer_direction);
err |= __get_user(sg_io64.cmd_len, &sg_io32->cmd_len);
err |= __get_user(sg_io64.mx_sb_len, &sg_io32->mx_sb_len);
err |= __get_user(sg_io64.iovec_count, &sg_io32->iovec_count);
err |= __get_user(sg_io64.dxfer_len, &sg_io32->dxfer_len);
err |= __get_user(sg_io64.timeout, &sg_io32->timeout);
err |= __get_user(sg_io64.flags, &sg_io32->flags);
err |= __get_user(sg_io64.pack_id, &sg_io32->pack_id);
sg_io64.dxferp = NULL;
sg_io64.cmdp = NULL;
sg_io64.sbp = NULL;
err |= __get_user(cmdp32, &sg_io32->cmdp);
sg_io64.cmdp = kmalloc(sg_io64.cmd_len, GFP_KERNEL);
if (!sg_io64.cmdp) {
err = -ENOMEM;
goto out;
}
if (copy_from_user(sg_io64.cmdp,
(void *) P(cmdp32),
sg_io64.cmd_len)) {
err = -EFAULT;
goto out;
}
err |= __get_user(sbp32, &sg_io32->sbp);
sg_io64.sbp = kmalloc(sg_io64.mx_sb_len, GFP_KERNEL);
if (!sg_io64.sbp) {
err = -ENOMEM;
goto out;
}
if (copy_from_user(sg_io64.sbp,
(void *) P(sbp32),
sg_io64.mx_sb_len)) {
err = -EFAULT;
goto out;
}
err |= __get_user(dxferp32, &sg_io32->dxferp);
if (sg_io64.iovec_count) {
int ret;
if ((ret = alloc_sg_iovec(&sg_io64, dxferp32))) {
err = ret;
goto out;
}
} else {
sg_io64.dxferp = kmalloc(sg_io64.dxfer_len, GFP_KERNEL);
if (!sg_io64.dxferp) {
err = -ENOMEM;
goto out;
}
if (copy_from_user(sg_io64.dxferp,
(void *) P(dxferp32),
sg_io64.dxfer_len)) {
err = -EFAULT;
goto out;
}
}
/* Unused internally, do not even bother to copy it over. */
sg_io64.usr_ptr = NULL;
if (err)
return -EFAULT;
old_fs = get_fs();
set_fs (KERNEL_DS);
err = sys_ioctl (fd, cmd, (unsigned long) &sg_io64);
set_fs (old_fs);
if (err < 0)
goto out;
err = __put_user(sg_io64.pack_id, &sg_io32->pack_id);
err |= __put_user(sg_io64.status, &sg_io32->status);
err |= __put_user(sg_io64.masked_status, &sg_io32->masked_status);
err |= __put_user(sg_io64.msg_status, &sg_io32->msg_status);
err |= __put_user(sg_io64.sb_len_wr, &sg_io32->sb_len_wr);
err |= __put_user(sg_io64.host_status, &sg_io32->host_status);
err |= __put_user(sg_io64.driver_status, &sg_io32->driver_status);
err |= __put_user(sg_io64.resid, &sg_io32->resid);
err |= __put_user(sg_io64.duration, &sg_io32->duration);
err |= __put_user(sg_io64.info, &sg_io32->info);
err |= copy_to_user((void *)P(sbp32), sg_io64.sbp, sg_io64.mx_sb_len);
if (sg_io64.dxferp) {
if (sg_io64.iovec_count)
err |= copy_back_sg_iovec(&sg_io64, dxferp32);
else
err |= copy_to_user((void *)P(dxferp32),
sg_io64.dxferp,
sg_io64.dxfer_len);
}
if (err)
err = -EFAULT;
out:
if (sg_io64.cmdp)
kfree(sg_io64.cmdp);
if (sg_io64.sbp)
kfree(sg_io64.sbp);
if (sg_io64.dxferp) {
if (sg_io64.iovec_count) {
free_sg_iovec(&sg_io64);
} else {
kfree(sg_io64.dxferp);
}
}
return err;
}
asmlinkage long asmlinkage long
sys32_ioctl (unsigned int fd, unsigned int cmd, unsigned int arg) sys32_ioctl (unsigned int fd, unsigned int cmd, unsigned int arg)
...@@ -271,6 +506,9 @@ sys32_ioctl (unsigned int fd, unsigned int cmd, unsigned int arg) ...@@ -271,6 +506,9 @@ sys32_ioctl (unsigned int fd, unsigned int cmd, unsigned int arg)
default: default:
return sys_ioctl(fd, cmd, (unsigned long)arg); return sys_ioctl(fd, cmd, (unsigned long)arg);
case IOCTL_NR(SG_IO):
return(sg_ioctl_trans(fd, cmd, arg));
} }
printk("%x:unimplemented IA32 ioctl system call\n", cmd); printk("%x:unimplemented IA32 ioctl system call\n", cmd);
return -EINVAL; return -EINVAL;
......
This diff is collapsed.
...@@ -2842,20 +2842,6 @@ putreg (struct task_struct *child, int regno, unsigned int value) ...@@ -2842,20 +2842,6 @@ putreg (struct task_struct *child, int regno, unsigned int value)
} }
} }
static inline void
ia32f2ia64f (void *dst, void *src)
{
asm volatile ("ldfe f6=[%1];; stf.spill [%0]=f6" :: "r"(dst), "r"(src) : "memory");
return;
}
static inline void
ia64f2ia32f (void *dst, void *src)
{
asm volatile ("ldf.fill f6=[%1];; stfe [%0]=f6" :: "r"(dst), "r"(src) : "memory");
return;
}
static void static void
put_fpreg (int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp, put_fpreg (int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp,
int tos) int tos)
......
...@@ -8,6 +8,9 @@ ...@@ -8,6 +8,9 @@
* Copyright (C) 2000 Intel Corp. * 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>
* Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> * Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
* Copyright (C) 2001 Jenna Hall <jenna.s.hall@intel.com>
* Copyright (C) 2001 Takayoshi Kochi <t-kouchi@cq.jp.nec.com>
* Copyright (C) 2002 Erich Focht <efocht@ess.nec.de>
* *
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* *
...@@ -43,6 +46,7 @@ ...@@ -43,6 +46,7 @@
#include <asm/machvec.h> #include <asm/machvec.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/numa.h>
#define PREFIX "ACPI: " #define PREFIX "ACPI: "
...@@ -447,6 +451,158 @@ acpi_parse_madt (unsigned long phys_addr, unsigned long size) ...@@ -447,6 +451,158 @@ acpi_parse_madt (unsigned long phys_addr, unsigned long size)
} }
#ifdef CONFIG_ACPI_NUMA
#define SLIT_DEBUG
#define PXM_FLAG_LEN ((MAX_PXM_DOMAINS + 1)/32)
static int __initdata srat_num_cpus; /* number of cpus */
static u32 __initdata pxm_flag[PXM_FLAG_LEN];
#define pxm_bit_set(bit) (set_bit(bit,(void *)pxm_flag))
#define pxm_bit_test(bit) (test_bit(bit,(void *)pxm_flag))
/* maps to convert between proximity domain and logical node ID */
int __initdata pxm_to_nid_map[MAX_PXM_DOMAINS];
int __initdata nid_to_pxm_map[NR_NODES];
static struct acpi_table_slit __initdata *slit_table;
/*
* ACPI 2.0 SLIT (System Locality Information Table)
* http://devresource.hp.com/devresource/Docs/TechPapers/IA64/slit.pdf
*/
void __init
acpi_numa_slit_init (struct acpi_table_slit *slit)
{
int i, j, node_from, node_to;
u32 len;
len = sizeof(struct acpi_table_header) + 8
+ slit->localities * slit->localities;
if (slit->header.length != len) {
printk("ACPI 2.0 SLIT: size mismatch: %d expected, %d actual\n",
len, slit->header.length);
memset(numa_slit, 10, sizeof(numa_slit));
return;
}
slit_table = slit;
}
void __init
acpi_numa_processor_affinity_init (struct acpi_table_processor_affinity *pa)
{
/* record this node in proximity bitmap */
pxm_bit_set(pa->proximity_domain);
node_cpuid[srat_num_cpus].phys_id = (pa->apic_id << 8) | (pa->lsapic_eid);
/* nid should be overridden as logical node id later */
node_cpuid[srat_num_cpus].nid = pa->proximity_domain;
srat_num_cpus++;
}
void __init
acpi_numa_memory_affinity_init (struct acpi_table_memory_affinity *ma)
{
unsigned long paddr, size;
u8 pxm;
struct node_memblk_s *p, *q, *pend;
pxm = ma->proximity_domain;
/* record this node in proximity bitmap */
pxm_bit_set(pxm);
/* fill node memory chunk structure */
paddr = ma->base_addr_hi;
paddr = (paddr << 32) | ma->base_addr_lo;
size = ma->length_hi;
size = (size << 32) | ma->length_lo;
if (num_memblks >= NR_MEMBLKS) {
printk("Too many mem chunks in SRAT. Ignoring %ld MBytes at %lx\n",
size/(1024*1024), paddr);
return;
}
/* Insertion sort based on base address */
pend = &node_memblk[num_memblks];
for (p = &node_memblk[0]; p < pend; p++) {
if (paddr < p->start_paddr)
break;
}
if (p < pend) {
for (q = pend; q >= p; q--)
*(q + 1) = *q;
}
p->start_paddr = paddr;
p->size = size;
p->nid = pxm;
num_memblks++;
}
void __init
acpi_numa_arch_fixup(void)
{
int i, j;
/* calculate total number of nodes in system from PXM bitmap */
numnodes = 0; /* init total nodes in system */
memset(pxm_to_nid_map, -1, sizeof(pxm_to_nid_map));
memset(nid_to_pxm_map, -1, sizeof(nid_to_pxm_map));
for (i = 0; i < MAX_PXM_DOMAINS; i++) {
if (pxm_bit_test(i)) {
pxm_to_nid_map[i] = numnodes;
nid_to_pxm_map[numnodes++] = i;
}
}
/* set logical node id in memory chunk structure */
for (i = 0; i < num_memblks; i++)
node_memblk[i].nid = pxm_to_nid_map[node_memblk[i].nid];
/* assign memory bank numbers for each chunk on each node */
for (i = 0; i < numnodes; i++) {
int bank;
bank = 0;
for (j = 0; j < num_memblks; j++)
if (node_memblk[j].nid == i)
node_memblk[j].bank = bank++;
}
/* set logical node id in cpu structure */
for (i = 0; i < srat_num_cpus; i++)
node_cpuid[i].nid = pxm_to_nid_map[node_cpuid[i].nid];
printk("Number of logical nodes in system = %d\n", numnodes);
printk("Number of memory chunks in system = %d\n", num_memblks);
if (!slit_table) return;
memset(numa_slit, -1, sizeof(numa_slit));
for (i=0; i<slit_table->localities; i++) {
if (!pxm_bit_test(i))
continue;
node_from = pxm_to_nid_map[i];
for (j=0; j<slit_table->localities; j++) {
if (!pxm_bit_test(j))
continue;
node_to = pxm_to_nid_map[j];
node_distance(node_from, node_to) =
slit_table->entry[i*slit_table->localities + j];
}
}
#ifdef SLIT_DEBUG
printk("ACPI 2.0 SLIT locality table:\n");
for (i = 0; i < numnodes; i++) {
for (j = 0; j < numnodes; j++)
printk("%03d ", node_distance(i,j));
printk("\n");
}
#endif
}
#endif /* CONFIG_ACPI_NUMA */
static int __init static int __init
acpi_parse_fadt (unsigned long phys_addr, unsigned long size) acpi_parse_fadt (unsigned long phys_addr, unsigned long size)
{ {
...@@ -556,12 +712,6 @@ acpi_parse_spcr (unsigned long phys_addr, unsigned long size) ...@@ -556,12 +712,6 @@ acpi_parse_spcr (unsigned long phys_addr, unsigned long size)
int __init int __init
acpi_boot_init (char *cmdline) acpi_boot_init (char *cmdline)
{ {
int result;
/* Initialize the ACPI boot-time table parser */
result = acpi_table_init(cmdline);
if (result)
return result;
/* /*
* MADT * MADT
......
...@@ -60,67 +60,157 @@ struct proc_dir_entry *efi_dir = NULL; ...@@ -60,67 +60,157 @@ struct proc_dir_entry *efi_dir = NULL;
static unsigned long mem_limit = ~0UL; static unsigned long mem_limit = ~0UL;
static efi_status_t #define efi_call_virt(f, args...) (*(f))(args)
phys_get_time (efi_time_t *tm, efi_time_cap_t *tc)
{ #define STUB_GET_TIME(prefix, adjust_arg) \
return efi_call_phys(__va(runtime->get_time), __pa(tm), __pa(tc)); static efi_status_t \
prefix##_get_time (efi_time_t *tm, efi_time_cap_t *tc) \
{ \
struct ia64_fpreg fr[6]; \
efi_status_t ret; \
\
ia64_save_scratch_fpregs(fr); \
ret = efi_call_##prefix((efi_get_time_t *) __va(runtime->get_time), adjust_arg(tm), \
adjust_arg(tc)); \
ia64_load_scratch_fpregs(fr); \
return ret; \
} }
static efi_status_t #define STUB_SET_TIME(prefix, adjust_arg) \
phys_set_time (efi_time_t *tm) static efi_status_t \
{ prefix##_set_time (efi_time_t *tm) \
return efi_call_phys(__va(runtime->set_time), __pa(tm)); { \
struct ia64_fpreg fr[6]; \
efi_status_t ret; \
\
ia64_save_scratch_fpregs(fr); \
ret = efi_call_##prefix((efi_set_time_t *) __va(runtime->set_time), adjust_arg(tm)); \
ia64_load_scratch_fpregs(fr); \
return ret; \
} }
static efi_status_t #define STUB_GET_WAKEUP_TIME(prefix, adjust_arg) \
phys_get_wakeup_time (efi_bool_t *enabled, efi_bool_t *pending, efi_time_t *tm) static efi_status_t \
{ prefix##_get_wakeup_time (efi_bool_t *enabled, efi_bool_t *pending, efi_time_t *tm) \
return efi_call_phys(__va(runtime->get_wakeup_time), __pa(enabled), __pa(pending), { \
__pa(tm)); struct ia64_fpreg fr[6]; \
efi_status_t ret; \
\
ia64_save_scratch_fpregs(fr); \
ret = efi_call_##prefix((efi_get_wakeup_time_t *) __va(runtime->get_wakeup_time), \
adjust_arg(enabled), adjust_arg(pending), adjust_arg(tm)); \
ia64_load_scratch_fpregs(fr); \
return ret; \
} }
static efi_status_t #define STUB_SET_WAKEUP_TIME(prefix, adjust_arg) \
phys_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm) static efi_status_t \
{ prefix##_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm) \
return efi_call_phys(__va(runtime->set_wakeup_time), enabled, __pa(tm)); { \
struct ia64_fpreg fr[6]; \
efi_status_t ret; \
\
ia64_save_scratch_fpregs(fr); \
ret = efi_call_##prefix((efi_set_wakeup_time_t *) __va(runtime->set_wakeup_time), \
enabled, adjust_arg(tm)); \
ia64_load_scratch_fpregs(fr); \
return ret; \
} }
static efi_status_t #define STUB_GET_VARIABLE(prefix, adjust_arg) \
phys_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr, static efi_status_t \
unsigned long *data_size, void *data) prefix##_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr, \
{ unsigned long *data_size, void *data) \
return efi_call_phys(__va(runtime->get_variable), __pa(name), __pa(vendor), __pa(attr), { \
__pa(data_size), __pa(data)); struct ia64_fpreg fr[6]; \
efi_status_t ret; \
\
ia64_save_scratch_fpregs(fr); \
ret = efi_call_##prefix((efi_get_variable_t *) __va(runtime->get_variable), \
adjust_arg(name), adjust_arg(vendor), adjust_arg(attr), \
adjust_arg(data_size), adjust_arg(data)); \
ia64_load_scratch_fpregs(fr); \
return ret; \
} }
static efi_status_t #define STUB_GET_NEXT_VARIABLE(prefix, adjust_arg) \
phys_get_next_variable (unsigned long *name_size, efi_char16_t *name, efi_guid_t *vendor) static efi_status_t \
{ prefix##_get_next_variable (unsigned long *name_size, efi_char16_t *name, efi_guid_t *vendor) \
return efi_call_phys(__va(runtime->get_next_variable), __pa(name_size), __pa(name), { \
__pa(vendor)); struct ia64_fpreg fr[6]; \
efi_status_t ret; \
\
ia64_save_scratch_fpregs(fr); \
ret = efi_call_##prefix((efi_get_next_variable_t *) __va(runtime->get_next_variable), \
adjust_arg(name_size), adjust_arg(name), adjust_arg(vendor)); \
ia64_load_scratch_fpregs(fr); \
return ret; \
} }
static efi_status_t #define STUB_SET_VARIABLE(prefix, adjust_arg) \
phys_set_variable (efi_char16_t *name, efi_guid_t *vendor, u32 attr, static efi_status_t \
unsigned long data_size, void *data) prefix##_set_variable (efi_char16_t *name, efi_guid_t *vendor, u32 attr, \
{ unsigned long data_size, void *data) \
return efi_call_phys(__va(runtime->set_variable), __pa(name), __pa(vendor), attr, { \
data_size, __pa(data)); struct ia64_fpreg fr[6]; \
efi_status_t ret; \
\
ia64_save_scratch_fpregs(fr); \
ret = efi_call_##prefix((efi_set_variable_t *) __va(runtime->set_variable), \
adjust_arg(name), adjust_arg(vendor), attr, data_size, \
adjust_arg(data)); \
ia64_load_scratch_fpregs(fr); \
return ret; \
} }
static efi_status_t #define STUB_GET_NEXT_HIGH_MONO_COUNT(prefix, adjust_arg) \
phys_get_next_high_mono_count (u64 *count) static efi_status_t \
{ prefix##_get_next_high_mono_count (u64 *count) \
return efi_call_phys(__va(runtime->get_next_high_mono_count), __pa(count)); { \
struct ia64_fpreg fr[6]; \
efi_status_t ret; \
\
ia64_save_scratch_fpregs(fr); \
ret = efi_call_##prefix((efi_get_next_high_mono_count_t *) \
__va(runtime->get_next_high_mono_count), adjust_arg(count)); \
ia64_load_scratch_fpregs(fr); \
return ret; \
} }
static void #define STUB_RESET_SYSTEM(prefix, adjust_arg) \
phys_reset_system (int reset_type, efi_status_t status, static void \
unsigned long data_size, efi_char16_t *data) prefix##_reset_system (int reset_type, efi_status_t status, \
{ unsigned long data_size, efi_char16_t *data) \
efi_call_phys(__va(runtime->reset_system), status, data_size, __pa(data)); { \
struct ia64_fpreg fr[6]; \
\
ia64_save_scratch_fpregs(fr); \
efi_call_##prefix((efi_reset_system_t *) __va(runtime->reset_system), \
reset_type, status, data_size, adjust_arg(data)); \
/* should not return, but just in case... */ \
ia64_load_scratch_fpregs(fr); \
} }
STUB_GET_TIME(phys, __pa)
STUB_SET_TIME(phys, __pa)
STUB_GET_WAKEUP_TIME(phys, __pa)
STUB_SET_WAKEUP_TIME(phys, __pa)
STUB_GET_VARIABLE(phys, __pa)
STUB_GET_NEXT_VARIABLE(phys, __pa)
STUB_SET_VARIABLE(phys, __pa)
STUB_GET_NEXT_HIGH_MONO_COUNT(phys, __pa)
STUB_RESET_SYSTEM(phys, __pa)
STUB_GET_TIME(virt, )
STUB_SET_TIME(virt, )
STUB_GET_WAKEUP_TIME(virt, )
STUB_SET_WAKEUP_TIME(virt, )
STUB_GET_VARIABLE(virt, )
STUB_GET_NEXT_VARIABLE(virt, )
STUB_SET_VARIABLE(virt, )
STUB_GET_NEXT_HIGH_MONO_COUNT(virt, )
STUB_RESET_SYSTEM(virt, )
void void
efi_gettimeofday (struct timeval *tv) efi_gettimeofday (struct timeval *tv)
{ {
...@@ -574,18 +664,17 @@ efi_enter_virtual_mode (void) ...@@ -574,18 +664,17 @@ efi_enter_virtual_mode (void)
} }
/* /*
* Now that EFI is in virtual mode, we arrange for EFI functions to be * Now that EFI is in virtual mode, we call the EFI functions more efficiently:
* called directly:
*/ */
efi.get_time = __va(runtime->get_time); efi.get_time = virt_get_time;
efi.set_time = __va(runtime->set_time); efi.set_time = virt_set_time;
efi.get_wakeup_time = __va(runtime->get_wakeup_time); efi.get_wakeup_time = virt_get_wakeup_time;
efi.set_wakeup_time = __va(runtime->set_wakeup_time); efi.set_wakeup_time = virt_set_wakeup_time;
efi.get_variable = __va(runtime->get_variable); efi.get_variable = virt_get_variable;
efi.get_next_variable = __va(runtime->get_next_variable); efi.get_next_variable = virt_get_next_variable;
efi.set_variable = __va(runtime->set_variable); efi.set_variable = virt_set_variable;
efi.get_next_high_mono_count = __va(runtime->get_next_high_mono_count); efi.get_next_high_mono_count = virt_get_next_high_mono_count;
efi.reset_system = __va(runtime->reset_system); efi.reset_system = virt_reset_system;
} }
/* /*
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* PAL & SAL emulation. * PAL & SAL emulation.
* *
* Copyright (C) 1998-2001 Hewlett-Packard Co * Copyright (C) 1998-2001 Hewlett-Packard Co
* Copyright (C) 1998-2001 David Mosberger-Tang <davidm@hpl.hp.com> * David Mosberger-Tang <davidm@hpl.hp.com>
* *
* For the HP simulator, this file gets include in boot/bootloader.c. * For the HP simulator, this file gets include in boot/bootloader.c.
* For SoftSDV, this file gets included in sys_softsdv.c. * For SoftSDV, this file gets included in sys_softsdv.c.
......
...@@ -133,12 +133,8 @@ find_iosapic (unsigned int gsi) ...@@ -133,12 +133,8 @@ find_iosapic (unsigned int gsi)
return -1; return -1;
} }
/* static inline int
* Translate GSI number to the corresponding IA-64 interrupt vector. If no _gsi_to_vector (unsigned int gsi)
* entry exists, return -1.
*/
int
gsi_to_vector (unsigned int gsi)
{ {
struct iosapic_intr_info *info; struct iosapic_intr_info *info;
...@@ -148,6 +144,26 @@ gsi_to_vector (unsigned int gsi) ...@@ -148,6 +144,26 @@ gsi_to_vector (unsigned int gsi)
return -1; return -1;
} }
/*
* Translate GSI number to the corresponding IA-64 interrupt vector. If no
* entry exists, return -1.
*/
inline int
gsi_to_vector (unsigned int gsi)
{
return _gsi_to_vector(gsi);
}
int
gsi_to_irq (unsigned int gsi)
{
/*
* XXX fix me: this assumes an identity mapping vetween IA-64 vector and Linux irq
* numbers...
*/
return _gsi_to_vector(gsi);
}
static void static void
set_rte (unsigned int vector, unsigned int dest) set_rte (unsigned int vector, unsigned int dest)
{ {
...@@ -157,7 +173,7 @@ set_rte (unsigned int vector, unsigned int dest) ...@@ -157,7 +173,7 @@ set_rte (unsigned int vector, unsigned int dest)
int rte_index; int rte_index;
char redir; char redir;
DBG(KERN_DEBUG"IOSAPIC: routing vector %d to %x\n", vector, dest); DBG(KERN_DEBUG"IOSAPIC: routing vector %d to 0x%x\n", vector, dest);
rte_index = iosapic_intr_info[vector].rte_index; rte_index = iosapic_intr_info[vector].rte_index;
if (rte_index < 0) if (rte_index < 0)
......
...@@ -116,8 +116,8 @@ ENTRY(vhpt_miss) ...@@ -116,8 +116,8 @@ ENTRY(vhpt_miss)
;; ;;
(p8) dep r25=r18,r25,2,6 (p8) dep r25=r18,r25,2,6
(p8) shr r22=r22,HPAGE_SHIFT-PAGE_SHIFT (p8) shr r22=r22,HPAGE_SHIFT-PAGE_SHIFT
;;
#endif #endif
;;
cmp.eq p6,p7=5,r17 // is IFA pointing into to region 5? cmp.eq p6,p7=5,r17 // is IFA pointing into to region 5?
shr.u r18=r22,PGDIR_SHIFT // get bits 33-63 of the faulting address shr.u r18=r22,PGDIR_SHIFT // get bits 33-63 of the faulting address
;; ;;
......
...@@ -1012,28 +1012,13 @@ ia64_log_prt_oem_data (int header_len, int sect_len, u8 *p_data, prfunc_t prfunc ...@@ -1012,28 +1012,13 @@ ia64_log_prt_oem_data (int header_len, int sect_len, u8 *p_data, prfunc_t prfunc
void void
ia64_log_rec_header_print (sal_log_record_header_t *lh, prfunc_t prfunc) ia64_log_rec_header_print (sal_log_record_header_t *lh, prfunc_t prfunc)
{ {
char str_buf[32]; prfunc("+Err Record ID: %d SAL Rev: %2x.%02x\n", lh->id,
lh->revision.major, lh->revision.minor);
sprintf(str_buf, "%2d.%02d", prfunc("+Time: %02x/%02x/%02x%02x %02x:%02x:%02x Severity %d\n",
(lh->revision.major >> 4) * 10 + (lh->revision.major & 0xf), lh->timestamp.slh_month, lh->timestamp.slh_day,
(lh->revision.minor >> 4) * 10 + (lh->revision.minor & 0xf)); lh->timestamp.slh_century, lh->timestamp.slh_year,
prfunc("+Err Record ID: %d SAL Rev: %s\n", lh->id, str_buf); lh->timestamp.slh_hour, lh->timestamp.slh_minute,
sprintf(str_buf, "%02d/%02d/%04d/ %02d:%02d:%02d", lh->timestamp.slh_second, lh->severity);
(lh->timestamp.slh_month >> 4) * 10 +
(lh->timestamp.slh_month & 0xf),
(lh->timestamp.slh_day >> 4) * 10 +
(lh->timestamp.slh_day & 0xf),
(lh->timestamp.slh_century >> 4) * 1000 +
(lh->timestamp.slh_century & 0xf) * 100 +
(lh->timestamp.slh_year >> 4) * 10 +
(lh->timestamp.slh_year & 0xf),
(lh->timestamp.slh_hour >> 4) * 10 +
(lh->timestamp.slh_hour & 0xf),
(lh->timestamp.slh_minute >> 4) * 10 +
(lh->timestamp.slh_minute & 0xf),
(lh->timestamp.slh_second >> 4) * 10 +
(lh->timestamp.slh_second & 0xf));
prfunc("+Time: %s Severity %d\n", str_buf, lh->severity);
} }
/* /*
......
...@@ -63,6 +63,26 @@ ...@@ -63,6 +63,26 @@
* Misc macros and definitions * Misc macros and definitions
*/ */
#define PMU_FIRST_COUNTER 4 #define PMU_FIRST_COUNTER 4
#define PMU_MAX_PMCS 256
#define PMU_MAX_PMDS 256
/*
* type of a PMU register (bitmask).
* bitmask structure:
* bit0 : register implemented
* bit1 : end marker
* bit2-3 : reserved
* bit4-7 : register type
* bit8-31: reserved
*/
#define PFM_REG_IMPL 0x1 /* register implemented */
#define PFM_REG_END 0x2 /* end marker */
#define PFM_REG_MONITOR (0x1<<4|PFM_REG_IMPL) /* a PMC with a pmc.pm field only */
#define PFM_REG_COUNTING (0x2<<4|PFM_REG_IMPL) /* a PMC with a pmc.pm AND pmc.oi, a PMD used as a counter */
#define PFM_REG_CONTROL (0x3<<4|PFM_REG_IMPL) /* PMU control register */
#define PFM_REG_CONFIG (0x4<<4|PFM_REG_IMPL) /* refine configuration */
#define PFM_REG_BUFFER (0x5<<4|PFM_REG_IMPL) /* PMD used as buffer */
#define PFM_IS_DISABLED() pmu_conf.pfm_is_disabled #define PFM_IS_DISABLED() pmu_conf.pfm_is_disabled
...@@ -70,13 +90,18 @@ ...@@ -70,13 +90,18 @@
#define PFM_FL_INHERIT_MASK (PFM_FL_INHERIT_NONE|PFM_FL_INHERIT_ONCE|PFM_FL_INHERIT_ALL) #define PFM_FL_INHERIT_MASK (PFM_FL_INHERIT_NONE|PFM_FL_INHERIT_ONCE|PFM_FL_INHERIT_ALL)
/* i assume unsigned */ /* i assume unsigned */
#define PMC_IS_IMPL(i) (i<pmu_conf.num_pmcs && pmu_conf.impl_regs[i>>6] & (1UL<< (i) %64)) #define PMC_IS_IMPL(i) (i< PMU_MAX_PMCS && (pmu_conf.pmc_desc[i].type & PFM_REG_IMPL))
#define PMD_IS_IMPL(i) (i<pmu_conf.num_pmds && pmu_conf.impl_regs[4+(i>>6)] & (1UL<<(i) % 64)) #define PMD_IS_IMPL(i) (i< PMU_MAX_PMDS && (pmu_conf.pmd_desc[i].type & PFM_REG_IMPL))
/* XXX: these three assume that register i is implemented */ /* XXX: these three assume that register i is implemented */
#define PMD_IS_COUNTING(i) (pmu_conf.pmd_desc[i].type == PFM_REG_COUNTING) #define PMD_IS_COUNTING(i) (pmu_conf.pmd_desc[i].type == PFM_REG_COUNTING)
#define PMC_IS_COUNTING(i) (pmu_conf.pmc_desc[i].type == PFM_REG_COUNTING) #define PMC_IS_COUNTING(i) (pmu_conf.pmc_desc[i].type == PFM_REG_COUNTING)
#define PMC_IS_MONITOR(i) (pmu_conf.pmc_desc[i].type == PFM_REG_MONITOR) #define PMC_IS_MONITOR(i) (pmu_conf.pmc_desc[i].type == PFM_REG_MONITOR)
#define PMC_DFL_VAL(i) pmu_conf.pmc_desc[i].default_value
#define PMC_RSVD_MASK(i) pmu_conf.pmc_desc[i].reserved_mask
#define PMD_PMD_DEP(i) pmu_conf.pmd_desc[i].dep_pmd[0]
#define PMC_PMD_DEP(i) pmu_conf.pmc_desc[i].dep_pmd[0]
/* k assume unsigned */ /* k assume unsigned */
#define IBR_IS_IMPL(k) (k<pmu_conf.num_ibrs) #define IBR_IS_IMPL(k) (k<pmu_conf.num_ibrs)
...@@ -175,19 +200,6 @@ typedef struct _pfm_smpl_buffer_desc { ...@@ -175,19 +200,6 @@ typedef struct _pfm_smpl_buffer_desc {
#define LOCK_PSB(p) spin_lock(&(p)->psb_lock) #define LOCK_PSB(p) spin_lock(&(p)->psb_lock)
#define UNLOCK_PSB(p) spin_unlock(&(p)->psb_lock) #define UNLOCK_PSB(p) spin_unlock(&(p)->psb_lock)
/*
* The possible type of a PMU register
*/
typedef enum {
PFM_REG_NOTIMPL, /* not implemented */
PFM_REG_NONE, /* end marker */
PFM_REG_MONITOR, /* a PMC with a pmc.pm field only */
PFM_REG_COUNTING,/* a PMC with a pmc.pm AND pmc.oi, a PMD used as a counter */
PFM_REG_CONTROL, /* PMU control register */
PFM_REG_CONFIG, /* refine configuration */
PFM_REG_BUFFER /* PMD used as buffer */
} pfm_pmu_reg_type_t;
/* /*
* 64-bit software counter structure * 64-bit software counter structure
*/ */
...@@ -283,13 +295,16 @@ typedef struct { ...@@ -283,13 +295,16 @@ typedef struct {
* dep_pmc[]: a bitmask of dependent PMC registers * dep_pmc[]: a bitmask of dependent PMC registers
*/ */
typedef struct { typedef struct {
pfm_pmu_reg_type_t type; unsigned int type;
int pm_pos; int pm_pos;
unsigned long default_value; /* power-on default value */
unsigned long reserved_mask; /* bitmask of reserved bits */
int (*read_check)(struct task_struct *task, unsigned int cnum, unsigned long *val, struct pt_regs *regs); int (*read_check)(struct task_struct *task, unsigned int cnum, unsigned long *val, struct pt_regs *regs);
int (*write_check)(struct task_struct *task, unsigned int cnum, unsigned long *val, struct pt_regs *regs); int (*write_check)(struct task_struct *task, unsigned int cnum, unsigned long *val, struct pt_regs *regs);
unsigned long dep_pmd[4]; unsigned long dep_pmd[4];
unsigned long dep_pmc[4]; unsigned long dep_pmc[4];
} pfm_reg_desc_t; } pfm_reg_desc_t;
/* assume cnum is a valid monitor */ /* assume cnum is a valid monitor */
#define PMC_PM(cnum, val) (((val) >> (pmu_conf.pmc_desc[cnum].pm_pos)) & 0x1) #define PMC_PM(cnum, val) (((val) >> (pmu_conf.pmc_desc[cnum].pm_pos)) & 0x1)
#define PMC_WR_FUNC(cnum) (pmu_conf.pmc_desc[cnum].write_check) #define PMC_WR_FUNC(cnum) (pmu_conf.pmc_desc[cnum].write_check)
...@@ -401,8 +416,6 @@ static ctl_table pfm_sysctl_root[] = { ...@@ -401,8 +416,6 @@ static ctl_table pfm_sysctl_root[] = {
}; };
static struct ctl_table_header *pfm_sysctl_header; static struct ctl_table_header *pfm_sysctl_header;
static unsigned long reset_pmcs[IA64_NUM_PMC_REGS]; /* contains PAL reset values for PMCS */
static void pfm_vm_close(struct vm_area_struct * area); static void pfm_vm_close(struct vm_area_struct * area);
static struct vm_operations_struct pfm_vm_ops={ static struct vm_operations_struct pfm_vm_ops={
...@@ -422,7 +435,7 @@ static struct { ...@@ -422,7 +435,7 @@ static struct {
/* /*
* forward declarations * forward declarations
*/ */
static void ia64_reset_pmu(struct task_struct *); static void pfm_reset_pmu(struct task_struct *);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
static void pfm_fetch_regs(int cpu, struct task_struct *task, pfm_context_t *ctx); static void pfm_fetch_regs(int cpu, struct task_struct *task, pfm_context_t *ctx);
#endif #endif
...@@ -2244,7 +2257,7 @@ pfm_enable(struct task_struct *task, pfm_context_t *ctx, void *arg, int count, ...@@ -2244,7 +2257,7 @@ pfm_enable(struct task_struct *task, pfm_context_t *ctx, void *arg, int count,
pfm_lazy_save_regs(PMU_OWNER()); pfm_lazy_save_regs(PMU_OWNER());
/* reset all registers to stable quiet state */ /* reset all registers to stable quiet state */
ia64_reset_pmu(task); pfm_reset_pmu(task);
/* make sure nothing starts */ /* make sure nothing starts */
if (ctx->ctx_fl_system) { if (ctx->ctx_fl_system) {
...@@ -2307,7 +2320,7 @@ pfm_get_pmc_reset(struct task_struct *task, pfm_context_t *ctx, void *arg, int c ...@@ -2307,7 +2320,7 @@ pfm_get_pmc_reset(struct task_struct *task, pfm_context_t *ctx, void *arg, int c
if (!PMC_IS_IMPL(cnum)) goto abort_mission; if (!PMC_IS_IMPL(cnum)) goto abort_mission;
tmp.reg_value = reset_pmcs[cnum]; tmp.reg_value = PMC_DFL_VAL(cnum);
PFM_REG_RETFLAG_SET(tmp.reg_flags, 0); PFM_REG_RETFLAG_SET(tmp.reg_flags, 0);
...@@ -2998,6 +3011,8 @@ perfmon_proc_info(char *page) ...@@ -2998,6 +3011,8 @@ perfmon_proc_info(char *page)
p += sprintf(p, "CPU%-2d recorded samples : %lu\n", i, pfm_stats[i].pfm_recorded_samples_count); p += sprintf(p, "CPU%-2d recorded samples : %lu\n", i, pfm_stats[i].pfm_recorded_samples_count);
p += sprintf(p, "CPU%-2d smpl buffer full : %lu\n", i, pfm_stats[i].pfm_full_smpl_buffer_count); p += sprintf(p, "CPU%-2d smpl buffer full : %lu\n", i, pfm_stats[i].pfm_full_smpl_buffer_count);
p += sprintf(p, "CPU%-2d owner : %d\n", i, pmu_owners[i].owner ? pmu_owners[i].owner->pid: -1); p += sprintf(p, "CPU%-2d owner : %d\n", i, pmu_owners[i].owner ? pmu_owners[i].owner->pid: -1);
p += sprintf(p, "CPU%-2d syst_wide : %d\n", i, per_cpu(pfm_syst_wide, i));
p += sprintf(p, "CPU%-2d dcr_pp : %d\n", i, per_cpu(pfm_dcr_pp, i));
} }
LOCK_PFS(); LOCK_PFS();
...@@ -3398,11 +3413,10 @@ pfm_load_regs (struct task_struct *task) ...@@ -3398,11 +3413,10 @@ pfm_load_regs (struct task_struct *task)
* XXX: make this routine able to work with non current context * XXX: make this routine able to work with non current context
*/ */
static void static void
ia64_reset_pmu(struct task_struct *task) pfm_reset_pmu(struct task_struct *task)
{ {
struct thread_struct *t = &task->thread; struct thread_struct *t = &task->thread;
pfm_context_t *ctx = t->pfm_context; pfm_context_t *ctx = t->pfm_context;
unsigned long mask;
int i; int i;
if (task != current) { if (task != current) {
...@@ -3415,30 +3429,27 @@ ia64_reset_pmu(struct task_struct *task) ...@@ -3415,30 +3429,27 @@ ia64_reset_pmu(struct task_struct *task)
/* /*
* install reset values for PMC. We skip PMC0 (done above) * install reset values for PMC. We skip PMC0 (done above)
* XX: good up to 64 PMCS
*/ */
mask = pmu_conf.impl_regs[0] >> 1; for (i=1; (pmu_conf.pmc_desc[i].type & PFM_REG_END) == 0; i++) {
for(i=1; mask; mask>>=1, i++) { if ((pmu_conf.pmc_desc[i].type & PFM_REG_IMPL) == 0) continue;
if (mask & 0x1) { ia64_set_pmc(i, PMC_DFL_VAL(i));
ia64_set_pmc(i, reset_pmcs[i]); /*
/* * When restoring context, we must restore ALL pmcs, even the ones
* When restoring context, we must restore ALL pmcs, even the ones * that the task does not use to avoid leaks and possibly corruption
* that the task does not use to avoid leaks and possibly corruption * of the sesion because of configuration conflicts. So here, we
* of the sesion because of configuration conflicts. So here, we * initialize the entire set used in the context switch restore routine.
* initialize the entire set used in the context switch restore routine. */
*/ t->pmc[i] = PMC_DFL_VAL(i);
t->pmc[i] = reset_pmcs[i]; DBprintk(("pmc[%d]=0x%lx\n", i, t->pmc[i]));
DBprintk((" pmc[%d]=0x%lx\n", i, reset_pmcs[i]));
}
} }
/* /*
* clear reset values for PMD. * clear reset values for PMD.
* XXX: good up to 64 PMDS. Suppose that zero is a valid value. * XXX: good up to 64 PMDS. Suppose that zero is a valid value.
*/ */
mask = pmu_conf.impl_regs[4]; for (i=0; (pmu_conf.pmd_desc[i].type & PFM_REG_END) == 0; i++) {
for(i=0; mask; mask>>=1, i++) { if ((pmu_conf.pmd_desc[i].type & PFM_REG_IMPL) == 0) continue;
if (mask & 0x1) ia64_set_pmd(i, 0UL); ia64_set_pmd(i, 0UL);
t->pmd[i] = 0UL; t->pmd[i] = 0UL;
} }
...@@ -4119,23 +4130,6 @@ static struct irqaction perfmon_irqaction = { ...@@ -4119,23 +4130,6 @@ static struct irqaction perfmon_irqaction = {
}; };
static void
pfm_pmu_snapshot(void)
{
int i;
for (i=0; i < IA64_NUM_PMC_REGS; i++) {
if (i >= pmu_conf.num_pmcs) break;
if (PMC_IS_IMPL(i)) reset_pmcs[i] = ia64_get_pmc(i);
}
#ifdef CONFIG_MCKINLEY
/*
* set the 'stupid' enable bit to power the PMU!
*/
reset_pmcs[4] |= 1UL << 23;
#endif
}
/* /*
* perfmon initialization routine, called from the initcall() table * perfmon initialization routine, called from the initcall() table
*/ */
...@@ -4160,6 +4154,9 @@ perfmon_init (void) ...@@ -4160,6 +4154,9 @@ perfmon_init (void)
} }
pmu_conf.perf_ovfl_val = (1UL << pm_info.pal_perf_mon_info_s.width) - 1; pmu_conf.perf_ovfl_val = (1UL << pm_info.pal_perf_mon_info_s.width) - 1;
/*
* XXX: use the pfm_*_desc tables instead and simply verify with PAL
*/
pmu_conf.max_counters = pm_info.pal_perf_mon_info_s.generic; pmu_conf.max_counters = pm_info.pal_perf_mon_info_s.generic;
pmu_conf.num_pmcs = find_num_pm_regs(pmu_conf.impl_regs); pmu_conf.num_pmcs = find_num_pm_regs(pmu_conf.impl_regs);
pmu_conf.num_pmds = find_num_pm_regs(&pmu_conf.impl_regs[4]); pmu_conf.num_pmds = find_num_pm_regs(&pmu_conf.impl_regs[4]);
...@@ -4183,24 +4180,11 @@ perfmon_init (void) ...@@ -4183,24 +4180,11 @@ perfmon_init (void)
pmu_conf.num_ibrs <<=1; pmu_conf.num_ibrs <<=1;
pmu_conf.num_dbrs <<=1; pmu_conf.num_dbrs <<=1;
/*
* take a snapshot of all PMU registers. PAL is supposed
* to configure them with stable/safe values, i.e., not
* capturing anything.
* We take a snapshot now, before we make any modifications. This
* will become our master copy. Then we will reuse the snapshot
* to reset the PMU in pfm_enable(). Using this technique, perfmon
* does NOT have to know about the specific values to program for
* the PMC/PMD. The safe values may be different from one CPU model to
* the other.
*/
pfm_pmu_snapshot();
/* /*
* setup the register configuration descriptions for the CPU * setup the register configuration descriptions for the CPU
*/ */
pmu_conf.pmc_desc = pmc_desc; pmu_conf.pmc_desc = pfm_pmc_desc;
pmu_conf.pmd_desc = pmd_desc; pmu_conf.pmd_desc = pfm_pmd_desc;
/* we are all set */ /* we are all set */
pmu_conf.pfm_is_disabled = 0; pmu_conf.pfm_is_disabled = 0;
...@@ -4222,11 +4206,34 @@ __initcall(perfmon_init); ...@@ -4222,11 +4206,34 @@ __initcall(perfmon_init);
void void
perfmon_init_percpu (void) perfmon_init_percpu (void)
{ {
int i;
if (smp_processor_id() == 0) if (smp_processor_id() == 0)
register_percpu_irq(IA64_PERFMON_VECTOR, &perfmon_irqaction); register_percpu_irq(IA64_PERFMON_VECTOR, &perfmon_irqaction);
ia64_set_pmv(IA64_PERFMON_VECTOR); ia64_set_pmv(IA64_PERFMON_VECTOR);
ia64_srlz_d(); ia64_srlz_d();
/*
* we first initialize the PMU to a stable state.
* the values may have been changed from their power-up
* values by software executed before the kernel took over.
*
* At this point, pmu_conf has not yet been initialized
*
* On McKinley, this code is ineffective until PMC4 is initialized.
*/
for (i=1; (pfm_pmc_desc[i].type & PFM_REG_END) == 0; i++) {
if ((pfm_pmc_desc[i].type & PFM_REG_IMPL) == 0) continue;
ia64_set_pmc(i, pfm_pmc_desc[i].default_value);
}
for (i=0; (pfm_pmd_desc[i].type & PFM_REG_END) == 0; i++) {
if ((pfm_pmd_desc[i].type & PFM_REG_IMPL) == 0) continue;
ia64_set_pmd(i, 0UL);
}
ia64_set_pmc(0,1UL);
ia64_srlz_d();
} }
#else /* !CONFIG_PERFMON */ #else /* !CONFIG_PERFMON */
......
#define RDEP(x) (1UL<<(x))
#if defined(CONFIG_ITANIUM) || defined(CONFIG_MCKINLEY)
#error "This file should only be used when CONFIG_ITANIUM and CONFIG_MCKINLEY are not defined"
#endif
static pfm_reg_desc_t pmc_desc[PMU_MAX_PMCS]={
/* pmc0 */ { PFM_REG_CONTROL , 0, 0x1UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc1 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc2 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc3 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc4 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(4),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc5 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(5),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc6 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(6),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc7 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(7),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
{ PFM_REG_END , 0, 0x0UL, -1UL, NULL, NULL, {0,}, {0,}}, /* end marker */
};
static pfm_reg_desc_t pmd_desc[PMU_MAX_PMDS]={
/* pmd0 */ { PFM_REG_NOTIMPL , 0, 0x0UL, -1UL, NULL, NULL, {0,}, {0,}},
/* pmd1 */ { PFM_REG_NOTIMPL , 0, 0x0UL, -1UL, NULL, NULL, {0,}, {0,}},
/* pmd2 */ { PFM_REG_NOTIMPL , 0, 0x0UL, -1UL, NULL, NULL, {0,}, {0,}},
/* pmd3 */ { PFM_REG_NOTIMPL , 0, 0x0UL, -1UL, NULL, NULL, {0,}, {0,}},
/* pmd4 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(4),0UL, 0UL, 0UL}},
/* pmd5 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(5),0UL, 0UL, 0UL}},
/* pmd6 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(6),0UL, 0UL, 0UL}},
/* pmd7 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(7),0UL, 0UL, 0UL}},
{ PFM_REG_END , 0, 0x0UL, -1UL, NULL, NULL, {0,}, {0,}}, /* end marker */
};
...@@ -15,44 +15,44 @@ ...@@ -15,44 +15,44 @@
static int pfm_ita_pmc_check(struct task_struct *task, unsigned int cnum, unsigned long *val, struct pt_regs *regs); static int pfm_ita_pmc_check(struct task_struct *task, unsigned int cnum, unsigned long *val, struct pt_regs *regs);
static int pfm_write_ibr_dbr(int mode, struct task_struct *task, void *arg, int count, struct pt_regs *regs); static int pfm_write_ibr_dbr(int mode, struct task_struct *task, void *arg, int count, struct pt_regs *regs);
static pfm_reg_desc_t pmc_desc[256]={ static pfm_reg_desc_t pfm_pmc_desc[PMU_MAX_PMCS]={
/* pmc0 */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc0 */ { PFM_REG_CONTROL , 0, 0x1UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc1 */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc1 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc2 */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc2 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc3 */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc3 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc4 */ { PFM_REG_COUNTING, 6, NULL, NULL, {RDEP(4),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc4 */ { PFM_REG_COUNTING, 6, 0x0UL, -1UL, NULL, NULL, {RDEP(4),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc5 */ { PFM_REG_COUNTING, 6, NULL, NULL, {RDEP(5),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc5 */ { PFM_REG_COUNTING, 6, 0x0UL, -1UL, NULL, NULL, {RDEP(5),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc6 */ { PFM_REG_COUNTING, 6, NULL, NULL, {RDEP(6),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc6 */ { PFM_REG_COUNTING, 6, 0x0UL, -1UL, NULL, NULL, {RDEP(6),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc7 */ { PFM_REG_COUNTING, 6, NULL, NULL, {RDEP(7),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc7 */ { PFM_REG_COUNTING, 6, 0x0UL, -1UL, NULL, NULL, {RDEP(7),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc8 */ { PFM_REG_CONFIG, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc8 */ { PFM_REG_CONFIG , 0, 0xf00000003ffffff8UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc9 */ { PFM_REG_CONFIG, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc9 */ { PFM_REG_CONFIG , 0, 0xf00000003ffffff8UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc10 */ { PFM_REG_MONITOR, 6, NULL, NULL, {RDEP(0)|RDEP(1),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc10 */ { PFM_REG_MONITOR , 6, 0x0UL, -1UL, NULL, NULL, {RDEP(0)|RDEP(1),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc11 */ { PFM_REG_MONITOR, 6, NULL, pfm_ita_pmc_check, {RDEP(2)|RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc11 */ { PFM_REG_MONITOR , 6, 0x0000000010000000UL, -1UL, NULL, pfm_ita_pmc_check, {RDEP(2)|RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc12 */ { PFM_REG_MONITOR, 6, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc12 */ { PFM_REG_MONITOR , 6, 0x0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc13 */ { PFM_REG_CONFIG, 0, NULL, pfm_ita_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc13 */ { PFM_REG_CONFIG , 0, 0x0003ffff00000001UL, -1UL, NULL, pfm_ita_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
{ PFM_REG_NONE, 0, NULL, NULL, {0,}, {0,}}, /* end marker */ { PFM_REG_END , 0, 0x0UL, -1UL, NULL, NULL, {0,}, {0,}}, /* end marker */
}; };
static pfm_reg_desc_t pmd_desc[256]={ static pfm_reg_desc_t pfm_pmd_desc[PMU_MAX_PMDS]={
/* pmd0 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(1),0UL, 0UL, 0UL}, {RDEP(10),0UL, 0UL, 0UL}}, /* pmd0 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(1),0UL, 0UL, 0UL}, {RDEP(10),0UL, 0UL, 0UL}},
/* pmd1 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(0),0UL, 0UL, 0UL}, {RDEP(10),0UL, 0UL, 0UL}}, /* pmd1 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(0),0UL, 0UL, 0UL}, {RDEP(10),0UL, 0UL, 0UL}},
/* pmd2 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}}, /* pmd2 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}},
/* pmd3 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(2)|RDEP(17),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}}, /* pmd3 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(2)|RDEP(17),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}},
/* pmd4 */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(4),0UL, 0UL, 0UL}}, /* pmd4 */ { PFM_REG_COUNTING, 0, 0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(4),0UL, 0UL, 0UL}},
/* pmd5 */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(5),0UL, 0UL, 0UL}}, /* pmd5 */ { PFM_REG_COUNTING, 0, 0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(5),0UL, 0UL, 0UL}},
/* pmd6 */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(6),0UL, 0UL, 0UL}}, /* pmd6 */ { PFM_REG_COUNTING, 0, 0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(6),0UL, 0UL, 0UL}},
/* pmd7 */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(7),0UL, 0UL, 0UL}}, /* pmd7 */ { PFM_REG_COUNTING, 0, 0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(7),0UL, 0UL, 0UL}},
/* pmd8 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, /* pmd8 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
/* pmd9 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, /* pmd9 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
/* pmd10 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, /* pmd10 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
/* pmd11 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, /* pmd11 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
/* pmd12 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, /* pmd12 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
/* pmd13 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, /* pmd13 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
/* pmd14 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, /* pmd14 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
/* pmd15 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, /* pmd15 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
/* pmd16 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, /* pmd16 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
/* pmd17 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(2)|RDEP(3),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}}, /* pmd17 */ { PFM_REG_BUFFER , 0, 0UL, -1UL, NULL, NULL, {RDEP(2)|RDEP(3),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}},
{ PFM_REG_NONE, 0, NULL, NULL, {0,}, {0,}}, /* end marker */ { PFM_REG_END , 0, 0UL, -1UL, NULL, NULL, {0,}, {0,}}, /* end marker */
}; };
static int static int
......
This diff is collapsed.
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/module.h>
#include <linux/personality.h> #include <linux/personality.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -45,8 +46,9 @@ static void ...@@ -45,8 +46,9 @@ static void
do_show_stack (struct unw_frame_info *info, void *arg) do_show_stack (struct unw_frame_info *info, void *arg)
{ {
unsigned long ip, sp, bsp; unsigned long ip, sp, bsp;
char buf[80]; /* don't make it so big that it overflows the stack! */
printk("\nCall Trace: "); printk("\nCall Trace:\n");
do { do {
unw_get_ip(info, &ip); unw_get_ip(info, &ip);
if (ip == 0) if (ip == 0)
...@@ -54,7 +56,9 @@ do_show_stack (struct unw_frame_info *info, void *arg) ...@@ -54,7 +56,9 @@ do_show_stack (struct unw_frame_info *info, void *arg)
unw_get_sp(info, &sp); unw_get_sp(info, &sp);
unw_get_bsp(info, &bsp); unw_get_bsp(info, &bsp);
printk("[<%016lx>] sp=0x%016lx bsp=0x%016lx\n", ip, sp, bsp); snprintf(buf, sizeof(buf), " [<%016lx>] %%s sp=0x%016lx bsp=0x%016lx\n",
ip, sp, bsp);
print_symbol(buf, ip);
} while (unw_unwind(info) >= 0); } while (unw_unwind(info) >= 0);
} }
...@@ -94,6 +98,7 @@ show_regs (struct pt_regs *regs) ...@@ -94,6 +98,7 @@ show_regs (struct pt_regs *regs)
printk("\nPid: %d, comm: %20s\n", current->pid, current->comm); printk("\nPid: %d, comm: %20s\n", current->pid, current->comm);
printk("psr : %016lx ifs : %016lx ip : [<%016lx>] %s\n", printk("psr : %016lx ifs : %016lx ip : [<%016lx>] %s\n",
regs->cr_ipsr, regs->cr_ifs, ip, print_tainted()); regs->cr_ipsr, regs->cr_ifs, ip, print_tainted());
print_symbol("ip is at %s\n", ip);
printk("unat: %016lx pfs : %016lx rsc : %016lx\n", printk("unat: %016lx pfs : %016lx rsc : %016lx\n",
regs->ar_unat, regs->ar_pfs, regs->ar_rsc); regs->ar_unat, regs->ar_pfs, regs->ar_rsc);
printk("rnat: %016lx bsps: %016lx pr : %016lx\n", printk("rnat: %016lx bsps: %016lx pr : %016lx\n",
...@@ -199,10 +204,8 @@ ia64_save_extra (struct task_struct *task) ...@@ -199,10 +204,8 @@ ia64_save_extra (struct task_struct *task)
if ((task->thread.flags & IA64_THREAD_PM_VALID) != 0) if ((task->thread.flags & IA64_THREAD_PM_VALID) != 0)
pfm_save_regs(task); pfm_save_regs(task);
# ifdef CONFIG_SMP
if (__get_cpu_var(pfm_syst_wide)) if (__get_cpu_var(pfm_syst_wide))
pfm_syst_wide_update_task(task, 0); pfm_syst_wide_update_task(task, 0);
# endif
#endif #endif
#ifdef CONFIG_IA32_SUPPORT #ifdef CONFIG_IA32_SUPPORT
...@@ -221,9 +224,8 @@ ia64_load_extra (struct task_struct *task) ...@@ -221,9 +224,8 @@ ia64_load_extra (struct task_struct *task)
if ((task->thread.flags & IA64_THREAD_PM_VALID) != 0) if ((task->thread.flags & IA64_THREAD_PM_VALID) != 0)
pfm_load_regs(task); pfm_load_regs(task);
# ifdef CONFIG_SMP if (__get_cpu_var(pfm_syst_wide))
if (__get_cpu_var(pfm_syst_wide)) pfm_syst_wide_update_task(task, 1); pfm_syst_wide_update_task(task, 1);
# endif
#endif #endif
#ifdef CONFIG_IA32_SUPPORT #ifdef CONFIG_IA32_SUPPORT
......
...@@ -296,6 +296,16 @@ setup_arch (char **cmdline_p) ...@@ -296,6 +296,16 @@ setup_arch (char **cmdline_p)
efi_init(); efi_init();
#ifdef CONFIG_ACPI_BOOT
/* Initialize the ACPI boot-time table parser */
acpi_table_init(*cmdline_p);
#ifdef CONFIG_ACPI_NUMA
acpi_numa_init();
#endif
#endif /* CONFIG_APCI_BOOT */
find_memory(); find_memory();
#if 0 #if 0
......
...@@ -41,6 +41,16 @@ ...@@ -41,6 +41,16 @@
# define GET_SIGSET(k,u) __get_user((k)->sig[0], &(u)->sig[0]) # define GET_SIGSET(k,u) __get_user((k)->sig[0], &(u)->sig[0])
#endif #endif
register double f16 asm ("f16"); register double f17 asm ("f17");
register double f18 asm ("f18"); register double f19 asm ("f19");
register double f20 asm ("f20"); register double f21 asm ("f21");
register double f22 asm ("f22"); register double f23 asm ("f23");
register double f24 asm ("f24"); register double f25 asm ("f25");
register double f26 asm ("f26"); register double f27 asm ("f27");
register double f28 asm ("f28"); register double f29 asm ("f29");
register double f30 asm ("f30"); register double f31 asm ("f31");
long long
ia64_rt_sigsuspend (sigset_t *uset, size_t sigsetsize, struct sigscratch *scr) ia64_rt_sigsuspend (sigset_t *uset, size_t sigsetsize, struct sigscratch *scr)
{ {
......
...@@ -282,18 +282,20 @@ sys_free_hugepages (unsigned long addr) ...@@ -282,18 +282,20 @@ sys_free_hugepages (unsigned long addr)
extern int free_hugepages(struct vm_area_struct *); extern int free_hugepages(struct vm_area_struct *);
int retval; int retval;
vma = find_vma(mm, addr);
if (!vma || !is_vm_hugetlb_page(vma) || (vma->vm_start != addr))
return -EINVAL;
down_write(&mm->mmap_sem); down_write(&mm->mmap_sem);
{ {
vma = find_vma(mm, addr);
if (!vma || !is_vm_hugetlb_page(vma) || (vma->vm_start != addr))
retval = -EINVAL;
goto out;
spin_lock(&mm->page_table_lock); spin_lock(&mm->page_table_lock);
{ {
retval = free_hugepages(vma); retval = free_hugepages(vma);
} }
spin_unlock(&mm->page_table_lock); spin_unlock(&mm->page_table_lock);
} }
out:
up_write(&mm->mmap_sem); up_write(&mm->mmap_sem);
return retval; return retval;
} }
......
...@@ -54,8 +54,8 @@ trap_init (void) ...@@ -54,8 +54,8 @@ trap_init (void)
if (ia64_boot_param->fpswa) { if (ia64_boot_param->fpswa) {
/* FPSWA fixup: make the interface pointer a kernel virtual address: */ /* FPSWA fixup: make the interface pointer a kernel virtual address: */
fpswa_interface = __va(ia64_boot_param->fpswa); fpswa_interface = __va(ia64_boot_param->fpswa);
major = fpswa_interface->revision & 0xffff; major = fpswa_interface->revision >> 16;
minor = fpswa_interface->revision >> 16; minor = fpswa_interface->revision & 0xffff;
} }
printk("fpswa interface at %lx (rev %d.%d)\n", ia64_boot_param->fpswa, major, minor); printk("fpswa interface at %lx (rev %d.%d)\n", ia64_boot_param->fpswa, major, minor);
} }
......
...@@ -9,5 +9,6 @@ ...@@ -9,5 +9,6 @@
obj-y := init.o fault.o tlb.o extable.o obj-y := init.o fault.o tlb.o extable.o
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
obj-$(CONFIG_NUMA) += numa.o
include $(TOPDIR)/Rules.make include $(TOPDIR)/Rules.make
...@@ -78,7 +78,7 @@ ia64_init_addr_space (void) ...@@ -78,7 +78,7 @@ ia64_init_addr_space (void)
vma->vm_mm = current->mm; vma->vm_mm = current->mm;
vma->vm_start = IA64_RBS_BOT; vma->vm_start = IA64_RBS_BOT;
vma->vm_end = vma->vm_start + PAGE_SIZE; vma->vm_end = vma->vm_start + PAGE_SIZE;
vma->vm_page_prot = protection_map[VM_READ | VM_WRITE]; vma->vm_page_prot = protection_map[VM_DATA_DEFAULT_FLAGS & 0x7];
vma->vm_flags = VM_READ|VM_WRITE|VM_MAYREAD|VM_MAYWRITE|VM_GROWSUP; vma->vm_flags = VM_READ|VM_WRITE|VM_MAYREAD|VM_MAYWRITE|VM_GROWSUP;
vma->vm_ops = NULL; vma->vm_ops = NULL;
vma->vm_pgoff = 0; vma->vm_pgoff = 0;
......
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* This file contains NUMA specific variables and functions which can
* be split away from DISCONTIGMEM and are used on NUMA machines with
* contiguous memory.
*
* 2002/08/07 Erich Focht <efocht@ess.nec.de>
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/bootmem.h>
#include <linux/mmzone.h>
#include <asm/numa.h>
/*
* The following structures are usually initialized by ACPI or
* similar mechanisms and describe the NUMA characteristics of the machine.
*/
int num_memblks = 0;
struct node_memblk_s node_memblk[NR_MEMBLKS];
struct node_cpuid_s node_cpuid[NR_CPUS];
/*
* This is a matrix with "distances" between nodes, they should be
* proportional to the memory access latency ratios.
*/
u8 numa_slit[NR_NODES * NR_NODES];
/* Identify which cnode a physical address resides on */
int
paddr_to_nid(unsigned long paddr)
{
int i;
for (i = 0; i < num_memblks; i++)
if (paddr >= node_memblk[i].start_paddr &&
paddr < node_memblk[i].start_paddr + node_memblk[i].size)
break;
return (i < num_memblks) ? node_memblk[i].nid : -1;
}
...@@ -141,13 +141,13 @@ pcibios_scan_root (int bus) ...@@ -141,13 +141,13 @@ pcibios_scan_root (int bus)
/* /*
* Called after each bus is probed, but before its children are examined. * Called after each bus is probed, but before its children are examined.
*/ */
void __init void __devinit
pcibios_fixup_bus (struct pci_bus *b) pcibios_fixup_bus (struct pci_bus *b)
{ {
return; return;
} }
void __init void __devinit
pcibios_update_resource (struct pci_dev *dev, struct resource *root, pcibios_update_resource (struct pci_dev *dev, struct resource *root,
struct resource *res, int resource) struct resource *res, int resource)
{ {
...@@ -163,7 +163,7 @@ pcibios_update_resource (struct pci_dev *dev, struct resource *root, ...@@ -163,7 +163,7 @@ pcibios_update_resource (struct pci_dev *dev, struct resource *root,
/* ??? FIXME -- record old value for shutdown. */ /* ??? FIXME -- record old value for shutdown. */
} }
void __init void __devinit
pcibios_update_irq (struct pci_dev *dev, int irq) pcibios_update_irq (struct pci_dev *dev, int irq)
{ {
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
...@@ -171,7 +171,7 @@ pcibios_update_irq (struct pci_dev *dev, int irq) ...@@ -171,7 +171,7 @@ pcibios_update_irq (struct pci_dev *dev, int irq)
/* ??? FIXME -- record old value for shutdown. */ /* ??? FIXME -- record old value for shutdown. */
} }
void __init void __devinit
pcibios_fixup_pbus_ranges (struct pci_bus * bus, struct pbus_set_ranges_data * ranges) pcibios_fixup_pbus_ranges (struct pci_bus * bus, struct pbus_set_ranges_data * ranges)
{ {
} }
......
...@@ -160,6 +160,14 @@ SECTIONS ...@@ -160,6 +160,14 @@ SECTIONS
.bss : AT(ADDR(.bss) - PAGE_OFFSET) .bss : AT(ADDR(.bss) - PAGE_OFFSET)
{ *(.bss) *(COMMON) } { *(.bss) *(COMMON) }
/* XXX Must this come last to avoid shifting other symbols? --davidm */
__kallsyms : AT(ADDR(__kallsyms) - PAGE_OFFSET)
{
__start___kallsyms = .; /* All kernel symbols */
*(__kallsyms)
__stop___kallsyms = .;
}
_end = .; _end = .;
/* Stabs debugging sections. */ /* Stabs debugging sections. */
......
...@@ -97,17 +97,18 @@ ...@@ -97,17 +97,18 @@
} while (0) } while (0)
const char *acpi_get_sysname (void); const char *acpi_get_sysname (void);
int acpi_boot_init (char *cdline);
int acpi_request_vector (u32 int_type); int acpi_request_vector (u32 int_type);
int acpi_get_prt (struct pci_vector_struct **vectors, int *count); int acpi_get_prt (struct pci_vector_struct **vectors, int *count);
int acpi_get_interrupt_model (int *type); int acpi_get_interrupt_model (int *type);
int acpi_irq_to_vector (u32 irq); int acpi_irq_to_vector (u32 irq);
#ifdef CONFIG_DISCONTIGMEM #ifdef CONFIG_ACPI_NUMA
#define NODE_ARRAY_INDEX(x) ((x) / 8) /* 8 bits/char */ #include <asm/numa.h>
#define NODE_ARRAY_OFFSET(x) ((x) % 8) /* 8 bits/char */ /* Proximity bitmap length; _PXM is at most 255 (8 bit)*/
#define MAX_PXM_DOMAINS (256) #define MAX_PXM_DOMAINS (256)
#endif /* CONFIG_DISCONTIGMEM */ extern int __initdata pxm_to_nid_map[MAX_PXM_DOMAINS];
extern int __initdata nid_to_pxm_map[NR_NODES];
#endif
#endif /*__KERNEL__*/ #endif /*__KERNEL__*/
......
...@@ -73,6 +73,17 @@ struct _fpreg_ia32 { ...@@ -73,6 +73,17 @@ struct _fpreg_ia32 {
unsigned short exponent; unsigned short exponent;
}; };
struct _fpxreg_ia32 {
unsigned short significand[4];
unsigned short exponent;
unsigned short padding[3];
};
struct _xmmreg_ia32 {
unsigned int element[4];
};
struct _fpstate_ia32 { struct _fpstate_ia32 {
unsigned int cw, unsigned int cw,
sw, sw,
...@@ -82,7 +93,16 @@ struct _fpstate_ia32 { ...@@ -82,7 +93,16 @@ struct _fpstate_ia32 {
dataoff, dataoff,
datasel; datasel;
struct _fpreg_ia32 _st[8]; struct _fpreg_ia32 _st[8];
unsigned int status; unsigned short status;
unsigned short magic; /* 0xffff = regular FPU data only */
/* FXSR FPU environment */
unsigned int _fxsr_env[6]; /* FXSR FPU env is ignored */
unsigned int mxcsr;
unsigned int reserved;
struct _fpxreg_ia32 _fxsr_st[8]; /* FXSR FPU reg data is ignored */
struct _xmmreg_ia32 _xmm[8];
unsigned int padding[56];
}; };
struct sigcontext_ia32 { struct sigcontext_ia32 {
...@@ -486,6 +506,18 @@ extern int ia32_intercept (struct pt_regs *regs, unsigned long isr); ...@@ -486,6 +506,18 @@ extern int ia32_intercept (struct pt_regs *regs, unsigned long isr);
extern unsigned long ia32_do_mmap (struct file *, unsigned long, unsigned long, int, int, loff_t); extern unsigned long ia32_do_mmap (struct file *, unsigned long, unsigned long, int, int, loff_t);
extern void ia32_load_segment_descriptors (struct task_struct *task); extern void ia32_load_segment_descriptors (struct task_struct *task);
#define ia32f2ia64f(dst,src) \
do { \
register double f6 asm ("f6"); \
asm volatile ("ldfe f6=[%2];; stf.spill [%1]=f6" : "=f"(f6): "r"(dst), "r"(src) : "memory"); \
} while(0)
#define ia64f2ia32f(dst,src) \
do { \
register double f6 asm ("f6"); \
asm volatile ("ldf.fill f6=[%2];; stfe [%1]=f6" : "=f"(f6): "r"(dst), "r"(src) : "memory"); \
} while(0)
#endif /* !CONFIG_IA32_SUPPORT */ #endif /* !CONFIG_IA32_SUPPORT */
#endif /* _ASM_IA64_IA32_H */ #endif /* _ASM_IA64_IA32_H */
...@@ -55,6 +55,8 @@ extern void __devinit iosapic_init (unsigned long address, ...@@ -55,6 +55,8 @@ extern void __devinit iosapic_init (unsigned long address,
unsigned int gsi_base, unsigned int gsi_base,
int pcat_compat); int pcat_compat);
extern int gsi_to_vector (unsigned int gsi); extern int gsi_to_vector (unsigned int gsi);
extern int gsi_to_irq (unsigned int gsi);
extern void iosapic_parse_prt (void);
extern int iosapic_register_intr (unsigned int gsi, unsigned long polarity, extern int iosapic_register_intr (unsigned int gsi, unsigned long polarity,
unsigned long edge_triggered, unsigned long edge_triggered,
u32 gsi_base, char *iosapic_address); u32 gsi_base, char *iosapic_address);
......
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* This file contains NUMA specific prototypes and definitions.
*
* 2002/08/05 Erich Focht <efocht@ess.nec.de>
*
*/
#ifndef _ASM_IA64_NUMA_H
#define _ASM_IA64_NUMA_H
#ifdef CONFIG_NUMA
#ifdef CONFIG_DISCONTIGMEM
# include <asm/mmzone.h>
# define NR_NODES (PLAT_MAX_COMPACT_NODES)
# define NR_MEMBLKS (PLAT_MAXCLUMPS)
#else
# define NR_NODES (8)
# define NR_MEMBLKS (NR_NODES * 8)
#endif
/* Stuff below this line could be architecture independent */
extern int num_memblks; /* total number of memory chunks */
/*
* List of node memory chunks. Filled when parsing SRAT table to
* obtain information about memory nodes.
*/
struct node_memblk_s {
unsigned long start_paddr;
unsigned long size;
int nid; /* which logical node contains this chunk? */
int bank; /* which mem bank on this node */
};
struct node_cpuid_s {
u16 phys_id; /* id << 8 | eid */
int nid; /* logical node containing this CPU */
};
extern struct node_memblk_s node_memblk[NR_MEMBLKS];
extern struct node_cpuid_s node_cpuid[NR_CPUS];
/*
* ACPI 2.0 SLIT (System Locality Information Table)
* http://devresource.hp.com/devresource/Docs/TechPapers/IA64/slit.pdf
*
* This is a matrix with "distances" between nodes, they should be
* proportional to the memory access latency ratios.
*/
extern u8 numa_slit[NR_NODES * NR_NODES];
#define node_distance(from,to) (numa_slit[from * numnodes + to])
extern int paddr_to_nid(unsigned long paddr);
#endif /* CONFIG_NUMA */
#endif /* _ASM_IA64_NUMA_H */
...@@ -123,7 +123,7 @@ typedef struct { ...@@ -123,7 +123,7 @@ typedef struct {
* Define the version numbers for both perfmon as a whole and the sampling buffer format. * Define the version numbers for both perfmon as a whole and the sampling buffer format.
*/ */
#define PFM_VERSION_MAJ 1U #define PFM_VERSION_MAJ 1U
#define PFM_VERSION_MIN 0U #define PFM_VERSION_MIN 1U
#define PFM_VERSION (((PFM_VERSION_MAJ&0xffff)<<16)|(PFM_VERSION_MIN & 0xffff)) #define PFM_VERSION (((PFM_VERSION_MAJ&0xffff)<<16)|(PFM_VERSION_MIN & 0xffff))
#define PFM_SMPL_VERSION_MAJ 1U #define PFM_SMPL_VERSION_MAJ 1U
......
...@@ -148,8 +148,8 @@ copy_siginfo (siginfo_t *to, siginfo_t *from) ...@@ -148,8 +148,8 @@ copy_siginfo (siginfo_t *to, siginfo_t *from)
if (from->si_code < 0) if (from->si_code < 0)
memcpy(to, from, sizeof(siginfo_t)); memcpy(to, from, sizeof(siginfo_t));
else else
/* _sigchld is currently the largest know union member */ /* _sigprof is currently the largest know union member */
memcpy(to, from, 4*sizeof(int) + sizeof(from->_sifields._sigchld)); memcpy(to, from, 4*sizeof(int) + sizeof(from->_sifields._sigprof));
} }
extern int copy_siginfo_from_user(siginfo_t *to, siginfo_t *from); extern int copy_siginfo_from_user(siginfo_t *to, siginfo_t *from);
......
...@@ -250,7 +250,7 @@ bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification) ...@@ -250,7 +250,7 @@ bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification)
* status register into the notification area. * status register into the notification area.
* This fakes the shub performing the copy. * This fakes the shub performing the copy.
*/ */
if (jiffies > bte->idealTransferTimeout) { if (time_after(jiffies, bte->idealTransferTimeout)) {
bte->notify = HUB_L(bte->bte_base_addr); bte->notify = HUB_L(bte->bte_base_addr);
bte->idealTransferTimeoutReached++; bte->idealTransferTimeoutReached++;
bte->idealTransferTimeout = jiffies + bte->idealTransferTimeout = jiffies +
......
...@@ -37,11 +37,11 @@ struct thread_info { ...@@ -37,11 +37,11 @@ struct thread_info {
#define INIT_THREAD_INFO(ti) \ #define INIT_THREAD_INFO(ti) \
{ \ { \
exec_domain: &default_exec_domain, \ .exec_domain = &default_exec_domain, \
flags: 0, \ .flags = 0, \
cpu: 0, \ .cpu = 0, \
addr_limit: KERNEL_DS, \ .addr_limit = KERNEL_DS, \
preempt_count: 0, \ .preempt_count = 0, \
} }
/* how to get the thread information struct from C */ /* how to get the thread information struct from C */
......
...@@ -53,9 +53,10 @@ ...@@ -53,9 +53,10 @@
typedef struct { typedef struct {
struct mm_struct *mm; struct mm_struct *mm;
unsigned int nr; /* == ~0U => fast mode */ unsigned int nr; /* == ~0U => fast mode */
unsigned int fullmm; /* non-zero means full mm flush */ unsigned char fullmm; /* non-zero means full mm flush */
unsigned long freed; /* number of pages freed */ unsigned char need_flush; /* really unmapped some PTEs? */
unsigned long freed; /* number of pages freed */
unsigned long start_addr; unsigned long start_addr;
unsigned long end_addr; unsigned long end_addr;
struct page *pages[FREE_PTE_NR]; struct page *pages[FREE_PTE_NR];
...@@ -73,6 +74,10 @@ ia64_tlb_flush_mmu (mmu_gather_t *tlb, unsigned long start, unsigned long end) ...@@ -73,6 +74,10 @@ ia64_tlb_flush_mmu (mmu_gather_t *tlb, unsigned long start, unsigned long end)
{ {
unsigned int nr; unsigned int nr;
if (!tlb->need_flush)
return;
tlb->need_flush = 0;
if (tlb->fullmm) { if (tlb->fullmm) {
/* /*
* Tearing down the entire address space. This happens both as a result * Tearing down the entire address space. This happens both as a result
...@@ -167,18 +172,6 @@ tlb_finish_mmu (mmu_gather_t *tlb, unsigned long start, unsigned long end) ...@@ -167,18 +172,6 @@ tlb_finish_mmu (mmu_gather_t *tlb, unsigned long start, unsigned long end)
check_pgt_cache(); check_pgt_cache();
} }
/*
* Remove TLB entry for PTE mapped at virtual address ADDRESS. This is called for any
* PTE, not just those pointing to (normal) physical memory.
*/
static inline void
__tlb_remove_tlb_entry (mmu_gather_t *tlb, pte_t *ptep, unsigned long address)
{
if (tlb->start_addr == ~0UL)
tlb->start_addr = address;
tlb->end_addr = address + PAGE_SIZE;
}
/* /*
* Logically, this routine frees PAGE. On MP machines, the actual freeing of the page * Logically, this routine frees PAGE. On MP machines, the actual freeing of the page
* must be delayed until after the TLB has been flushed (see comments at the beginning of * must be delayed until after the TLB has been flushed (see comments at the beginning of
...@@ -187,6 +180,8 @@ __tlb_remove_tlb_entry (mmu_gather_t *tlb, pte_t *ptep, unsigned long address) ...@@ -187,6 +180,8 @@ __tlb_remove_tlb_entry (mmu_gather_t *tlb, pte_t *ptep, unsigned long address)
static inline void static inline void
tlb_remove_page (mmu_gather_t *tlb, struct page *page) tlb_remove_page (mmu_gather_t *tlb, struct page *page)
{ {
tlb->need_flush = 1;
if (tlb_fast_mode(tlb)) { if (tlb_fast_mode(tlb)) {
free_page_and_swap_cache(page); free_page_and_swap_cache(page);
return; return;
...@@ -196,11 +191,37 @@ tlb_remove_page (mmu_gather_t *tlb, struct page *page) ...@@ -196,11 +191,37 @@ tlb_remove_page (mmu_gather_t *tlb, struct page *page)
ia64_tlb_flush_mmu(tlb, tlb->start_addr, tlb->end_addr); ia64_tlb_flush_mmu(tlb, tlb->start_addr, tlb->end_addr);
} }
/*
* Remove TLB entry for PTE mapped at virtual address ADDRESS. This is called for any
* PTE, not just those pointing to (normal) physical memory.
*/
static inline void
__tlb_remove_tlb_entry (mmu_gather_t *tlb, pte_t *ptep, unsigned long address)
{
if (tlb->start_addr == ~0UL)
tlb->start_addr = address;
tlb->end_addr = address + PAGE_SIZE;
}
#define tlb_start_vma(tlb, vma) do { } while (0) #define tlb_start_vma(tlb, vma) do { } while (0)
#define tlb_end_vma(tlb, vma) do { } while (0) #define tlb_end_vma(tlb, vma) do { } while (0)
#define tlb_remove_tlb_entry(tlb, ptep, addr) __tlb_remove_tlb_entry(tlb, ptep, addr) #define tlb_remove_tlb_entry(tlb, ptep, addr) \
#define pte_free_tlb(tlb, ptep) __pte_free_tlb(tlb, ptep) do { \
#define pmd_free_tlb(tlb, ptep) __pmd_free_tlb(tlb, ptep) tlb->need_flush = 1; \
__tlb_remove_tlb_entry(tlb, ptep, addr); \
} while (0)
#define pte_free_tlb(tlb, ptep) \
do { \
tlb->need_flush = 1; \
__pte_free_tlb(tlb, ptep); \
} while (0)
#define pmd_free_tlb(tlb, ptep) \
do { \
tlb->need_flush = 1; \
__pmd_free_tlb(tlb, ptep); \
} while (0)
#endif /* _ASM_IA64_TLB_H */ #endif /* _ASM_IA64_TLB_H */
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