Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
1740c41c
Commit
1740c41c
authored
Apr 12, 2004
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
http://lia64.bkbits.net/to-linus-2.5
into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents
4c268c6b
4006f663
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
407 additions
and
348 deletions
+407
-348
arch/ia64/Kconfig
arch/ia64/Kconfig
+2
-2
arch/ia64/hp/common/sba_iommu.c
arch/ia64/hp/common/sba_iommu.c
+12
-1
arch/ia64/hp/sim/Kconfig
arch/ia64/hp/sim/Kconfig
+1
-1
arch/ia64/kernel/acpi.c
arch/ia64/kernel/acpi.c
+9
-1
arch/ia64/kernel/efi.c
arch/ia64/kernel/efi.c
+1
-2
arch/ia64/kernel/iosapic.c
arch/ia64/kernel/iosapic.c
+10
-6
arch/ia64/kernel/perfmon.c
arch/ia64/kernel/perfmon.c
+323
-292
arch/ia64/kernel/perfmon_mckinley.h
arch/ia64/kernel/perfmon_mckinley.h
+9
-4
arch/ia64/kernel/sys_ia64.c
arch/ia64/kernel/sys_ia64.c
+7
-1
arch/ia64/mm/hugetlbpage.c
arch/ia64/mm/hugetlbpage.c
+1
-0
arch/ia64/pci/pci.c
arch/ia64/pci/pci.c
+0
-1
arch/ia64/sn/io/hwgfs/interface.c
arch/ia64/sn/io/hwgfs/interface.c
+3
-3
arch/ia64/sn/io/machvec/pci_bus_cvlink.c
arch/ia64/sn/io/machvec/pci_bus_cvlink.c
+10
-16
arch/ia64/sn/io/machvec/pci_dma.c
arch/ia64/sn/io/machvec/pci_dma.c
+8
-4
arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c
arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c
+2
-1
drivers/char/sn_serial.c
drivers/char/sn_serial.c
+3
-1
include/asm-ia64/machvec_hpzx1.h
include/asm-ia64/machvec_hpzx1.h
+2
-1
include/asm-ia64/perfmon.h
include/asm-ia64/perfmon.h
+4
-3
include/asm-ia64/processor.h
include/asm-ia64/processor.h
+0
-8
No files found.
arch/ia64/Kconfig
View file @
1740c41c
...
...
@@ -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".
...
...
arch/ia64/hp/common/sba_iommu.c
View file @
1740c41c
...
...
@@ -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
)
{
...
...
arch/ia64/hp/sim/Kconfig
View file @
1740c41c
...
...
@@ -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
...
...
arch/ia64/kernel/acpi.c
View file @
1740c41c
...
...
@@ -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
;
}
...
...
arch/ia64/kernel/efi.c
View file @
1740c41c
...
...
@@ -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
;
}
}
...
...
arch/ia64/kernel/iosapic.c
View file @
1740c41c
...
...
@@ -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
);
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_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
...
...
arch/ia64/kernel/perfmon.c
View file @
1740c41c
...
...
@@ -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
((
"[%d] ctx_state=%d
\n
"
,
current
->
pid
,
ctx
->
ctx_state
));
DPRINT
((
"ctx_state=%d
\n
"
,
ctx
->
ctx_state
));
}
goto
doit
;
}
/*
* 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
));
if
(
PFM_IS_FILE
(
filp
)
==
0
)
{
DPRINT
((
"bad magic
\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
);
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 cas
e
, 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
terminat
ed at this point
* context is
unload
ed 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 fre
e
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
;
is_system
=
ctx
->
ctx_fl_system
;
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,7 +4485,8 @@ 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.
*/
pfm_unreserve_session
(
ctx
,
1
,
ctx
->
ctx_cpu
);
if
(
prev_state
!=
PFM_CTX_ZOMBIE
)
pfm_unreserve_session
(
ctx
,
1
,
ctx
->
ctx_cpu
);
/*
* disconnect context from task
...
...
@@ -4497,8 +4525,11 @@ 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.
*/
pfm_unreserve_session
(
ctx
,
0
,
ctx
->
ctx_cpu
);
if
(
prev_state
!=
PFM_CTX_ZOMBIE
)
pfm_unreserve_session
(
ctx
,
0
,
ctx
->
ctx_cpu
);
/*
* reset activation counter and psr
...
...
@@ -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
;
...
...
arch/ia64/kernel/perfmon_mckinley.h
View file @
1740c41c
...
...
@@ -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
;
}
...
...
arch/ia64/kernel/sys_ia64.c
View file @
1740c41c
...
...
@@ -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
...
...
arch/ia64/mm/hugetlbpage.c
View file @
1740c41c
...
...
@@ -9,6 +9,7 @@
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/mm.h>
...
...
arch/ia64/pci/pci.c
View file @
1740c41c
...
...
@@ -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
);
}
...
...
arch/ia64/sn/io/hwgfs/interface.c
View file @
1740c41c
...
...
@@ -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! */
...
...
arch/ia64/sn/io/machvec/pci_bus_cvlink.c
View file @
1740c41c
...
...
@@ -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
)
{
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
++
)
pci_scan_bus
(
i
,
&
sn_pci_ops
,
controller
);
if
(
!
controller
)
{
printk
(
KERN_WARNING
"cannot allocate PCI controller
\n
"
);
return
0
;
}
/*
* actually find devices and fill in hwgraph structs
*/
memset
(
controller
,
0
,
sizeof
(
struct
pci_controller
));
for
(
i
=
0
;
i
<
PCI_BUSES_TO_SCAN
;
i
++
)
if
(
pci_bus_to_vertex
(
i
))
pci_scan_bus
(
i
,
&
sn_pci_ops
,
controller
);
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
ioport_resource
.
start
=
0xc000000000000000
;
ioport_resource
.
end
=
0xcfffffffffffffff
;
/*
* Set the root start and end for Mem Resource.
...
...
arch/ia64/sn/io/machvec/pci_dma.c
View file @
1740c41c
...
...
@@ -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
;
}
...
...
arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c
View file @
1740c41c
...
...
@@ -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
);
...
...
drivers/char/sn_serial.c
View file @
1740c41c
...
...
@@ -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.
...
...
include/asm-ia64/machvec_hpzx1.h
View file @
1740c41c
...
...
@@ -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
...
...
include/asm-ia64/perfmon.h
View file @
1740c41c
...
...
@@ -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
...
...
include/asm-ia64/processor.h
View file @
1740c41c
...
...
@@ -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 */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment