Commit 1740c41c authored by Linus Torvalds's avatar Linus Torvalds

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

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents 4c268c6b 4006f663
......@@ -16,7 +16,7 @@ config IA64
The Itanium Processor Family is Intel's 64-bit successor to
the 32-bit X86 line. The IA-64 Linux project has a home
page at <http://www.linuxia64.org/> and a mailing list at
linux-ia64@vger.kernel.org.
<linux-ia64@vger.kernel.org>.
config 64BIT
bool
......@@ -57,7 +57,7 @@ config IA64_GENERIC
DIG-compliant For DIG ("Developer's Interface Guide") compliant systems
HP-zx1/sx1000 For HP systems
SGI-SN2 For SGI Altix systems
Ski-simulator For the HP simulator (<http://www.hpl.hp.com/research/linux/ski/>)
Ski-simulator For the HP simulator <http://www.hpl.hp.com/research/linux/ski/>
If you don't know what to do, choose "generic".
......
......@@ -1732,7 +1732,6 @@ ioc_init(u64 hpa, void *handle)
if ((long) ~iovp_mask > (long) ia64_max_iommu_merge_mask)
ia64_max_iommu_merge_mask = ~iovp_mask;
MAX_DMA_ADDRESS = ~0UL;
printk(KERN_INFO PFX
"%s %d.%d HPA 0x%lx IOVA space %dMb at 0x%lx\n",
......@@ -1966,6 +1965,18 @@ sba_init(void)
subsys_initcall(sba_init); /* must be initialized after ACPI etc., but before any drivers... */
extern void dig_setup(char**);
/*
* MAX_DMA_ADDRESS needs to be setup prior to paging_init to do any good,
* so we use the platform_setup hook to fix it up.
*/
void __init
sba_setup(char **cmdline_p)
{
MAX_DMA_ADDRESS = ~0UL;
dig_setup(cmdline_p);
}
static int __init
nosbagart(char *str)
{
......
......@@ -13,7 +13,7 @@ config HP_SIMSERIAL_CONSOLE
depends on HP_SIMSERIAL
config HP_SIMSCSI
bool "Simulated SCSI disk"
tristate "Simulated SCSI disk"
depends on SCSI
endmenu
......
......@@ -455,6 +455,7 @@ acpi_numa_arch_fixup (void)
for (i = 0; i < MAX_PXM_DOMAINS; i++) {
if (pxm_bit_test(i)) {
pxm_to_nid_map[i] = numnodes;
node_set_online(numnodes);
nid_to_pxm_map[numnodes++] = i;
}
}
......@@ -506,6 +507,13 @@ acpi_numa_arch_fixup (void)
}
#endif /* CONFIG_ACPI_NUMA */
unsigned int
acpi_register_gsi (u32 gsi, int polarity, int trigger)
{
return acpi_register_irq(gsi, polarity, trigger);
}
EXPORT_SYMBOL(acpi_register_gsi);
static int __init
acpi_parse_fadt (unsigned long phys_addr, unsigned long size)
{
......@@ -527,7 +535,7 @@ acpi_parse_fadt (unsigned long phys_addr, unsigned long size)
if (fadt->iapc_boot_arch & BAF_LEGACY_DEVICES)
acpi_legacy_devices = 1;
acpi_register_irq(fadt->sci_int, ACPI_ACTIVE_LOW, ACPI_LEVEL_SENSITIVE);
acpi_register_gsi(fadt->sci_int, ACPI_ACTIVE_LOW, ACPI_LEVEL_SENSITIVE);
return 0;
}
......
......@@ -674,8 +674,7 @@ efi_get_iobase (void)
for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
md = p;
if (md->type == EFI_MEMORY_MAPPED_IO_PORT_SPACE) {
/* paranoia attribute checking */
if (md->attribute == (EFI_MEMORY_UC | EFI_MEMORY_RUNTIME))
if (md->attribute & EFI_MEMORY_UC)
return md->phys_addr;
}
}
......
......@@ -172,7 +172,7 @@ gsi_to_irq (unsigned int gsi)
static void
set_rte (unsigned int vector, unsigned int dest, int mask)
{
unsigned long pol, trigger, dmode;
unsigned long pol, trigger, dmode, flags;
u32 low32, high32;
char *addr;
int rte_index;
......@@ -211,11 +211,15 @@ set_rte (unsigned int vector, unsigned int dest, int mask)
/* dest contains both id and eid */
high32 = (dest << IOSAPIC_DEST_SHIFT);
spin_lock_irqsave(&iosapic_lock, flags);
{
writel(IOSAPIC_RTE_HIGH(rte_index), addr + IOSAPIC_REG_SELECT);
writel(high32, addr + IOSAPIC_WINDOW);
writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT);
writel(low32, addr + IOSAPIC_WINDOW);
iosapic_intr_info[vector].low32 = low32;
}
spin_unlock_irqrestore(&iosapic_lock, flags);
}
static void
......
......@@ -57,7 +57,6 @@
#define PFM_CTX_LOADED 2 /* context is loaded onto a task */
#define PFM_CTX_MASKED 3 /* context is loaded but monitoring is masked due to overflow */
#define PFM_CTX_ZOMBIE 4 /* owner of the context is closing it */
#define PFM_CTX_TERMINATED 5 /* the task the context was loaded onto is gone */
#define PFM_INVALID_ACTIVATION (~0UL)
......@@ -473,6 +472,7 @@ typedef struct {
int debug; /* turn on/off debugging via syslog */
int debug_ovfl; /* turn on/off debug printk in overflow handler */
int fastctxsw; /* turn on/off fast (unsecure) ctxsw */
int expert_mode; /* turn on/off value checking */
int debug_pfm_read;
} pfm_sysctl_t;
......@@ -508,6 +508,7 @@ static ctl_table pfm_ctl_table[]={
{1, "debug", &pfm_sysctl.debug, sizeof(int), 0666, NULL, &proc_dointvec, NULL,},
{2, "debug_ovfl", &pfm_sysctl.debug_ovfl, sizeof(int), 0666, NULL, &proc_dointvec, NULL,},
{3, "fastctxsw", &pfm_sysctl.fastctxsw, sizeof(int), 0600, NULL, &proc_dointvec, NULL,},
{4, "expert_mode", &pfm_sysctl.expert_mode, sizeof(int), 0600, NULL, &proc_dointvec, NULL,},
{ 0, },
};
static ctl_table pfm_sysctl_dir[] = {
......@@ -520,11 +521,8 @@ static ctl_table pfm_sysctl_root[] = {
};
static struct ctl_table_header *pfm_sysctl_header;
static void pfm_vm_close(struct vm_area_struct * area);
static struct vm_operations_struct pfm_vm_ops={
close: pfm_vm_close
};
static int pfm_context_unload(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs);
static int pfm_flush(struct file *filp);
#define pfm_get_cpu_var(v) __ia64_per_cpu_var(v)
#define pfm_get_cpu_data(a,b) per_cpu(a, b)
......@@ -697,6 +695,28 @@ pfm_unfreeze_pmu(void)
ia64_srlz_d();
}
static inline void
pfm_restore_ibrs(unsigned long *ibrs, unsigned int nibrs)
{
int i;
for (i=0; i < nibrs; i++) {
ia64_set_ibr(i, ibrs[i]);
}
ia64_srlz_i();
}
static inline void
pfm_restore_dbrs(unsigned long *dbrs, unsigned int ndbrs)
{
int i;
for (i=0; i < ndbrs; i++) {
ia64_set_dbr(i, dbrs[i]);
}
ia64_srlz_d();
}
/*
* PMD[i] must be a counter. no check is made
*/
......@@ -827,7 +847,10 @@ pfm_context_alloc(void)
{
pfm_context_t *ctx;
/* allocate context descriptor */
/*
* allocate context descriptor
* must be able to free with interrupts disabled
*/
ctx = kmalloc(sizeof(pfm_context_t), GFP_KERNEL);
if (ctx) {
memset(ctx, 0, sizeof(pfm_context_t));
......@@ -853,7 +876,7 @@ pfm_mask_monitoring(struct task_struct *task)
unsigned long mask, val, ovfl_mask;
int i;
DPRINT_ovfl(("[%d] masking monitoring for [%d]\n", current->pid, task->pid));
DPRINT_ovfl(("masking monitoring for [%d]\n", task->pid));
ovfl_mask = pmu_conf.ovfl_val;
/*
......@@ -996,6 +1019,15 @@ pfm_restore_monitoring(struct task_struct *task)
}
ia64_srlz_d();
/*
* must restore DBR/IBR because could be modified while masked
* XXX: need to optimize
*/
if (ctx->ctx_fl_using_dbreg) {
pfm_restore_ibrs(ctx->ctx_ibrs, pmu_conf.num_ibrs);
pfm_restore_dbrs(ctx->ctx_dbrs, pmu_conf.num_dbrs);
}
/*
* now restore PSR
*/
......@@ -1106,28 +1138,6 @@ pfm_restore_pmcs(unsigned long *pmcs, unsigned long mask)
ia64_srlz_d();
}
static inline void
pfm_restore_ibrs(unsigned long *ibrs, unsigned int nibrs)
{
int i;
for (i=0; i < nibrs; i++) {
ia64_set_ibr(i, ibrs[i]);
}
ia64_srlz_i();
}
static inline void
pfm_restore_dbrs(unsigned long *dbrs, unsigned int ndbrs)
{
int i;
for (i=0; i < ndbrs; i++) {
ia64_set_dbr(i, dbrs[i]);
}
ia64_srlz_d();
}
static inline int
pfm_uuid_cmp(pfm_uuid_t a, pfm_uuid_t b)
{
......@@ -1684,8 +1694,7 @@ pfm_fasync(int fd, struct file *filp, int on)
ret = pfm_do_fasync(fd, filp, ctx, on);
DPRINT(("pfm_fasync called by [%d] on ctx_fd=%d on=%d async_queue=%p ret=%d\n",
current->pid,
DPRINT(("pfm_fasync called on ctx_fd=%d on=%d async_queue=%p ret=%d\n",
fd,
on,
ctx->ctx_async_queue, ret));
......@@ -1707,6 +1716,8 @@ pfm_syswide_force_stop(void *info)
pfm_context_t *ctx = (pfm_context_t *)info;
struct pt_regs *regs = ia64_task_regs(current);
struct task_struct *owner;
unsigned long flags;
int ret;
if (ctx->ctx_cpu != smp_processor_id()) {
printk(KERN_ERR "perfmon: pfm_syswide_force_stop for CPU%d but on CPU%d\n",
......@@ -1728,27 +1739,23 @@ pfm_syswide_force_stop(void *info)
return;
}
DPRINT(("[%d] on CPU%d forcing system wide stop for [%d]\n", current->pid, smp_processor_id(), ctx->ctx_task->pid));
DPRINT(("on CPU%d forcing system wide stop for [%d]\n", smp_processor_id(), ctx->ctx_task->pid));
/*
* Update local PMU
* the context is already protected in pfm_close(), we simply
* need to mask interrupts to avoid a PMU interrupt race on
* this CPU
*/
ia64_setreg(_IA64_REG_CR_DCR, ia64_getreg(_IA64_REG_CR_DCR) & ~IA64_DCR_PP);
ia64_srlz_i();
/*
* update local cpuinfo
*/
PFM_CPUINFO_CLEAR(PFM_CPUINFO_DCR_PP);
PFM_CPUINFO_CLEAR(PFM_CPUINFO_SYST_WIDE);
PFM_CPUINFO_CLEAR(PFM_CPUINFO_EXCL_IDLE);
local_irq_save(flags);
pfm_clear_psr_pp();
ret = pfm_context_unload(ctx, NULL, 0, regs);
if (ret) {
DPRINT(("context_unload returned %d\n", ret));
}
/*
* also stop monitoring in the local interrupted task
* unmask interrupts, PMU interrupts are now spurious here
*/
ia64_psr(regs)->pp = 0;
SET_PMU_OWNER(NULL, NULL);
local_irq_restore(flags);
}
static void
......@@ -1756,59 +1763,38 @@ pfm_syswide_cleanup_other_cpu(pfm_context_t *ctx)
{
int ret;
DPRINT(("[%d] calling CPU%d for cleanup\n", current->pid, ctx->ctx_cpu));
DPRINT(("calling CPU%d for cleanup\n", ctx->ctx_cpu));
ret = smp_call_function_single(ctx->ctx_cpu, pfm_syswide_force_stop, ctx, 0, 1);
DPRINT(("[%d] called CPU%d for cleanup ret=%d\n", current->pid, ctx->ctx_cpu, ret));
DPRINT(("called CPU%d for cleanup ret=%d\n", ctx->ctx_cpu, ret));
}
#endif /* CONFIG_SMP */
/*
* called either on explicit close() or from exit_files().
*
* IMPORTANT: we get called ONLY when the refcnt on the file gets to zero (fput()),i.e,
* last task to access the file. Nobody else can access the file at this point.
*
* When called from exit_files(), the VMA has been freed because exit_mm()
* is executed before exit_files().
*
* When called from exit_files(), the current task is not yet ZOMBIE but we will
* flush the PMU state to the context. This means * that when we see the context
* state as TERMINATED we are guranteed to have the latest PMU state available,
* even if the task itself is in the middle of being ctxsw out.
* called for each close(). Partially free resources.
* When caller is self-monitoring, the context is unloaded.
*/
static int pfm_context_unload(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs);
static int
pfm_close(struct inode *inode, struct file *filp)
pfm_flush(struct file *filp)
{
pfm_context_t *ctx;
struct task_struct *task;
struct pt_regs *regs;
DECLARE_WAITQUEUE(wait, current);
unsigned long flags;
unsigned long smpl_buf_size = 0UL;
void *smpl_buf_vaddr = NULL;
void *smpl_buf_addr = NULL;
int free_possible = 1;
int state, is_system;
DPRINT(("pfm_close called private=%p\n", filp->private_data));
if (!inode) {
printk(KERN_ERR "pfm_close: NULL inode\n");
return 0;
}
if (PFM_IS_FILE(filp) == 0) {
DPRINT(("bad magic for [%d]\n", current->pid));
DPRINT(("bad magic for\n"));
return -EBADF;
}
ctx = (pfm_context_t *)filp->private_data;
if (ctx == NULL) {
printk(KERN_ERR "perfmon: pfm_close: NULL ctx [%d]\n", current->pid);
printk(KERN_ERR "perfmon: pfm_flush: NULL ctx [%d]\n", current->pid);
return -EBADF;
}
/*
* remove our file from the async queue, if we use this mode.
* This can be done without the context being protected. We come
......@@ -1823,7 +1809,7 @@ pfm_close(struct inode *inode, struct file *filp)
* signal will be sent. In both case, we are safe
*/
if (filp->f_flags & FASYNC) {
DPRINT(("[%d] cleaning up async_queue=%p\n", current->pid, ctx->ctx_async_queue));
DPRINT(("cleaning up async_queue=%p\n", ctx->ctx_async_queue));
pfm_do_fasync (-1, filp, ctx, 0);
}
......@@ -1833,23 +1819,18 @@ pfm_close(struct inode *inode, struct file *filp)
is_system = ctx->ctx_fl_system;
task = PFM_CTX_TASK(ctx);
regs = ia64_task_regs(task);
DPRINT(("[%d] ctx_state=%d is_current=%d\n",
current->pid, state,
DPRINT(("ctx_state=%d is_current=%d\n",
state,
task == current ? 1 : 0));
if (state == PFM_CTX_UNLOADED || state == PFM_CTX_TERMINATED) {
goto doit;
}
/*
* if state == UNLOADED, then task is NULL
*/
/*
* context still loaded/masked and self monitoring,
* we stop/unload and we destroy right here
*
* We always go here for system-wide sessions
* we must stop and unload because we are losing access to the context.
*/
if (task == current) {
#ifdef CONFIG_SMP
......@@ -1862,46 +1843,134 @@ pfm_close(struct inode *inode, struct file *filp)
*/
if (is_system && ctx->ctx_cpu != smp_processor_id()) {
DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu));
UNPROTECT_CTX(ctx, flags);
DPRINT(("should be running on CPU%d\n", ctx->ctx_cpu));
/*
* keep context protected but unmask interrupt for IPI
*/
local_irq_restore(flags);
pfm_syswide_cleanup_other_cpu(ctx);
PROTECT_CTX(ctx, flags);
/*
* short circuit pfm_context_unload();
* restore interrupt masking
*/
task->thread.pfm_context = NULL;
ctx->ctx_task = NULL;
ctx->ctx_state = state = PFM_CTX_UNLOADED;
pfm_unreserve_session(ctx, 1 , ctx->ctx_cpu);
local_irq_save(flags);
/*
* context is unloaded at this point
*/
} else
#endif /* CONFIG_SMP */
{
DPRINT(("forcing unload on [%d]\n", current->pid));
DPRINT(("forcing unload\n"));
/*
* stop and unload, returning with state UNLOADED
* and session unreserved.
*/
pfm_context_unload(ctx, NULL, 0, regs);
ctx->ctx_state = PFM_CTX_TERMINATED;
DPRINT(("ctx_state=%d\n", ctx->ctx_state));
}
}
/*
* remove virtual mapping, if any, for the calling task.
* cannot reset ctx field until last user is calling close().
*
* ctx_smpl_vaddr must never be cleared because it is needed
* by every task with access to the context
*
* When called from do_exit(), the mm context is gone already, therefore
* mm is NULL, i.e., the VMA is already gone and we do not have to
* do anything here
*/
if (ctx->ctx_smpl_vaddr && current->mm) {
smpl_buf_vaddr = ctx->ctx_smpl_vaddr;
smpl_buf_size = ctx->ctx_smpl_size;
}
UNPROTECT_CTX(ctx, flags);
/*
* if there was a mapping, then we systematically remove it
* at this point. Cannot be done inside critical section
* because some VM function reenables interrupts.
*
*/
if (smpl_buf_vaddr) pfm_remove_smpl_mapping(current, smpl_buf_vaddr, smpl_buf_size);
return 0;
}
/*
* called either on explicit close() or from exit_files().
* Only the LAST user of the file gets to this point, i.e., it is
* called only ONCE.
*
* IMPORTANT: we get called ONLY when the refcnt on the file gets to zero
* (fput()),i.e, last task to access the file. Nobody else can access the
* file at this point.
*
* When called from exit_files(), the VMA has been freed because exit_mm()
* is executed before exit_files().
*
* When called from exit_files(), the current task is not yet ZOMBIE but we
* flush the PMU state to the context.
*/
static int
pfm_close(struct inode *inode, struct file *filp)
{
pfm_context_t *ctx;
struct task_struct *task;
struct pt_regs *regs;
DECLARE_WAITQUEUE(wait, current);
unsigned long flags;
unsigned long smpl_buf_size = 0UL;
void *smpl_buf_addr = NULL;
int free_possible = 1;
int state, is_system;
DPRINT(("pfm_close called private=%p\n", filp->private_data));
DPRINT(("[%d] ctx_state=%d\n", current->pid, ctx->ctx_state));
if (PFM_IS_FILE(filp) == 0) {
DPRINT(("bad magic\n"));
return -EBADF;
}
goto doit;
ctx = (pfm_context_t *)filp->private_data;
if (ctx == NULL) {
printk(KERN_ERR "perfmon: pfm_close: NULL ctx [%d]\n", current->pid);
return -EBADF;
}
PROTECT_CTX(ctx, flags);
state = ctx->ctx_state;
is_system = ctx->ctx_fl_system;
task = PFM_CTX_TASK(ctx);
regs = ia64_task_regs(task);
DPRINT(("ctx_state=%d is_current=%d\n",
state,
task == current ? 1 : 0));
/*
* if task == current, then pfm_flush() unloaded the context
*/
if (state == PFM_CTX_UNLOADED) goto doit;
/*
* context is loaded/masked and task != current, we need to
* either force an unload or go zombie
*/
/*
* The task is currently blocked or will block after an overflow.
* we must force it to wakeup to get out of the
* MASKED state and transition to the unloaded state by itself
* MASKED state and transition to the unloaded state by itself.
*
* This situation is only possible for per-task mode
*/
if (state == PFM_CTX_MASKED && CTX_OVFL_NOBLOCK(ctx) == 0) {
......@@ -1911,7 +1980,7 @@ pfm_close(struct inode *inode, struct file *filp)
*
* We cannot use the ZOMBIE state, because it is checked
* by pfm_load_regs() which is called upon wakeup from down().
* In such cas, it would free the context and then we would
* In such case, it would free the context and then we would
* return to pfm_handle_work() which would access the
* stale context. Instead, we set a flag invisible to pfm_load_regs()
* but visible to pfm_handle_work().
......@@ -1926,7 +1995,7 @@ pfm_close(struct inode *inode, struct file *filp)
*/
up(&ctx->ctx_restart_sem);
DPRINT(("waking up ctx_state=%d for [%d]\n", state, current->pid));
DPRINT(("waking up ctx_state=%d\n", state));
/*
* put ourself to sleep waiting for the other
......@@ -1956,11 +2025,11 @@ pfm_close(struct inode *inode, struct file *filp)
set_current_state(TASK_RUNNING);
/*
* context is terminated at this point
* context is unloaded at this point
*/
DPRINT(("after zombie wakeup ctx_state=%d for [%d]\n", state, current->pid));
DPRINT(("after zombie wakeup ctx_state=%d for\n", state));
}
else {
else if (task != current) {
#ifdef CONFIG_SMP
/*
* switch context to zombie state
......@@ -1978,8 +2047,7 @@ pfm_close(struct inode *inode, struct file *filp)
#endif
}
doit: /* cannot assume task is defined from now on */
doit:
/* reload state, may have changed during opening of critical section */
state = ctx->ctx_state;
......@@ -1987,18 +2055,9 @@ pfm_close(struct inode *inode, struct file *filp)
* the context is still attached to a task (possibly current)
* we cannot destroy it right now
*/
/*
* remove virtual mapping, if any. will be NULL when
* called from exit_files().
*/
if (ctx->ctx_smpl_vaddr) {
smpl_buf_vaddr = ctx->ctx_smpl_vaddr;
smpl_buf_size = ctx->ctx_smpl_size;
ctx->ctx_smpl_vaddr = NULL;
}
/*
* we must fre the sampling buffer right here because
* we must free the sampling buffer right here because
* we cannot rely on it being cleaned up later by the
* monitored task. It is not possible to free vmalloc'ed
* memory in pfm_load_regs(). Instead, we remove the buffer
......@@ -2011,21 +2070,19 @@ pfm_close(struct inode *inode, struct file *filp)
smpl_buf_size = ctx->ctx_smpl_size;
/* no more sampling */
ctx->ctx_smpl_hdr = NULL;
ctx->ctx_fl_is_sampling = 0;
}
DPRINT(("[%d] ctx_state=%d free_possible=%d vaddr=%p addr=%p size=%lu\n",
current->pid,
DPRINT(("ctx_state=%d free_possible=%d addr=%p size=%lu\n",
state,
free_possible,
smpl_buf_vaddr,
smpl_buf_addr,
smpl_buf_size));
if (smpl_buf_addr) pfm_exit_smpl_buffer(ctx->ctx_buf_fmt);
/*
* UNLOADED and TERMINATED mean that the session has already been
* unreserved.
* UNLOADED that the session has already been unreserved.
*/
if (state == PFM_CTX_ZOMBIE) {
pfm_unreserve_session(ctx, ctx->ctx_fl_system , ctx->ctx_cpu);
......@@ -2047,14 +2104,9 @@ pfm_close(struct inode *inode, struct file *filp)
UNPROTECT_CTX(ctx, flags);
/*
* if there was a mapping, then we systematically remove it
* at this point. Cannot be done inside critical section
* because some VM function reenables interrupts.
*
* All memory free operations (especially for vmalloc'ed memory)
* MUST be done with interrupts ENABLED.
*/
if (smpl_buf_vaddr) pfm_remove_smpl_mapping(current, smpl_buf_vaddr, smpl_buf_size);
if (smpl_buf_addr) pfm_rvfree(smpl_buf_addr, smpl_buf_size);
/*
......@@ -2072,6 +2124,8 @@ pfm_no_open(struct inode *irrelevant, struct file *dontcare)
return -ENXIO;
}
static struct file_operations pfm_file_ops = {
.llseek = pfm_lseek,
.read = pfm_read,
......@@ -2080,7 +2134,8 @@ static struct file_operations pfm_file_ops = {
.ioctl = pfm_ioctl,
.open = pfm_no_open, /* special open code to disallow open via /proc */
.fasync = pfm_fasync,
.release = pfm_close
.release = pfm_close,
.flush = pfm_flush
};
static int
......@@ -2088,6 +2143,7 @@ pfmfs_delete_dentry(struct dentry *dentry)
{
return 1;
}
static struct dentry_operations pfmfs_dentry_operations = {
.d_delete = pfmfs_delete_dentry,
};
......@@ -2172,27 +2228,6 @@ pfm_free_fd(int fd, struct file *file)
put_unused_fd(fd);
}
/*
* This function gets called from mm/mmap.c:exit_mmap() only when there is a sampling buffer
* attached to the context AND the current task has a mapping for it, i.e., it is the original
* creator of the context.
*
* This function is used to remember the fact that the vma describing the sampling buffer
* has now been removed. It can only be called when no other tasks share the same mm context.
*
*/
static void
pfm_vm_close(struct vm_area_struct *vma)
{
pfm_context_t *ctx = (pfm_context_t *)vma->vm_private_data;
unsigned long flags;
PROTECT_CTX(ctx, flags);
ctx->ctx_smpl_vaddr = NULL;
UNPROTECT_CTX(ctx, flags);
DPRINT(("[%d] clearing vaddr for ctx %p\n", current->pid, ctx));
}
static int
pfm_remap_buffer(struct vm_area_struct *vma, unsigned long buf, unsigned long addr, unsigned long size)
{
......@@ -2252,7 +2287,7 @@ pfm_smpl_buffer_alloc(struct task_struct *task, pfm_context_t *ctx, unsigned lon
return -ENOMEM;
}
DPRINT(("[%d] smpl_buf @%p\n", current->pid, smpl_buf));
DPRINT(("smpl_buf @%p\n", smpl_buf));
/* allocate vma */
vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
......@@ -2268,12 +2303,12 @@ pfm_smpl_buffer_alloc(struct task_struct *task, pfm_context_t *ctx, unsigned lon
* what we want.
*/
vma->vm_mm = mm;
vma->vm_flags = VM_READ| VM_MAYREAD |VM_RESERVED|VM_DONTCOPY;
vma->vm_flags = VM_READ| VM_MAYREAD |VM_RESERVED;
vma->vm_page_prot = PAGE_READONLY; /* XXX may need to change */
vma->vm_ops = &pfm_vm_ops;
vma->vm_ops = NULL;
vma->vm_pgoff = 0;
vma->vm_file = NULL;
vma->vm_private_data = ctx; /* information needed by the pfm_vm_close() function */
vma->vm_private_data = NULL;
/*
* Now we have everything we need and we can initialize
......@@ -2342,8 +2377,7 @@ static int
pfm_bad_permissions(struct task_struct *task)
{
/* inspired by ptrace_attach() */
DPRINT(("[%d] cur: uid=%d gid=%d task: euid=%d suid=%d uid=%d egid=%d sgid=%d\n",
current->pid,
DPRINT(("cur: uid=%d gid=%d task: euid=%d suid=%d uid=%d egid=%d sgid=%d\n",
current->uid,
current->gid,
task->euid,
......@@ -2532,11 +2566,11 @@ pfm_task_incompatible(pfm_context_t *ctx, struct task_struct *task)
* no kernel task or task not owner by caller
*/
if (task->mm == NULL) {
DPRINT(("[%d] task [%d] has not memory context (kernel thread)\n", current->pid, task->pid));
DPRINT(("task [%d] has not memory context (kernel thread)\n", task->pid));
return -EPERM;
}
if (pfm_bad_permissions(task)) {
DPRINT(("[%d] no permission to attach to [%d]\n", current->pid, task->pid));
DPRINT(("no permission to attach to [%d]\n", task->pid));
return -EPERM;
}
/*
......@@ -2548,7 +2582,7 @@ pfm_task_incompatible(pfm_context_t *ctx, struct task_struct *task)
}
if (task->state == TASK_ZOMBIE) {
DPRINT(("[%d] cannot attach to zombie task [%d]\n", current->pid, task->pid));
DPRINT(("cannot attach to zombie task [%d]\n", task->pid));
return -EBUSY;
}
......@@ -2558,7 +2592,7 @@ pfm_task_incompatible(pfm_context_t *ctx, struct task_struct *task)
if (task == current) return 0;
if (task->state != TASK_STOPPED) {
DPRINT(("[%d] cannot attach to non-stopped task [%d] state=%ld\n", current->pid, task->pid, task->state));
DPRINT(("cannot attach to non-stopped task [%d] state=%ld\n", task->pid, task->state));
return -EBUSY;
}
/*
......@@ -2835,7 +2869,7 @@ pfm_write_pmcs(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
task = ctx->ctx_task;
impl_pmds = pmu_conf.impl_pmds[0];
if (state == PFM_CTX_TERMINATED || state == PFM_CTX_ZOMBIE) return -EINVAL;
if (state == PFM_CTX_ZOMBIE) return -EINVAL;
if (is_loaded) {
thread = &task->thread;
......@@ -2845,7 +2879,7 @@ pfm_write_pmcs(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
* It does not have to be the owner (ctx_task) of the context per se.
*/
if (is_system && ctx->ctx_cpu != smp_processor_id()) {
DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu));
DPRINT(("should be running on CPU%d\n", ctx->ctx_cpu));
return -EBUSY;
}
can_access_pmu = GET_PMU_OWNER() == task || is_system ? 1 : 0;
......@@ -2928,7 +2962,7 @@ pfm_write_pmcs(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
/*
* execute write checker, if any
*/
if (PMC_WR_FUNC(cnum)) {
if (pfm_sysctl.expert_mode == 0 && PMC_WR_FUNC(cnum)) {
ret = PMC_WR_FUNC(cnum)(task, ctx, cnum, &value, regs);
if (ret) goto error;
ret = -EINVAL;
......@@ -3072,7 +3106,7 @@ pfm_write_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
ovfl_mask = pmu_conf.ovfl_val;
task = ctx->ctx_task;
if (unlikely(state == PFM_CTX_TERMINATED || state == PFM_CTX_ZOMBIE)) return -EINVAL;
if (unlikely(state == PFM_CTX_ZOMBIE)) return -EINVAL;
/*
* on both UP and SMP, we can only write to the PMC when the task is
......@@ -3086,7 +3120,7 @@ pfm_write_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
* It does not have to be the owner (ctx_task) of the context per se.
*/
if (unlikely(is_system && ctx->ctx_cpu != smp_processor_id())) {
DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu));
DPRINT(("should be running on CPU%d\n", ctx->ctx_cpu));
return -EBUSY;
}
can_access_pmu = GET_PMU_OWNER() == task || is_system ? 1 : 0;
......@@ -3106,7 +3140,7 @@ pfm_write_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
/*
* execute write checker, if any
*/
if (PMD_WR_FUNC(cnum)) {
if (pfm_sysctl.expert_mode == 0 && PMD_WR_FUNC(cnum)) {
unsigned long v = value;
ret = PMD_WR_FUNC(cnum)(task, ctx, cnum, &v, regs);
......@@ -3279,7 +3313,7 @@ pfm_read_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
* It does not have to be the owner (ctx_task) of the context per se.
*/
if (unlikely(is_system && ctx->ctx_cpu != smp_processor_id())) {
DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu));
DPRINT(("should be running on CPU%d\n", ctx->ctx_cpu));
return -EBUSY;
}
/*
......@@ -3347,7 +3381,7 @@ pfm_read_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
/*
* execute read checker, if any
*/
if (unlikely(PMD_RD_FUNC(cnum))) {
if (unlikely(pfm_sysctl.expert_mode == 0 && PMD_RD_FUNC(cnum))) {
unsigned long v = val;
ret = PMD_RD_FUNC(cnum)(ctx->ctx_task, ctx, cnum, &v, regs);
if (ret) goto error;
......@@ -3376,14 +3410,14 @@ pfm_read_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
return ret;
}
long
pfm_mod_write_pmcs(struct task_struct *task, pfarg_reg_t *req, unsigned int nreq, struct pt_regs *regs)
int
pfm_mod_write_pmcs(struct task_struct *task, void *req, unsigned int nreq, struct pt_regs *regs)
{
pfm_context_t *ctx;
if (task == NULL || req == NULL) return -EINVAL;
if (req == NULL) return -EINVAL;
ctx = task->thread.pfm_context;
ctx = GET_PMU_CTX();
if (ctx == NULL) return -EINVAL;
......@@ -3391,20 +3425,19 @@ pfm_mod_write_pmcs(struct task_struct *task, pfarg_reg_t *req, unsigned int nreq
* for now limit to current task, which is enough when calling
* from overflow handler
*/
if (task != current) return -EBUSY;
if (task != current && ctx->ctx_fl_system == 0) return -EBUSY;
return pfm_write_pmcs(ctx, req, nreq, regs);
}
EXPORT_SYMBOL(pfm_mod_write_pmcs);
long
pfm_mod_read_pmds(struct task_struct *task, pfarg_reg_t *req, unsigned int nreq, struct pt_regs *regs)
int
pfm_mod_read_pmds(struct task_struct *task, void *req, unsigned int nreq, struct pt_regs *regs)
{
pfm_context_t *ctx;
if (task == NULL || req == NULL) return -EINVAL;
if (req == NULL) return -EINVAL;
//ctx = task->thread.pfm_context;
ctx = GET_PMU_CTX();
if (ctx == NULL) return -EINVAL;
......@@ -3419,48 +3452,6 @@ pfm_mod_read_pmds(struct task_struct *task, pfarg_reg_t *req, unsigned int nreq,
}
EXPORT_SYMBOL(pfm_mod_read_pmds);
long
pfm_mod_fast_read_pmds(struct task_struct *task, unsigned long mask[4], unsigned long *addr, struct pt_regs *regs)
{
pfm_context_t *ctx;
unsigned long m, val;
unsigned int j;
if (task == NULL || addr == NULL) return -EINVAL;
//ctx = task->thread.pfm_context;
ctx = GET_PMU_CTX();
if (ctx == NULL) return -EINVAL;
/*
* for now limit to current task, which is enough when calling
* from overflow handler
*/
if (task != current && ctx->ctx_fl_system == 0) return -EBUSY;
m = mask[0];
for (j=0; m; m >>=1, j++) {
if ((m & 0x1) == 0) continue;
if (!(PMD_IS_IMPL(j) && CTX_IS_USED_PMD(ctx, j)) ) return -EINVAL;
if (PMD_IS_COUNTING(j)) {
val = pfm_read_soft_counter(ctx, j);
} else {
val = ia64_get_pmd(j);
}
*addr++ = val;
/* XXX: should call read checker routine? */
DPRINT(("single_read_pmd[%u]=0x%lx\n", j, val));
}
return 0;
}
EXPORT_SYMBOL(pfm_mod_fast_read_pmds);
/*
* Only call this function when a process it trying to
* write the debug registers (reading is always allowed)
......@@ -3565,9 +3556,6 @@ pfm_restart(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
case PFM_CTX_ZOMBIE:
DPRINT(("invalid state=%d\n", state));
return -EBUSY;
case PFM_CTX_TERMINATED:
DPRINT(("context is terminated, nothing to do\n"));
return 0;
default:
DPRINT(("state=%d, cannot operate (no active_restart handler)\n", state));
return -EINVAL;
......@@ -3579,7 +3567,7 @@ pfm_restart(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
* It does not have to be the owner (ctx_task) of the context per se.
*/
if (is_system && ctx->ctx_cpu != smp_processor_id()) {
DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu));
DPRINT(("should be running on CPU%d\n", ctx->ctx_cpu));
return -EBUSY;
}
......@@ -3739,7 +3727,7 @@ pfm_write_ibr_dbr(int mode, pfm_context_t *ctx, void *arg, int count, struct pt_
is_system = ctx->ctx_fl_system;
task = ctx->ctx_task;
if (state == PFM_CTX_TERMINATED || state == PFM_CTX_ZOMBIE) return -EINVAL;
if (state == PFM_CTX_ZOMBIE) return -EINVAL;
/*
* on both UP and SMP, we can only write to the PMC when the task is
......@@ -3753,7 +3741,7 @@ pfm_write_ibr_dbr(int mode, pfm_context_t *ctx, void *arg, int count, struct pt_
* It does not have to be the owner (ctx_task) of the context per se.
*/
if (unlikely(is_system && ctx->ctx_cpu != smp_processor_id())) {
DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu));
DPRINT(("should be running on CPU%d\n", ctx->ctx_cpu));
return -EBUSY;
}
can_access_pmu = GET_PMU_OWNER() == task || is_system ? 1 : 0;
......@@ -3920,6 +3908,49 @@ pfm_write_dbrs(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
return pfm_write_ibr_dbr(PFM_DATA_RR, ctx, arg, count, regs);
}
int
pfm_mod_write_ibrs(struct task_struct *task, void *req, unsigned int nreq, struct pt_regs *regs)
{
pfm_context_t *ctx;
if (req == NULL) return -EINVAL;
ctx = GET_PMU_CTX();
if (ctx == NULL) return -EINVAL;
/*
* for now limit to current task, which is enough when calling
* from overflow handler
*/
if (task != current && ctx->ctx_fl_system == 0) return -EBUSY;
return pfm_write_ibrs(ctx, req, nreq, regs);
}
EXPORT_SYMBOL(pfm_mod_write_ibrs);
int
pfm_mod_write_dbrs(struct task_struct *task, void *req, unsigned int nreq, struct pt_regs *regs)
{
pfm_context_t *ctx;
if (req == NULL) return -EINVAL;
ctx = GET_PMU_CTX();
if (ctx == NULL) return -EINVAL;
/*
* for now limit to current task, which is enough when calling
* from overflow handler
*/
if (task != current && ctx->ctx_fl_system == 0) return -EBUSY;
return pfm_write_dbrs(ctx, req, nreq, regs);
}
EXPORT_SYMBOL(pfm_mod_write_dbrs);
static int
pfm_get_features(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
{
......@@ -3947,11 +3978,10 @@ pfm_stop(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
* It does not have to be the owner (ctx_task) of the context per se.
*/
if (is_system && ctx->ctx_cpu != smp_processor_id()) {
DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu));
DPRINT(("should be running on CPU%d\n", ctx->ctx_cpu));
return -EBUSY;
}
DPRINT(("current [%d] task [%d] ctx_state=%d is_system=%d\n",
current->pid,
DPRINT(("task [%d] ctx_state=%d is_system=%d\n",
PFM_CTX_TASK(ctx)->pid,
state,
is_system));
......@@ -4010,7 +4040,7 @@ pfm_stop(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
* monitoring disabled in kernel at next reschedule
*/
ctx->ctx_saved_psr_up = 0;
DPRINT(("pfm_stop: current [%d] task=[%d]\n", current->pid, task->pid));
DPRINT(("task=[%d]\n", task->pid));
}
return 0;
}
......@@ -4033,7 +4063,7 @@ pfm_start(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
* It does not have to be the owner (ctx_task) of the context per se.
*/
if (is_system && ctx->ctx_cpu != smp_processor_id()) {
DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu));
DPRINT(("should be running on CPU%d\n", ctx->ctx_cpu));
return -EBUSY;
}
......@@ -4167,9 +4197,8 @@ pfm_context_load(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
/*
* can only load from unloaded or terminated state
*/
if (state != PFM_CTX_UNLOADED && state != PFM_CTX_TERMINATED) {
DPRINT(("[%d] cannot load to [%d], invalid ctx_state=%d\n",
current->pid,
if (state != PFM_CTX_UNLOADED) {
DPRINT(("cannot load to [%d], invalid ctx_state=%d\n",
req->load_pid,
ctx->ctx_state));
return -EINVAL;
......@@ -4178,7 +4207,7 @@ pfm_context_load(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
DPRINT(("load_pid [%d] using_dbreg=%d\n", req->load_pid, ctx->ctx_fl_using_dbreg));
if (CTX_OVFL_NOBLOCK(ctx) == 0 && req->load_pid == current->pid) {
DPRINT(("cannot use blocking mode on self for [%d]\n", current->pid));
DPRINT(("cannot use blocking mode on self\n"));
return -EINVAL;
}
......@@ -4194,8 +4223,7 @@ pfm_context_load(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
* system wide is self monitoring only
*/
if (is_system && task != current) {
DPRINT(("system wide is self monitoring only current=%d load_pid=%d\n",
current->pid,
DPRINT(("system wide is self monitoring only load_pid=%d\n",
req->load_pid));
goto error;
}
......@@ -4264,8 +4292,7 @@ pfm_context_load(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
*
* XXX: needs to be atomic
*/
DPRINT(("[%d] before cmpxchg() old_ctx=%p new_ctx=%p\n",
current->pid,
DPRINT(("before cmpxchg() old_ctx=%p new_ctx=%p\n",
thread->pfm_context, ctx));
old = ia64_cmpxchg(acq, &thread->pfm_context, NULL, ctx, sizeof(pfm_context_t *));
......@@ -4409,19 +4436,19 @@ pfm_context_unload(pfm_context_t *ctx, void *arg, int count, struct pt_regs *reg
{
struct task_struct *task = PFM_CTX_TASK(ctx);
struct pt_regs *tregs;
int state, is_system;
int prev_state, is_system;
int ret;
DPRINT(("ctx_state=%d task [%d]\n", ctx->ctx_state, task ? task->pid : -1));
state = ctx->ctx_state;
prev_state = ctx->ctx_state;
is_system = ctx->ctx_fl_system;
/*
* unload only when necessary
*/
if (state == PFM_CTX_TERMINATED || state == PFM_CTX_UNLOADED) {
DPRINT(("[%d] ctx_state=%d, nothing to do\n", current->pid, ctx->ctx_state));
if (prev_state == PFM_CTX_UNLOADED) {
DPRINT(("ctx_state=%d, nothing to do\n", prev_state));
return 0;
}
......@@ -4431,7 +4458,7 @@ pfm_context_unload(pfm_context_t *ctx, void *arg, int count, struct pt_regs *reg
ret = pfm_stop(ctx, NULL, 0, regs);
if (ret) return ret;
ctx->ctx_state = state = PFM_CTX_UNLOADED;
ctx->ctx_state = PFM_CTX_UNLOADED;
/*
* in system mode, we need to update the PMU directly
......@@ -4458,6 +4485,7 @@ pfm_context_unload(pfm_context_t *ctx, void *arg, int count, struct pt_regs *reg
* at this point we are done with the PMU
* so we can unreserve the resource.
*/
if (prev_state != PFM_CTX_ZOMBIE)
pfm_unreserve_session(ctx, 1 , ctx->ctx_cpu);
/*
......@@ -4497,7 +4525,10 @@ pfm_context_unload(pfm_context_t *ctx, void *arg, int count, struct pt_regs *reg
/*
* at this point we are done with the PMU
* so we can unreserve the resource.
*
* when state was ZOMBIE, we have already unreserved.
*/
if (prev_state != PFM_CTX_ZOMBIE)
pfm_unreserve_session(ctx, 0 , ctx->ctx_cpu);
/*
......@@ -4549,12 +4580,14 @@ pfm_force_cleanup(pfm_context_t *ctx, struct pt_regs *regs)
task->thread.pfm_context = NULL;
task->thread.flags &= ~IA64_THREAD_PM_VALID;
DPRINT(("context <%d> force cleanup for [%d] by [%d]\n", ctx->ctx_fd, task->pid, current->pid));
DPRINT(("force cleanupf for [%d]\n", task->pid));
}
/*
* called only from exit_thread(): task == current
* we come here only if current has a context attached (loaded or masked)
*/
void
pfm_exit_thread(struct task_struct *task)
......@@ -4575,7 +4608,8 @@ pfm_exit_thread(struct task_struct *task)
switch(state) {
case PFM_CTX_UNLOADED:
/*
* come here only if attached
* only comes to thios function if pfm_context is not NULL, i.e., cannot
* be in unloaded state
*/
printk(KERN_ERR "perfmon: pfm_exit_thread [%d] ctx unloaded\n", task->pid);
break;
......@@ -4583,20 +4617,17 @@ pfm_exit_thread(struct task_struct *task)
case PFM_CTX_MASKED:
ret = pfm_context_unload(ctx, NULL, 0, regs);
if (ret) {
printk(KERN_ERR "perfmon: pfm_exit_thread [%d] state=%d unload failed %d\n", task->pid, ctx->ctx_state, ret);
printk(KERN_ERR "perfmon: pfm_exit_thread [%d] state=%d unload failed %d\n", task->pid, state, ret);
}
ctx->ctx_state = PFM_CTX_TERMINATED;
DPRINT(("ctx terminated by [%d]\n", task->pid));
DPRINT(("ctx unloaded for current state was %d\n", state));
pfm_end_notify_user(ctx);
break;
case PFM_CTX_ZOMBIE:
pfm_clear_psr_up();
BUG_ON(ctx->ctx_smpl_hdr);
pfm_force_cleanup(ctx, regs);
ret = pfm_context_unload(ctx, NULL, 0, regs);
if (ret) {
printk(KERN_ERR "perfmon: pfm_exit_thread [%d] state=%d unload failed %d\n", task->pid, state, ret);
}
free_ok = 1;
break;
default:
......@@ -4696,7 +4727,7 @@ pfm_check_task_state(pfm_context_t *ctx, int cmd, unsigned long flags)
if (task == current || ctx->ctx_fl_system) return 0;
/*
* context is UNLOADED, MASKED, TERMINATED we are safe to go
* context is UNLOADED, MASKED we are safe to go
*/
if (state != PFM_CTX_LOADED) return 0;
......@@ -4749,7 +4780,7 @@ sys_perfmonctl (int fd, int cmd, void *arg, int count, long arg5, long arg6, lon
if (unlikely(PFM_IS_DISABLED())) return -ENOSYS;
if (unlikely(cmd < 0 || cmd >= PFM_CMD_COUNT)) {
DPRINT(("[%d] invalid cmd=%d\n", current->pid, cmd));
DPRINT(("invalid cmd=%d\n", cmd));
return -EINVAL;
}
......@@ -4760,7 +4791,7 @@ sys_perfmonctl (int fd, int cmd, void *arg, int count, long arg5, long arg6, lon
cmd_flags = pfm_cmd_tab[cmd].cmd_flags;
if (unlikely(func == NULL)) {
DPRINT(("[%d] invalid cmd=%d\n", current->pid, cmd));
DPRINT(("invalid cmd=%d\n", cmd));
return -EINVAL;
}
......@@ -4803,7 +4834,7 @@ sys_perfmonctl (int fd, int cmd, void *arg, int count, long arg5, long arg6, lon
* assume sz = 0 for command without parameters
*/
if (sz && copy_from_user(args_k, arg, sz)) {
DPRINT(("[%d] cannot copy_from_user %lu bytes @%p\n", current->pid, sz, arg));
DPRINT(("cannot copy_from_user %lu bytes @%p\n", sz, arg));
goto error_args;
}
......@@ -4819,7 +4850,7 @@ sys_perfmonctl (int fd, int cmd, void *arg, int count, long arg5, long arg6, lon
completed_args = 1;
DPRINT(("[%d] restart_args sz=%lu xtra_sz=%lu\n", current->pid, sz, xtra_sz));
DPRINT(("restart_args sz=%lu xtra_sz=%lu\n", sz, xtra_sz));
/* retry if necessary */
if (likely(xtra_sz)) goto restart_args;
......@@ -4831,17 +4862,17 @@ sys_perfmonctl (int fd, int cmd, void *arg, int count, long arg5, long arg6, lon
file = fget(fd);
if (unlikely(file == NULL)) {
DPRINT(("[%d] invalid fd %d\n", current->pid, fd));
DPRINT(("invalid fd %d\n", fd));
goto error_args;
}
if (unlikely(PFM_IS_FILE(file) == 0)) {
DPRINT(("[%d] fd %d not related to perfmon\n", current->pid, fd));
DPRINT(("fd %d not related to perfmon\n", fd));
goto error_args;
}
ctx = (pfm_context_t *)file->private_data;
if (unlikely(ctx == NULL)) {
DPRINT(("[%d] no context for fd %d\n", current->pid, fd));
DPRINT(("no context for fd %d\n", fd));
goto error_args;
}
prefetch(&ctx->ctx_state);
......@@ -4861,7 +4892,7 @@ sys_perfmonctl (int fd, int cmd, void *arg, int count, long arg5, long arg6, lon
abort_locked:
if (likely(ctx)) {
DPRINT(("[%d] context unlocked\n", current->pid));
DPRINT(("context unlocked\n"));
UNPROTECT_CTX(ctx, flags);
fput(file);
}
......@@ -4945,12 +4976,7 @@ pfm_context_force_terminate(pfm_context_t *ctx, struct pt_regs *regs)
current->thread.flags &= ~IA64_THREAD_PM_VALID;
ctx->ctx_task = NULL;
/*
* switch to terminated state
*/
ctx->ctx_state = PFM_CTX_TERMINATED;
DPRINT(("context <%d> terminated for [%d]\n", ctx->ctx_fd, current->pid));
DPRINT(("context terminated\n"));
/*
* and wakeup controlling task, indicating we are now disconnected
......@@ -4995,15 +5021,15 @@ pfm_handle_work(void)
*/
reason = ctx->ctx_fl_trap_reason;
ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE;
ovfl_regs = ctx->ctx_ovfl_regs[0];
DPRINT(("[%d] reason=%d state=%d\n", current->pid, reason, ctx->ctx_state));
DPRINT(("reason=%d state=%d\n", reason, ctx->ctx_state));
/*
* must be done before we check non-blocking mode
* must be done before we check for simple-reset mode
*/
if (ctx->ctx_fl_going_zombie || ctx->ctx_state == PFM_CTX_ZOMBIE) goto do_zombie;
ovfl_regs = ctx->ctx_ovfl_regs[0];
//if (CTX_OVFL_NOBLOCK(ctx)) goto skip_blocking;
if (reason == PFM_TRAP_REASON_RESET) goto skip_blocking;
......@@ -5022,6 +5048,14 @@ pfm_handle_work(void)
PROTECT_CTX(ctx, flags);
/*
* we need to read the ovfl_regs only after wake-up
* because we may have had pfm_write_pmds() in between
* and that can changed PMD values and therefore
* ovfl_regs is reset for these new PMD values.
*/
ovfl_regs = ctx->ctx_ovfl_regs[0];
if (ctx->ctx_fl_going_zombie) {
do_zombie:
DPRINT(("context is zombie, bailing out\n"));
......@@ -5050,7 +5084,7 @@ pfm_notify_user(pfm_context_t *ctx, pfm_msg_t *msg)
return 0;
}
DPRINT(("[%d] waking up somebody\n", current->pid));
DPRINT(("waking up somebody\n"));
if (msg) wake_up_interruptible(&ctx->ctx_msgq_wait);
......@@ -5085,11 +5119,10 @@ pfm_ovfl_notify_user(pfm_context_t *ctx, unsigned long ovfl_pmds)
msg->pfm_ovfl_msg.msg_tstamp = 0UL;
}
DPRINT(("ovfl msg: msg=%p no_msg=%d fd=%d pid=%d ovfl_pmds=0x%lx\n",
DPRINT(("ovfl msg: msg=%p no_msg=%d fd=%d ovfl_pmds=0x%lx\n",
msg,
ctx->ctx_fl_no_msg,
ctx->ctx_fd,
current->pid,
ovfl_pmds));
return pfm_notify_user(ctx, msg);
......@@ -5112,10 +5145,10 @@ pfm_end_notify_user(pfm_context_t *ctx)
msg->pfm_end_msg.msg_ctx_fd = ctx->ctx_fd;
msg->pfm_ovfl_msg.msg_tstamp = 0UL;
DPRINT(("end msg: msg=%p no_msg=%d ctx_fd=%d pid=%d\n",
DPRINT(("end msg: msg=%p no_msg=%d ctx_fd=%d\n",
msg,
ctx->ctx_fl_no_msg,
ctx->ctx_fd, current->pid));
ctx->ctx_fd));
return pfm_notify_user(ctx, msg);
}
......@@ -5275,8 +5308,7 @@ pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, str
* when the module cannot handle the rest of the overflows, we abort right here
*/
if (ret && pmd_mask) {
DPRINT(("current [%d] handler aborts leftover ovfl_pmds=0x%lx\n",
current->pid,
DPRINT(("handler aborts leftover ovfl_pmds=0x%lx\n",
pmd_mask<<PMU_FIRST_COUNTER));
}
/*
......@@ -5298,8 +5330,7 @@ pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, str
if (ovfl_notify == 0) reset_pmds = ovfl_pmds;
}
DPRINT(("current [%d] ovfl_pmds=0x%lx reset_pmds=0x%lx\n",
current->pid,
DPRINT(("ovfl_pmds=0x%lx reset_pmds=0x%lx\n",
ovfl_pmds,
reset_pmds));
/*
......@@ -5341,8 +5372,7 @@ pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, str
must_notify = 1;
}
DPRINT_ovfl(("current [%d] owner [%d] pending=%ld reason=%u ovfl_pmds=0x%lx ovfl_notify=0x%lx masked=%d\n",
current->pid,
DPRINT_ovfl(("owner [%d] pending=%ld reason=%u ovfl_pmds=0x%lx ovfl_notify=0x%lx masked=%d\n",
GET_PMU_OWNER() ? GET_PMU_OWNER()->pid : -1,
PFM_GET_WORK_PENDING(task),
ctx->ctx_fl_trap_reason,
......@@ -5521,6 +5551,7 @@ pfm_proc_info(char *page)
p += sprintf(p, "perfmon version : %u.%u\n", PFM_VERSION_MAJ, PFM_VERSION_MIN);
p += sprintf(p, "model : %s\n", pmu_conf.pmu_name);
p += sprintf(p, "fastctxsw : %s\n", pfm_sysctl.fastctxsw > 0 ? "Yes": "No");
p += sprintf(p, "expert mode : %s\n", pfm_sysctl.expert_mode > 0 ? "Yes": "No");
p += sprintf(p, "ovfl_mask : 0x%lx\n", pmu_conf.ovfl_val);
for(i=0; i < NR_CPUS; i++) {
......@@ -6490,7 +6521,7 @@ pfm_inherit(struct task_struct *task, struct pt_regs *regs)
{
struct thread_struct *thread;
DPRINT(("perfmon: pfm_inherit clearing state for [%d] current [%d]\n", task->pid, current->pid));
DPRINT(("perfmon: pfm_inherit clearing state for [%d]\n", task->pid));
thread = &task->thread;
......
......@@ -101,6 +101,7 @@ pfm_mck_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnu
{
int ret = 0, check_case1 = 0;
unsigned long val8 = 0, val14 = 0, val13 = 0;
int is_loaded;
/* first preserve the reserved fields */
pfm_mck_reserved(cnum, val, regs);
......@@ -108,6 +109,8 @@ pfm_mck_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnu
/* sanitfy check */
if (ctx == NULL) return -EINVAL;
is_loaded = ctx->ctx_state == PFM_CTX_LOADED || ctx->ctx_state == PFM_CTX_MASKED;
/*
* we must clear the debug registers if pmc13 has a value which enable
* memory pipeline event constraints. In this case we need to clear the
......@@ -120,7 +123,9 @@ pfm_mck_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnu
*
* For now, we just check on cfg_dbrXX != 0x3.
*/
if (cnum == 13 && ((*val & 0x18181818UL) != 0x18181818UL) && ctx->ctx_fl_using_dbreg == 0) {
DPRINT(("cnum=%u val=0x%lx, using_dbreg=%d loaded=%d\n", cnum, *val, ctx->ctx_fl_using_dbreg, is_loaded));
if (cnum == 13 && is_loaded && ((*val & 0x18181818UL) != 0x18181818UL) && ctx->ctx_fl_using_dbreg == 0) {
DPRINT(("pmc[%d]=0x%lx has active pmc13 settings, clearing dbr\n", cnum, *val));
......@@ -131,14 +136,14 @@ pfm_mck_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnu
* a count of 0 will mark the debug registers as in use and also
* ensure that they are properly cleared.
*/
ret = pfm_write_ibr_dbr(1, ctx, NULL, 0, regs);
ret = pfm_write_ibr_dbr(PFM_DATA_RR, ctx, NULL, 0, regs);
if (ret) return ret;
}
/*
* we must clear the (instruction) debug registers if any pmc14.ibrpX bit is enabled
* before they are (fl_using_dbreg==0) to avoid picking up stale information.
*/
if (cnum == 14 && ((*val & 0x2222UL) != 0x2222UL) && ctx->ctx_fl_using_dbreg == 0) {
if (cnum == 14 && is_loaded && ((*val & 0x2222UL) != 0x2222UL) && ctx->ctx_fl_using_dbreg == 0) {
DPRINT(("pmc[%d]=0x%lx has active pmc14 settings, clearing ibr\n", cnum, *val));
......@@ -149,7 +154,7 @@ pfm_mck_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnu
* a count of 0 will mark the debug registers as in use and also
* ensure that they are properly cleared.
*/
ret = pfm_write_ibr_dbr(0, ctx, NULL, 0, regs);
ret = pfm_write_ibr_dbr(PFM_CODE_RR, ctx, NULL, 0, regs);
if (ret) return ret;
}
......
......@@ -201,10 +201,16 @@ do_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, un
* A zero mmap always succeeds in Linux, independent of whether or not the
* remaining arguments are valid.
*/
len = PAGE_ALIGN(len);
if (len == 0)
goto out;
/* Careful about overflows.. */
len = PAGE_ALIGN(len);
if (!len || len > TASK_SIZE) {
addr = -EINVAL;
goto out;
}
/*
* 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
......
......@@ -9,6 +9,7 @@
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/mm.h>
......
......@@ -442,7 +442,6 @@ pcibios_enable_device (struct pci_dev *dev, int mask)
if (ret < 0)
return ret;
printk(KERN_INFO "PCI: Found IRQ %d for device %s\n", dev->irq, pci_name(dev));
return acpi_pci_irq_enable(dev);
}
......
......@@ -36,7 +36,7 @@ walk_parents_mkdir(
memcpy(buf, *path, len);
buf[len] = '\0';
error = link_path_walk(buf, nd);
error = path_walk(buf, nd);
if (unlikely(error))
return error;
......@@ -83,7 +83,7 @@ hwgfs_decode(
if (unlikely(error))
return error;
error = link_path_walk(name, &nd);
error = path_walk(name, &nd);
if (unlikely(error))
return error;
......@@ -274,7 +274,7 @@ hwgfs_find_handle(
nd.dentry = dget(base ? base : hwgfs_vfsmount->mnt_sb->s_root);
nd.flags = (traverse_symlinks ? LOOKUP_FOLLOW : 0);
error = link_path_walk(name, &nd);
error = path_walk(name, &nd);
if (likely(!error)) {
dentry = nd.dentry;
path_release(&nd); /* stale data from here! */
......
......@@ -811,7 +811,6 @@ sn_pci_init (void)
/*
* set pci_raw_ops, etc.
*/
sgi_master_io_infr_init();
for (cnode = 0; cnode < numnodes; cnode++) {
......@@ -826,16 +825,16 @@ sn_pci_init (void)
#endif
controller = kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
if (controller) {
if (!controller) {
printk(KERN_WARNING "cannot allocate PCI controller\n");
return 0;
}
memset(controller, 0, sizeof(struct pci_controller));
/* just allocate some devices and fill in the pci_dev structs */
for (i = 0; i < PCI_BUSES_TO_SCAN; i++)
if (pci_bus_to_vertex(i))
pci_scan_bus(i, &sn_pci_ops, controller);
}
/*
* actually find devices and fill in hwgraph structs
*/
done_probing = 1;
......@@ -857,13 +856,8 @@ sn_pci_init (void)
* set the root start and end so that drivers calling check_region()
* won't see a conflict
*/
#ifdef CONFIG_IA64_SGI_SN_SIM
if (! IS_RUNNING_ON_SIMULATOR()) {
ioport_resource.start = 0xc000000000000000;
ioport_resource.end = 0xcfffffffffffffff;
}
#endif
/*
* Set the root start and end for Mem Resource.
......
......@@ -391,11 +391,9 @@ sn_pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction)
dma_map = pcibr_dmamap_alloc(vhdl, NULL, size, PCIIO_DMA_DATA |
MINIMAL_ATE_FLAG(phys_addr, size));
if (!dma_map) {
printk(KERN_ERR "pci_map_single: Unable to allocate anymore "
"32 bit page map entries.\n");
/* PMU out of entries */
if (!dma_map)
return 0;
}
dma_addr = (dma_addr_t) pcibr_dmamap_addr(dma_map, phys_addr, size);
dma_map->bd_dma_addr = dma_addr;
......@@ -655,6 +653,12 @@ EXPORT_SYMBOL(sn_dma_sync_sg_for_device);
int
sn_dma_mapping_error(dma_addr_t dma_addr)
{
/*
* We can only run out of page mapping entries, so if there's
* an error, tell the caller to try again later.
*/
if (!dma_addr)
return -EAGAIN;
return 0;
}
......
......@@ -47,6 +47,7 @@ void pcibr_bus_addr_free(pciio_win_info_t);
cfg_p pcibr_find_capability(cfg_p, unsigned);
extern uint64_t do_pcibr_config_get(cfg_p, unsigned, unsigned);
void do_pcibr_config_set(cfg_p, unsigned, unsigned, uint64_t);
int pcibr_slot_pwr(vertex_hdl_t pcibr_vhdl, pciio_slot_t slot, int up, char *err_msg);
/*
......@@ -351,7 +352,7 @@ pcibr_slot_enable(vertex_hdl_t pcibr_vhdl, struct pcibr_slot_enable_req_s *req_p
goto enable_unlock;
}
error = pcibr_slot_attach(pcibr_vhdl, slot, NULL,
error = pcibr_slot_attach(pcibr_vhdl, slot, 0,
req_p->req_resp.resp_l1_msg,
&req_p->req_resp.resp_sub_errno);
......
......@@ -82,10 +82,10 @@ static DECLARE_TASKLET(sn_sal_tasklet, sn_sal_tasklet_action, 0);
static unsigned long sn_interrupt_timeout;
extern u64 master_node_bedrock_address;
static int sn_debug_printf(const char *fmt, ...);
#undef DEBUG
#ifdef DEBUG
static int sn_debug_printf(const char *fmt, ...);
#define DPRINTF(x...) sn_debug_printf(x)
#else
#define DPRINTF(x...) do { } while (0)
......@@ -247,6 +247,7 @@ early_printk_sn_sal(const char *s, unsigned count)
sn_func->sal_puts(s, count);
}
#ifdef DEBUG
/* this is as "close to the metal" as we can get, used when the driver
* itself may be broken */
static int
......@@ -262,6 +263,7 @@ sn_debug_printf(const char *fmt, ...)
va_end(args);
return printed_len;
}
#endif /* DEBUG */
/*
* Interrupt handling routines.
......
......@@ -2,6 +2,7 @@
#define _ASM_IA64_MACHVEC_HPZX1_h
extern ia64_mv_setup_t dig_setup;
extern ia64_mv_setup_t sba_setup;
extern ia64_mv_dma_alloc_coherent sba_alloc_coherent;
extern ia64_mv_dma_free_coherent sba_free_coherent;
extern ia64_mv_dma_map_single sba_map_single;
......@@ -19,7 +20,7 @@ extern ia64_mv_dma_mapping_error sba_dma_mapping_error;
* the macros are used directly.
*/
#define platform_name "hpzx1"
#define platform_setup dig_setup
#define platform_setup sba_setup
#define platform_dma_init machvec_noop
#define platform_dma_alloc_coherent sba_alloc_coherent
#define platform_dma_free_coherent sba_free_coherent
......
......@@ -242,9 +242,10 @@ extern int pfm_unregister_buffer_fmt(pfm_uuid_t uuid);
/*
* perfmon interface exported to modules
*/
extern long pfm_mod_fast_read_pmds(struct task_struct *, unsigned long mask[4], unsigned long *addr, struct pt_regs *regs);
extern long pfm_mod_read_pmds(struct task_struct *, pfarg_reg_t *req, unsigned int nreq, struct pt_regs *regs);
extern long pfm_mod_write_pmcs(struct task_struct *, pfarg_reg_t *req, unsigned int nreq, struct pt_regs *regs);
extern int pfm_mod_read_pmds(struct task_struct *, void *req, unsigned int nreq, struct pt_regs *regs);
extern int pfm_mod_write_pmcs(struct task_struct *, void *req, unsigned int nreq, struct pt_regs *regs);
extern int pfm_mod_write_ibrs(struct task_struct *task, void *req, unsigned int nreq, struct pt_regs *regs);
extern int pfm_mod_write_dbrs(struct task_struct *task, void *req, unsigned int nreq, struct pt_regs *regs);
/*
* describe the content of the local_cpu_date->pfm_syst_info field
......
......@@ -137,14 +137,6 @@ struct ia64_psr {
* state comes earlier:
*/
struct cpuinfo_ia64 {
/* irq_stat must be 64-bit aligned */
union {
struct {
__u32 irq_count;
__u32 bh_count;
} f;
__u64 irq_and_bh_counts;
} irq_stat;
__u32 softirq_pending;
__u64 itm_delta; /* # of clock cycles between clock ticks */
__u64 itm_next; /* interval timer mask value to use for next clock tick */
......
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