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
d25e93e6
Commit
d25e93e6
authored
Oct 20, 2003
by
David Mosberger
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ia64: Based on patch by Arun Sharma: fix IA-32 subsystem to support NPTL.
parent
b8e3ead1
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
271 additions
and
48 deletions
+271
-48
arch/ia64/ia32/binfmt_elf32.c
arch/ia64/ia32/binfmt_elf32.c
+4
-2
arch/ia64/ia32/ia32_entry.S
arch/ia64/ia32/ia32_entry.S
+9
-7
arch/ia64/ia32/ia32_ldt.c
arch/ia64/ia32/ia32_ldt.c
+1
-1
arch/ia64/ia32/ia32_support.c
arch/ia64/ia32/ia32_support.c
+67
-30
arch/ia64/ia32/ia32priv.h
arch/ia64/ia32/ia32priv.h
+50
-5
arch/ia64/ia32/sys_ia32.c
arch/ia64/ia32/sys_ia32.c
+108
-0
arch/ia64/kernel/process.c
arch/ia64/kernel/process.c
+6
-2
arch/ia64/kernel/smpboot.c
arch/ia64/kernel/smpboot.c
+4
-0
arch/ia64/mm/init.c
arch/ia64/mm/init.c
+1
-1
include/asm-ia64/ia32.h
include/asm-ia64/ia32.h
+2
-0
include/asm-ia64/processor.h
include/asm-ia64/processor.h
+19
-0
No files found.
arch/ia64/ia32/binfmt_elf32.c
View file @
d25e93e6
...
@@ -62,14 +62,16 @@ extern unsigned long *ia32_gdt;
...
@@ -62,14 +62,16 @@ extern unsigned long *ia32_gdt;
struct
page
*
struct
page
*
ia32_install_shared_page
(
struct
vm_area_struct
*
vma
,
unsigned
long
address
,
int
no_share
)
ia32_install_shared_page
(
struct
vm_area_struct
*
vma
,
unsigned
long
address
,
int
no_share
)
{
{
struct
page
*
pg
=
ia32_shared_page
[(
address
-
vma
->
vm_start
)
/
PAGE_SIZE
];
# define NUM_SHARED_PAGES (PAGE_SIZE > IA32_PAGE_SIZE ? 1 : 2)
struct
page
*
pg
=
ia32_shared_page
[
NUM_SHARED__PAGES
*
smp_processor_id
()
+
(
address
-
vma
->
vm_start
)
/
PAGE_SIZE
];
get_page
(
pg
);
get_page
(
pg
);
return
pg
;
return
pg
;
}
}
static
struct
vm_operations_struct
ia32_shared_page_vm_ops
=
{
static
struct
vm_operations_struct
ia32_shared_page_vm_ops
=
{
.
nopage
=
ia32_install_shared_page
.
nopage
=
ia32_install_shared_page
};
};
void
void
...
...
arch/ia64/ia32/ia32_entry.S
View file @
d25e93e6
...
@@ -32,7 +32,7 @@ END(ia32_execve)
...
@@ -32,7 +32,7 @@ END(ia32_execve)
ENTRY
(
ia32_clone
)
ENTRY
(
ia32_clone
)
.
prologue
ASM_UNW_PRLG_RP
|
ASM_UNW_PRLG_PFS
,
ASM_UNW_PRLG_GRSAVE
(
2
)
.
prologue
ASM_UNW_PRLG_RP
|
ASM_UNW_PRLG_PFS
,
ASM_UNW_PRLG_GRSAVE
(
2
)
alloc
r16
=
ar
.
pfs
,
2
,
2
,
4
,
0
alloc
r16
=
ar
.
pfs
,
5
,
2
,
6
,
0
DO_SAVE_SWITCH_STACK
DO_SAVE_SWITCH_STACK
mov
loc0
=
rp
mov
loc0
=
rp
mov
loc1
=
r16
//
save
ar
.
pfs
across
do_fork
mov
loc1
=
r16
//
save
ar
.
pfs
across
do_fork
...
@@ -41,6 +41,8 @@ ENTRY(ia32_clone)
...
@@ -41,6 +41,8 @@ ENTRY(ia32_clone)
mov
out3
=
16
//
stacksize
(
compensates
for
16
-
byte
scratch
area
)
mov
out3
=
16
//
stacksize
(
compensates
for
16
-
byte
scratch
area
)
adds
out2
=
IA64_SWITCH_STACK_SIZE
+
16
,
sp
//
out2
=
&
regs
adds
out2
=
IA64_SWITCH_STACK_SIZE
+
16
,
sp
//
out2
=
&
regs
dep
out0
=
0
,
in0
,
CLONE_IDLETASK_BIT
,
1
//
out0
=
clone_flags
&
~
CLONE_IDLETASK
dep
out0
=
0
,
in0
,
CLONE_IDLETASK_BIT
,
1
//
out0
=
clone_flags
&
~
CLONE_IDLETASK
zxt4
out4
=
in2
//
out4
=
parent_tidptr
zxt4
out5
=
in4
//
out5
=
child_tidptr
br.call.sptk.many
rp
=
do_fork
br.call.sptk.many
rp
=
do_fork
.
ret0
:
.
restore
sp
.
ret0
:
.
restore
sp
adds
sp
=
IA64_SWITCH_STACK_SIZE
,
sp
//
pop
the
switch
stack
adds
sp
=
IA64_SWITCH_STACK_SIZE
,
sp
//
pop
the
switch
stack
...
@@ -437,13 +439,13 @@ ia32_syscall_table:
...
@@ -437,13 +439,13 @@ ia32_syscall_table:
data8
sys_ni_syscall
/*
235
*/
data8
sys_ni_syscall
/*
235
*/
data8
sys_ni_syscall
data8
sys_ni_syscall
data8
sys_ni_syscall
data8
sys_ni_syscall
data8
sys_
ni_sysca
ll
data8
sys_
tki
ll
data8
sys_ni_syscall
data8
sys_ni_syscall
data8
compat_sys_futex
/*
240
*/
data8
compat_sys_futex
/*
240
*/
data8
compat_sys_sched_setaffinity
data8
compat_sys_sched_setaffinity
data8
compat_sys_sched_getaffinity
data8
compat_sys_sched_getaffinity
data8
sys
_ni_syscall
data8
sys
32_set_thread_area
data8
sys
_ni_syscall
data8
sys
32_get_thread_area
data8
sys_ni_syscall
/*
245
*/
data8
sys_ni_syscall
/*
245
*/
data8
sys_ni_syscall
data8
sys_ni_syscall
data8
sys_ni_syscall
data8
sys_ni_syscall
...
@@ -451,13 +453,13 @@ ia32_syscall_table:
...
@@ -451,13 +453,13 @@ ia32_syscall_table:
data8
sys_ni_syscall
data8
sys_ni_syscall
data8
sys_ni_syscall
/*
250
*/
data8
sys_ni_syscall
/*
250
*/
data8
sys_ni_syscall
data8
sys_ni_syscall
data8
sys_
ni_syscall
data8
sys_
exit_group
data8
sys_ni_syscall
data8
sys_ni_syscall
data8
sys_epoll_create
data8
sys_epoll_create
data8
sys32_epoll_ctl
/*
255
*/
data8
sys32_epoll_ctl
/*
255
*/
data8
sys32_epoll_wait
data8
sys32_epoll_wait
data8
sys_
ni_syscall
data8
sys_
remap_file_pages
data8
sys_
ni_syscall
data8
sys_
set_tid_address
data8
sys_ni_syscall
data8
sys_ni_syscall
data8
sys_ni_syscall
/*
260
*/
data8
sys_ni_syscall
/*
260
*/
data8
sys_ni_syscall
data8
sys_ni_syscall
...
...
arch/ia64/ia32/ia32_ldt.c
View file @
d25e93e6
...
@@ -82,7 +82,7 @@ read_default_ldt (void * ptr, unsigned long bytecount)
...
@@ -82,7 +82,7 @@ read_default_ldt (void * ptr, unsigned long bytecount)
static
int
static
int
write_ldt
(
void
*
ptr
,
unsigned
long
bytecount
,
int
oldmode
)
write_ldt
(
void
*
ptr
,
unsigned
long
bytecount
,
int
oldmode
)
{
{
struct
ia32_
modify_ldt_ldt_s
ldt_info
;
struct
ia32_
user_desc
ldt_info
;
__u64
entry
;
__u64
entry
;
int
ret
;
int
ret
;
...
...
arch/ia64/ia32/ia32_support.c
View file @
d25e93e6
...
@@ -23,14 +23,16 @@
...
@@ -23,14 +23,16 @@
#include <asm/pgtable.h>
#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/system.h>
#include <asm/processor.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
#include "ia32priv.h"
#include "ia32priv.h"
extern
void
die_if_kernel
(
char
*
str
,
struct
pt_regs
*
regs
,
long
err
);
extern
void
die_if_kernel
(
char
*
str
,
struct
pt_regs
*
regs
,
long
err
);
struct
exec_domain
ia32_exec_domain
;
struct
exec_domain
ia32_exec_domain
;
struct
page
*
ia32_shared_page
[(
2
*
IA32_PAGE_SIZE
+
PAGE_SIZE
-
1
)
/
PAGE_SIZE
];
struct
page
*
ia32_shared_page
[(
PAGE_ALIGN
(
IA32_PAGE_SIZE
)
/
PAGE_SIZE
)
*
NR_CPUS
];
unsigned
long
*
ia32_gdt
;
unsigned
long
*
ia32_boot_gdt
;
unsigned
long
*
cpu_gdt_table
[
NR_CPUS
];
static
unsigned
long
static
unsigned
long
load_desc
(
u16
selector
)
load_desc
(
u16
selector
)
...
@@ -43,8 +45,8 @@ load_desc (u16 selector)
...
@@ -43,8 +45,8 @@ load_desc (u16 selector)
table
=
(
unsigned
long
*
)
IA32_LDT_OFFSET
;
table
=
(
unsigned
long
*
)
IA32_LDT_OFFSET
;
limit
=
IA32_LDT_ENTRIES
;
limit
=
IA32_LDT_ENTRIES
;
}
else
{
}
else
{
table
=
ia32_gdt
;
table
=
cpu_gdt_table
[
smp_processor_id
()]
;
limit
=
IA32_PAGE_SIZE
/
sizeof
(
ia32_gdt
[
0
]);
limit
=
IA32_PAGE_SIZE
/
sizeof
(
ia32_
boot_
gdt
[
0
]);
}
}
index
=
selector
>>
IA32_SEGSEL_INDEX_SHIFT
;
index
=
selector
>>
IA32_SEGSEL_INDEX_SHIFT
;
if
(
index
>=
limit
)
if
(
index
>=
limit
)
...
@@ -66,6 +68,34 @@ ia32_load_segment_descriptors (struct task_struct *task)
...
@@ -66,6 +68,34 @@ ia32_load_segment_descriptors (struct task_struct *task)
regs
->
ar_ssd
=
load_desc
(
regs
->
r17
>>
16
);
/* SSD */
regs
->
ar_ssd
=
load_desc
(
regs
->
r17
>>
16
);
/* SSD */
}
}
int
ia32_clone_tls
(
struct
task_struct
*
child
,
struct
pt_regs
*
childregs
)
{
struct
desc_struct
*
desc
;
struct
ia32_user_desc
info
;
int
idx
;
if
(
copy_from_user
(
&
info
,
(
void
*
)(
childregs
->
r14
&
0xffffffff
),
sizeof
(
info
)))
return
-
EFAULT
;
if
(
LDT_empty
(
&
info
))
return
-
EINVAL
;
idx
=
info
.
entry_number
;
if
(
idx
<
GDT_ENTRY_TLS_MIN
||
idx
>
GDT_ENTRY_TLS_MAX
)
return
-
EINVAL
;
desc
=
child
->
thread
.
tls_array
+
idx
-
GDT_ENTRY_TLS_MIN
;
desc
->
a
=
LDT_entry_a
(
&
info
);
desc
->
b
=
LDT_entry_b
(
&
info
);
/* XXX: can this be done in a cleaner way ? */
load_TLS
(
&
child
->
thread
,
smp_processor_id
());
ia32_load_segment_descriptors
(
child
);
load_TLS
(
&
current
->
thread
,
smp_processor_id
());
return
0
;
}
void
void
ia32_save_state
(
struct
task_struct
*
t
)
ia32_save_state
(
struct
task_struct
*
t
)
{
{
...
@@ -83,14 +113,13 @@ ia32_load_state (struct task_struct *t)
...
@@ -83,14 +113,13 @@ ia32_load_state (struct task_struct *t)
{
{
unsigned
long
eflag
,
fsr
,
fcr
,
fir
,
fdr
,
tssd
;
unsigned
long
eflag
,
fsr
,
fcr
,
fir
,
fdr
,
tssd
;
struct
pt_regs
*
regs
=
ia64_task_regs
(
t
);
struct
pt_regs
*
regs
=
ia64_task_regs
(
t
);
int
nr
=
get_cpu
();
/* LDT and TSS depend on CPU number: */
eflag
=
t
->
thread
.
eflag
;
eflag
=
t
->
thread
.
eflag
;
fsr
=
t
->
thread
.
fsr
;
fsr
=
t
->
thread
.
fsr
;
fcr
=
t
->
thread
.
fcr
;
fcr
=
t
->
thread
.
fcr
;
fir
=
t
->
thread
.
fir
;
fir
=
t
->
thread
.
fir
;
fdr
=
t
->
thread
.
fdr
;
fdr
=
t
->
thread
.
fdr
;
tssd
=
load_desc
(
_TSS
(
nr
)
);
/* TSSD */
tssd
=
load_desc
(
_TSS
);
/* TSSD */
ia64_setreg
(
_IA64_REG_AR_EFLAG
,
eflag
);
ia64_setreg
(
_IA64_REG_AR_EFLAG
,
eflag
);
ia64_setreg
(
_IA64_REG_AR_FSR
,
fsr
);
ia64_setreg
(
_IA64_REG_AR_FSR
,
fsr
);
...
@@ -102,8 +131,10 @@ ia32_load_state (struct task_struct *t)
...
@@ -102,8 +131,10 @@ ia32_load_state (struct task_struct *t)
ia64_set_kr
(
IA64_KR_IO_BASE
,
IA32_IOBASE
);
ia64_set_kr
(
IA64_KR_IO_BASE
,
IA32_IOBASE
);
ia64_set_kr
(
IA64_KR_TSSD
,
tssd
);
ia64_set_kr
(
IA64_KR_TSSD
,
tssd
);
regs
->
r17
=
(
_TSS
(
nr
)
<<
48
)
|
(
_LDT
(
nr
)
<<
32
)
|
(
__u32
)
regs
->
r17
;
regs
->
r17
=
(
_TSS
<<
48
)
|
(
_LDT
<<
32
)
|
(
__u32
)
regs
->
r17
;
regs
->
r30
=
load_desc
(
_LDT
(
nr
));
/* LDTD */
regs
->
r30
=
load_desc
(
_LDT
);
/* LDTD */
load_TLS
(
&
t
->
thread
,
smp_processor_id
());
put_cpu
();
put_cpu
();
}
}
...
@@ -113,37 +144,43 @@ ia32_load_state (struct task_struct *t)
...
@@ -113,37 +144,43 @@ ia32_load_state (struct task_struct *t)
void
void
ia32_gdt_init
(
void
)
ia32_gdt_init
(
void
)
{
{
unsigned
long
*
tss
;
int
cpu
=
smp_processor_id
();
ia32_shared_page
[
cpu
]
=
alloc_page
(
GFP_KERNEL
);
cpu_gdt_table
[
cpu
]
=
page_address
(
ia32_shared_page
[
cpu
]);
/* Copy from the boot cpu's GDT */
memcpy
(
cpu_gdt_table
[
cpu
],
ia32_boot_gdt
,
PAGE_SIZE
);
}
/*
* Setup IA32 GDT and TSS
*/
void
ia32_boot_gdt_init
(
void
)
{
unsigned
long
ldt_size
;
unsigned
long
ldt_size
;
int
nr
;
ia32_shared_page
[
0
]
=
alloc_page
(
GFP_KERNEL
);
ia32_shared_page
[
0
]
=
alloc_page
(
GFP_KERNEL
);
ia32_gdt
=
page_address
(
ia32_shared_page
[
0
]);
ia32_boot_gdt
=
page_address
(
ia32_shared_page
[
0
]);
tss
=
ia32_gdt
+
IA32_PAGE_SIZE
/
sizeof
(
ia32_gdt
[
0
]);
cpu_gdt_table
[
0
]
=
ia32_boot_gdt
;
if
(
IA32_PAGE_SIZE
==
PAGE_SIZE
)
{
ia32_shared_page
[
1
]
=
alloc_page
(
GFP_KERNEL
);
tss
=
page_address
(
ia32_shared_page
[
1
]);
}
/* CS descriptor in IA-32 (scrambled) format */
/* CS descriptor in IA-32 (scrambled) format */
ia32_gdt
[
__USER_CS
>>
3
]
=
IA32_SEG_DESCRIPTOR
(
0
,
(
IA32_PAGE_OFFSET
-
1
)
>>
IA32_PAGE_SHIFT
,
ia32_boot_gdt
[
__USER_CS
>>
3
]
=
IA32_SEG_DESCRIPTOR
(
0
,
(
IA32_PAGE_OFFSET
-
1
)
>>
IA32_PAGE_SHIFT
,
0xb
,
1
,
3
,
1
,
1
,
1
,
1
);
0xb
,
1
,
3
,
1
,
1
,
1
,
1
);
/* DS descriptor in IA-32 (scrambled) format */
/* DS descriptor in IA-32 (scrambled) format */
ia32_gdt
[
__USER_DS
>>
3
]
=
IA32_SEG_DESCRIPTOR
(
0
,
(
IA32_PAGE_OFFSET
-
1
)
>>
IA32_PAGE_SHIFT
,
ia32_boot_gdt
[
__USER_DS
>>
3
]
=
IA32_SEG_DESCRIPTOR
(
0
,
(
IA32_PAGE_OFFSET
-
1
)
>>
IA32_PAGE_SHIFT
,
0x3
,
1
,
3
,
1
,
1
,
1
,
1
);
0x3
,
1
,
3
,
1
,
1
,
1
,
1
);
/* We never change the TSS and LDT descriptors, so we can share them across all CPUs. */
ldt_size
=
PAGE_ALIGN
(
IA32_LDT_ENTRIES
*
IA32_LDT_ENTRY_SIZE
);
ldt_size
=
PAGE_ALIGN
(
IA32_LDT_ENTRIES
*
IA32_LDT_ENTRY_SIZE
);
for
(
nr
=
0
;
nr
<
NR_CPUS
;
++
nr
)
{
ia32_boot_gdt
[
TSS_ENTRY
]
=
IA32_SEG_DESCRIPTOR
(
IA32_TSS_OFFSET
,
235
,
ia32_gdt
[
_TSS
(
nr
)
>>
IA32_SEGSEL_INDEX_SHIFT
]
=
IA32_SEG_DESCRIPTOR
(
IA32_TSS_OFFSET
,
235
,
0xb
,
0
,
3
,
1
,
1
,
1
,
0
);
0xb
,
0
,
3
,
1
,
1
,
1
,
0
);
ia32_gdt
[
_LDT
(
nr
)
>>
IA32_SEGSEL_INDEX_SHIFT
]
ia32_boot_gdt
[
LDT_ENTRY
]
=
IA32_SEG_DESCRIPTOR
(
IA32_LDT_OFFSET
,
ldt_size
-
1
,
=
IA32_SEG_DESCRIPTOR
(
IA32_LDT_OFFSET
,
ldt_size
-
1
,
0x2
,
0
,
3
,
1
,
1
,
1
,
0
);
0x2
,
0
,
3
,
1
,
1
,
1
,
0
);
}
}
}
/*
/*
...
...
arch/ia64/ia32/ia32priv.h
View file @
d25e93e6
...
@@ -10,6 +10,8 @@
...
@@ -10,6 +10,8 @@
#include <linux/binfmts.h>
#include <linux/binfmts.h>
#include <linux/compat.h>
#include <linux/compat.h>
#include <asm/processor.h>
/*
/*
* 32 bit structures for IA32 support.
* 32 bit structures for IA32 support.
*/
*/
...
@@ -327,15 +329,23 @@ void ia64_elf32_init(struct pt_regs *regs);
...
@@ -327,15 +329,23 @@ void ia64_elf32_init(struct pt_regs *regs);
#define __USER_CS 0x23
#define __USER_CS 0x23
#define __USER_DS 0x2B
#define __USER_DS 0x2B
#define FIRST_TSS_ENTRY 6
/*
#define FIRST_LDT_ENTRY (FIRST_TSS_ENTRY+1)
* The per-cpu GDT has 32 entries: see <asm-i386/segment.h>
#define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3))
*/
#define _LDT(n) ((((unsigned long) n)<<4)+(FIRST_LDT_ENTRY<<3))
#define GDT_ENTRIES 32
#define GDT_SIZE (GDT_ENTRIES * 8)
#define TSS_ENTRY 14
#define LDT_ENTRY (TSS_ENTRY + 1)
#define IA32_SEGSEL_RPL (0x3 << 0)
#define IA32_SEGSEL_RPL (0x3 << 0)
#define IA32_SEGSEL_TI (0x1 << 2)
#define IA32_SEGSEL_TI (0x1 << 2)
#define IA32_SEGSEL_INDEX_SHIFT 3
#define IA32_SEGSEL_INDEX_SHIFT 3
#define _TSS ((unsigned long) TSS_ENTRY << IA32_SEGSEL_INDEX_SHIFT)
#define _LDT ((unsigned long) LDT_ENTRY << IA32_SEGSEL_INDEX_SHIFT)
#define IA32_SEG_BASE 16
#define IA32_SEG_BASE 16
#define IA32_SEG_TYPE 40
#define IA32_SEG_TYPE 40
#define IA32_SEG_SYS 44
#define IA32_SEG_SYS 44
...
@@ -419,7 +429,42 @@ void ia64_elf32_init(struct pt_regs *regs);
...
@@ -419,7 +429,42 @@ void ia64_elf32_init(struct pt_regs *regs);
#define IA32_LDT_ENTRIES 8192
/* Maximum number of LDT entries supported. */
#define IA32_LDT_ENTRIES 8192
/* Maximum number of LDT entries supported. */
#define IA32_LDT_ENTRY_SIZE 8
/* The size of each LDT entry. */
#define IA32_LDT_ENTRY_SIZE 8
/* The size of each LDT entry. */
struct
ia32_modify_ldt_ldt_s
{
#define LDT_entry_a(info) \
((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
#define LDT_entry_b(info) \
(((info)->base_addr & 0xff000000) | \
(((info)->base_addr & 0x00ff0000) >> 16) | \
((info)->limit & 0xf0000) | \
(((info)->read_exec_only ^ 1) << 9) | \
((info)->contents << 10) | \
(((info)->seg_not_present ^ 1) << 15) | \
((info)->seg_32bit << 22) | \
((info)->limit_in_pages << 23) | \
((info)->useable << 20) | \
0x7100)
#define LDT_empty(info) ( \
(info)->base_addr == 0 && \
(info)->limit == 0 && \
(info)->contents == 0 && \
(info)->read_exec_only == 1 && \
(info)->seg_32bit == 0 && \
(info)->limit_in_pages == 0 && \
(info)->seg_not_present == 1 && \
(info)->useable == 0 )
static
inline
void
load_TLS
(
struct
thread_struct
*
t
,
unsigned
int
cpu
)
{
extern
struct
desc_struct
*
cpu_gdt_table
[
NR_CPUS
];
cpu_gdt_table
[
cpu
][
GDT_ENTRY_TLS_MIN
+
0
]
=
t
->
tls_array
[
0
];
cpu_gdt_table
[
cpu
][
GDT_ENTRY_TLS_MIN
+
1
]
=
t
->
tls_array
[
1
];
cpu_gdt_table
[
cpu
][
GDT_ENTRY_TLS_MIN
+
2
]
=
t
->
tls_array
[
2
];
}
struct
ia32_user_desc
{
unsigned
int
entry_number
;
unsigned
int
entry_number
;
unsigned
int
base_addr
;
unsigned
int
base_addr
;
unsigned
int
limit
;
unsigned
int
limit
;
...
...
arch/ia64/ia32/sys_ia32.c
View file @
d25e93e6
...
@@ -2817,6 +2817,114 @@ sys32_epoll_wait(int epfd, struct epoll_event32 *events, int maxevents,
...
@@ -2817,6 +2817,114 @@ sys32_epoll_wait(int epfd, struct epoll_event32 *events, int maxevents,
return
numevents
;
return
numevents
;
}
}
/*
* Get a yet unused TLS descriptor index.
*/
static
int
get_free_idx
(
void
)
{
struct
thread_struct
*
t
=
&
current
->
thread
;
int
idx
;
for
(
idx
=
0
;
idx
<
GDT_ENTRY_TLS_ENTRIES
;
idx
++
)
if
(
desc_empty
(
t
->
tls_array
+
idx
))
return
idx
+
GDT_ENTRY_TLS_MIN
;
return
-
ESRCH
;
}
/*
* Set a given TLS descriptor:
*/
asmlinkage
int
sys32_set_thread_area
(
struct
ia32_user_desc
*
u_info
)
{
struct
thread_struct
*
t
=
&
current
->
thread
;
struct
ia32_user_desc
info
;
struct
desc_struct
*
desc
;
int
cpu
,
idx
;
if
(
copy_from_user
(
&
info
,
u_info
,
sizeof
(
info
)))
return
-
EFAULT
;
idx
=
info
.
entry_number
;
/*
* index -1 means the kernel should try to find and allocate an empty descriptor:
*/
if
(
idx
==
-
1
)
{
idx
=
get_free_idx
();
if
(
idx
<
0
)
return
idx
;
if
(
put_user
(
idx
,
&
u_info
->
entry_number
))
return
-
EFAULT
;
}
if
(
idx
<
GDT_ENTRY_TLS_MIN
||
idx
>
GDT_ENTRY_TLS_MAX
)
return
-
EINVAL
;
desc
=
t
->
tls_array
+
idx
-
GDT_ENTRY_TLS_MIN
;
cpu
=
smp_processor_id
();
if
(
LDT_empty
(
&
info
))
{
desc
->
a
=
0
;
desc
->
b
=
0
;
}
else
{
desc
->
a
=
LDT_entry_a
(
&
info
);
desc
->
b
=
LDT_entry_b
(
&
info
);
}
load_TLS
(
t
,
cpu
);
return
0
;
}
/*
* Get the current Thread-Local Storage area:
*/
#define GET_BASE(desc) ( \
(((desc)->a >> 16) & 0x0000ffff) | \
(((desc)->b << 16) & 0x00ff0000) | \
( (desc)->b & 0xff000000) )
#define GET_LIMIT(desc) ( \
((desc)->a & 0x0ffff) | \
((desc)->b & 0xf0000) )
#define GET_32BIT(desc) (((desc)->b >> 23) & 1)
#define GET_CONTENTS(desc) (((desc)->b >> 10) & 3)
#define GET_WRITABLE(desc) (((desc)->b >> 9) & 1)
#define GET_LIMIT_PAGES(desc) (((desc)->b >> 23) & 1)
#define GET_PRESENT(desc) (((desc)->b >> 15) & 1)
#define GET_USEABLE(desc) (((desc)->b >> 20) & 1)
asmlinkage
int
sys32_get_thread_area
(
struct
ia32_user_desc
*
u_info
)
{
struct
ia32_user_desc
info
;
struct
desc_struct
*
desc
;
int
idx
;
if
(
get_user
(
idx
,
&
u_info
->
entry_number
))
return
-
EFAULT
;
if
(
idx
<
GDT_ENTRY_TLS_MIN
||
idx
>
GDT_ENTRY_TLS_MAX
)
return
-
EINVAL
;
desc
=
current
->
thread
.
tls_array
+
idx
-
GDT_ENTRY_TLS_MIN
;
info
.
entry_number
=
idx
;
info
.
base_addr
=
GET_BASE
(
desc
);
info
.
limit
=
GET_LIMIT
(
desc
);
info
.
seg_32bit
=
GET_32BIT
(
desc
);
info
.
contents
=
GET_CONTENTS
(
desc
);
info
.
read_exec_only
=
!
GET_WRITABLE
(
desc
);
info
.
limit_in_pages
=
GET_LIMIT_PAGES
(
desc
);
info
.
seg_not_present
=
!
GET_PRESENT
(
desc
);
info
.
useable
=
GET_USEABLE
(
desc
);
if
(
copy_to_user
(
u_info
,
&
info
,
sizeof
(
info
)))
return
-
EFAULT
;
return
0
;
}
#ifdef NOTYET
/* UNTESTED FOR IA64 FROM HERE DOWN */
#ifdef NOTYET
/* UNTESTED FOR IA64 FROM HERE DOWN */
struct
ncp_mount_data32
{
struct
ncp_mount_data32
{
...
...
arch/ia64/kernel/process.c
View file @
d25e93e6
...
@@ -25,6 +25,7 @@
...
@@ -25,6 +25,7 @@
#include <asm/delay.h>
#include <asm/delay.h>
#include <asm/elf.h>
#include <asm/elf.h>
#include <asm/ia32.h>
#include <asm/pgalloc.h>
#include <asm/pgalloc.h>
#include <asm/processor.h>
#include <asm/processor.h>
#include <asm/sal.h>
#include <asm/sal.h>
...
@@ -324,7 +325,7 @@ copy_thread (int nr, unsigned long clone_flags,
...
@@ -324,7 +325,7 @@ copy_thread (int nr, unsigned long clone_flags,
memcpy
((
void
*
)
child_rbs
,
(
void
*
)
rbs
,
rbs_size
);
memcpy
((
void
*
)
child_rbs
,
(
void
*
)
rbs
,
rbs_size
);
if
(
user_mode
(
child_ptregs
))
{
if
(
user_mode
(
child_ptregs
))
{
if
(
clone_flags
&
CLONE_SETTLS
)
if
(
(
clone_flags
&
CLONE_SETTLS
)
&&
!
IS_IA32_PROCESS
(
regs
)
)
child_ptregs
->
r13
=
regs
->
r16
;
/* see sys_clone2() in entry.S */
child_ptregs
->
r13
=
regs
->
r16
;
/* see sys_clone2() in entry.S */
if
(
user_stack_base
)
{
if
(
user_stack_base
)
{
child_ptregs
->
r12
=
user_stack_base
+
user_stack_size
-
16
;
child_ptregs
->
r12
=
user_stack_base
+
user_stack_size
-
16
;
...
@@ -383,8 +384,11 @@ copy_thread (int nr, unsigned long clone_flags,
...
@@ -383,8 +384,11 @@ copy_thread (int nr, unsigned long clone_flags,
* If we're cloning an IA32 task then save the IA32 extra
* If we're cloning an IA32 task then save the IA32 extra
* state from the current task to the new task
* state from the current task to the new task
*/
*/
if
(
IS_IA32_PROCESS
(
ia64_task_regs
(
current
)))
if
(
IS_IA32_PROCESS
(
ia64_task_regs
(
current
)))
{
ia32_save_state
(
p
);
ia32_save_state
(
p
);
if
(
clone_flags
&
CLONE_SETTLS
)
retval
=
ia32_clone_tls
(
p
,
child_ptregs
);
}
#endif
#endif
#ifdef CONFIG_PERFMON
#ifdef CONFIG_PERFMON
...
...
arch/ia64/kernel/smpboot.c
View file @
d25e93e6
...
@@ -35,6 +35,7 @@
...
@@ -35,6 +35,7 @@
#include <asm/cache.h>
#include <asm/cache.h>
#include <asm/current.h>
#include <asm/current.h>
#include <asm/delay.h>
#include <asm/delay.h>
#include <asm/ia32.h>
#include <asm/io.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/irq.h>
#include <asm/machvec.h>
#include <asm/machvec.h>
...
@@ -312,6 +313,9 @@ smp_callin (void)
...
@@ -312,6 +313,9 @@ smp_callin (void)
local_irq_enable
();
local_irq_enable
();
calibrate_delay
();
calibrate_delay
();
local_cpu_data
->
loops_per_jiffy
=
loops_per_jiffy
;
local_cpu_data
->
loops_per_jiffy
=
loops_per_jiffy
;
#ifdef CONFIG_IA32_SUPPORT
ia32_gdt_init
();
#endif
if
(
!
(
sal_platform_features
&
IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT
))
{
if
(
!
(
sal_platform_features
&
IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT
))
{
/*
/*
...
...
arch/ia64/mm/init.c
View file @
d25e93e6
...
@@ -558,6 +558,6 @@ mem_init (void)
...
@@ -558,6 +558,6 @@ mem_init (void)
setup_gate
();
/* setup gate pages before we free up boot memory... */
setup_gate
();
/* setup gate pages before we free up boot memory... */
#ifdef CONFIG_IA32_SUPPORT
#ifdef CONFIG_IA32_SUPPORT
ia32_gdt_init
();
ia32_
boot_
gdt_init
();
#endif
#endif
}
}
include/asm-ia64/ia32.h
View file @
d25e93e6
...
@@ -9,9 +9,11 @@
...
@@ -9,9 +9,11 @@
#ifdef CONFIG_IA32_SUPPORT
#ifdef CONFIG_IA32_SUPPORT
extern
void
ia32_cpu_init
(
void
);
extern
void
ia32_cpu_init
(
void
);
extern
void
ia32_boot_gdt_init
(
void
);
extern
void
ia32_gdt_init
(
void
);
extern
void
ia32_gdt_init
(
void
);
extern
int
ia32_exception
(
struct
pt_regs
*
regs
,
unsigned
long
isr
);
extern
int
ia32_exception
(
struct
pt_regs
*
regs
,
unsigned
long
isr
);
extern
int
ia32_intercept
(
struct
pt_regs
*
regs
,
unsigned
long
isr
);
extern
int
ia32_intercept
(
struct
pt_regs
*
regs
,
unsigned
long
isr
);
extern
int
ia32_clone_tls
(
struct
task_struct
*
child
,
struct
pt_regs
*
childregs
);
#endif
/* !CONFIG_IA32_SUPPORT */
#endif
/* !CONFIG_IA32_SUPPORT */
...
...
include/asm-ia64/processor.h
View file @
d25e93e6
...
@@ -230,6 +230,22 @@ typedef struct {
...
@@ -230,6 +230,22 @@ typedef struct {
(int *) (addr)); \
(int *) (addr)); \
})
})
#ifdef CONFIG_IA32_SUPPORT
struct
desc_struct
{
unsigned
int
a
,
b
;
};
#define desc_empty(desc) (!((desc)->a + (desc)->b))
#define desc_equal(desc1, desc2) (((desc1)->a == (desc2)->a) && ((desc1)->b == (desc2)->b))
#define GDT_ENTRY_TLS_ENTRIES 3
#define GDT_ENTRY_TLS_MIN 6
#define GDT_ENTRY_TLS_MAX (GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1)
#define TLS_SIZE (GDT_ENTRY_TLS_ENTRIES * 8)
#endif
struct
thread_struct
{
struct
thread_struct
{
__u32
flags
;
/* various thread flags (see IA64_THREAD_*) */
__u32
flags
;
/* various thread flags (see IA64_THREAD_*) */
/* writing on_ustack is performance-critical, so it's worth spending 8 bits on it... */
/* writing on_ustack is performance-critical, so it's worth spending 8 bits on it... */
...
@@ -249,6 +265,9 @@ struct thread_struct {
...
@@ -249,6 +265,9 @@ struct thread_struct {
__u64
fdr
;
/* IA32 fp except. data reg */
__u64
fdr
;
/* IA32 fp except. data reg */
__u64
old_k1
;
/* old value of ar.k1 */
__u64
old_k1
;
/* old value of ar.k1 */
__u64
old_iob
;
/* old IOBase value */
__u64
old_iob
;
/* old IOBase value */
/* cached TLS descriptors. */
struct
desc_struct
tls_array
[
GDT_ENTRY_TLS_ENTRIES
];
# define INIT_THREAD_IA32 .eflag = 0, \
# define INIT_THREAD_IA32 .eflag = 0, \
.fsr = 0, \
.fsr = 0, \
.fcr = 0x17800000037fULL, \
.fcr = 0x17800000037fULL, \
...
...
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