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
a49072bb
Commit
a49072bb
authored
Apr 17, 2008
by
Tony Luck
Browse files
Options
Browse Files
Download
Plain Diff
Pull kvm-patches into release branch
parents
fc494d6c
31a6b11f
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
364 additions
and
0 deletions
+364
-0
arch/ia64/kernel/mca.c
arch/ia64/kernel/mca.c
+49
-0
arch/ia64/kernel/mca_asm.S
arch/ia64/kernel/mca_asm.S
+5
-0
arch/ia64/kernel/smp.c
arch/ia64/kernel/smp.c
+82
-0
arch/ia64/mm/tlb.c
arch/ia64/mm/tlb.c
+196
-0
include/asm-ia64/kregs.h
include/asm-ia64/kregs.h
+3
-0
include/asm-ia64/smp.h
include/asm-ia64/smp.h
+3
-0
include/asm-ia64/tlb.h
include/asm-ia64/tlb.h
+26
-0
No files found.
arch/ia64/kernel/mca.c
View file @
a49072bb
...
...
@@ -97,6 +97,7 @@
#include <asm/irq.h>
#include <asm/hw_irq.h>
#include <asm/tlb.h>
#include "mca_drv.h"
#include "entry.h"
...
...
@@ -112,6 +113,7 @@ DEFINE_PER_CPU(u64, ia64_mca_data); /* == __per_cpu_mca[smp_processor_id()] */
DEFINE_PER_CPU
(
u64
,
ia64_mca_per_cpu_pte
);
/* PTE to map per-CPU area */
DEFINE_PER_CPU
(
u64
,
ia64_mca_pal_pte
);
/* PTE to map PAL code */
DEFINE_PER_CPU
(
u64
,
ia64_mca_pal_base
);
/* vaddr PAL code granule */
DEFINE_PER_CPU
(
u64
,
ia64_mca_tr_reload
);
/* Flag for TR reload */
unsigned
long
__per_cpu_mca
[
NR_CPUS
];
...
...
@@ -1182,6 +1184,49 @@ ia64_wait_for_slaves(int monarch, const char *type)
return
;
}
/* mca_insert_tr
*
* Switch rid when TR reload and needed!
* iord: 1: itr, 2: itr;
*
*/
static
void
mca_insert_tr
(
u64
iord
)
{
int
i
;
u64
old_rr
;
struct
ia64_tr_entry
*
p
;
unsigned
long
psr
;
int
cpu
=
smp_processor_id
();
psr
=
ia64_clear_ic
();
for
(
i
=
IA64_TR_ALLOC_BASE
;
i
<
IA64_TR_ALLOC_MAX
;
i
++
)
{
p
=
&
__per_cpu_idtrs
[
cpu
][
iord
-
1
][
i
];
if
(
p
->
pte
&
0x1
)
{
old_rr
=
ia64_get_rr
(
p
->
ifa
);
if
(
old_rr
!=
p
->
rr
)
{
ia64_set_rr
(
p
->
ifa
,
p
->
rr
);
ia64_srlz_d
();
}
ia64_ptr
(
iord
,
p
->
ifa
,
p
->
itir
>>
2
);
ia64_srlz_i
();
if
(
iord
&
0x1
)
{
ia64_itr
(
0x1
,
i
,
p
->
ifa
,
p
->
pte
,
p
->
itir
>>
2
);
ia64_srlz_i
();
}
if
(
iord
&
0x2
)
{
ia64_itr
(
0x2
,
i
,
p
->
ifa
,
p
->
pte
,
p
->
itir
>>
2
);
ia64_srlz_i
();
}
if
(
old_rr
!=
p
->
rr
)
{
ia64_set_rr
(
p
->
ifa
,
old_rr
);
ia64_srlz_d
();
}
}
}
ia64_set_psr
(
psr
);
}
/*
* ia64_mca_handler
*
...
...
@@ -1271,6 +1316,10 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
monarch_cpu
=
-
1
;
#endif
}
if
(
__get_cpu_var
(
ia64_mca_tr_reload
))
{
mca_insert_tr
(
0x1
);
/*Reload dynamic itrs*/
mca_insert_tr
(
0x2
);
/*Reload dynamic itrs*/
}
if
(
notify_die
(
DIE_MCA_MONARCH_LEAVE
,
"MCA"
,
regs
,
(
long
)
&
nd
,
0
,
recover
)
==
NOTIFY_STOP
)
ia64_mca_spin
(
__func__
);
...
...
arch/ia64/kernel/mca_asm.S
View file @
a49072bb
...
...
@@ -219,8 +219,13 @@ ia64_reload_tr:
mov
r20
=
IA64_TR_CURRENT_STACK
;;
itr.d
dtr
[
r20
]=
r16
GET_THIS_PADDR
(
r2
,
ia64_mca_tr_reload
)
mov
r18
=
1
;;
srlz.d
;;
st8
[
r2
]
=
r18
;;
done_tlb_purge_and_reload
:
...
...
arch/ia64/kernel/smp.c
View file @
a49072bb
...
...
@@ -209,6 +209,19 @@ send_IPI_allbutself (int op)
}
}
/*
* Called with preemption disabled.
*/
static
inline
void
send_IPI_mask
(
cpumask_t
mask
,
int
op
)
{
unsigned
int
cpu
;
for_each_cpu_mask
(
cpu
,
mask
)
{
send_IPI_single
(
cpu
,
op
);
}
}
/*
* Called with preemption disabled.
*/
...
...
@@ -401,6 +414,75 @@ smp_call_function_single (int cpuid, void (*func) (void *info), void *info, int
}
EXPORT_SYMBOL
(
smp_call_function_single
);
/**
* smp_call_function_mask(): Run a function on a set of other CPUs.
* <mask> The set of cpus to run on. Must not include the current cpu.
* <func> The function to run. This must be fast and non-blocking.
* <info> An arbitrary pointer to pass to the function.
* <wait> If true, wait (atomically) until function
* has completed on other CPUs.
*
* Returns 0 on success, else a negative status code.
*
* If @wait is true, then returns once @func has returned; otherwise
* it returns just before the target cpu calls @func.
*
* You must not call this function with disabled interrupts or from a
* hardware interrupt handler or from a bottom half handler.
*/
int
smp_call_function_mask
(
cpumask_t
mask
,
void
(
*
func
)(
void
*
),
void
*
info
,
int
wait
)
{
struct
call_data_struct
data
;
cpumask_t
allbutself
;
int
cpus
;
spin_lock
(
&
call_lock
);
allbutself
=
cpu_online_map
;
cpu_clear
(
smp_processor_id
(),
allbutself
);
cpus_and
(
mask
,
mask
,
allbutself
);
cpus
=
cpus_weight
(
mask
);
if
(
!
cpus
)
{
spin_unlock
(
&
call_lock
);
return
0
;
}
/* Can deadlock when called with interrupts disabled */
WARN_ON
(
irqs_disabled
());
data
.
func
=
func
;
data
.
info
=
info
;
atomic_set
(
&
data
.
started
,
0
);
data
.
wait
=
wait
;
if
(
wait
)
atomic_set
(
&
data
.
finished
,
0
);
call_data
=
&
data
;
mb
();
/* ensure store to call_data precedes setting of IPI_CALL_FUNC*/
/* Send a message to other CPUs */
if
(
cpus_equal
(
mask
,
allbutself
))
send_IPI_allbutself
(
IPI_CALL_FUNC
);
else
send_IPI_mask
(
mask
,
IPI_CALL_FUNC
);
/* Wait for response */
while
(
atomic_read
(
&
data
.
started
)
!=
cpus
)
cpu_relax
();
if
(
wait
)
while
(
atomic_read
(
&
data
.
finished
)
!=
cpus
)
cpu_relax
();
call_data
=
NULL
;
spin_unlock
(
&
call_lock
);
return
0
;
}
EXPORT_SYMBOL
(
smp_call_function_mask
);
/*
* this function sends a 'generic call function' IPI to all other CPUs
* in the system.
...
...
arch/ia64/mm/tlb.c
View file @
a49072bb
...
...
@@ -26,6 +26,8 @@
#include <asm/pal.h>
#include <asm/tlbflush.h>
#include <asm/dma.h>
#include <asm/processor.h>
#include <asm/tlb.h>
static
struct
{
unsigned
long
mask
;
/* mask of supported purge page-sizes */
...
...
@@ -39,6 +41,10 @@ struct ia64_ctx ia64_ctx = {
};
DEFINE_PER_CPU
(
u8
,
ia64_need_tlb_flush
);
DEFINE_PER_CPU
(
u8
,
ia64_tr_num
);
/*Number of TR slots in current processor*/
DEFINE_PER_CPU
(
u8
,
ia64_tr_used
);
/*Max Slot number used by kernel*/
struct
ia64_tr_entry
__per_cpu_idtrs
[
NR_CPUS
][
2
][
IA64_TR_ALLOC_MAX
];
/*
* Initializes the ia64_ctx.bitmap array based on max_ctx+1.
...
...
@@ -190,6 +196,9 @@ ia64_tlb_init (void)
ia64_ptce_info_t
uninitialized_var
(
ptce_info
);
/* GCC be quiet */
unsigned
long
tr_pgbits
;
long
status
;
pal_vm_info_1_u_t
vm_info_1
;
pal_vm_info_2_u_t
vm_info_2
;
int
cpu
=
smp_processor_id
();
if
((
status
=
ia64_pal_vm_page_size
(
&
tr_pgbits
,
&
purge
.
mask
))
!=
0
)
{
printk
(
KERN_ERR
"PAL_VM_PAGE_SIZE failed with status=%ld; "
...
...
@@ -206,4 +215,191 @@ ia64_tlb_init (void)
local_cpu_data
->
ptce_stride
[
1
]
=
ptce_info
.
stride
[
1
];
local_flush_tlb_all
();
/* nuke left overs from bootstrapping... */
status
=
ia64_pal_vm_summary
(
&
vm_info_1
,
&
vm_info_2
);
if
(
status
)
{
printk
(
KERN_ERR
"ia64_pal_vm_summary=%ld
\n
"
,
status
);
per_cpu
(
ia64_tr_num
,
cpu
)
=
8
;
return
;
}
per_cpu
(
ia64_tr_num
,
cpu
)
=
vm_info_1
.
pal_vm_info_1_s
.
max_itr_entry
+
1
;
if
(
per_cpu
(
ia64_tr_num
,
cpu
)
>
(
vm_info_1
.
pal_vm_info_1_s
.
max_dtr_entry
+
1
))
per_cpu
(
ia64_tr_num
,
cpu
)
=
vm_info_1
.
pal_vm_info_1_s
.
max_dtr_entry
+
1
;
if
(
per_cpu
(
ia64_tr_num
,
cpu
)
>
IA64_TR_ALLOC_MAX
)
{
per_cpu
(
ia64_tr_num
,
cpu
)
=
IA64_TR_ALLOC_MAX
;
printk
(
KERN_DEBUG
"TR register number exceeds IA64_TR_ALLOC_MAX!"
"IA64_TR_ALLOC_MAX should be extended
\n
"
);
}
}
/*
* is_tr_overlap
*
* Check overlap with inserted TRs.
*/
static
int
is_tr_overlap
(
struct
ia64_tr_entry
*
p
,
u64
va
,
u64
log_size
)
{
u64
tr_log_size
;
u64
tr_end
;
u64
va_rr
=
ia64_get_rr
(
va
);
u64
va_rid
=
RR_TO_RID
(
va_rr
);
u64
va_end
=
va
+
(
1
<<
log_size
)
-
1
;
if
(
va_rid
!=
RR_TO_RID
(
p
->
rr
))
return
0
;
tr_log_size
=
(
p
->
itir
&
0xff
)
>>
2
;
tr_end
=
p
->
ifa
+
(
1
<<
tr_log_size
)
-
1
;
if
(
va
>
tr_end
||
p
->
ifa
>
va_end
)
return
0
;
return
1
;
}
/*
* ia64_insert_tr in virtual mode. Allocate a TR slot
*
* target_mask : 0x1 : itr, 0x2 : dtr, 0x3 : idtr
*
* va : virtual address.
* pte : pte entries inserted.
* log_size: range to be covered.
*
* Return value: <0 : error No.
*
* >=0 : slot number allocated for TR.
* Must be called with preemption disabled.
*/
int
ia64_itr_entry
(
u64
target_mask
,
u64
va
,
u64
pte
,
u64
log_size
)
{
int
i
,
r
;
unsigned
long
psr
;
struct
ia64_tr_entry
*
p
;
int
cpu
=
smp_processor_id
();
r
=
-
EINVAL
;
/*Check overlap with existing TR entries*/
if
(
target_mask
&
0x1
)
{
p
=
&
__per_cpu_idtrs
[
cpu
][
0
][
0
];
for
(
i
=
IA64_TR_ALLOC_BASE
;
i
<=
per_cpu
(
ia64_tr_used
,
cpu
);
i
++
,
p
++
)
{
if
(
p
->
pte
&
0x1
)
if
(
is_tr_overlap
(
p
,
va
,
log_size
))
{
printk
(
KERN_DEBUG
"Overlapped Entry"
"Inserted for TR Reigster!!
\n
"
);
goto
out
;
}
}
}
if
(
target_mask
&
0x2
)
{
p
=
&
__per_cpu_idtrs
[
cpu
][
1
][
0
];
for
(
i
=
IA64_TR_ALLOC_BASE
;
i
<=
per_cpu
(
ia64_tr_used
,
cpu
);
i
++
,
p
++
)
{
if
(
p
->
pte
&
0x1
)
if
(
is_tr_overlap
(
p
,
va
,
log_size
))
{
printk
(
KERN_DEBUG
"Overlapped Entry"
"Inserted for TR Reigster!!
\n
"
);
goto
out
;
}
}
}
for
(
i
=
IA64_TR_ALLOC_BASE
;
i
<
per_cpu
(
ia64_tr_num
,
cpu
);
i
++
)
{
switch
(
target_mask
&
0x3
)
{
case
1
:
if
(
!
(
__per_cpu_idtrs
[
cpu
][
0
][
i
].
pte
&
0x1
))
goto
found
;
continue
;
case
2
:
if
(
!
(
__per_cpu_idtrs
[
cpu
][
1
][
i
].
pte
&
0x1
))
goto
found
;
continue
;
case
3
:
if
(
!
(
__per_cpu_idtrs
[
cpu
][
0
][
i
].
pte
&
0x1
)
&&
!
(
__per_cpu_idtrs
[
cpu
][
1
][
i
].
pte
&
0x1
))
goto
found
;
continue
;
default:
r
=
-
EINVAL
;
goto
out
;
}
}
found:
if
(
i
>=
per_cpu
(
ia64_tr_num
,
cpu
))
return
-
EBUSY
;
/*Record tr info for mca hander use!*/
if
(
i
>
per_cpu
(
ia64_tr_used
,
cpu
))
per_cpu
(
ia64_tr_used
,
cpu
)
=
i
;
psr
=
ia64_clear_ic
();
if
(
target_mask
&
0x1
)
{
ia64_itr
(
0x1
,
i
,
va
,
pte
,
log_size
);
ia64_srlz_i
();
p
=
&
__per_cpu_idtrs
[
cpu
][
0
][
i
];
p
->
ifa
=
va
;
p
->
pte
=
pte
;
p
->
itir
=
log_size
<<
2
;
p
->
rr
=
ia64_get_rr
(
va
);
}
if
(
target_mask
&
0x2
)
{
ia64_itr
(
0x2
,
i
,
va
,
pte
,
log_size
);
ia64_srlz_i
();
p
=
&
__per_cpu_idtrs
[
cpu
][
1
][
i
];
p
->
ifa
=
va
;
p
->
pte
=
pte
;
p
->
itir
=
log_size
<<
2
;
p
->
rr
=
ia64_get_rr
(
va
);
}
ia64_set_psr
(
psr
);
r
=
i
;
out:
return
r
;
}
EXPORT_SYMBOL_GPL
(
ia64_itr_entry
);
/*
* ia64_purge_tr
*
* target_mask: 0x1: purge itr, 0x2 : purge dtr, 0x3 purge idtr.
* slot: slot number to be freed.
*
* Must be called with preemption disabled.
*/
void
ia64_ptr_entry
(
u64
target_mask
,
int
slot
)
{
int
cpu
=
smp_processor_id
();
int
i
;
struct
ia64_tr_entry
*
p
;
if
(
slot
<
IA64_TR_ALLOC_BASE
||
slot
>=
per_cpu
(
ia64_tr_num
,
cpu
))
return
;
if
(
target_mask
&
0x1
)
{
p
=
&
__per_cpu_idtrs
[
cpu
][
0
][
slot
];
if
((
p
->
pte
&
0x1
)
&&
is_tr_overlap
(
p
,
p
->
ifa
,
p
->
itir
>>
2
))
{
p
->
pte
=
0
;
ia64_ptr
(
0x1
,
p
->
ifa
,
p
->
itir
>>
2
);
ia64_srlz_i
();
}
}
if
(
target_mask
&
0x2
)
{
p
=
&
__per_cpu_idtrs
[
cpu
][
1
][
slot
];
if
((
p
->
pte
&
0x1
)
&&
is_tr_overlap
(
p
,
p
->
ifa
,
p
->
itir
>>
2
))
{
p
->
pte
=
0
;
ia64_ptr
(
0x2
,
p
->
ifa
,
p
->
itir
>>
2
);
ia64_srlz_i
();
}
}
for
(
i
=
per_cpu
(
ia64_tr_used
,
cpu
);
i
>=
IA64_TR_ALLOC_BASE
;
i
--
)
{
if
((
__per_cpu_idtrs
[
cpu
][
0
][
i
].
pte
&
0x1
)
||
(
__per_cpu_idtrs
[
cpu
][
1
][
i
].
pte
&
0x1
))
break
;
}
per_cpu
(
ia64_tr_used
,
cpu
)
=
i
;
}
EXPORT_SYMBOL_GPL
(
ia64_ptr_entry
);
include/asm-ia64/kregs.h
View file @
a49072bb
...
...
@@ -31,6 +31,9 @@
#define IA64_TR_PALCODE 1
/* itr1: maps PALcode as required by EFI */
#define IA64_TR_CURRENT_STACK 1
/* dtr1: maps kernel's memory- & register-stacks */
#define IA64_TR_ALLOC_BASE 2
/* itr&dtr: Base of dynamic TR resource*/
#define IA64_TR_ALLOC_MAX 32
/* Max number for dynamic use*/
/* Processor status register bits: */
#define IA64_PSR_BE_BIT 1
#define IA64_PSR_UP_BIT 2
...
...
include/asm-ia64/smp.h
View file @
a49072bb
...
...
@@ -38,6 +38,9 @@ ia64_get_lid (void)
return
lid
.
f
.
id
<<
8
|
lid
.
f
.
eid
;
}
extern
int
smp_call_function_mask
(
cpumask_t
mask
,
void
(
*
func
)(
void
*
),
void
*
info
,
int
wait
);
#define hard_smp_processor_id() ia64_get_lid()
#ifdef CONFIG_SMP
...
...
include/asm-ia64/tlb.h
View file @
a49072bb
...
...
@@ -64,6 +64,32 @@ struct mmu_gather {
struct
page
*
pages
[
FREE_PTE_NR
];
};
struct
ia64_tr_entry
{
u64
ifa
;
u64
itir
;
u64
pte
;
u64
rr
;
};
/*Record for tr entry!*/
extern
int
ia64_itr_entry
(
u64
target_mask
,
u64
va
,
u64
pte
,
u64
log_size
);
extern
void
ia64_ptr_entry
(
u64
target_mask
,
int
slot
);
extern
struct
ia64_tr_entry
__per_cpu_idtrs
[
NR_CPUS
][
2
][
IA64_TR_ALLOC_MAX
];
/*
region register macros
*/
#define RR_TO_VE(val) (((val) >> 0) & 0x0000000000000001)
#define RR_VE(val) (((val) & 0x0000000000000001) << 0)
#define RR_VE_MASK 0x0000000000000001L
#define RR_VE_SHIFT 0
#define RR_TO_PS(val) (((val) >> 2) & 0x000000000000003f)
#define RR_PS(val) (((val) & 0x000000000000003f) << 2)
#define RR_PS_MASK 0x00000000000000fcL
#define RR_PS_SHIFT 2
#define RR_RID_MASK 0x00000000ffffff00L
#define RR_TO_RID(val) ((val >> 8) & 0xffffff)
/* Users of the generic TLB shootdown code must declare this storage space. */
DECLARE_PER_CPU
(
struct
mmu_gather
,
mmu_gathers
);
...
...
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