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
c9195267
Commit
c9195267
authored
Jun 21, 2002
by
Anton Blanchard
Browse files
Options
Browse Files
Download
Plain Diff
Merge samba.org:/scratch/anton/linux-2.5
into samba.org:/scratch/anton/linux-2.5_ppc64
parents
278b098b
99b63362
Changes
56
Hide whitespace changes
Inline
Side-by-side
Showing
56 changed files
with
1146 additions
and
1058 deletions
+1146
-1058
arch/ppc64/config.in
arch/ppc64/config.in
+6
-0
arch/ppc64/defconfig
arch/ppc64/defconfig
+8
-2
arch/ppc64/kernel/LparData.c
arch/ppc64/kernel/LparData.c
+0
-1
arch/ppc64/kernel/Makefile
arch/ppc64/kernel/Makefile
+7
-0
arch/ppc64/kernel/chrp_setup.c
arch/ppc64/kernel/chrp_setup.c
+5
-13
arch/ppc64/kernel/eeh.c
arch/ppc64/kernel/eeh.c
+8
-7
arch/ppc64/kernel/entry.S
arch/ppc64/kernel/entry.S
+2
-2
arch/ppc64/kernel/head.S
arch/ppc64/kernel/head.S
+8
-5
arch/ppc64/kernel/htab.c
arch/ppc64/kernel/htab.c
+32
-18
arch/ppc64/kernel/iSeries_pci.c
arch/ppc64/kernel/iSeries_pci.c
+0
-1
arch/ppc64/kernel/iSeries_pci_reset.c
arch/ppc64/kernel/iSeries_pci_reset.c
+0
-1
arch/ppc64/kernel/irq.c
arch/ppc64/kernel/irq.c
+4
-2
arch/ppc64/kernel/mk_defs.c
arch/ppc64/kernel/mk_defs.c
+0
-1
arch/ppc64/kernel/open_pic.c
arch/ppc64/kernel/open_pic.c
+0
-1
arch/ppc64/kernel/pSeries_htab.c
arch/ppc64/kernel/pSeries_htab.c
+14
-16
arch/ppc64/kernel/pSeries_lpar.c
arch/ppc64/kernel/pSeries_lpar.c
+7
-9
arch/ppc64/kernel/pSeries_pci.c
arch/ppc64/kernel/pSeries_pci.c
+4
-6
arch/ppc64/kernel/pci_dn.c
arch/ppc64/kernel/pci_dn.c
+0
-1
arch/ppc64/kernel/ppc_asm.h
arch/ppc64/kernel/ppc_asm.h
+0
-2
arch/ppc64/kernel/proc_pmc.c
arch/ppc64/kernel/proc_pmc.c
+9
-6
arch/ppc64/kernel/process.c
arch/ppc64/kernel/process.c
+0
-2
arch/ppc64/kernel/prom.c
arch/ppc64/kernel/prom.c
+3
-4
arch/ppc64/kernel/ptrace.c
arch/ppc64/kernel/ptrace.c
+24
-75
arch/ppc64/kernel/ptrace32.c
arch/ppc64/kernel/ptrace32.c
+103
-143
arch/ppc64/kernel/rtas.c
arch/ppc64/kernel/rtas.c
+90
-6
arch/ppc64/kernel/rtas_flash.c
arch/ppc64/kernel/rtas_flash.c
+240
-0
arch/ppc64/kernel/setup.c
arch/ppc64/kernel/setup.c
+2
-6
arch/ppc64/kernel/signal.c
arch/ppc64/kernel/signal.c
+80
-78
arch/ppc64/kernel/signal32.c
arch/ppc64/kernel/signal32.c
+106
-152
arch/ppc64/kernel/smp.c
arch/ppc64/kernel/smp.c
+3
-13
arch/ppc64/kernel/time.c
arch/ppc64/kernel/time.c
+0
-1
arch/ppc64/mm/init.c
arch/ppc64/mm/init.c
+80
-96
arch/ppc64/vmlinux.lds
arch/ppc64/vmlinux.lds
+0
-13
arch/ppc64/xmon/privinst.h
arch/ppc64/xmon/privinst.h
+0
-1
arch/ppc64/xmon/xmon.c
arch/ppc64/xmon/xmon.c
+0
-259
include/asm-ppc64/bitops.h
include/asm-ppc64/bitops.h
+6
-0
include/asm-ppc64/cache.h
include/asm-ppc64/cache.h
+2
-1
include/asm-ppc64/iSeries/HvCall.h
include/asm-ppc64/iSeries/HvCall.h
+7
-0
include/asm-ppc64/iSeries/HvCallHpt.h
include/asm-ppc64/iSeries/HvCallHpt.h
+4
-4
include/asm-ppc64/iSeries/HvCallSc.h
include/asm-ppc64/iSeries/HvCallSc.h
+1
-0
include/asm-ppc64/init.h
include/asm-ppc64/init.h
+1
-29
include/asm-ppc64/lmb.h
include/asm-ppc64/lmb.h
+1
-0
include/asm-ppc64/md.h
include/asm-ppc64/md.h
+0
-17
include/asm-ppc64/mmzone.h
include/asm-ppc64/mmzone.h
+93
-0
include/asm-ppc64/page.h
include/asm-ppc64/page.h
+11
-15
include/asm-ppc64/pgalloc.h
include/asm-ppc64/pgalloc.h
+3
-0
include/asm-ppc64/pgtable.h
include/asm-ppc64/pgtable.h
+3
-13
include/asm-ppc64/prom.h
include/asm-ppc64/prom.h
+0
-3
include/asm-ppc64/ptrace-common.h
include/asm-ppc64/ptrace-common.h
+55
-0
include/asm-ppc64/rtas.h
include/asm-ppc64/rtas.h
+27
-0
include/asm-ppc64/softirq.h
include/asm-ppc64/softirq.h
+1
-3
include/asm-ppc64/system.h
include/asm-ppc64/system.h
+0
-19
include/asm-ppc64/time.h
include/asm-ppc64/time.h
+1
-0
include/asm-ppc64/tlb.h
include/asm-ppc64/tlb.h
+85
-0
include/asm-ppc64/tlbflush.h
include/asm-ppc64/tlbflush.h
+0
-8
include/asm-ppc64/uaccess.h
include/asm-ppc64/uaccess.h
+0
-3
No files found.
arch/ppc64/config.in
View file @
c9195267
...
...
@@ -23,12 +23,18 @@ if [ "$CONFIG_SMP" = "y" ]; then
bool ' Distribute interrupts on all CPUs by default' CONFIG_IRQ_ALL_CPUS
if [ "$CONFIG_PPC_PSERIES" = "y" ]; then
bool ' Hardware multithreading' CONFIG_HMT
bool ' Discontiguous Memory Support' CONFIG_DISCONTIGMEM
if [ "$CONFIG_DISCONTIGMEM" = "y" ]; then
bool ' NUMA support' CONFIG_NUMA
fi
fi
fi
define_bool CONFIG_PREEMPT n
if [ "$CONFIG_PPC_ISERIES" = "y" ]; then
define_bool CONFIG_MSCHUNKS y
else
tristate ' Firmware flash interface' CONFIG_RTAS_FLASH
fi
endmenu
...
...
arch/ppc64/defconfig
View file @
c9195267
...
...
@@ -37,7 +37,9 @@ CONFIG_PPC64=y
CONFIG_SMP=y
CONFIG_IRQ_ALL_CPUS=y
# CONFIG_HMT is not set
# CONFIG_DISCONTIGMEM is not set
# CONFIG_PREEMPT is not set
# CONFIG_RTAS_FLASH is not set
#
# General setup
...
...
@@ -60,6 +62,7 @@ CONFIG_PCI_NAMES=y
#
# CONFIG_PARPORT is not set
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
#
# Memory Technology Devices (MTD)
...
...
@@ -83,6 +86,7 @@ CONFIG_BLK_DEV_FD=y
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_CISS_SCSI_TAPE is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_NBD=y
CONFIG_BLK_DEV_RAM=y
...
...
@@ -364,7 +368,7 @@ CONFIG_IBMOL=y
# CONFIG_WAN is not set
#
#
"Tulip"
family network device support
#
Tulip
family network device support
#
# CONFIG_NET_TULIP is not set
...
...
@@ -397,7 +401,6 @@ CONFIG_IBMOL=y
#
CONFIG_FB=y
CONFIG_DUMMY_CONSOLE=y
# CONFIG_FB_RIVA is not set
# CONFIG_FB_CLGEN is not set
# CONFIG_FB_PM2 is not set
# CONFIG_FB_CYBER2000 is not set
...
...
@@ -409,6 +412,7 @@ CONFIG_FB_OF=y
# CONFIG_FB_IMSTT is not set
# CONFIG_FB_S3TRIO is not set
# CONFIG_FB_VGA16 is not set
# CONFIG_FB_RIVA is not set
CONFIG_FB_MATROX=y
CONFIG_FB_MATROX_MILLENIUM=y
CONFIG_FB_MATROX_MYSTIQUE=y
...
...
@@ -422,6 +426,8 @@ CONFIG_FB_MATROX_G100=y
# CONFIG_FB_NEOMAGIC is not set
# CONFIG_FB_3DFX is not set
# CONFIG_FB_VOODOO1 is not set
# CONFIG_FB_TRIDENT is not set
# CONFIG_FB_PM3 is not set
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FBCON_ADVANCED is not set
CONFIG_FBCON_CFB8=y
...
...
arch/ppc64/kernel/LparData.c
View file @
c9195267
...
...
@@ -13,7 +13,6 @@
#include <linux/threads.h>
#include <asm/processor.h>
#include <asm/ptrace.h>
#include <asm/init.h>
#include <asm/naca.h>
#include <asm/abs_addr.h>
#include <asm/bitops.h>
...
...
arch/ppc64/kernel/Makefile
View file @
c9195267
...
...
@@ -32,6 +32,8 @@ obj-$(CONFIG_PCI) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o eeh.o
obj-y
+=
rtasd.o nvram.o
endif
obj-$(CONFIG_RTAS_FLASH)
+=
rtas_flash.o
obj-$(CONFIG_SMP)
+=
smp.o
obj-y
+=
prom.o lmb.o rtas.o rtas-proc.o chrp_setup.o i8259.o
...
...
@@ -43,6 +45,11 @@ include $(TOPDIR)/Rules.make
#
head.o
:
head.S ppc_defs.h
misc.o
:
misc.S ppc_defs.h
entry.o
:
entry.S ppc_defs.h
hvCall.o
:
hvCall.S ppc_defs.h
pSeries_hvCall.o
:
pSeries_hvCall.S ppc_defs.h
sys32.o
:
sys32.S ppc_defs.h
ppc_defs.h
:
mk_defs.c ppc_defs.head
\
$(TOPDIR)/include/asm/mmu.h
\
...
...
arch/ppc64/kernel/chrp_setup.c
View file @
c9195267
...
...
@@ -57,7 +57,6 @@
#include <asm/machdep.h>
#include <asm/irq.h>
#include <asm/keyboard.h>
#include <asm/init.h>
#include <asm/naca.h>
#include <asm/time.h>
...
...
@@ -98,16 +97,10 @@ int fwnmi_active; /* TRUE if an FWNMI handler is present */
kdev_t
boot_dev
;
unsigned
long
virtPython0Facilities
=
0
;
// python0 facility area (memory mapped io) (64-bit format) VIRTUAL address.
extern
HPTE
*
Hash
,
*
Hash_end
;
extern
unsigned
long
Hash_size
,
Hash_mask
;
extern
int
probingmem
;
extern
unsigned
long
loops_per_jiffy
;
#ifdef CONFIG_BLK_DEV_RAM
extern
int
rd_doload
;
/* 1 = load ramdisk, 0 = don't load */
extern
int
rd_prompt
;
/* 1 = prompt for ramdisk, 0 = don't prompt */
extern
int
rd_image_start
;
/* starting block # of image */
#endif
extern
unsigned
long
ppc_proc_freq
;
extern
unsigned
long
ppc_tb_freq
;
void
chrp_get_cpuinfo
(
struct
seq_file
*
m
)
...
...
@@ -115,6 +108,8 @@ chrp_get_cpuinfo(struct seq_file *m)
struct
device_node
*
root
;
const
char
*
model
=
""
;
seq_printf
(
m
,
"timebase
\t
: %lu
\n
"
,
ppc_tb_freq
);
root
=
find_path_device
(
"/"
);
if
(
root
)
model
=
get_property
(
root
,
"model"
,
NULL
);
...
...
@@ -304,7 +299,7 @@ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md
.
progress
(
"Linux ppc64
\n
"
,
0x0
);
}
void
__chrp
void
chrp_progress
(
char
*
s
,
unsigned
short
hex
)
{
struct
device_node
*
root
;
...
...
@@ -362,9 +357,6 @@ chrp_progress(char *s, unsigned short hex)
extern
void
setup_default_decr
(
void
);
extern
unsigned
long
ppc_proc_freq
;
extern
unsigned
long
ppc_tb_freq
;
void
__init
pSeries_calibrate_decr
(
void
)
{
struct
device_node
*
cpu
;
...
...
arch/ppc64/kernel/eeh.c
View file @
c9195267
...
...
@@ -59,15 +59,14 @@ unsigned long eeh_token(unsigned long phb, unsigned long bus, unsigned long devf
return
((
IO_UNMAPPED_REGION_ID
<<
60
)
|
(
phb
<<
48UL
)
|
((
bus
&
0xff
)
<<
40UL
)
|
(
devfn
<<
32UL
)
|
(
offset
&
0xffffffff
));
}
int
eeh_get_state
(
unsigned
long
ea
)
{
int
eeh_get_state
(
unsigned
long
ea
)
{
return
0
;
}
/* Check for an eeh failure at the given token address.
* The given value has been read and it should be 1's (0xff, 0xffff or 0xffffffff).
* The given value has been read and it should be 1's (0xff, 0xffff or
* 0xffffffff).
*
* Probe to determine if an error actually occurred. If not return val.
* Otherwise panic.
...
...
@@ -113,7 +112,8 @@ unsigned long eeh_check_failure(void *token, unsigned long val)
return
val
;
/* good case */
}
void
eeh_init
(
void
)
{
void
eeh_init
(
void
)
{
extern
char
cmd_line
[];
/* Very early cmd line parse. Cheap, but works. */
char
*
eeh_force_off
=
strstr
(
cmd_line
,
"eeh-force-off"
);
char
*
eeh_force_on
=
strstr
(
cmd_line
,
"eeh-force-on"
);
...
...
@@ -121,7 +121,7 @@ void eeh_init(void) {
ibm_set_eeh_option
=
rtas_token
(
"ibm,set-eeh-option"
);
ibm_set_slot_reset
=
rtas_token
(
"ibm,set-slot-reset"
);
ibm_read_slot_reset_state
=
rtas_token
(
"ibm,read-slot-reset-state"
);
if
(
ibm_set_eeh_option
!=
RTAS_UNKNOWN_SERVICE
&&
naca
->
platform
==
PLATFORM_PSERIES_LPAR
)
if
(
ibm_set_eeh_option
!=
RTAS_UNKNOWN_SERVICE
)
eeh_implemented
=
1
;
if
(
eeh_force_off
>
eeh_force_on
)
{
...
...
@@ -334,6 +334,7 @@ static int __init eehoff_parm(char *str)
{
return
eeh_parm
(
str
,
0
);
}
static
int
__init
eehon_parm
(
char
*
str
)
{
return
eeh_parm
(
str
,
1
);
...
...
arch/ppc64/kernel/entry.S
View file @
c9195267
...
...
@@ -353,7 +353,7 @@ recheck:
li
r4
,
0
ori
r4
,
r4
,
MSR_EE
|
MSR_RI
andc
r10
,
r10
,
r4
/*
clear
MSR_EE
and
MSR_RI
*/
mtmsrd
r10
/*
Update
machine
state
*/
mtmsrd
r10
,
1
/*
Update
machine
state
*/
#ifdef CONFIG_PPC_ISERIES
#error fix iSeries soft disable
...
...
@@ -411,7 +411,7 @@ restore:
do_work
:
/
*
Enable
interrupts
*/
ori
r10
,
r10
,
MSR_EE
|
MSR_RI
mtmsrd
r10
mtmsrd
r10
,
1
andi
.
r0
,
r3
,
_TIF_NEED_RESCHED
beq
1
f
...
...
arch/ppc64/kernel/head.S
View file @
c9195267
...
...
@@ -575,7 +575,8 @@ stab_bolted_user_return:
bl
.
do_stab_SI
b
1
f
2
:
bl
.
do_hash_page_DSI
/*
Try
to
handle
as
hpte
fault
*/
2
:
li
r5
,
0x300
bl
.
do_hash_page_DSI
/*
Try
to
handle
as
hpte
fault
*/
1
:
ld
r4
,
_DAR
(
r1
)
ld
r5
,
_DSISR
(
r1
)
...
...
@@ -627,9 +628,8 @@ InstructionAccess_common:
bl
.
do_stab_SI
b
1
f
2
:
andis
.
r0
,
r23
,
0x4000
/*
no
pte
found
?
*/
beq
1
f
/*
if
so
,
try
to
put
a
PTE
*/
mr
r3
,
r22
/*
into
the
hash
table
*/
2
:
mr
r3
,
r22
li
r5
,
0x400
bl
.
do_hash_page_ISI
/*
Try
to
handle
as
hpte
fault
*/
1
:
mr
r4
,
r22
...
...
@@ -804,6 +804,7 @@ _GLOBAL(do_hash_page_DSI)
/
*
*
r3
contains
the
faulting
address
*
r4
contains
the
required
access
permissions
*
r5
contains
the
trap
number
*
*
at
return
r3
=
0
for
success
*/
...
...
@@ -852,11 +853,13 @@ _GLOBAL(do_stab_bolted)
ld
r22
,
8
(
r21
)
/*
get
SRR1
*/
andi
.
r22
,
r22
,
MSR_PR
/*
check
if
from
user
*/
bne
+
stab_bolted_user_return
/*
from
user
,
send
the
error
on
up
*/
#if 0
li
r3
,
0
#ifdef CONFIG_XMON
bl
.
xmon
#endif
1
:
b
1
b
#endif
2
:
/
*
(((
ea
>>
28
)
&
0x1fff
)
<<
15
)
|
(
ea
>>
60
)
*/
mfspr
r21
,
DAR
...
...
@@ -1119,7 +1122,7 @@ _GLOBAL(save_remaining_regs)
rldimi
r22
,
r20
,
15
,
48
/*
Insert
desired
EE
value
*/
#endif
mtmsrd
r22
mtmsrd
r22
,
1
blr
...
...
arch/ppc64/kernel/htab.c
View file @
c9195267
...
...
@@ -35,7 +35,6 @@
#include <asm/mmu_context.h>
#include <asm/page.h>
#include <asm/types.h>
#include <asm/init.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/naca.h>
...
...
@@ -45,9 +44,8 @@
#include <asm/lmb.h>
#include <asm/abs_addr.h>
#include <asm/tlbflush.h>
#ifdef CONFIG_PPC_EEH
#include <asm/eeh.h>
#
endif
#
include <asm/tlb.h>
/*
* Note: pte --> Linux PTE
...
...
@@ -196,7 +194,7 @@ static inline unsigned long computeHptePP(unsigned long pte)
* to be valid via Linux page tables, return 1. If handled return 0
*/
int
__hash_page
(
unsigned
long
ea
,
unsigned
long
access
,
unsigned
long
vsid
,
pte_t
*
ptep
)
pte_t
*
ptep
,
unsigned
long
trap
)
{
unsigned
long
va
,
vpn
;
unsigned
long
newpp
,
prpn
;
...
...
@@ -212,7 +210,7 @@ int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid,
* If no pte found or not present, send the problem up to
* do_page_fault
*/
if
(
!
ptep
||
!
pte_present
(
*
ptep
))
if
(
unlikely
(
!
ptep
||
!
pte_present
(
*
ptep
)
))
return
1
;
/*
...
...
@@ -220,7 +218,7 @@ int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid,
* prevented then send the problem up to do_page_fault.
*/
access
|=
_PAGE_PRESENT
;
if
(
access
&
~
(
pte_val
(
*
ptep
)))
if
(
unlikely
(
access
&
~
(
pte_val
(
*
ptep
)
)))
return
1
;
/*
...
...
@@ -245,8 +243,27 @@ int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid,
newpp
=
computeHptePP
(
pte_val
(
new_pte
));
#define PPC64_HWNOEXEC (1 << 2)
/* We do lazy icache flushing on POWER4 */
if
(
unlikely
(
__is_processor
(
PV_POWER4
)
&&
pfn_valid
(
pte_pfn
(
new_pte
))))
{
struct
page
*
page
=
pte_page
(
new_pte
);
/* page is dirty */
if
(
!
PageReserved
(
page
)
&&
!
test_bit
(
PG_arch_1
,
&
page
->
flags
))
{
if
(
trap
==
0x400
)
{
__flush_dcache_icache
(
page_address
(
page
));
set_bit
(
PG_arch_1
,
&
page
->
flags
);
}
else
{
newpp
|=
PPC64_HWNOEXEC
;
}
}
}
/* Check if pte already has an hpte (case 2) */
if
(
pte_val
(
old_pte
)
&
_PAGE_HASHPTE
)
{
if
(
unlikely
(
pte_val
(
old_pte
)
&
_PAGE_HASHPTE
)
)
{
/* There MIGHT be an HPTE for this pte */
unsigned
long
hash
,
slot
,
secondary
;
...
...
@@ -266,7 +283,7 @@ int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid,
*
ptep
=
new_pte
;
}
if
(
!
(
pte_val
(
old_pte
)
&
_PAGE_HASHPTE
))
{
if
(
likely
(
!
(
pte_val
(
old_pte
)
&
_PAGE_HASHPTE
)
))
{
/* XXX fix large pte flag */
unsigned
long
hash
=
hpt_hash
(
vpn
,
0
);
unsigned
long
hpte_group
;
...
...
@@ -318,7 +335,7 @@ int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid,
return
0
;
}
int
hash_page
(
unsigned
long
ea
,
unsigned
long
access
)
int
hash_page
(
unsigned
long
ea
,
unsigned
long
access
,
unsigned
long
trap
)
{
void
*
pgdir
;
unsigned
long
vsid
;
...
...
@@ -346,13 +363,11 @@ int hash_page(unsigned long ea, unsigned long access)
mm
=
&
init_mm
;
vsid
=
get_kernel_vsid
(
ea
);
break
;
#ifdef CONFIG_PPC_EEH
case
IO_UNMAPPED_REGION_ID
:
udbg_printf
(
"EEH Error ea = 0x%lx
\n
"
,
ea
);
PPCDBG_ENTER_DEBUGGER
();
panic
(
"EEH Error ea = 0x%lx
\n
"
,
ea
);
break
;
#endif
case
KERNEL_REGION_ID
:
/*
* As htab_initialize is now, we shouldn't ever get here since
...
...
@@ -379,7 +394,7 @@ int hash_page(unsigned long ea, unsigned long access)
*/
spin_lock
(
&
mm
->
page_table_lock
);
ptep
=
find_linux_pte
(
pgdir
,
ea
);
ret
=
__hash_page
(
ea
,
access
,
vsid
,
ptep
);
ret
=
__hash_page
(
ea
,
access
,
vsid
,
ptep
,
trap
);
spin_unlock
(
&
mm
->
page_table_lock
);
return
ret
;
...
...
@@ -419,12 +434,11 @@ void flush_hash_range(unsigned long context, unsigned long number, int local)
ppc_md
.
flush_hash_range
(
context
,
number
,
local
);
}
else
{
int
i
;
struct
tlb_batch_data
*
ptes
=
&
tlb_batch_array
[
smp_processor_id
()][
0
];
struct
ppc64_tlb_batch
*
batch
=
&
ppc64_tlb_batch
[
smp_processor_id
()
];
for
(
i
=
0
;
i
<
number
;
i
++
)
{
flush_hash_page
(
context
,
ptes
->
addr
,
ptes
->
pte
,
local
);
ptes
++
;
}
for
(
i
=
0
;
i
<
number
;
i
++
)
flush_hash_page
(
context
,
batch
->
addr
[
i
],
batch
->
pte
[
i
],
local
);
}
}
arch/ppc64/kernel/iSeries_pci.c
View file @
c9195267
...
...
@@ -21,7 +21,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/string.h>
...
...
arch/ppc64/kernel/iSeries_pci_reset.c
View file @
c9195267
...
...
@@ -32,7 +32,6 @@
#include <linux/irq.h>
#include <asm/io.h>
#include <asm/init.h>
#include <asm/iSeries/HvCallPci.h>
#include <asm/iSeries/HvTypes.h>
#include <asm/iSeries/mf.h>
...
...
arch/ppc64/kernel/irq.c
View file @
c9195267
...
...
@@ -81,7 +81,7 @@ unsigned long lpEvent_count = 0;
* this needs to be removed.
* -- Cort
*/
#define IRQ_KMALLOC_ENTRIES
8
#define IRQ_KMALLOC_ENTRIES
16
static
int
cache_bitmask
=
0
;
static
struct
irqaction
malloc_cache
[
IRQ_KMALLOC_ENTRIES
];
extern
int
mem_init_done
;
...
...
@@ -474,7 +474,9 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq)
int
cpu
=
smp_processor_id
();
irq_desc_t
*
desc
=
irq_desc
+
irq
;
balance_irq
(
irq
);
/* XXX This causes bad performance and lockups on XICS - Anton */
if
(
naca
->
interrupt_controller
==
IC_OPEN_PIC
)
balance_irq
(
irq
);
kstat
.
irqs
[
cpu
][
irq
]
++
;
spin_lock
(
&
desc
->
lock
);
...
...
arch/ppc64/kernel/mk_defs.c
View file @
c9195267
...
...
@@ -14,7 +14,6 @@
*/
#include <stddef.h>
#include <linux/config.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/kernel.h>
...
...
arch/ppc64/kernel/open_pic.c
View file @
c9195267
...
...
@@ -33,7 +33,6 @@ void* OpenPIC_Addr;
static
volatile
struct
OpenPIC
*
OpenPIC
=
NULL
;
u_int
OpenPIC_NumInitSenses
__initdata
=
0
;
u_char
*
OpenPIC_InitSenses
__initdata
=
NULL
;
extern
int
use_of_interrupt_tree
;
void
find_ISUs
(
void
);
...
...
arch/ppc64/kernel/pSeries_htab.c
View file @
c9195267
...
...
@@ -20,6 +20,7 @@
#include <asm/mmu_context.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
#include <asm/tlb.h>
/*
* Create a pte. Used during initialization only.
...
...
@@ -214,7 +215,7 @@ static inline void set_pp_bit(unsigned long pp, HPTE *addr)
__asm__
__volatile__
(
"1: ldarx %0,0,%3
\n
\
rldimi %0,%2,0,6
2
\n
\
rldimi %0,%2,0,6
1
\n
\
stdcx. %0,0,%3
\n
\
bne 1b"
:
"=&r"
(
old
),
"=m"
(
*
p
)
...
...
@@ -265,8 +266,6 @@ static long pSeries_hpte_updatepp(unsigned long slot, unsigned long newpp,
unsigned
long
vpn
,
avpn
;
unsigned
long
flags
;
udbg_printf
(
"updatepp
\n
"
);
if
(
large
)
vpn
=
va
>>
LARGE_PAGE_SHIFT
;
else
...
...
@@ -372,31 +371,32 @@ static void pSeries_flush_hash_range(unsigned long context,
{
unsigned
long
vsid
,
vpn
,
va
,
hash
,
secondary
,
slot
,
flags
,
avpn
;
int
i
,
j
;
unsigned
long
va_array
[
MAX_BATCH_FLUSH
];
HPTE
*
hptep
;
Hpte_dword0
dw0
;
struct
tlb_batch_data
*
ptes
=
&
tlb_batch_array
[
smp_processor_id
()][
0
];
struct
ppc64_tlb_batch
*
batch
=
&
ppc64_tlb_batch
[
smp_processor_id
()
];
/* XXX fix for large ptes */
unsigned
long
large
=
0
;
j
=
0
;
for
(
i
=
0
;
i
<
number
;
i
++
)
{
if
((
ptes
->
addr
>=
USER_START
)
&&
(
ptes
->
addr
<=
USER_END
))
vsid
=
get_vsid
(
context
,
ptes
->
addr
);
if
((
batch
->
addr
[
i
]
>=
USER_START
)
&&
(
batch
->
addr
[
i
]
<=
USER_END
))
vsid
=
get_vsid
(
context
,
batch
->
addr
[
i
]);
else
vsid
=
get_kernel_vsid
(
ptes
->
addr
);
vsid
=
get_kernel_vsid
(
batch
->
addr
[
i
]
);
va
=
(
vsid
<<
28
)
|
(
ptes
->
addr
&
0x0fffffff
);
va_array
[
j
]
=
va
;
va
=
(
vsid
<<
28
)
|
(
batch
->
addr
[
i
]
&
0x0fffffff
);
batch
->
vaddr
[
j
]
=
va
;
if
(
large
)
vpn
=
va
>>
LARGE_PAGE_SHIFT
;
else
vpn
=
va
>>
PAGE_SHIFT
;
hash
=
hpt_hash
(
vpn
,
large
);
secondary
=
(
pte_val
(
ptes
->
pte
)
&
_PAGE_SECONDARY
)
>>
15
;
secondary
=
(
pte_val
(
batch
->
pte
[
i
]
)
&
_PAGE_SECONDARY
)
>>
15
;
if
(
secondary
)
hash
=
~
hash
;
slot
=
(
hash
&
htab_data
.
htab_hash_mask
)
*
HPTES_PER_GROUP
;
slot
+=
(
pte_val
(
ptes
->
pte
)
&
_PAGE_GROUP_IX
)
>>
12
;
slot
+=
(
pte_val
(
batch
->
pte
[
i
]
)
&
_PAGE_GROUP_IX
)
>>
12
;
hptep
=
htab_data
.
htab
+
slot
;
avpn
=
vpn
>>
11
;
...
...
@@ -405,8 +405,6 @@ static void pSeries_flush_hash_range(unsigned long context,
dw0
=
hptep
->
dw0
.
dw0
;
ptes
++
;
if
((
dw0
.
avpn
!=
avpn
)
||
!
dw0
.
v
)
{
pSeries_unlock_hpte
(
hptep
);
udbg_printf
(
"invalidate missed
\n
"
);
...
...
@@ -426,7 +424,7 @@ static void pSeries_flush_hash_range(unsigned long context,
asm
volatile
(
"
\n
\
clrldi %0,%0,16
\n
\
tlbiel %0"
:
:
"r"
(
va_array
[
i
])
:
"memory"
);
:
:
"r"
(
batch
->
vaddr
[
i
])
:
"memory"
);
}
asm
volatile
(
"ptesync"
:::
"memory"
);
...
...
@@ -440,7 +438,7 @@ static void pSeries_flush_hash_range(unsigned long context,
asm
volatile
(
"
\n
\
clrldi %0,%0,16
\n
\
tlbie %0"
:
:
"r"
(
va_array
[
i
])
:
"memory"
);
:
:
"r"
(
batch
->
vaddr
[
i
])
:
"memory"
);
}
asm
volatile
(
"eieio; tlbsync; ptesync"
:::
"memory"
);
...
...
arch/ppc64/kernel/pSeries_lpar.c
View file @
c9195267
...
...
@@ -33,6 +33,7 @@
#include <linux/pci.h>
#include <asm/naca.h>
#include <asm/tlbflush.h>
#include <asm/tlb.h>
/* Status return values */
#define H_Success 0
...
...
@@ -646,11 +647,9 @@ static long pSeries_lpar_hpte_updatepp(unsigned long slot, unsigned long newpp,
{
unsigned
long
lpar_rc
;
unsigned
long
flags
;
flags
=
(
newpp
&
3
)
|
H_AVPN
;
flags
=
(
newpp
&
7
)
|
H_AVPN
;
unsigned
long
vpn
=
va
>>
PAGE_SHIFT
;
udbg_printf
(
"updatepp
\n
"
);
lpar_rc
=
plpar_pte_protect
(
flags
,
slot
,
(
vpn
>>
4
)
&
~
0x7fUL
);
if
(
lpar_rc
==
H_Not_Found
)
{
...
...
@@ -775,15 +774,14 @@ void pSeries_lpar_flush_hash_range(unsigned long context, unsigned long number,
int
local
)
{
int
i
;
struct
tlb_batch_data
*
ptes
=
&
tlb_batch_array
[
smp_processor_id
()][
0
];
unsigned
long
flags
;
struct
ppc64_tlb_batch
*
batch
=
&
ppc64_tlb_batch
[
smp_processor_id
()];
spin_lock_irqsave
(
&
pSeries_lpar_tlbie_lock
,
flags
);
for
(
i
=
0
;
i
<
number
;
i
++
)
{
flush_hash_page
(
context
,
ptes
->
addr
,
ptes
->
pte
,
local
);
ptes
++
;
}
for
(
i
=
0
;
i
<
number
;
i
++
)
flush_hash_page
(
context
,
batch
->
addr
[
i
],
batch
->
pte
[
i
],
local
)
;
spin_unlock_irqrestore
(
&
pSeries_lpar_tlbie_lock
,
flags
);
}
...
...
arch/ppc64/kernel/pSeries_pci.c
View file @
c9195267
...
...
@@ -22,7 +22,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/threads.h>
#include <linux/pci.h>
...
...
@@ -36,7 +35,6 @@
#include <asm/irq.h>
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/init.h>
#include <asm/pci-bridge.h>
#include <asm/ppcdebug.h>
#include <asm/naca.h>
...
...
@@ -71,7 +69,7 @@ static int s7a_workaround;
*
*****************************************************************************/
#define RTAS_PCI_READ_OP(size, type, nbytes) \
int
__chrp
\
int \
rtas_read_config_##size(struct device_node *dn, int offset, type val) { \
unsigned long returnval = ~0L; \
unsigned long buid; \
...
...
@@ -96,7 +94,7 @@ rtas_read_config_##size(struct device_node *dn, int offset, type val) { \
*val = returnval; \
return ret; \
} \
int
__chrp
\
int \
rtas_pci_read_config_##size(struct pci_dev *dev, int offset, type val) { \
struct device_node *dn = pci_device_to_OF_node(dev); \
int ret = rtas_read_config_##size(dn, offset, val); \
...
...
@@ -105,7 +103,7 @@ rtas_pci_read_config_##size(struct pci_dev *dev, int offset, type val) { \
}
#define RTAS_PCI_WRITE_OP(size, type, nbytes) \
int
__chrp
\
int \
rtas_write_config_##size(struct device_node *dn, int offset, type val) { \
unsigned long buid; \
unsigned int addr; \
...
...
@@ -126,7 +124,7 @@ rtas_write_config_##size(struct device_node *dn, int offset, type val) { \
} \
return ret; \
} \
int
__chrp
\
int \
rtas_pci_write_config_##size(struct pci_dev *dev, int offset, type val) { \
struct device_node* dn = pci_device_to_OF_node(dev); \
int ret = rtas_write_config_##size(dn, offset, val); \
...
...
arch/ppc64/kernel/pci_dn.c
View file @
c9195267
...
...
@@ -33,7 +33,6 @@
#include <asm/irq.h>
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/init.h>
#include <asm/pci-bridge.h>
#include <asm/ppcdebug.h>
#include <asm/naca.h>
...
...
arch/ppc64/kernel/ppc_asm.h
View file @
c9195267
...
...
@@ -11,8 +11,6 @@
* 2 of the License, or (at your option) any later version.
*/
#include <linux/config.h>
#include <asm/ppc_asm.tmpl>
#include "ppc_defs.h"
...
...
arch/ppc64/kernel/proc_pmc.c
View file @
c9195267
...
...
@@ -24,6 +24,10 @@
* End Change Activity
*/
#include <linux/config.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
#include <asm/proc_fs.h>
#include <asm/paca.h>
#include <asm/iSeries/ItLpPaca.h>
...
...
@@ -33,12 +37,10 @@
#include <asm/processor.h>
#include <asm/time.h>
#include <asm/iSeries/LparData.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
#include <asm/pmc.h>
#include <asm/uaccess.h>
#include <asm/naca.h>
#include <asm/rtas.h>
static
int
proc_pmc_control_mode
=
0
;
...
...
@@ -100,9 +102,9 @@ void proc_ppc64_init(void)
if
(
!
proc_ppc64_root
)
return
;
spin_unlock
(
&
proc_ppc64_lock
);
#ifdef CONFIG_PPC_EEH
eeh_init_proc
(
proc_ppc64_root
);
#endif
/* Placeholder for rtas interfaces. */
rtas_proc_dir
=
proc_mkdir
(
"rtas"
,
proc_ppc64_root
);
proc_ppc64_pmc_root
=
proc_mkdir
(
"pmc"
,
proc_ppc64_root
);
...
...
@@ -324,6 +326,7 @@ void pmc_proc_init(struct proc_dir_entry *iSeries_proc)
if
(
!
ent
)
return
;
ent
->
nlink
=
1
;
ent
->
data
=
(
void
*
)
0
;
ent
->
size
=
0
;
ent
->
read_proc
=
proc_get_titanTod
;
ent
->
write_proc
=
NULL
;
...
...
arch/ppc64/kernel/process.c
View file @
c9195267
...
...
@@ -44,8 +44,6 @@
#include <asm/machdep.h>
#include <asm/iSeries/HvCallHpt.h>
int
dump_fpu
(
struct
pt_regs
*
regs
,
elf_fpregset_t
*
fpregs
);
struct
task_struct
*
last_task_used_math
=
NULL
;
struct
mm_struct
ioremap_mm
=
{
pgd
:
ioremap_dir
...
...
arch/ppc64/kernel/prom.c
View file @
c9195267
...
...
@@ -48,7 +48,6 @@
#define call_yaboot(FUNC,...) do { ; } while (0)
#endif
#include <asm/init.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <asm/prom.h>
...
...
@@ -2110,7 +2109,7 @@ find_type_devices(const char *type)
/*
* Returns all nodes linked together
*/
struct
device_node
*
__openfirmware
struct
device_node
*
find_all_nodes
(
void
)
{
struct
device_node
*
head
,
**
prevp
,
*
np
;
...
...
@@ -2235,7 +2234,7 @@ get_property(struct device_node *np, const char *name, int *lenp)
/*
* Add a property to a node
*/
void
__openfirmware
void
prom_add_property
(
struct
device_node
*
np
,
struct
property
*
prop
)
{
struct
property
**
next
=
&
np
->
properties
;
...
...
@@ -2247,7 +2246,7 @@ prom_add_property(struct device_node* np, struct property* prop)
}
#if 0
void
__openfirmware
void
print_properties(struct device_node *np)
{
struct property *pp;
...
...
arch/ppc64/kernel/ptrace.c
View file @
c9195267
/*
* linux/arch/ppc/kernel/ptrace.c
* linux/arch/ppc
64
/kernel/ptrace.c
*
* PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
...
...
@@ -30,59 +30,13 @@
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/system.h>
/*
* Set of msr bits that gdb can change on behalf of a process.
*/
#define MSR_DEBUGCHANGE (MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1)
#include <asm/ptrace-common.h>
/*
* does not yet catch signals sent when the child dies.
* in exit.c or in signal.c.
*/
/*
* Get contents of register REGNO in task TASK.
*/
static
inline
unsigned
long
get_reg
(
struct
task_struct
*
task
,
int
regno
)
{
if
(
regno
<
sizeof
(
struct
pt_regs
)
/
sizeof
(
unsigned
long
))
return
((
unsigned
long
*
)
task
->
thread
.
regs
)[
regno
];
return
(
0
);
}
/*
* Write contents of register REGNO in task TASK.
*/
static
inline
int
put_reg
(
struct
task_struct
*
task
,
int
regno
,
unsigned
long
data
)
{
if
(
regno
<
PT_SOFTE
)
{
if
(
regno
==
PT_MSR
)
data
=
(
data
&
MSR_DEBUGCHANGE
)
|
(
task
->
thread
.
regs
->
msr
&
~
MSR_DEBUGCHANGE
);
((
unsigned
long
*
)
task
->
thread
.
regs
)[
regno
]
=
data
;
return
0
;
}
return
-
EIO
;
}
static
inline
void
set_single_step
(
struct
task_struct
*
task
)
{
struct
pt_regs
*
regs
=
task
->
thread
.
regs
;
if
(
regs
!=
NULL
)
regs
->
msr
|=
MSR_SE
;
}
static
inline
void
clear_single_step
(
struct
task_struct
*
task
)
{
struct
pt_regs
*
regs
=
task
->
thread
.
regs
;
if
(
regs
!=
NULL
)
regs
->
msr
&=
~
MSR_SE
;
}
/*
* Called by kernel/ptrace.c when detaching..
*
...
...
@@ -148,16 +102,17 @@ int sys_ptrace(long request, long pid, long addr, long data)
/* read the word at location addr in the USER area. */
case
PTRACE_PEEKUSR
:
{
unsigned
long
index
,
tmp
;
unsigned
long
index
;
unsigned
long
tmp
;
ret
=
-
EIO
;
/* convert to index and check */
index
=
(
unsigned
long
)
addr
>>
3
;
if
((
addr
&
7
)
||
index
>
PT_FPSCR
)
if
((
addr
&
7
)
||
(
index
>
PT_FPSCR
)
)
break
;
if
(
index
<
PT_FPR0
)
{
tmp
=
get_reg
(
child
,
(
int
)
index
);
tmp
=
get_reg
(
child
,
(
int
)
index
);
}
else
{
if
(
child
->
thread
.
regs
->
msr
&
MSR_FP
)
giveup_fpu
(
child
);
...
...
@@ -171,7 +126,8 @@ int sys_ptrace(long request, long pid, long addr, long data)
case
PTRACE_POKETEXT
:
/* write the word at location addr. */
case
PTRACE_POKEDATA
:
ret
=
0
;
if
(
access_process_vm
(
child
,
addr
,
&
data
,
sizeof
(
data
),
1
)
==
sizeof
(
data
))
if
(
access_process_vm
(
child
,
addr
,
&
data
,
sizeof
(
data
),
1
)
==
sizeof
(
data
))
break
;
ret
=
-
EIO
;
break
;
...
...
@@ -183,7 +139,7 @@ int sys_ptrace(long request, long pid, long addr, long data)
ret
=
-
EIO
;
/* convert to index and check */
index
=
(
unsigned
long
)
addr
>>
3
;
if
((
addr
&
7
)
||
index
>
PT_FPSCR
)
if
((
addr
&
7
)
||
(
index
>
PT_FPSCR
)
)
break
;
if
(
index
==
PT_ORIG_R3
)
...
...
@@ -216,11 +172,11 @@ int sys_ptrace(long request, long pid, long addr, long data)
break
;
}
/*
* make the child exit. Best I can do is send it a sigkill.
* perhaps it should be put in the status that it wants to
* exit.
*/
/*
* make the child exit. Best I can do is send it a sigkill.
* perhaps it should be put in the status that it wants to
* exit.
*/
case
PTRACE_KILL
:
{
ret
=
0
;
if
(
child
->
state
==
TASK_ZOMBIE
)
/* already dead */
...
...
@@ -249,56 +205,50 @@ int sys_ptrace(long request, long pid, long addr, long data)
ret
=
ptrace_detach
(
child
,
data
);
break
;
case
PPC_PTRACE_GETREGS
:
{
/* Get GPRs 0 - 31. */
case
PPC_PTRACE_GETREGS
:
{
/* Get GPRs 0 - 31. */
u64
tmp
;
u64
cntr
;
ret
=
0
;
for
(
cntr
=
0
;
cntr
<
32
&&
ret
==
0
;
++
cntr
)
{
for
(
cntr
=
0
;
cntr
<
32
&&
ret
==
0
;
++
cntr
)
{
tmp
=
((
u64
*
)
child
->
thread
.
regs
)[
cntr
];
ret
=
put_user
(
tmp
,
(
u64
*
)(
data
+
cntr
));
}
break
;
}
case
PPC_PTRACE_SETREGS
:
{
/* Set GPRs 0 - 31. */
case
PPC_PTRACE_SETREGS
:
{
/* Set GPRs 0 - 31. */
u64
cntr
;
ret
=
0
;
for
(
cntr
=
0
;
cntr
<
32
&&
ret
==
0
;
++
cntr
)
{
ret
=
put_reg
(
child
,
cntr
,
*
(
u64
*
)(
data
+
cntr
));
}
break
;
}
case
PPC_PTRACE_GETFPREGS
:
{
/* Get FPRs 0 - 31. */
case
PPC_PTRACE_GETFPREGS
:
{
/* Get FPRs 0 - 31. */
u64
tmp
;
u64
cntr
;
ret
=
-
EIO
;
if
(
child
->
thread
.
regs
->
msr
&
MSR_FP
)
giveup_fpu
(
child
);
ret
=
0
;
for
(
cntr
=
0
;
cntr
<
32
&&
ret
==
0
;
++
cntr
)
{
for
(
cntr
=
0
;
cntr
<
32
&&
ret
==
0
;
++
cntr
)
{
tmp
=
((
u64
*
)
child
->
thread
.
fpr
)[
cntr
];
ret
=
put_user
(
tmp
,
(
u64
*
)(
data
+
cntr
));
}
break
;
}
case
PPC_PTRACE_SETFPREGS
:
{
/* Get FPRs 0 - 31. */
case
PPC_PTRACE_SETFPREGS
:
{
/* Get FPRs 0 - 31. */
u64
cntr
;
ret
=
-
EIO
;
if
(
child
->
thread
.
regs
->
msr
&
MSR_FP
)
giveup_fpu
(
child
);
for
(
cntr
=
0
;
cntr
<
32
;
++
cntr
)
{
((
u64
*
)
child
->
thread
.
fpr
)[
cntr
]
=
*
(
u64
*
)(
data
+
cntr
);
}
ret
=
0
;
break
;
}
...
...
@@ -334,4 +284,3 @@ void do_syscall_trace(void)
current
->
exit_code
=
0
;
}
}
arch/ppc64/kernel/ptrace32.c
View file @
c9195267
/*
* linux/arch/ppc/kernel/ptrace32.c
* linux/arch/ppc
64
/kernel/ptrace32.c
*
* PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
...
...
@@ -30,64 +30,18 @@
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/system.h>
/*
* Set of msr bits that gdb can change on behalf of a process.
*/
#define MSR_DEBUGCHANGE (MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1)
#include <asm/ptrace-common.h>
/*
* does not yet catch signals sent when the child dies.
* in exit.c or in signal.c.
*/
/*
* Get contents of register REGNO in task TASK.
*/
static
inline
unsigned
long
get_reg
(
struct
task_struct
*
task
,
int
regno
)
{
if
(
regno
<
sizeof
(
struct
pt_regs
)
/
sizeof
(
unsigned
long
))
return
((
unsigned
long
*
)
task
->
thread
.
regs
)[
regno
];
return
(
0
);
}
/*
* Write contents of register REGNO in task TASK.
* (Put DATA into task TASK's register REGNO.)
*/
static
inline
int
put_reg
(
struct
task_struct
*
task
,
int
regno
,
unsigned
long
data
)
{
if
(
regno
<
PT_SOFTE
)
{
if
(
regno
==
PT_MSR
)
data
=
(
data
&
MSR_DEBUGCHANGE
)
|
(
task
->
thread
.
regs
->
msr
&
~
MSR_DEBUGCHANGE
);
((
unsigned
long
*
)
task
->
thread
.
regs
)[
regno
]
=
data
;
return
0
;
}
return
-
EIO
;
}
static
inline
void
set_single_step
(
struct
task_struct
*
task
)
{
struct
pt_regs
*
regs
=
task
->
thread
.
regs
;
if
(
regs
!=
NULL
)
regs
->
msr
|=
MSR_SE
;
}
static
inline
void
clear_single_step
(
struct
task_struct
*
task
)
{
struct
pt_regs
*
regs
=
task
->
thread
.
regs
;
if
(
regs
!=
NULL
)
regs
->
msr
&=
~
MSR_SE
;
}
int
sys32_ptrace
(
long
request
,
long
pid
,
unsigned
long
addr
,
unsigned
long
data
)
{
struct
task_struct
*
child
;
int
ret
=
-
EPERM
;
int
ret
=
-
EPERM
;
lock_kernel
();
if
(
request
==
PTRACE_TRACEME
)
{
/* are we already being traced? */
...
...
@@ -120,92 +74,95 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
if
(
ret
<
0
)
goto
out_tsk
;
switch
(
request
)
{
/* Read word at location ADDR */
switch
(
request
)
{
/* when I and D space are separate, these will need to be fixed. */
case
PTRACE_PEEKTEXT
:
/* read word at location addr. */
case
PTRACE_PEEKDATA
:
{
unsigned
int
tmp_mem_value
;
case
PTRACE_PEEKDATA
:
{
unsigned
int
tmp
;
int
copied
;
copied
=
access_process_vm
(
child
,
addr
,
&
tmp
_mem_value
,
sizeof
(
tmp_mem_value
),
0
);
copied
=
access_process_vm
(
child
,
addr
,
&
tmp
,
sizeof
(
tmp
),
0
);
ret
=
-
EIO
;
if
(
copied
!=
sizeof
(
tmp
_mem_value
))
if
(
copied
!=
sizeof
(
tmp
))
break
;
ret
=
put_user
(
tmp
_mem_value
,
(
u32
*
)
data
);
// copy 4 bytes of data into the user location specified by the 8 byte pointer in "data".
ret
=
put_user
(
tmp
,
(
u32
*
)
data
);
break
;
}
/* Read 4 bytes of the other process' storage */
/* data is a pointer specifying where the user wants the 4 bytes copied into */
/* addr is a pointer in the user's storage that contains an 8 byte address in the other process of the 4 bytes that is to be read */
/* (this is run in a 32-bit process looking at a 64-bit process) */
/* when I and D space are separate, these will need to be fixed. */
/*
* Read 4 bytes of the other process' storage
* data is a pointer specifying where the user wants the
* 4 bytes copied into
* addr is a pointer in the user's storage that contains an 8 byte
* address in the other process of the 4 bytes that is to be read
* (this is run in a 32-bit process looking at a 64-bit process)
* when I and D space are separate, these will need to be fixed.
*/
case
PPC_PTRACE_PEEKTEXT_3264
:
case
PPC_PTRACE_PEEKDATA_3264
:
{
u32
tmp_mem_value
;
int
copied
;
case
PPC_PTRACE_PEEKDATA_3264
:
{
u32
tmp
;
int
copied
;
u32
*
addrOthers
;
ret
=
-
EIO
;
/* Get the addr in the other process that we want to read */
if
(
get_user
(
addrOthers
,(
u32
**
)
addr
)
!=
0
)
if
(
get_user
(
addrOthers
,
(
u32
**
)
addr
)
!=
0
)
break
;
copied
=
access_process_vm
(
child
,
(
u64
)
addrOthers
,
&
tmp_mem_value
,
sizeof
(
tmp_mem_value
),
0
);
if
(
copied
!=
sizeof
(
tmp_mem_value
))
copied
=
access_process_vm
(
child
,
(
u64
)
addrOthers
,
&
tmp
,
sizeof
(
tmp
),
0
);
if
(
copied
!=
sizeof
(
tmp
))
break
;
ret
=
put_user
(
tmp
_mem_value
,
(
u32
*
)
data
);
// copy 4 bytes of data into the user location specified by the 8 byte pointer in "data".
ret
=
put_user
(
tmp
,
(
u32
*
)
data
);
break
;
}
/* Read a register (specified by ADDR) out of the "user area" */
case
PTRACE_PEEKUSR
:
{
int
index
;
unsigned
int
reg32bits
;
unsigned
long
tmp_reg_value
;
unsigned
long
tmp
;
ret
=
-
EIO
;
/* convert to index and check */
index
=
(
unsigned
long
)
addr
>>
2
;
if
((
addr
&
3
)
||
index
>
PT_FPSCR32
)
if
((
addr
&
3
)
||
(
index
>
PT_FPSCR32
)
)
break
;
if
(
index
<
PT_FPR0
)
{
tmp
_reg_value
=
get_reg
(
child
,
index
);
tmp
=
get_reg
(
child
,
index
);
}
else
{
if
(
child
->
thread
.
regs
->
msr
&
MSR_FP
)
giveup_fpu
(
child
);
/* the user space code considers the floating point to be
* an array of unsigned int (32 bits) - the index passed
* in is based on this assumption.
/*
* the user space code considers the floating point
* to be an array of unsigned int (32 bits) - the
* index passed in is based on this assumption.
*/
tmp
_reg_value
=
((
unsigned
int
*
)
child
->
thread
.
fpr
)[
index
-
PT_FPR0
];
tmp
=
((
unsigned
int
*
)
child
->
thread
.
fpr
)[
index
-
PT_FPR0
];
}
reg32bits
=
tmp_reg_value
;
ret
=
put_user
(
reg32bits
,
(
u32
*
)
data
);
// copy 4 bytes of data into the user location specified by the 8 byte pointer in "data".
ret
=
put_user
((
unsigned
int
)
tmp
,
(
u32
*
)
data
);
break
;
}
/* Read 4 bytes out of the other process' pt_regs area */
/* data is a pointer specifying where the user wants the 4 bytes copied into */
/* addr is the offset into the other process' pt_regs structure that is to be read */
/* (this is run in a 32-bit process looking at a 64-bit process) */
case
PPC_PTRACE_PEEKUSR_3264
:
{
/*
* Read 4 bytes out of the other process' pt_regs area
* data is a pointer specifying where the user wants the
* 4 bytes copied into
* addr is the offset into the other process' pt_regs structure
* that is to be read
* (this is run in a 32-bit process looking at a 64-bit process)
*/
case
PPC_PTRACE_PEEKUSR_3264
:
{
u32
index
;
u32
reg32bits
;
u64
tmp
_reg_value
;
u64
tmp
;
u32
numReg
;
u32
part
;
ret
=
-
EIO
;
/* Determine which register the user wants */
index
=
(
u64
)
addr
>>
2
;
/* Divide addr by 4 */
index
=
(
u64
)
addr
>>
2
;
numReg
=
index
/
2
;
/* Determine which part of the register the user wants */
if
(
index
%
2
)
...
...
@@ -217,117 +174,120 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
if
((
addr
&
3
)
||
numReg
>
PT_FPSCR
)
break
;
if
(
numReg
>=
PT_FPR0
)
{
if
(
numReg
>=
PT_FPR0
)
{
if
(
child
->
thread
.
regs
->
msr
&
MSR_FP
)
giveup_fpu
(
child
);
}
tmp_reg_value
=
get_reg
(
child
,
numReg
);
reg32bits
=
((
u32
*
)
&
tmp_reg_value
)[
part
];
ret
=
put_user
(
reg32bits
,
(
u32
*
)
data
);
/* copy 4 bytes of data into the user location specified by the 8 byte pointer in "data". */
if
(
numReg
==
PT_FPSCR
)
tmp
=
((
unsigned
int
*
)
child
->
thread
.
fpscr
);
else
tmp
=
((
unsigned
long
int
*
)
child
->
thread
.
fpr
)[
numReg
-
PT_FPR0
];
}
else
{
/* register within PT_REGS struct */
tmp
=
get_reg
(
child
,
numReg
);
}
reg32bits
=
((
u32
*
)
&
tmp
)[
part
];
ret
=
put_user
(
reg32bits
,
(
u32
*
)
data
);
break
;
}
/* Write the word at location ADDR */
/* If I and D space are separate, this will have to be fixed. */
case
PTRACE_POKETEXT
:
/* write the word at location addr. */
case
PTRACE_POKEDATA
:
{
unsigned
int
tmp
_value_to_write
;
tmp
_value_to_write
=
data
;
unsigned
int
tmp
;
tmp
=
data
;
ret
=
0
;
if
(
access_process_vm
(
child
,
addr
,
&
tmp_value_to_write
,
sizeof
(
tmp_value_to_write
),
1
)
==
sizeof
(
tmp_value_to_write
))
if
(
access_process_vm
(
child
,
addr
,
&
tmp
,
sizeof
(
tmp
),
1
)
==
sizeof
(
tmp
))
break
;
ret
=
-
EIO
;
break
;
}
/* Write 4 bytes into the other process' storage */
/* data is the 4 bytes that the user wants written */
/* addr is a pointer in the user's storage that contains an 8 byte address in the other process where the 4 bytes that is to be written */
/* (this is run in a 32-bit process looking at a 64-bit process) */
/* when I and D space are separate, these will need to be fixed. */
/*
* Write 4 bytes into the other process' storage
* data is the 4 bytes that the user wants written
* addr is a pointer in the user's storage that contains an
* 8 byte address in the other process where the 4 bytes
* that is to be written
* (this is run in a 32-bit process looking at a 64-bit process)
* when I and D space are separate, these will need to be fixed.
*/
case
PPC_PTRACE_POKETEXT_3264
:
case
PPC_PTRACE_POKEDATA_3264
:
{
u32
tmp_value_to_write
=
data
;
case
PPC_PTRACE_POKEDATA_3264
:
{
u32
tmp
=
data
;
u32
*
addrOthers
;
int
bytesWritten
;
/* Get the addr in the other process that we want to write into */
ret
=
-
EIO
;
if
(
get_user
(
addrOthers
,(
u32
**
)
addr
)
!=
0
)
if
(
get_user
(
addrOthers
,
(
u32
**
)
addr
)
!=
0
)
break
;
ret
=
0
;
bytesWritten
=
access_process_vm
(
child
,
(
u64
)
addrOthers
,
&
tmp_value_to_write
,
sizeof
(
tmp_value_to_write
),
1
);
if
(
bytesWritten
==
sizeof
(
tmp_value_to_write
))
if
(
access_process_vm
(
child
,
(
u64
)
addrOthers
,
&
tmp
,
sizeof
(
tmp
),
1
)
==
sizeof
(
tmp
))
break
;
ret
=
-
EIO
;
break
;
}
/*
Write DATA into location ADDR within the USER area
*/
/*
write the word at location addr in the USER area
*/
case
PTRACE_POKEUSR
:
{
unsigned
long
index
;
ret
=
-
EIO
;
/* convert to index and check */
index
=
(
unsigned
long
)
addr
>>
2
;
if
((
addr
&
3
)
||
index
>
PT_FPSCR32
)
if
((
addr
&
3
)
||
(
index
>
PT_FPSCR32
)
)
break
;
if
(
index
==
PT_ORIG_R3
)
break
;
if
(
index
<
PT_FPR0
)
{
ret
=
put_reg
(
child
,
index
,
data
);
}
else
{
if
(
child
->
thread
.
regs
->
msr
&
MSR_FP
)
giveup_fpu
(
child
);
/* the user space code considers the floating point to be
* an array of unsigned int (32 bits) - the index passed
* in is based on this assumption.
*/
/*
* the user space code considers the floating point
* to be an array of unsigned int (32 bits) - the
* index passed in is based on this assumption.
*/
((
unsigned
int
*
)
child
->
thread
.
fpr
)[
index
-
PT_FPR0
]
=
data
;
ret
=
0
;
}
break
;
}
/* Write 4 bytes into the other process' pt_regs area */
/* data is the 4 bytes that the user wants written */
/* addr is the offset into the other process' pt_regs structure that is to be written into */
/* (this is run in a 32-bit process looking at a 64-bit process) */
case
PPC_PTRACE_POKEUSR_3264
:
{
/*
* Write 4 bytes into the other process' pt_regs area
* data is the 4 bytes that the user wants written
* addr is the offset into the other process' pt_regs structure
* that is to be written into
* (this is run in a 32-bit process looking at a 64-bit process)
*/
case
PPC_PTRACE_POKEUSR_3264
:
{
u32
index
;
u32
numReg
;
ret
=
-
EIO
;
/* Determine which register the user wants */
index
=
(
u64
)
addr
>>
2
;
/* Divide addr by 4 */
index
=
(
u64
)
addr
>>
2
;
numReg
=
index
/
2
;
/* Validate the input - check to see if address is on the wrong boundary or beyond the end of the user area */
if
((
addr
&
3
)
||
numReg
>
PT_FPSCR
)
/*
* Validate the input - check to see if address is on the
* wrong boundary or beyond the end of the user area
*/
if
((
addr
&
3
)
||
(
numReg
>
PT_FPSCR
))
break
;
/* Insure it is a register we let them change */
if
((
numReg
==
PT_ORIG_R3
)
||
((
numReg
>
PT_CCR
)
&&
(
numReg
<
PT_FPR0
)))
if
((
numReg
==
PT_ORIG_R3
)
||
((
numReg
>
PT_CCR
)
&&
(
numReg
<
PT_FPR0
)))
break
;
if
(
numReg
>=
PT_FPR0
)
{
if
(
numReg
>=
PT_FPR0
)
{
if
(
child
->
thread
.
regs
->
msr
&
MSR_FP
)
giveup_fpu
(
child
);
}
if
(
numReg
==
PT_MSR
)
data
=
(
data
&
MSR_DEBUGCHANGE
)
|
(
child
->
thread
.
regs
->
msr
&
~
MSR_DEBUGCHANGE
);
data
=
(
data
&
MSR_DEBUGCHANGE
)
|
(
child
->
thread
.
regs
->
msr
&
~
MSR_DEBUGCHANGE
);
((
u32
*
)
child
->
thread
.
regs
)[
index
]
=
data
;
ret
=
0
;
break
;
...
...
@@ -351,8 +311,8 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
}
/*
* make the child exit. Best I can do is send it a sigkill.
* perhaps it should be put in the status that it wants to
* make the child exit. Best I can do is send it a sigkill.
* perhaps it should be put in the status that it wants to
* exit.
*/
case
PTRACE_KILL
:
{
...
...
arch/ppc64/kernel/rtas.c
View file @
c9195267
...
...
@@ -16,15 +16,19 @@
#include <linux/types.h>
#include <linux/spinlock.h>
#include <asm/init.h>
#include <asm/prom.h>
#include <asm/rtas.h>
#include <asm/semaphore.h>
#include <asm/machdep.h>
#include <asm/paca.h>
#include <asm/page.h>
#include <asm/system.h>
#include <asm/abs_addr.h>
#include <asm/udbg.h>
struct
proc_dir_entry
*
rtas_proc_dir
;
/* /proc/ppc64/rtas dir */
struct
flash_block_list_header
rtas_firmware_flash_list
=
{
0
,
0
};
/*
* prom_init() is called very early on, before the kernel text
* and data have been mapped to KERNELBASE. At this point the code
...
...
@@ -105,7 +109,6 @@ call_rtas_display_status(char c)
#if 0
#define DEBUG_RTAS
#endif
__openfirmware
int
rtas_token
(
const
char
*
service
)
{
...
...
@@ -120,7 +123,6 @@ rtas_token(const char *service)
return
tokp
?
*
tokp
:
RTAS_UNKNOWN_SERVICE
;
}
__openfirmware
long
rtas_call
(
int
token
,
int
nargs
,
int
nret
,
unsigned
long
*
outputs
,
...)
...
...
@@ -184,25 +186,107 @@ rtas_call(int token, int nargs, int nret,
return
(
ulong
)((
nret
>
0
)
?
rtas_args
->
rets
[
0
]
:
0
);
}
void
__chrp
#define FLASH_BLOCK_LIST_VERSION (1UL)
static
void
rtas_flash_firmware
(
void
)
{
unsigned
long
image_size
;
struct
flash_block_list
*
f
,
*
next
,
*
flist
;
unsigned
long
rtas_block_list
;
int
i
,
status
,
update_token
;
update_token
=
rtas_token
(
"ibm,update-flash-64-and-reboot"
);
if
(
update_token
==
RTAS_UNKNOWN_SERVICE
)
{
printk
(
KERN_ALERT
"FLASH: ibm,update-flash-64-and-reboot is not available -- not a service partition?
\n
"
);
printk
(
KERN_ALERT
"FLASH: firmware will not be flashed
\n
"
);
return
;
}
/* NOTE: the "first" block list is a global var with no data
* blocks in the kernel data segment. We do this because
* we want to ensure this block_list addr is under 4GB.
*/
rtas_firmware_flash_list
.
num_blocks
=
0
;
flist
=
(
struct
flash_block_list
*
)
&
rtas_firmware_flash_list
;
rtas_block_list
=
virt_to_absolute
((
unsigned
long
)
flist
);
if
(
rtas_block_list
>=
(
4UL
<<
20
))
{
printk
(
KERN_ALERT
"FLASH: kernel bug...flash list header addr above 4GB
\n
"
);
return
;
}
printk
(
KERN_ALERT
"FLASH: preparing saved firmware image for flash
\n
"
);
/* Update the block_list in place. */
image_size
=
0
;
for
(
f
=
flist
;
f
;
f
=
next
)
{
/* Translate data addrs to absolute */
for
(
i
=
0
;
i
<
f
->
num_blocks
;
i
++
)
{
f
->
blocks
[
i
].
data
=
(
char
*
)
virt_to_absolute
((
unsigned
long
)
f
->
blocks
[
i
].
data
);
image_size
+=
f
->
blocks
[
i
].
length
;
}
next
=
f
->
next
;
f
->
next
=
(
struct
flash_block_list
*
)
virt_to_absolute
((
unsigned
long
)
f
->
next
);
/* make num_blocks into the version/length field */
f
->
num_blocks
=
(
FLASH_BLOCK_LIST_VERSION
<<
56
)
|
((
f
->
num_blocks
+
1
)
*
16
);
}
printk
(
KERN_ALERT
"FLASH: flash image is %ld bytes
\n
"
,
image_size
);
printk
(
KERN_ALERT
"FLASH: performing flash and reboot
\n
"
);
ppc_md
.
progress
(
"Flashing
\n
"
,
0x0
);
ppc_md
.
progress
(
"Please Wait... "
,
0x0
);
printk
(
KERN_ALERT
"FLASH: this will take several minutes. Do not power off!
\n
"
);
status
=
rtas_call
(
update_token
,
1
,
1
,
NULL
,
rtas_block_list
);
switch
(
status
)
{
/* should only get "bad" status */
case
0
:
printk
(
KERN_ALERT
"FLASH: success
\n
"
);
break
;
case
-
1
:
printk
(
KERN_ALERT
"FLASH: hardware error. Firmware may not be not flashed
\n
"
);
break
;
case
-
3
:
printk
(
KERN_ALERT
"FLASH: image is corrupt or not correct for this platform. Firmware not flashed
\n
"
);
break
;
case
-
4
:
printk
(
KERN_ALERT
"FLASH: flash failed when partially complete. System may not reboot
\n
"
);
break
;
default:
printk
(
KERN_ALERT
"FLASH: unknown flash return code %d
\n
"
,
status
);
break
;
}
}
void
rtas_flash_bypass_warning
(
void
)
{
printk
(
KERN_ALERT
"FLASH: firmware flash requires a reboot
\n
"
);
printk
(
KERN_ALERT
"FLASH: the firmware image will NOT be flashed
\n
"
);
}
void
rtas_restart
(
char
*
cmd
)
{
if
(
rtas_firmware_flash_list
.
next
)
rtas_flash_firmware
();
printk
(
"RTAS system-reboot returned %ld
\n
"
,
rtas_call
(
rtas_token
(
"system-reboot"
),
0
,
1
,
NULL
));
for
(;;);
}
void
__chrp
void
rtas_power_off
(
void
)
{
if
(
rtas_firmware_flash_list
.
next
)
rtas_flash_bypass_warning
();
/* allow power on only with power button press */
printk
(
"RTAS power-off returned %ld
\n
"
,
rtas_call
(
rtas_token
(
"power-off"
),
2
,
1
,
NULL
,
0xffffffff
,
0xffffffff
));
for
(;;);
}
void
__chrp
void
rtas_halt
(
void
)
{
if
(
rtas_firmware_flash_list
.
next
)
rtas_flash_bypass_warning
();
rtas_power_off
();
}
arch/ppc64/kernel/rtas_flash.c
0 → 100644
View file @
c9195267
/*
* c 2001 PPC 64 Team, IBM Corp
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* /proc/ppc64/rtas/firmware_flash interface
*
* This file implements a firmware_flash interface to pump a firmware
* image into the kernel. At reboot time rtas_restart() will see the
* firmware image and flash it as it reboots (see rtas.c).
*/
#include <linux/module.h>
#include <linux/config.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/rtas.h>
#define MODULE_VERSION "1.0"
#define MODULE_NAME "rtas_flash"
#define FIRMWARE_FLASH_NAME "firmware_flash"
/* Local copy of the flash block list.
* We only allow one open of the flash proc file and create this
* list as we go. This list will be put in the kernel's
* rtas_firmware_flash_list global var once it is fully read.
*
* For convenience as we build the list we use virtual addrs,
* we do not fill in the version number, and the length field
* is treated as the number of entries currently in the block
* (i.e. not a byte count). This is all fixed on release.
*/
static
struct
flash_block_list
*
flist
;
static
char
*
flash_msg
;
static
int
flash_possible
;
static
int
rtas_flash_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
if
((
file
->
f_mode
&
FMODE_WRITE
)
&&
flash_possible
)
{
if
(
flist
)
return
-
EBUSY
;
flist
=
(
struct
flash_block_list
*
)
get_free_page
(
GFP_KERNEL
);
if
(
!
flist
)
return
-
ENOMEM
;
}
return
0
;
}
/* Do simple sanity checks on the flash image. */
static
int
flash_list_valid
(
struct
flash_block_list
*
flist
)
{
struct
flash_block_list
*
f
;
int
i
;
unsigned
long
block_size
,
image_size
;
flash_msg
=
NULL
;
/* Paranoid self test here. We also collect the image size. */
image_size
=
0
;
for
(
f
=
flist
;
f
;
f
=
f
->
next
)
{
for
(
i
=
0
;
i
<
f
->
num_blocks
;
i
++
)
{
if
(
f
->
blocks
[
i
].
data
==
NULL
)
{
flash_msg
=
"error: internal error null data
\n
"
;
return
0
;
}
block_size
=
f
->
blocks
[
i
].
length
;
if
(
block_size
<=
0
||
block_size
>
PAGE_SIZE
)
{
flash_msg
=
"error: internal error bad length
\n
"
;
return
0
;
}
image_size
+=
block_size
;
}
}
if
(
image_size
<
(
256
<<
10
))
{
if
(
image_size
<
2
)
flash_msg
=
NULL
;
/* allow "clear" of image */
else
flash_msg
=
"error: flash image short
\n
"
;
return
0
;
}
printk
(
KERN_INFO
"FLASH: flash image with %ld bytes stored for hardware flash on reboot
\n
"
,
image_size
);
return
1
;
}
static
void
free_flash_list
(
struct
flash_block_list
*
f
)
{
struct
flash_block_list
*
next
;
int
i
;
while
(
f
)
{
for
(
i
=
0
;
i
<
f
->
num_blocks
;
i
++
)
free_page
((
unsigned
long
)(
f
->
blocks
[
i
].
data
));
next
=
f
->
next
;
free_page
((
unsigned
long
)
f
);
f
=
next
;
}
}
static
int
rtas_flash_release
(
struct
inode
*
inode
,
struct
file
*
file
)
{
if
(
flist
)
{
/* Always clear saved list on a new attempt. */
if
(
rtas_firmware_flash_list
.
next
)
{
free_flash_list
(
rtas_firmware_flash_list
.
next
);
rtas_firmware_flash_list
.
next
=
NULL
;
}
if
(
flash_list_valid
(
flist
))
rtas_firmware_flash_list
.
next
=
flist
;
else
free_flash_list
(
flist
);
flist
=
NULL
;
}
return
0
;
}
/* Reading the proc file will show status (not the firmware contents) */
static
ssize_t
rtas_flash_read
(
struct
file
*
file
,
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
int
error
;
char
*
msg
;
int
msglen
;
if
(
!
flash_possible
)
{
msg
=
"error: this partition does not have service authority
\n
"
;
}
else
if
(
flist
)
{
msg
=
"info: this file is busy for write by some process
\n
"
;
}
else
if
(
flash_msg
)
{
msg
=
flash_msg
;
/* message from last flash attempt */
}
else
if
(
rtas_firmware_flash_list
.
next
)
{
msg
=
"ready: firmware image ready for flash on reboot
\n
"
;
}
else
{
msg
=
"info: no firmware image for flash
\n
"
;
}
msglen
=
strlen
(
msg
);
if
(
msglen
>
count
)
msglen
=
count
;
if
(
ppos
&&
*
ppos
!=
0
)
return
0
;
/* be cheap */
error
=
verify_area
(
VERIFY_WRITE
,
buf
,
msglen
);
if
(
error
)
return
-
EINVAL
;
copy_to_user
(
buf
,
msg
,
msglen
);
if
(
ppos
)
*
ppos
=
msglen
;
return
msglen
;
}
/* We could be much more efficient here. But to keep this function
* simple we allocate a page to the block list no matter how small the
* count is. If the system is low on memory it will be just as well
* that we fail....
*/
static
ssize_t
rtas_flash_write
(
struct
file
*
file
,
const
char
*
buffer
,
size_t
count
,
loff_t
*
off
)
{
size_t
len
=
count
;
char
*
p
;
int
next_free
;
struct
flash_block_list
*
fl
=
flist
;
if
(
!
flash_possible
||
len
==
0
)
return
len
;
/* discard data */
while
(
fl
->
next
)
fl
=
fl
->
next
;
/* seek to last block_list for append */
next_free
=
fl
->
num_blocks
;
if
(
next_free
==
FLASH_BLOCKS_PER_NODE
)
{
/* Need to allocate another block_list */
fl
->
next
=
(
struct
flash_block_list
*
)
get_free_page
(
GFP_KERNEL
);
if
(
!
fl
->
next
)
return
-
ENOMEM
;
fl
=
fl
->
next
;
next_free
=
0
;
}
if
(
len
>
PAGE_SIZE
)
len
=
PAGE_SIZE
;
p
=
(
char
*
)
get_free_page
(
GFP_KERNEL
);
if
(
!
p
)
return
-
ENOMEM
;
if
(
copy_from_user
(
p
,
buffer
,
len
))
{
free_page
((
unsigned
long
)
p
);
return
-
EFAULT
;
}
fl
->
blocks
[
next_free
].
data
=
p
;
fl
->
blocks
[
next_free
].
length
=
len
;
fl
->
num_blocks
++
;
return
len
;
}
static
struct
file_operations
rtas_flash_operations
=
{
read:
rtas_flash_read
,
write:
rtas_flash_write
,
open:
rtas_flash_open
,
release:
rtas_flash_release
,
};
int
__init
rtas_flash_init
(
void
)
{
struct
proc_dir_entry
*
ent
=
NULL
;
if
(
!
rtas_proc_dir
)
{
printk
(
KERN_WARNING
"rtas proc dir does not already exist"
);
return
-
ENOENT
;
}
if
(
rtas_token
(
"ibm,update-flash-64-and-reboot"
)
!=
RTAS_UNKNOWN_SERVICE
)
flash_possible
=
1
;
if
((
ent
=
create_proc_entry
(
FIRMWARE_FLASH_NAME
,
S_IRUSR
|
S_IWUSR
,
rtas_proc_dir
))
!=
NULL
)
{
ent
->
nlink
=
1
;
ent
->
proc_fops
=
&
rtas_flash_operations
;
ent
->
owner
=
THIS_MODULE
;
}
return
0
;
}
void
__exit
rtas_flash_cleanup
(
void
)
{
if
(
!
rtas_proc_dir
)
return
;
remove_proc_entry
(
FIRMWARE_FLASH_NAME
,
rtas_proc_dir
);
}
module_init
(
rtas_flash_init
);
module_exit
(
rtas_flash_cleanup
);
MODULE_LICENSE
(
"GPL"
);
arch/ppc64/kernel/setup.c
View file @
c9195267
...
...
@@ -23,7 +23,6 @@
#include <linux/ioport.h>
#include <linux/tty.h>
#include <linux/root_dev.h>
#include <asm/init.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/processor.h>
...
...
@@ -43,9 +42,6 @@ extern unsigned long klimit;
extern
HTAB
htab_data
;
extern
unsigned
long
loops_per_jiffy
;
extern
unsigned
long
embedded_sysmap_start
;
extern
unsigned
long
embedded_sysmap_end
;
int
have_of
=
1
;
extern
void
chrp_init
(
unsigned
long
r3
,
...
...
@@ -54,7 +50,6 @@ extern void chrp_init(unsigned long r3,
unsigned
long
r6
,
unsigned
long
r7
);
extern
void
chrp_init_map_io_space
(
void
);
extern
void
iSeries_init
(
void
);
extern
void
iSeries_init_early
(
void
);
extern
void
pSeries_init_early
(
void
);
...
...
@@ -338,7 +333,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
if
(
ppc_md
.
setup_residual
!=
NULL
)
ppc_md
.
setup_residual
(
m
,
cpu_id
);
seq_printf
(
m
,
"revision
\t
: %hd.%hd
\n
"
,
maj
,
min
);
seq_printf
(
m
,
"revision
\t
: %hd.%hd
\n
\n
"
,
maj
,
min
);
return
0
;
}
...
...
@@ -499,6 +494,7 @@ void __init ppc64_calibrate_delay(void)
}
extern
void
(
*
calibrate_delay
)(
void
);
extern
void
sort_exception_table
(
void
);
/*
* Called into from start_kernel, after lock_kernel has been called.
...
...
arch/ppc64/kernel/signal.c
View file @
c9195267
...
...
@@ -26,8 +26,6 @@
#include <linux/unistd.h>
#include <linux/stddef.h>
#include <linux/elf.h>
#include <linux/tty.h>
#include <linux/binfmts.h>
#include <asm/ppc32.h>
#include <asm/sigcontext.h>
#include <asm/ucontext.h>
...
...
@@ -59,9 +57,36 @@
*/
#define MSR_USERCHANGE (MSR_FE0 | MSR_FE1)
int
do_signal
(
sigset_t
*
oldset
,
struct
pt_regs
*
regs
);
extern
long
sys_wait4
(
pid_t
pid
,
unsigned
int
*
stat_addr
,
int
options
,
/*unsigned long*/
struct
rusage
*
ru
);
/*
* When we have signals to deliver, we set up on the
* user stack, going down from the original stack pointer:
* a sigregs struct
* one or more sigcontext structs with
* a gap of __SIGNAL_FRAMESIZE bytes
*
* Each of these things must be a multiple of 16 bytes in size.
*
*/
struct
sigregs
{
elf_gregset_t
gp_regs
;
double
fp_regs
[
ELF_NFPREG
];
unsigned
int
tramp
[
2
];
/* 64 bit API allows for 288 bytes below sp before
decrementing it. */
int
abigap
[
72
];
};
struct
rt_sigframe
{
unsigned
long
_unused
[
2
];
struct
siginfo
*
pinfo
;
void
*
puc
;
struct
siginfo
info
;
struct
ucontext
uc
;
};
extern
int
do_signal
(
sigset_t
*
oldset
,
struct
pt_regs
*
regs
);
/*
* Atomically swap in the new signal mask, and wait for a signal.
...
...
@@ -127,7 +152,7 @@ long sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, int p3, int p4, int
long
sys_sigaltstack
(
const
stack_t
*
uss
,
stack_t
*
uoss
)
{
struct
pt_regs
*
regs
=
(
struct
pt_regs
*
)
&
uss
;
struct
pt_regs
*
regs
=
(
struct
pt_regs
*
)
&
uss
;
return
do_sigaltstack
(
uss
,
uoss
,
regs
->
gpr
[
1
]);
}
...
...
@@ -139,6 +164,7 @@ long sys_sigaction(int sig, const struct old_sigaction *act,
if
(
act
)
{
old_sigset_t
mask
;
if
(
verify_area
(
VERIFY_READ
,
act
,
sizeof
(
*
act
))
||
__get_user
(
new_ka
.
sa
.
sa_handler
,
&
act
->
sa_handler
)
||
__get_user
(
new_ka
.
sa
.
sa_restorer
,
&
act
->
sa_restorer
))
...
...
@@ -148,8 +174,7 @@ long sys_sigaction(int sig, const struct old_sigaction *act,
siginitset
(
&
new_ka
.
sa
.
sa_mask
,
mask
);
}
ret
=
do_sigaction
(
sig
,
(
act
?
&
new_ka
:
NULL
),
(
oact
?
&
old_ka
:
NULL
));
ret
=
do_sigaction
(
sig
,
act
?
&
new_ka
:
NULL
,
oact
?
&
old_ka
:
NULL
);
if
(
!
ret
&&
oact
)
{
if
(
verify_area
(
VERIFY_WRITE
,
oact
,
sizeof
(
*
oact
))
||
__put_user
(
old_ka
.
sa
.
sa_handler
,
&
oact
->
sa_handler
)
||
...
...
@@ -162,35 +187,6 @@ long sys_sigaction(int sig, const struct old_sigaction *act,
return
ret
;
}
/*
* When we have signals to deliver, we set up on the
* user stack, going down from the original stack pointer:
* a sigregs struct
* one or more sigcontext structs with
* a gap of __SIGNAL_FRAMESIZE bytes
*
* Each of these things must be a multiple of 16 bytes in size.
*
*/
struct
sigregs
{
elf_gregset_t
gp_regs
;
double
fp_regs
[
ELF_NFPREG
];
unsigned
int
tramp
[
2
];
/* 64 bit API allows for 288 bytes below sp before
decrementing it. */
int
abigap
[
72
];
};
struct
rt_sigframe
{
unsigned
long
_unused
[
2
];
struct
siginfo
*
pinfo
;
void
*
puc
;
struct
siginfo
info
;
struct
ucontext
uc
;
};
/*
* When we have rt signals to deliver, we set up on the
* user stack, going down from the original stack pointer:
...
...
@@ -231,7 +227,7 @@ int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
* preamble frame (where registers are stored)
* see handle_signal()
*/
sr
=
(
struct
sigregs
*
)
sigctx
.
regs
;
sr
=
(
struct
sigregs
*
)
sigctx
.
regs
;
if
(
copy_from_user
(
saved_regs
,
&
sr
->
gp_regs
,
sizeof
(
sr
->
gp_regs
)))
goto
badframe
;
saved_regs
[
PT_MSR
]
=
(
regs
->
msr
&
~
MSR_USERCHANGE
)
...
...
@@ -251,11 +247,10 @@ int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
do_exit
(
SIGSEGV
);
}
static
void
setup_rt_frame
(
struct
pt_regs
*
regs
,
struct
sigregs
*
frame
,
static
void
setup_rt_frame
(
struct
pt_regs
*
regs
,
struct
sigregs
*
frame
,
signed
long
newsp
)
{
struct
rt_sigframe
*
rt_sf
=
(
struct
rt_sigframe
*
)
newsp
;
struct
rt_sigframe
*
rt_sf
=
(
struct
rt_sigframe
*
)
newsp
;
/* Handler is *really* a pointer to the function descriptor for
* the signal routine. The first entry in the function
* descriptor is the entry address of signal and the second
...
...
@@ -277,11 +272,13 @@ setup_rt_frame(struct pt_regs *regs, struct sigregs *frame,
if
(
__copy_to_user
(
&
frame
->
gp_regs
,
regs
,
GP_REGS_SIZE
)
||
__copy_to_user
(
&
frame
->
fp_regs
,
current
->
thread
.
fpr
,
ELF_NFPREG
*
sizeof
(
double
))
||
__put_user
(
0x38000000UL
+
__NR_rt_sigreturn
,
&
frame
->
tramp
[
0
])
/* li r0, __NR_rt_sigreturn */
||
__put_user
(
0x44000002UL
,
&
frame
->
tramp
[
1
]))
/* sc */
/* li r0, __NR_rt_sigreturn */
||
__put_user
(
0x38000000UL
+
__NR_rt_sigreturn
,
&
frame
->
tramp
[
0
])
/* sc */
||
__put_user
(
0x44000002UL
,
&
frame
->
tramp
[
1
]))
goto
badframe
;
flush_icache_range
((
unsigned
long
)
&
frame
->
tramp
[
0
],
(
unsigned
long
)
&
frame
->
tramp
[
2
]);
flush_icache_range
((
unsigned
long
)
&
frame
->
tramp
[
0
],
(
unsigned
long
)
&
frame
->
tramp
[
2
]);
current
->
thread
.
fpscr
=
0
;
/* turn off all fp exceptions */
/* Retrieve rt_sigframe from stack and
...
...
@@ -289,11 +286,11 @@ setup_rt_frame(struct pt_regs *regs, struct sigregs *frame,
*/
newsp
-=
__SIGNAL_FRAMESIZE
;
if
(
get_user
(
temp_ptr
,
&
rt_sf
->
uc
.
uc_mcontext
.
handler
))
{
if
(
get_user
(
temp_ptr
,
&
rt_sf
->
uc
.
uc_mcontext
.
handler
))
{
goto
badframe
;
}
funct_desc_ptr
=
(
struct
funct_descr_entry
*
)
temp_ptr
;
funct_desc_ptr
=
(
struct
funct_descr_entry
*
)
temp_ptr
;
if
(
put_user
(
regs
->
gpr
[
1
],
(
unsigned
long
*
)
newsp
)
||
get_user
(
regs
->
nip
,
&
funct_desc_ptr
->
entry
)
...
...
@@ -304,8 +301,8 @@ setup_rt_frame(struct pt_regs *regs, struct sigregs *frame,
goto
badframe
;
regs
->
gpr
[
1
]
=
newsp
;
regs
->
gpr
[
6
]
=
(
unsigned
long
)
rt_sf
;
regs
->
link
=
(
unsigned
long
)
frame
->
tramp
;
regs
->
gpr
[
6
]
=
(
unsigned
long
)
rt_sf
;
regs
->
link
=
(
unsigned
long
)
frame
->
tramp
;
return
;
...
...
@@ -342,11 +339,11 @@ long sys_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
current
->
blocked
=
set
;
recalc_sigpending
();
spin_unlock_irq
(
&
current
->
sigmask_lock
);
if
(
regs
->
msr
&
MSR_FP
)
if
(
regs
->
msr
&
MSR_FP
)
giveup_fpu
(
current
);
/* restore registers */
sr
=
(
struct
sigregs
*
)
sigctx
.
regs
;
sr
=
(
struct
sigregs
*
)
sigctx
.
regs
;
if
(
copy_from_user
(
saved_regs
,
&
sr
->
gp_regs
,
sizeof
(
sr
->
gp_regs
)))
goto
badframe
;
saved_regs
[
PT_MSR
]
=
(
regs
->
msr
&
~
MSR_USERCHANGE
)
...
...
@@ -367,8 +364,7 @@ long sys_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
/*
* Set up a signal frame.
*/
static
void
setup_frame
(
struct
pt_regs
*
regs
,
struct
sigregs
*
frame
,
static
void
setup_frame
(
struct
pt_regs
*
regs
,
struct
sigregs
*
frame
,
unsigned
long
newsp
)
{
...
...
@@ -385,7 +381,7 @@ setup_frame(struct pt_regs *regs, struct sigregs *frame,
struct
funct_descr_entry
*
funct_desc_ptr
;
unsigned
long
temp_ptr
;
struct
sigcontext_struct
*
sc
=
(
struct
sigcontext_struct
*
)
newsp
;
struct
sigcontext_struct
*
sc
=
(
struct
sigcontext_struct
*
)
newsp
;
if
(
verify_area
(
VERIFY_WRITE
,
frame
,
sizeof
(
*
frame
)))
goto
badframe
;
...
...
@@ -394,27 +390,29 @@ setup_frame(struct pt_regs *regs, struct sigregs *frame,
if
(
__copy_to_user
(
&
frame
->
gp_regs
,
regs
,
GP_REGS_SIZE
)
||
__copy_to_user
(
&
frame
->
fp_regs
,
current
->
thread
.
fpr
,
ELF_NFPREG
*
sizeof
(
double
))
||
__put_user
(
0x38000000UL
+
__NR_sigreturn
,
&
frame
->
tramp
[
0
])
/* li r0, __NR_sigreturn */
||
__put_user
(
0x44000002UL
,
&
frame
->
tramp
[
1
]))
/* sc */
/* li r0, __NR_sigreturn */
||
__put_user
(
0x38000000UL
+
__NR_sigreturn
,
&
frame
->
tramp
[
0
])
/* sc */
||
__put_user
(
0x44000002UL
,
&
frame
->
tramp
[
1
]))
goto
badframe
;
flush_icache_range
((
unsigned
long
)
&
frame
->
tramp
[
0
],
(
unsigned
long
)
&
frame
->
tramp
[
2
]);
flush_icache_range
((
unsigned
long
)
&
frame
->
tramp
[
0
],
(
unsigned
long
)
&
frame
->
tramp
[
2
]);
current
->
thread
.
fpscr
=
0
;
/* turn off all fp exceptions */
newsp
-=
__SIGNAL_FRAMESIZE
;
if
(
get_user
(
temp_ptr
,
&
sc
->
handler
))
if
(
get_user
(
temp_ptr
,
&
sc
->
handler
))
goto
badframe
;
funct_desc_ptr
=
(
struct
funct_descr_entry
*
)
temp_ptr
;
funct_desc_ptr
=
(
struct
funct_descr_entry
*
)
temp_ptr
;
if
(
put_user
(
regs
->
gpr
[
1
],
(
unsigned
long
*
)
newsp
)
||
get_user
(
regs
->
nip
,
&
funct_desc_ptr
->
entry
)
||
get_user
(
regs
->
gpr
[
2
],
&
funct_desc_ptr
->
toc
)
||
get_user
(
regs
->
nip
,
&
funct_desc_ptr
->
entry
)
||
get_user
(
regs
->
gpr
[
2
],
&
funct_desc_ptr
->
toc
)
||
get_user
(
regs
->
gpr
[
3
],
&
sc
->
signal
))
goto
badframe
;
regs
->
gpr
[
1
]
=
newsp
;
regs
->
gpr
[
4
]
=
(
unsigned
long
)
sc
;
regs
->
link
=
(
unsigned
long
)
frame
->
tramp
;
regs
->
gpr
[
4
]
=
(
unsigned
long
)
sc
;
regs
->
link
=
(
unsigned
long
)
frame
->
tramp
;
return
;
...
...
@@ -429,8 +427,7 @@ setup_frame(struct pt_regs *regs, struct sigregs *frame,
/*
* OK, we're invoking a handler
*/
static
void
handle_signal
(
unsigned
long
sig
,
siginfo_t
*
info
,
sigset_t
*
oldset
,
static
void
handle_signal
(
unsigned
long
sig
,
siginfo_t
*
info
,
sigset_t
*
oldset
,
struct
pt_regs
*
regs
,
unsigned
long
*
newspp
,
unsigned
long
frame
)
{
struct
sigcontext_struct
*
sc
;
...
...
@@ -447,11 +444,12 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
if
(
ka
->
sa
.
sa_flags
&
SA_SIGINFO
)
{
/* Put a Real Time Context onto stack */
*
newspp
-=
sizeof
(
*
rt_sf
);
rt_sf
=
(
struct
rt_sigframe
*
)
*
newspp
;
rt_sf
=
(
struct
rt_sigframe
*
)
*
newspp
;
if
(
verify_area
(
VERIFY_WRITE
,
rt_sf
,
sizeof
(
*
rt_sf
)))
goto
badframe
;
if
(
__put_user
((
unsigned
long
)
ka
->
sa
.
sa_handler
,
&
rt_sf
->
uc
.
uc_mcontext
.
handler
)
if
(
__put_user
((
unsigned
long
)
ka
->
sa
.
sa_handler
,
&
rt_sf
->
uc
.
uc_mcontext
.
handler
)
||
__put_user
(
&
rt_sf
->
info
,
&
rt_sf
->
pinfo
)
||
__put_user
(
&
rt_sf
->
uc
,
&
rt_sf
->
puc
)
/* Put the siginfo */
...
...
@@ -461,9 +459,11 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
||
__put_user
(
0
,
&
rt_sf
->
uc
.
uc_link
)
||
__put_user
(
current
->
sas_ss_sp
,
&
rt_sf
->
uc
.
uc_stack
.
ss_sp
)
||
__put_user
(
sas_ss_flags
(
regs
->
gpr
[
1
]),
&
rt_sf
->
uc
.
uc_stack
.
ss_flags
)
||
__put_user
(
current
->
sas_ss_size
,
&
rt_sf
->
uc
.
uc_stack
.
ss_size
)
||
__copy_to_user
(
&
rt_sf
->
uc
.
uc_sigmask
,
oldset
,
sizeof
(
*
oldset
))
&
rt_sf
->
uc
.
uc_stack
.
ss_flags
)
||
__put_user
(
current
->
sas_ss_size
,
&
rt_sf
->
uc
.
uc_stack
.
ss_size
)
||
__copy_to_user
(
&
rt_sf
->
uc
.
uc_sigmask
,
oldset
,
sizeof
(
*
oldset
))
/* mcontext.regs points to preamble register frame */
||
__put_user
((
struct
pt_regs
*
)
frame
,
&
rt_sf
->
uc
.
uc_mcontext
.
regs
)
||
__put_user
(
sig
,
&
rt_sf
->
uc
.
uc_mcontext
.
signal
))
...
...
@@ -471,11 +471,11 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
}
else
{
/* Put a sigcontext on the stack */
*
newspp
-=
sizeof
(
*
sc
);
sc
=
(
struct
sigcontext_struct
*
)
*
newspp
;
sc
=
(
struct
sigcontext_struct
*
)
*
newspp
;
if
(
verify_area
(
VERIFY_WRITE
,
sc
,
sizeof
(
*
sc
)))
goto
badframe
;
if
(
__put_user
((
unsigned
long
)
ka
->
sa
.
sa_handler
,
&
sc
->
handler
)
if
(
__put_user
((
unsigned
long
)
ka
->
sa
.
sa_handler
,
&
sc
->
handler
)
||
__put_user
(
oldset
->
sig
[
0
],
&
sc
->
oldmask
)
#if _NSIG_WORDS > 1
||
__put_user
(
oldset
->
sig
[
1
],
&
sc
->
_unused
[
3
])
...
...
@@ -512,6 +512,7 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
* mistake.
*/
extern
int
do_signal32
(
sigset_t
*
oldset
,
struct
pt_regs
*
regs
);
int
do_signal
(
sigset_t
*
oldset
,
struct
pt_regs
*
regs
)
{
siginfo_t
info
;
...
...
@@ -526,7 +527,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
if
(
test_thread_flag
(
TIF_32BIT
))
return
do_signal32
(
oldset
,
regs
);
if
(
!
oldset
)
if
(
!
oldset
)
oldset
=
&
current
->
blocked
;
newsp
=
frame
=
0
;
...
...
@@ -534,8 +535,8 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
signr
=
get_signal_to_deliver
(
&
info
,
regs
);
if
(
signr
>
0
)
{
ka
=
&
current
->
sig
->
action
[
signr
-
1
];
if
(
(
ka
->
sa
.
sa_flags
&
SA_ONSTACK
)
&&
(
!
on_sig_stack
(
regs
->
gpr
[
1
])))
if
((
ka
->
sa
.
sa_flags
&
SA_ONSTACK
)
&&
(
!
on_sig_stack
(
regs
->
gpr
[
1
])))
newsp
=
(
current
->
sas_ss_sp
+
current
->
sas_ss_size
);
else
newsp
=
regs
->
gpr
[
1
];
...
...
@@ -557,9 +558,10 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
if
(
newsp
==
frame
)
return
0
;
/* no signals delivered */
/* Invoke correct stack setup routine */
if
(
ka
->
sa
.
sa_flags
&
SA_SIGINFO
)
setup_rt_frame
(
regs
,
(
struct
sigregs
*
)
frame
,
newsp
);
setup_rt_frame
(
regs
,
(
struct
sigregs
*
)
frame
,
newsp
);
else
setup_frame
(
regs
,
(
struct
sigregs
*
)
frame
,
newsp
);
setup_frame
(
regs
,
(
struct
sigregs
*
)
frame
,
newsp
);
return
1
;
}
arch/ppc64/kernel/signal32.c
View file @
c9195267
...
...
@@ -14,43 +14,19 @@
* 2 of the License, or (at your option) any later version.
*/
#include <asm/ptrace.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/file.h>
#include <linux/signal.h>
#include <linux/utime.h>
#include <linux/resource.h>
#include <linux/times.h>
#include <linux/utsname.h>
#include <linux/timex.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/sem.h>
#include <linux/msg.h>
#include <linux/shm.h>
#include <linux/slab.h>
#include <linux/uio.h>
#include <linux/nfs_fs.h>
#include <linux/smb_fs.h>
#include <linux/smb_mount.h>
#include <linux/ncp_fs.h>
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/personality.h>
#include <linux/stat.h>
#include <linux/filter.h>
#include <linux/tty.h>
#include <linux/binfmts.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/elf.h>
#include <asm/types.h>
#include <asm/ipc.h>
#include <asm/uaccess.h>
#include <asm/ppc32.h>
#include <asm/uaccess.h>
#include <asm/ppcdebug.h>
#include <asm/unistd.h>
#include <asm/cacheflush.h>
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
/*
...
...
@@ -112,9 +88,6 @@ struct rt_sigframe_32 {
};
extern
asmlinkage
long
sys_wait4
(
pid_t
pid
,
unsigned
int
*
stat_addr
,
int
options
,
struct
rusage
*
ru
);
/*
* Start of nonRT signal support
...
...
@@ -133,7 +106,7 @@ extern asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr,
* setup_frame32
*/
asmlinkage
long
sys32_sigaction
(
int
sig
,
struct
old_sigaction32
*
act
,
long
sys32_sigaction
(
int
sig
,
struct
old_sigaction32
*
act
,
struct
old_sigaction32
*
oact
)
{
struct
k_sigaction
new_ka
,
old_ka
;
...
...
@@ -145,32 +118,30 @@ asmlinkage long sys32_sigaction(int sig, struct old_sigaction32 *act,
if
(
act
)
{
old_sigset_t32
mask
;
ret
=
get_user
((
long
)
new_ka
.
sa
.
sa_handler
,
&
act
->
sa_handler
);
ret
|=
__get_user
((
long
)
new_ka
.
sa
.
sa_restorer
,
&
act
->
sa_restorer
);
ret
|=
__get_user
(
new_ka
.
sa
.
sa_flags
,
&
act
->
sa_flags
);
ret
|=
__get_user
(
mask
,
&
act
->
sa_mask
);
if
(
ret
)
return
ret
;
if
(
get_user
((
long
)
new_ka
.
sa
.
sa_handler
,
&
act
->
sa_handler
)
||
__get_user
((
long
)
new_ka
.
sa
.
sa_restorer
,
&
act
->
sa_restorer
)
||
__get_user
(
new_ka
.
sa
.
sa_flags
,
&
act
->
sa_flags
)
||
__get_user
(
mask
,
&
act
->
sa_mask
))
return
-
EFAULT
;
siginitset
(
&
new_ka
.
sa
.
sa_mask
,
mask
);
}
ret
=
do_sigaction
(
sig
,
act
?
&
new_ka
:
NULL
,
oact
?
&
old_ka
:
NULL
);
if
(
!
ret
&&
oact
)
{
ret
=
put_user
((
long
)
old_ka
.
sa
.
sa_handler
,
&
oact
->
sa_handler
);
ret
|=
__put_user
((
long
)
old_ka
.
sa
.
sa_restorer
,
&
oact
->
sa_restorer
);
ret
|=
__put_user
(
old_ka
.
sa
.
sa_flags
,
&
oact
->
sa_flags
);
ret
|=
__put_user
(
old_ka
.
sa
.
sa_mask
.
sig
[
0
],
&
oact
->
sa_mask
);
if
(
put_user
((
long
)
old_ka
.
sa
.
sa_handler
,
&
oact
->
sa_handler
)
||
__put_user
((
long
)
old_ka
.
sa
.
sa_restorer
,
&
oact
->
sa_restorer
)
||
__put_user
(
old_ka
.
sa
.
sa_flags
,
&
oact
->
sa_flags
)
||
__put_user
(
old_ka
.
sa
.
sa_mask
.
sig
[
0
],
&
oact
->
sa_mask
))
return
-
EFAULT
;
}
return
ret
;
}
extern
long
sys_sigpending
(
old_sigset_t
*
set
);
extern
asmlinkage
long
sys_sigpending
(
old_sigset_t
*
set
);
asmlinkage
long
sys32_sigpending
(
old_sigset_t32
*
set
)
long
sys32_sigpending
(
old_sigset_t32
*
set
)
{
old_sigset_t
s
;
int
ret
;
...
...
@@ -185,9 +156,7 @@ asmlinkage long sys32_sigpending(old_sigset_t32 *set)
}
extern
asmlinkage
long
sys_sigprocmask
(
int
how
,
old_sigset_t
*
set
,
extern
long
sys_sigprocmask
(
int
how
,
old_sigset_t
*
set
,
old_sigset_t
*
oset
);
/*
...
...
@@ -197,7 +166,7 @@ extern asmlinkage long sys_sigprocmask(int how, old_sigset_t *set,
* of a signed int (msr in 32-bit mode) and the register representation
* of a signed int (msr in 64-bit mode) is performed.
*/
asmlinkage
long
sys32_sigprocmask
(
u32
how
,
old_sigset_t32
*
set
,
long
sys32_sigprocmask
(
u32
how
,
old_sigset_t32
*
set
,
old_sigset_t32
*
oset
)
{
old_sigset_t
s
;
...
...
@@ -252,23 +221,21 @@ long sys32_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
* Note that PPC32 puts the upper 32 bits of the sigmask in the
* unused part of the signal stackframe
*/
set
.
sig
[
0
]
=
sigctx
.
oldmask
+
((
long
)(
sigctx
.
_unused
[
3
])
<<
32
);
set
.
sig
[
0
]
=
sigctx
.
oldmask
+
((
long
)(
sigctx
.
_unused
[
3
])
<<
32
);
sigdelsetmask
(
&
set
,
~
_BLOCKABLE
);
spin_lock_irq
(
&
current
->
sigmask_lock
);
current
->
blocked
=
set
;
recalc_sigpending
();
spin_unlock_irq
(
&
current
->
sigmask_lock
);
/* Last stacked signal - restore registers */
sr
=
(
struct
sigregs32
*
)(
u64
)
sigctx
.
regs
;
if
(
regs
->
msr
&
MSR_FP
)
giveup_fpu
(
current
);
/* Last stacked signal - restore registers */
sr
=
(
struct
sigregs32
*
)(
u64
)
sigctx
.
regs
;
/*
* copy the 32 bit register values off the user stack
* into the 32 bit register area
*/
if
(
copy_from_user
(
saved_regs
,
&
sr
->
gp_regs
,
sizeof
(
sr
->
gp_regs
)))
if
(
copy_from_user
(
saved_regs
,
&
sr
->
gp_regs
,
sizeof
(
sr
->
gp_regs
)))
goto
badframe
;
/*
* The saved reg structure in the frame is an elf_grepset_t32,
...
...
@@ -323,7 +290,6 @@ long sys32_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
goto
badframe
;
ret
=
regs
->
result
;
return
ret
;
badframe:
...
...
@@ -387,12 +353,13 @@ static void setup_frame32(struct pt_regs *regs, struct sigregs32 *frame,
*/
if
(
__copy_to_user
(
&
frame
->
fp_regs
,
current
->
thread
.
fpr
,
ELF_NFPREG
*
sizeof
(
double
))
||
__put_user
(
0x38000000U
+
__NR_sigreturn
,
&
frame
->
tramp
[
0
])
/* li r0, __NR_sigreturn */
||
__put_user
(
0x44000002U
,
&
frame
->
tramp
[
1
]))
/* sc */
/* li r0, __NR_sigreturn */
||
__put_user
(
0x38000000U
+
__NR_sigreturn
,
&
frame
->
tramp
[
0
])
/* sc */
||
__put_user
(
0x44000002U
,
&
frame
->
tramp
[
1
]))
goto
badframe
;
flush_icache_range
((
unsigned
long
)
&
frame
->
tramp
[
0
],
(
unsigned
long
)
&
frame
->
tramp
[
2
]);
flush_icache_range
((
unsigned
long
)
&
frame
->
tramp
[
0
],
(
unsigned
long
)
&
frame
->
tramp
[
2
]);
current
->
thread
.
fpscr
=
0
;
/* turn off all fp exceptions */
newsp
-=
__SIGNAL_FRAMESIZE32
;
...
...
@@ -438,7 +405,7 @@ static void setup_frame32(struct pt_regs *regs, struct sigregs32 *frame,
*
* Other routines
* setup_rt_frame32
*
siginfo64to
32
*
copy_siginfo_to_user
32
* siginfo32to64
*/
...
...
@@ -451,50 +418,45 @@ long sys32_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned
long
r6
,
unsigned
long
r7
,
unsigned
long
r8
,
struct
pt_regs
*
regs
)
{
struct
rt_sigframe_32
*
rt_s
tack_frame
;
struct
rt_sigframe_32
*
rt_s
f
;
struct
sigcontext32_struct
sigctx
;
struct
sigregs32
*
s
ignalregs
;
struct
sigregs32
*
s
r
;
int
ret
;
elf_gregset_t32
saved_regs
;
/* an array of 32 bit register values */
sigset_t
s
ignal_s
et
;
stack_t
st
ack
;
sigset_t
set
;
stack_t
st
;
int
i
;
ret
=
0
;
/* Adjust the inputted reg1 to point to the first rt signal frame */
rt_s
tack_frame
=
(
struct
rt_sigframe_32
*
)(
regs
->
gpr
[
1
]
+
__SIGNAL_FRAMESIZE32
);
rt_s
f
=
(
struct
rt_sigframe_32
*
)(
regs
->
gpr
[
1
]
+
__SIGNAL_FRAMESIZE32
);
/* Copy the information from the user stack */
if
(
copy_from_user
(
&
sigctx
,
&
rt_stack_frame
->
uc
.
uc_mcontext
,
sizeof
(
sigctx
))
||
copy_from_user
(
&
signal_set
,
&
rt_stack_frame
->
uc
.
uc_sigmask
,
sizeof
(
signal_set
))
||
copy_from_user
(
&
stack
,
&
rt_stack_frame
->
uc
.
uc_stack
,
sizeof
(
stack
)))
if
(
copy_from_user
(
&
sigctx
,
&
rt_sf
->
uc
.
uc_mcontext
,
sizeof
(
sigctx
))
||
copy_from_user
(
&
set
,
&
rt_sf
->
uc
.
uc_sigmask
,
sizeof
(
set
))
||
copy_from_user
(
&
st
,
&
rt_sf
->
uc
.
uc_stack
,
sizeof
(
st
)))
goto
badframe
;
/*
* Unblock the signal that was processed
* After a signal handler runs -
* if the signal is blockable - the signal will be unblocked
* (
sigkill and sigstop are not blockable)
* (sigkill and sigstop are not blockable)
*/
sigdelsetmask
(
&
s
ignal_s
et
,
~
_BLOCKABLE
);
sigdelsetmask
(
&
set
,
~
_BLOCKABLE
);
/* update the current based on the sigmask found in the rt_stackframe */
spin_lock_irq
(
&
current
->
sigmask_lock
);
current
->
blocked
=
s
ignal_s
et
;
current
->
blocked
=
set
;
recalc_sigpending
();
spin_unlock_irq
(
&
current
->
sigmask_lock
);
/* If currently owning the floating point - give them up */
if
(
regs
->
msr
&
MSR_FP
)
giveup_fpu
(
current
);
/*
* Set to point to the next rt_sigframe - this is used to
* determine whether this is the last signal to process
*/
signalregs
=
(
struct
sigregs32
*
)
(
u64
)
sigctx
.
regs
;
/* If currently owning the floating point - give them up */
if
(
regs
->
msr
&
MSR_FP
)
giveup_fpu
(
current
);
if
(
copy_from_user
(
saved_regs
,
&
signalregs
->
gp_regs
,
sizeof
(
signalregs
->
gp_regs
)))
sr
=
(
struct
sigregs32
*
)(
u64
)
sigctx
.
regs
;
if
(
copy_from_user
(
saved_regs
,
&
sr
->
gp_regs
,
sizeof
(
sr
->
gp_regs
)))
goto
badframe
;
/*
* The saved reg structure in the frame is an elf_grepset_t32,
...
...
@@ -544,7 +506,7 @@ long sys32_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
asmlinkage
long
sys32_rt_sigaction
(
int
sig
,
const
struct
sigaction32
*
act
,
long
sys32_rt_sigaction
(
int
sig
,
const
struct
sigaction32
*
act
,
struct
sigaction32
*
oact
,
size_t
sigsetsize
)
{
struct
k_sigaction
new_ka
,
old_ka
;
...
...
@@ -599,7 +561,7 @@ asmlinkage long sys32_rt_sigaction(int sig, const struct sigaction32 *act,
}
extern
asmlinkage
long
sys_rt_sigprocmask
(
int
how
,
sigset_t
*
set
,
extern
long
sys_rt_sigprocmask
(
int
how
,
sigset_t
*
set
,
sigset_t
*
oset
,
size_t
sigsetsize
);
/*
...
...
@@ -609,7 +571,7 @@ extern asmlinkage long sys_rt_sigprocmask(int how, sigset_t *set,
* of a signed int (msr in 32-bit mode) and the register representation
* of a signed int (msr in 64-bit mode) is performed.
*/
asmlinkage
long
sys32_rt_sigprocmask
(
u32
how
,
sigset32_t
*
set
,
long
sys32_rt_sigprocmask
(
u32
how
,
sigset32_t
*
set
,
sigset32_t
*
oset
,
size_t
sigsetsize
)
{
sigset_t
s
;
...
...
@@ -649,10 +611,10 @@ asmlinkage long sys32_rt_sigprocmask(u32 how, sigset32_t *set,
}
extern
asmlinkage
long
sys_rt_sigpending
(
sigset_t
*
set
,
size_t
sigsetsize
);
extern
long
sys_rt_sigpending
(
sigset_t
*
set
,
size_t
sigsetsize
);
asmlinkage
long
sys32_rt_sigpending
(
sigset32_t
*
set
,
long
sys32_rt_sigpending
(
sigset32_t
*
set
,
__kernel_size_t32
sigsetsize
)
{
sigset_t
s
;
...
...
@@ -677,50 +639,54 @@ asmlinkage long sys32_rt_sigpending(sigset32_t *set,
}
s
iginfo_t32
*
siginfo64to
32
(
siginfo_t32
*
d
,
siginfo_t
*
s
)
s
tatic
int
copy_siginfo_to_user
32
(
siginfo_t32
*
d
,
siginfo_t
*
s
)
{
memset
(
d
,
0
,
sizeof
(
siginfo_t32
));
d
->
si_signo
=
s
->
si_signo
;
d
->
si_errno
=
s
->
si_errno
;
/* XXX why dont we just implement copy_siginfo_to_user32? - Anton */
d
->
si_code
=
s
->
si_code
&
0xffff
;
int
err
;
if
(
!
access_ok
(
VERIFY_WRITE
,
d
,
sizeof
(
*
d
)))
return
-
EFAULT
;
err
=
__put_user
(
s
->
si_signo
,
&
d
->
si_signo
);
err
|=
__put_user
(
s
->
si_errno
,
&
d
->
si_errno
);
err
|=
__put_user
((
short
)
s
->
si_code
,
&
d
->
si_code
);
if
(
s
->
si_signo
>=
SIGRTMIN
)
{
d
->
si_pid
=
s
->
si_pid
;
d
->
si_uid
=
s
->
si_uid
;
d
->
si_int
=
s
->
si_int
;
err
|=
__put_user
(
s
->
si_pid
,
&
d
->
si_pid
)
;
err
|=
__put_user
(
s
->
si_uid
,
&
d
->
si_uid
)
;
err
|=
__put_user
(
s
->
si_int
,
&
d
->
si_int
)
;
}
else
{
switch
(
s
->
si_signo
)
{
/* XXX: What about POSIX1.b timers */
case
SIGCHLD
:
d
->
si_pid
=
s
->
si_pid
;
d
->
si_status
=
s
->
si_status
;
d
->
si_utime
=
s
->
si_utime
;
d
->
si_stime
=
s
->
si_stime
;
err
|=
__put_user
(
s
->
si_pid
,
&
d
->
si_pid
)
;
err
|=
__put_user
(
s
->
si_status
,
&
d
->
si_status
)
;
err
|=
__put_user
(
s
->
si_utime
,
&
d
->
si_utime
)
;
err
|=
__put_user
(
s
->
si_stime
,
&
d
->
si_stime
)
;
break
;
case
SIGSEGV
:
case
SIGBUS
:
case
SIGFPE
:
case
SIGILL
:
d
->
si_addr
=
(
long
)(
s
->
si_addr
);
err
|=
__put_user
((
long
)(
s
->
si_addr
),
&
d
->
si_addr
);
break
;
case
SIGPOLL
:
d
->
si_band
=
s
->
si_band
;
d
->
si_fd
=
s
->
si_fd
;
err
|=
__put_user
(
s
->
si_band
,
&
d
->
si_band
)
;
err
|=
__put_user
(
s
->
si_fd
,
&
d
->
si_fd
)
;
break
;
default:
d
->
si_pid
=
s
->
si_pid
;
d
->
si_uid
=
s
->
si_uid
;
err
|=
__put_user
(
s
->
si_pid
,
&
d
->
si_pid
)
;
err
|=
__put_user
(
s
->
si_uid
,
&
d
->
si_uid
)
;
break
;
}
}
return
d
;
return
err
;
}
extern
asmlinkage
long
sys_rt_sigtimedwait
(
const
sigset_t
*
uthese
,
extern
long
sys_rt_sigtimedwait
(
const
sigset_t
*
uthese
,
siginfo_t
*
uinfo
,
const
struct
timespec
*
uts
,
size_t
sigsetsize
);
asmlinkage
long
sys32_rt_sigtimedwait
(
sigset32_t
*
uthese
,
siginfo_t32
*
uinfo
,
long
sys32_rt_sigtimedwait
(
sigset32_t
*
uthese
,
siginfo_t32
*
uinfo
,
struct
timespec32
*
uts
,
__kernel_size_t32
sigsetsize
)
{
sigset_t
s
;
...
...
@@ -729,8 +695,7 @@ asmlinkage long sys32_rt_sigtimedwait(sigset32_t *uthese, siginfo_t32 *uinfo,
int
ret
;
mm_segment_t
old_fs
=
get_fs
();
siginfo_t
info
;
siginfo_t32
info32
;
if
(
copy_from_user
(
&
s32
,
uthese
,
sizeof
(
sigset32_t
)))
return
-
EFAULT
;
switch
(
_NSIG_WORDS
)
{
...
...
@@ -753,8 +718,7 @@ asmlinkage long sys32_rt_sigtimedwait(sigset32_t *uthese, siginfo_t32 *uinfo,
sigsetsize
);
set_fs
(
old_fs
);
if
(
ret
>=
0
&&
uinfo
)
{
if
(
copy_to_user
(
uinfo
,
siginfo64to32
(
&
info32
,
&
info
),
sizeof
(
siginfo_t32
)))
if
(
copy_siginfo_to_user32
(
uinfo
,
&
info
))
return
-
EFAULT
;
}
return
ret
;
...
...
@@ -762,7 +726,7 @@ asmlinkage long sys32_rt_sigtimedwait(sigset32_t *uthese, siginfo_t32 *uinfo,
siginfo_t
*
siginfo32to64
(
siginfo_t
*
d
,
siginfo_t32
*
s
)
s
tatic
s
iginfo_t
*
siginfo32to64
(
siginfo_t
*
d
,
siginfo_t32
*
s
)
{
d
->
si_signo
=
s
->
si_signo
;
d
->
si_errno
=
s
->
si_errno
;
...
...
@@ -800,7 +764,7 @@ siginfo_t * siginfo32to64(siginfo_t *d, siginfo_t32 *s)
}
extern
asmlinkage
long
sys_rt_sigqueueinfo
(
int
pid
,
int
sig
,
siginfo_t
*
uinfo
);
extern
long
sys_rt_sigqueueinfo
(
int
pid
,
int
sig
,
siginfo_t
*
uinfo
);
/*
* Note: it is necessary to treat pid and sig as unsigned ints, with the
...
...
@@ -809,7 +773,7 @@ extern asmlinkage long sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo);
* (msr in 32-bit mode) and the register representation of a signed int
* (msr in 64-bit mode) is performed.
*/
asmlinkage
long
sys32_rt_sigqueueinfo
(
u32
pid
,
u32
sig
,
siginfo_t32
*
uinfo
)
long
sys32_rt_sigqueueinfo
(
u32
pid
,
u32
sig
,
siginfo_t32
*
uinfo
)
{
siginfo_t
info
;
siginfo_t32
info32
;
...
...
@@ -974,8 +938,7 @@ static void handle_signal32(unsigned long sig, siginfo_t *info,
unsigned
int
frame
)
{
struct
sigcontext32_struct
*
sc
;
struct
rt_sigframe_32
*
rt_stack_frame
;
siginfo_t32
siginfo32bit
;
struct
rt_sigframe_32
*
rt_sf
;
struct
k_sigaction
*
ka
=
&
current
->
sig
->
action
[
sig
-
1
];
if
(
regs
->
trap
==
0x0C00
/* System Call! */
...
...
@@ -986,42 +949,35 @@ static void handle_signal32(unsigned long sig, siginfo_t *info,
/*
* Set up the signal frame
* Determine if a
n real time frame - siginfo
required
* Determine if a
real time frame and a siginfo is
required
*/
if
(
ka
->
sa
.
sa_flags
&
SA_SIGINFO
)
{
siginfo64to32
(
&
siginfo32bit
,
info
);
*
newspp
-=
sizeof
(
*
rt_stack_frame
);
rt_stack_frame
=
(
struct
rt_sigframe_32
*
)(
u64
)(
*
newspp
);
if
(
verify_area
(
VERIFY_WRITE
,
rt_stack_frame
,
sizeof
(
*
rt_stack_frame
)))
*
newspp
-=
sizeof
(
*
rt_sf
);
rt_sf
=
(
struct
rt_sigframe_32
*
)(
u64
)(
*
newspp
);
if
(
verify_area
(
VERIFY_WRITE
,
rt_sf
,
sizeof
(
*
rt_sf
)))
goto
badframe
;
if
(
__put_user
((
u32
)(
u64
)
ka
->
sa
.
sa_handler
,
&
rt_stack_frame
->
uc
.
uc_mcontext
.
handler
)
||
__put_user
((
u32
)(
u64
)
&
rt_stack_frame
->
info
,
&
rt_stack_frame
->
pinfo
)
||
__put_user
((
u32
)(
u64
)
&
rt_stack_frame
->
uc
,
&
rt_stack_frame
->
puc
)
&
rt_sf
->
uc
.
uc_mcontext
.
handler
)
||
__put_user
((
u32
)(
u64
)
&
rt_sf
->
info
,
&
rt_sf
->
pinfo
)
||
__put_user
((
u32
)(
u64
)
&
rt_sf
->
uc
,
&
rt_sf
->
puc
)
/* put the siginfo on the user stack */
||
__copy_to_user
(
&
rt_stack_frame
->
info
,
&
siginfo32bit
,
sizeof
(
siginfo32bit
))
||
copy_siginfo_to_user32
(
&
rt_sf
->
info
,
info
)
/* set the ucontext on the user stack */
||
__put_user
(
0
,
&
rt_stack_frame
->
uc
.
uc_flags
)
||
__put_user
(
0
,
&
rt_stack_frame
->
uc
.
uc_link
)
||
__put_user
(
current
->
sas_ss_sp
,
&
rt_stack_frame
->
uc
.
uc_stack
.
ss_sp
)
||
__put_user
(
0
,
&
rt_sf
->
uc
.
uc_flags
)
||
__put_user
(
0
,
&
rt_sf
->
uc
.
uc_link
)
||
__put_user
(
current
->
sas_ss_sp
,
&
rt_sf
->
uc
.
uc_stack
.
ss_sp
)
||
__put_user
(
sas_ss_flags
(
regs
->
gpr
[
1
]),
&
rt_s
tack_frame
->
uc
.
uc_stack
.
ss_flags
)
&
rt_s
f
->
uc
.
uc_stack
.
ss_flags
)
||
__put_user
(
current
->
sas_ss_size
,
&
rt_s
tack_frame
->
uc
.
uc_stack
.
ss_size
)
||
__copy_to_user
(
&
rt_s
tack_frame
->
uc
.
uc_sigmask
,
&
rt_s
f
->
uc
.
uc_stack
.
ss_size
)
||
__copy_to_user
(
&
rt_s
f
->
uc
.
uc_sigmask
,
oldset
,
sizeof
(
*
oldset
))
/* point the mcontext.regs to the pramble register frame */
||
__put_user
(
frame
,
&
rt_s
tack_frame
->
uc
.
uc_mcontext
.
regs
)
||
__put_user
(
sig
,
&
rt_s
tack_frame
->
uc
.
uc_mcontext
.
signal
))
||
__put_user
(
frame
,
&
rt_s
f
->
uc
.
uc_mcontext
.
regs
)
||
__put_user
(
sig
,
&
rt_s
f
->
uc
.
uc_mcontext
.
signal
))
goto
badframe
;
}
else
{
/* Put a
nother
sigcontext on the stack */
/* Put a sigcontext on the stack */
*
newspp
-=
sizeof
(
*
sc
);
sc
=
(
struct
sigcontext32_struct
*
)(
u64
)
*
newspp
;
if
(
verify_area
(
VERIFY_WRITE
,
sc
,
sizeof
(
*
sc
)))
...
...
@@ -1048,7 +1004,6 @@ static void handle_signal32(unsigned long sig, siginfo_t *info,
recalc_sigpending
();
spin_unlock_irq
(
&
current
->
sigmask_lock
);
}
return
;
badframe:
...
...
@@ -1068,7 +1023,7 @@ static void handle_signal32(unsigned long sig, siginfo_t *info,
* sigaltatck sys32_sigaltstack
*/
asmlinkage
int
sys32_sigaltstack
(
u32
newstack
,
u32
oldstack
,
int
p3
,
int
sys32_sigaltstack
(
u32
newstack
,
u32
oldstack
,
int
p3
,
int
p4
,
int
p6
,
int
p7
,
struct
pt_regs
*
regs
)
{
stack_t
uss
,
uoss
;
...
...
@@ -1114,7 +1069,7 @@ asmlinkage int sys32_sigaltstack(u32 newstack, u32 oldstack, int p3,
/*
* Start of do_signal32 routine
*
* This routine gets control when a pe
m
ding signal needs to be processed
* This routine gets control when a pe
n
ding signal needs to be processed
* in the 32 bit target thread -
*
* It handles both rt and non-rt signals
...
...
@@ -1141,13 +1096,13 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
signr
=
get_signal_to_deliver
(
&
info
,
regs
);
if
(
signr
>
0
)
{
ka
=
&
current
->
sig
->
action
[
signr
-
1
];
if
((
ka
->
sa
.
sa_flags
&
SA_ONSTACK
)
&&
(
!
on_sig_stack
(
regs
->
gpr
[
1
])))
if
((
ka
->
sa
.
sa_flags
&
SA_ONSTACK
)
&&
(
!
on_sig_stack
(
regs
->
gpr
[
1
])))
newsp
=
(
current
->
sas_ss_sp
+
current
->
sas_ss_size
);
else
newsp
=
regs
->
gpr
[
1
];
newsp
=
frame
=
newsp
-
sizeof
(
struct
sigregs32
);
/* Whee! Actually deliver the signal. */
handle_signal32
(
signr
,
&
info
,
oldset
,
regs
,
&
newsp
,
frame
);
}
...
...
@@ -1165,10 +1120,9 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
return
0
;
/* no signals delivered */
/* Invoke correct stack setup routine */
if
(
ka
->
sa
.
sa_flags
&
SA_SIGINFO
)
if
(
ka
->
sa
.
sa_flags
&
SA_SIGINFO
)
setup_rt_frame32
(
regs
,
(
struct
sigregs32
*
)(
u64
)
frame
,
newsp
);
else
setup_frame32
(
regs
,
(
struct
sigregs32
*
)(
u64
)
frame
,
newsp
);
return
1
;
}
arch/ppc64/kernel/smp.c
View file @
c9195267
...
...
@@ -28,7 +28,6 @@
#define __KERNEL_SYSCALLS__
#include <linux/unistd.h>
#include <linux/init.h>
/* #include <linux/openpic.h> */
#include <linux/spinlock.h>
#include <linux/cache.h>
#include <linux/err.h>
...
...
@@ -40,7 +39,6 @@
#include <asm/pgtable.h>
#include <asm/hardirq.h>
#include <asm/softirq.h>
#include <asm/init.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/smp.h>
...
...
@@ -66,10 +64,6 @@ unsigned long cpu_online_map;
volatile
unsigned
long
cpu_callin_map
[
NR_CPUS
]
=
{
0
,};
#define TB_SYNC_PASSES 4
volatile
unsigned
long
__initdata
tb_sync_flag
=
0
;
volatile
unsigned
long
__initdata
tb_offset
=
0
;
extern
unsigned
char
stab_array
[];
int
start_secondary
(
void
*
);
...
...
@@ -595,13 +589,9 @@ void __init smp_boot_cpus(void)
}
/*
* XXX very rough. On POWER4 we optimise tlb flushes for
* tasks that only run on one cpu so we increase decay ticks.
* XXX very rough.
*/
if
(
__is_processor
(
PV_POWER4
))
cache_decay_ticks
=
HZ
/
50
;
else
cache_decay_ticks
=
HZ
/
100
;
cache_decay_ticks
=
HZ
/
100
;
/* Probe arch for CPUs */
cpu_nr
=
ppc_md
.
smp_probe
();
...
...
@@ -729,7 +719,7 @@ void __init smp_setup(char *str, int *ints)
{
}
int
__init
setup_profiling_timer
(
unsigned
int
multiplier
)
int
setup_profiling_timer
(
unsigned
int
multiplier
)
{
return
0
;
}
...
...
arch/ppc64/kernel/time.c
View file @
c9195267
...
...
@@ -53,7 +53,6 @@
#include <asm/nvram.h>
#include <asm/cache.h>
#include <asm/machdep.h>
#include <asm/init.h>
#ifdef CONFIG_PPC_ISERIES
#include <asm/iSeries/HvCallXm.h>
#endif
...
...
arch/ppc64/mm/init.c
View file @
c9195267
/*
*
*
* PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
*
...
...
@@ -62,8 +60,6 @@
#include <asm/ppcdebug.h>
#define PGTOKB(pages) (((pages) * PAGE_SIZE) >> 10)
#ifdef CONFIG_PPC_ISERIES
#include <asm/iSeries/iSeries_dma.h>
#endif
...
...
@@ -76,15 +72,10 @@ static int boot_mapsize;
extern
pgd_t
swapper_pg_dir
[];
extern
char
__init_begin
,
__init_end
;
extern
char
__chrp_begin
,
__chrp_end
;
extern
char
__openfirmware_begin
,
__openfirmware_end
;
extern
struct
_of_tce_table
of_tce_table
[];
extern
char
_start
[],
_end
[];
extern
char
_stext
[],
etext
[];
extern
struct
task_struct
*
current_set
[
NR_CPUS
];
void
mm_init_ppc64
(
void
);
extern
pgd_t
ioremap_dir
[];
pgd_t
*
ioremap_pgd
=
(
pgd_t
*
)
&
ioremap_dir
;
...
...
@@ -107,7 +98,7 @@ mmu_gather_t mmu_gathers[NR_CPUS];
void
show_mem
(
void
)
{
int
i
,
free
=
0
,
total
=
0
,
reserved
=
0
;
int
i
,
total
=
0
,
reserved
=
0
;
int
shared
=
0
,
cached
=
0
;
printk
(
"Mem-info:
\n
"
);
...
...
@@ -120,13 +111,10 @@ void show_mem(void)
reserved
++
;
else
if
(
PageSwapCache
(
mem_map
+
i
))
cached
++
;
else
if
(
!
atomic_read
(
&
mem_map
[
i
].
count
))
free
++
;
else
shared
+=
atomic_read
(
&
mem_map
[
i
].
count
)
-
1
;
else
if
(
page_count
(
mem_map
+
i
))
shared
+=
page_count
(
mem_map
+
i
)
-
1
;
}
printk
(
"%d pages of RAM
\n
"
,
total
);
printk
(
"%d free pages
\n
"
,
free
);
printk
(
"%d reserved pages
\n
"
,
reserved
);
printk
(
"%d pages shared
\n
"
,
shared
);
printk
(
"%d pages swap cached
\n
"
,
cached
);
...
...
@@ -179,7 +167,7 @@ __ioremap(unsigned long addr, unsigned long size, unsigned long flags)
else
{
ea
=
ioremap_bot
;
ioremap_bot
+=
size
;
}
}
if
((
flags
&
_PAGE_PRESENT
)
==
0
)
flags
|=
pgprot_val
(
PAGE_KERNEL
);
...
...
@@ -196,9 +184,9 @@ __ioremap(unsigned long addr, unsigned long size, unsigned long flags)
void
iounmap
(
void
*
addr
)
{
#ifdef CONFIG_PPC_ISERIES
/* iSeries I/O Remap is a noop */
/* iSeries I/O Remap is a noop */
return
;
#else
#else
/* DRENG / PPPBBB todo */
return
;
#endif
...
...
@@ -229,7 +217,7 @@ static void map_io_page(unsigned long ea, unsigned long pa, int flags)
/* If the mm subsystem is not fully up, we cannot create a
* linux page table entry for this mapping. Simply bolt an
* entry in the hardware page table.
*/
*/
vsid
=
get_kernel_vsid
(
ea
);
ppc_md
.
make_pte
(
htab_data
.
htab
,
(
vsid
<<
28
)
|
(
ea
&
0xFFFFFFF
),
// va (NOT the ea)
...
...
@@ -302,7 +290,7 @@ flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
}
}
struct
tlb_batch_data
tlb_batch_array
[
NR_CPUS
][
MAX_BATCH_FLUSH
];
struct
ppc64_tlb_batch
ppc64_tlb_batch
[
NR_CPUS
];
void
__flush_tlb_range
(
struct
mm_struct
*
mm
,
unsigned
long
start
,
unsigned
long
end
)
...
...
@@ -312,81 +300,69 @@ __flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end)
pte_t
*
ptep
;
pte_t
pte
;
unsigned
long
pgd_end
,
pmd_end
;
unsigned
long
context
;
int
i
=
0
;
struct
tlb_batch_data
*
ptes
=
&
tlb_batch_array
[
smp_processor_id
()][
0
]
;
unsigned
long
context
=
0
;
struct
ppc64_tlb_batch
*
batch
=
&
ppc64_tlb_batch
[
smp_processor_id
()]
;
unsigned
long
i
=
0
;
int
local
=
0
;
if
(
start
>=
end
)
panic
(
"flush_tlb_range: start (%016lx) greater than end (%016lx)
\n
"
,
start
,
end
);
if
(
REGION_ID
(
start
)
!=
REGION_ID
(
end
)
)
panic
(
"flush_tlb_range: start (%016lx) and end (%016lx) not in same region
\n
"
,
start
,
end
);
context
=
0
;
switch
(
REGION_ID
(
start
)
)
{
switch
(
REGION_ID
(
start
))
{
case
VMALLOC_REGION_ID
:
pgd
=
pgd_offset_k
(
start
);
pgd
=
pgd_offset_k
(
start
);
break
;
case
IO_REGION_ID
:
pgd
=
pgd_offset_i
(
start
);
pgd
=
pgd_offset_i
(
start
);
break
;
case
USER_REGION_ID
:
pgd
=
pgd_offset
(
mm
,
start
);
pgd
=
pgd_offset
(
mm
,
start
);
context
=
mm
->
context
;
/* XXX are there races with checking cpu_vm_mask? - Anton */
if
(
mm
->
cpu_vm_mask
==
(
1
<<
smp_processor_id
()))
{
if
(
mm
->
cpu_vm_mask
==
(
1
<<
smp_processor_id
()))
local
=
1
;
}
break
;
default:
panic
(
"flush_tlb_range: invalid region for start (%016lx) and end (%016lx)
\n
"
,
start
,
end
);
}
do
{
pgd_end
=
(
start
+
PGDIR_SIZE
)
&
PGDIR_MASK
;
if
(
pgd_end
>
end
)
if
(
pgd_end
>
end
)
pgd_end
=
end
;
if
(
!
pgd_none
(
*
pgd
)
)
{
pmd
=
pmd_offset
(
pgd
,
start
);
if
(
!
pgd_none
(
*
pgd
)
)
{
pmd
=
pmd_offset
(
pgd
,
start
);
do
{
pmd_end
=
(
start
+
PMD_SIZE
)
&
PMD_MASK
;
if
(
pmd_end
>
end
)
pmd_end
=
(
start
+
PMD_SIZE
)
&
PMD_MASK
;
if
(
pmd_end
>
end
)
pmd_end
=
end
;
if
(
!
pmd_none
(
*
pmd
)
)
{
ptep
=
pte_offset_kernel
(
pmd
,
start
);
if
(
!
pmd_none
(
*
pmd
)
)
{
ptep
=
pte_offset_kernel
(
pmd
,
start
);
do
{
if
(
pte_val
(
*
ptep
)
&
_PAGE_HASHPTE
)
{
if
(
pte_val
(
*
ptep
)
&
_PAGE_HASHPTE
)
{
pte
=
__pte
(
pte_update
(
ptep
,
_PAGE_HPTEFLAGS
,
0
));
if
(
pte_val
(
pte
)
&
_PAGE_HASHPTE
)
{
ptes
->
pte
=
pte
;
ptes
->
addr
=
start
;
ptes
++
;
if
(
pte_val
(
pte
)
&
_PAGE_HASHPTE
)
{
batch
->
pte
[
i
]
=
pte
;
batch
->
addr
[
i
]
=
start
;
i
++
;
if
(
i
==
MAX_BATCH_FLUSH
)
{
flush_hash_range
(
context
,
MAX_BATCH_FLUSH
,
local
);
if
(
i
==
PPC64_TLB_BATCH_NR
)
{
flush_hash_range
(
context
,
i
,
local
);
i
=
0
;
ptes
=
&
tlb_batch_array
[
smp_processor_id
()][
0
];
}
}
}
start
+=
PAGE_SIZE
;
++
ptep
;
}
while
(
start
<
pmd_end
);
}
else
}
while
(
start
<
pmd_end
);
}
else
{
start
=
pmd_end
;
}
++
pmd
;
}
while
(
start
<
pgd_end
);
}
else
}
while
(
start
<
pgd_end
);
}
else
{
start
=
pgd_end
;
}
++
pgd
;
}
while
(
start
<
end
);
}
while
(
start
<
end
);
if
(
i
)
flush_hash_range
(
context
,
i
,
local
);
...
...
@@ -435,12 +411,12 @@ void __init mm_init_ppc64(void)
* The range of contexts [FIRST_USER_CONTEXT, NUM_USER_CONTEXT)
* are stored on a stack/queue for easy allocation and deallocation.
*/
mmu_context_queue
.
lock
=
SPIN_LOCK_UNLOCKED
;
mmu_context_queue
.
head
=
0
;
mmu_context_queue
.
tail
=
NUM_USER_CONTEXT
-
1
;
mmu_context_queue
.
size
=
NUM_USER_CONTEXT
;
mmu_context_queue
.
lock
=
SPIN_LOCK_UNLOCKED
;
mmu_context_queue
.
head
=
0
;
mmu_context_queue
.
tail
=
NUM_USER_CONTEXT
-
1
;
mmu_context_queue
.
size
=
NUM_USER_CONTEXT
;
for
(
index
=
0
;
index
<
NUM_USER_CONTEXT
;
index
++
)
{
mmu_context_queue
.
elements
[
index
]
=
index
+
FIRST_USER_CONTEXT
;
mmu_context_queue
.
elements
[
index
]
=
index
+
FIRST_USER_CONTEXT
;
}
/* Setup guard pages for the Paca's */
...
...
@@ -463,7 +439,6 @@ void __init do_init_bootmem(void)
unsigned
long
start
,
bootmap_pages
;
unsigned
long
total_pages
=
lmb_end_of_DRAM
()
>>
PAGE_SHIFT
;
PPCDBG
(
PPCDBG_MMINIT
,
"do_init_bootmem: start
\n
"
);
/*
* Find an area to use for the bootmem bitmap. Calculate the size of
* bitmap required as (Total Memory) / PAGE_SIZE / BITS_PER_BYTE.
...
...
@@ -472,21 +447,16 @@ void __init do_init_bootmem(void)
bootmap_pages
=
bootmem_bootmap_pages
(
total_pages
);
start
=
(
unsigned
long
)
__a2p
(
lmb_alloc
(
bootmap_pages
<<
PAGE_SHIFT
,
PAGE_SIZE
));
if
(
start
==
0
)
{
if
(
start
==
0
)
{
udbg_printf
(
"do_init_bootmem: failed to allocate a bitmap.
\n
"
);
udbg_printf
(
"
\t
bootmap_pages = 0x%lx.
\n
"
,
bootmap_pages
);
PPCDBG_ENTER_DEBUGGER
();
}
PPCDBG
(
PPCDBG_MMINIT
,
"
\t
start = 0x%lx
\n
"
,
start
);
PPCDBG
(
PPCDBG_MMINIT
,
"
\t
bootmap_pages = 0x%lx
\n
"
,
bootmap_pages
);
PPCDBG
(
PPCDBG_MMINIT
,
"
\t
physicalMemorySize = 0x%lx
\n
"
,
naca
->
physicalMemorySize
);
boot_mapsize
=
init_bootmem
(
start
>>
PAGE_SHIFT
,
total_pages
);
PPCDBG
(
PPCDBG_MMINIT
,
"
\t
boot_mapsize = 0x%lx
\n
"
,
boot_mapsize
);
/* add all physical memory to the bootmem map */
for
(
i
=
0
;
i
<
lmb
.
memory
.
cnt
;
i
++
)
{
for
(
i
=
0
;
i
<
lmb
.
memory
.
cnt
;
i
++
)
{
unsigned
long
physbase
,
size
;
unsigned
long
type
=
lmb
.
memory
.
region
[
i
].
type
;
...
...
@@ -497,19 +467,14 @@ void __init do_init_bootmem(void)
size
=
lmb
.
memory
.
region
[
i
].
size
;
free_bootmem
(
physbase
,
size
);
}
/* reserve the sections we're already using */
for
(
i
=
0
;
i
<
lmb
.
reserved
.
cnt
;
i
++
)
{
for
(
i
=
0
;
i
<
lmb
.
reserved
.
cnt
;
i
++
)
{
unsigned
long
physbase
=
lmb
.
reserved
.
region
[
i
].
physbase
;
unsigned
long
size
=
lmb
.
reserved
.
region
[
i
].
size
;
#if 0 /* PPPBBB */
if ( (physbase == 0) && (size < (16<<20)) ) {
size = 16 << 20;
}
#endif
reserve_bootmem
(
physbase
,
size
);
}
PPCDBG
(
PPCDBG_MMINIT
,
"do_init_bootmem: end
\n
"
);
}
/*
...
...
@@ -522,7 +487,7 @@ void __init paging_init(void)
/*
* All pages are DMA-able so we put them all in the DMA zone.
*/
zones_size
[
0
]
=
lmb_end_of_DRAM
()
>>
PAGE_SHIFT
;
zones_size
[
ZONE_DMA
]
=
lmb_end_of_DRAM
()
>>
PAGE_SHIFT
;
for
(
i
=
1
;
i
<
MAX_NR_ZONES
;
i
++
)
zones_size
[
i
]
=
0
;
free_area_init
(
zones_size
);
...
...
@@ -554,14 +519,6 @@ void __init mem_init(void)
totalram_pages
+=
free_all_bootmem
();
ifppcdebug
(
PPCDBG_MMINIT
)
{
udbg_printf
(
"mem_init: totalram_pages = 0x%lx
\n
"
,
totalram_pages
);
udbg_printf
(
"mem_init: va_rtas_base = 0x%lx
\n
"
,
va_rtas_base
);
udbg_printf
(
"mem_init: va_rtas_end = 0x%lx
\n
"
,
PAGE_ALIGN
(
va_rtas_base
+
rtas
.
size
));
udbg_printf
(
"mem_init: pinned start = 0x%lx
\n
"
,
__va
(
0
));
udbg_printf
(
"mem_init: pinned end = 0x%lx
\n
"
,
PAGE_ALIGN
(
klimit
));
}
if
(
sysmap_size
)
for
(
addr
=
(
unsigned
long
)
sysmap
;
addr
<
PAGE_ALIGN
((
unsigned
long
)
sysmap
+
sysmap_size
)
;
...
...
@@ -582,7 +539,7 @@ void __init mem_init(void)
datapages
++
;
}
printk
(
"Memory: %luk available (%dk kernel code, %dk data, %dk init) [%08lx,%08lx]
\n
"
,
printk
(
"Memory: %luk available (%dk kernel code, %dk data, %dk init) [%08lx,%08lx]
\n
"
,
(
unsigned
long
)
nr_free_pages
()
<<
(
PAGE_SHIFT
-
10
),
codepages
<<
(
PAGE_SHIFT
-
10
),
datapages
<<
(
PAGE_SHIFT
-
10
),
initpages
<<
(
PAGE_SHIFT
-
10
),
...
...
@@ -613,6 +570,12 @@ void flush_dcache_page(struct page *page)
void
flush_icache_page
(
struct
vm_area_struct
*
vma
,
struct
page
*
page
)
{
if
(
__is_processor
(
PV_POWER4
))
return
;
if
((
vma
->
vm_flags
&
VM_EXEC
)
==
0
)
return
;
if
(
page
->
mapping
&&
!
PageReserved
(
page
)
&&
!
test_bit
(
PG_arch_1
,
&
page
->
flags
))
{
__flush_dcache_icache
(
page_address
(
page
));
...
...
@@ -620,15 +583,35 @@ void flush_icache_page(struct vm_area_struct *vma, struct page *page)
}
}
void
clear_user_page
(
void
*
page
,
unsigned
long
vaddr
)
void
clear_user_page
(
void
*
page
,
unsigned
long
vaddr
,
struct
page
*
pg
)
{
clear_page
(
page
);
/* XXX we shouldnt have to do this, but glibc requires it */
if
(
__is_processor
(
PV_POWER4
))
clear_bit
(
PG_arch_1
,
&
pg
->
flags
);
else
__flush_dcache_icache
(
page
);
}
void
copy_user_page
(
void
*
vto
,
void
*
vfrom
,
unsigned
long
vaddr
)
void
copy_user_page
(
void
*
vto
,
void
*
vfrom
,
unsigned
long
vaddr
,
struct
page
*
pg
)
{
copy_page
(
vto
,
vfrom
);
__flush_dcache_icache
(
vto
);
/*
* Unfortunately we havent always marked our GOT and PLT sections
* as executable, so we need to flush all file regions - Anton
*/
#if 0
if (!vma->vm_file && ((vma->vm_flags & VM_EXEC) == 0))
return;
#endif
if
(
__is_processor
(
PV_POWER4
))
clear_bit
(
PG_arch_1
,
&
pg
->
flags
);
else
__flush_dcache_icache
(
vto
);
}
void
flush_icache_user_range
(
struct
vm_area_struct
*
vma
,
struct
page
*
page
,
...
...
@@ -642,7 +625,7 @@ void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
extern
pte_t
*
find_linux_pte
(
pgd_t
*
pgdir
,
unsigned
long
ea
);
int
__hash_page
(
unsigned
long
ea
,
unsigned
long
access
,
unsigned
long
vsid
,
pte_t
*
ptep
);
pte_t
*
ptep
,
unsigned
long
trap
);
/*
* This is called at the end of handling a user page fault, when the
...
...
@@ -670,5 +653,6 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long ea,
ptep
=
find_linux_pte
(
pgdir
,
ea
);
vsid
=
get_vsid
(
vma
->
vm_mm
->
context
,
ea
);
__hash_page
(
ea
,
pte_val
(
pte
)
&
(
_PAGE_USER
|
_PAGE_RW
),
vsid
,
ptep
);
__hash_page
(
ea
,
pte_val
(
pte
)
&
(
_PAGE_USER
|
_PAGE_RW
),
vsid
,
ptep
,
0x300
);
}
arch/ppc64/vmlinux.lds
View file @
c9195267
...
...
@@ -117,19 +117,6 @@ SECTIONS
. = ALIGN(4096);
__init_end = .;
__chrp_begin = .;
.text.chrp : { *(.text.chrp) }
.data.chrp : { *(.data.chrp) }
. = ALIGN(4096);
__chrp_end = .;
. = ALIGN(4096);
__openfirmware_begin = .;
.text.openfirmware : { *(.text.openfirmware) }
.data.openfirmware : { *(.data.openfirmware) }
. = ALIGN(4096);
__openfirmware_end = .;
__toc_start = .;
.toc :
{
...
...
arch/ppc64/xmon/privinst.h
View file @
c9195267
...
...
@@ -6,7 +6,6 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <linux/config.h>
#define GETREG(reg) \
static inline unsigned long get_ ## reg (void) \
...
...
arch/ppc64/xmon/xmon.c
View file @
c9195267
...
...
@@ -123,11 +123,7 @@ static void mem_translate(void);
static
void
mem_check
(
void
);
static
void
mem_find_real
(
void
);
static
void
mem_find_vsid
(
void
);
static
void
mem_check_pagetable_vsids
(
void
);
static
void
mem_map_check_slab
(
void
);
static
void
mem_map_lock_pages
(
void
);
static
void
mem_check_dup_rpn
(
void
);
static
void
debug_trace
(
void
);
extern
int
print_insn_big_powerpc
(
FILE
*
,
unsigned
long
,
unsigned
long
);
...
...
@@ -642,27 +638,15 @@ cmds(struct pt_regs *excp)
case
'c'
:
mem_check
();
break
;
case
'j'
:
mem_map_check_slab
();
break
;
case
'f'
:
mem_find_real
();
break
;
case
'e'
:
mem_find_vsid
();
break
;
case
'r'
:
mem_check_dup_rpn
();
break
;
case
'i'
:
show_mem
();
break
;
case
'o'
:
mem_check_pagetable_vsids
();
break
;
case
'q'
:
mem_map_lock_pages
()
;
break
;
default:
termch
=
cmd
;
memex
();
...
...
@@ -2458,249 +2442,6 @@ void mem_find_vsid()
printf
(
"
\n
Done -------------------
\n
"
);
}
void
mem_map_check_slab
()
{
int
i
,
slab_count
;
i
=
max_mapnr
;
slab_count
=
0
;
while
(
i
--
>
0
)
{
if
(
PageSlab
(
mem_map
+
i
)){
printf
(
" slab entry - mem_map entry =%p
\n
"
,
mem_map
+
i
);
slab_count
++
;
}
}
printf
(
" count of pages for slab = %d
\n
"
,
slab_count
);
}
void
mem_map_lock_pages
()
{
int
i
,
lock_count
;
i
=
max_mapnr
;
lock_count
=
0
;
while
(
i
--
>
0
)
{
if
(
PageLocked
(
mem_map
+
i
)){
printf
(
" locked entry - mem_map entry =%p
\n
"
,
mem_map
+
i
);
lock_count
++
;
}
}
printf
(
" count of locked pages = %d
\n
"
,
lock_count
);
}
void
mem_check_dup_rpn
()
{
unsigned
long
htab_size_bytes
;
unsigned
long
htab_end
;
unsigned
long
last_rpn
;
HPTE
*
hpte1
,
*
hpte2
;
int
dup_count
;
struct
task_struct
*
p
;
unsigned
long
kernel_vsid_c0
,
kernel_vsid_c1
,
kernel_vsid_c2
,
kernel_vsid_c3
;
unsigned
long
kernel_vsid_c4
,
kernel_vsid_c5
,
kernel_vsid_d
,
kernel_vsid_e
;
unsigned
long
kernel_vsid_f
;
unsigned
long
vsid0
,
vsid1
,
vsidB
,
vsid2
;
htab_size_bytes
=
htab_data
.
htab_num_ptegs
*
128
;
// 128B / PTEG
htab_end
=
(
unsigned
long
)
htab_data
.
htab
+
htab_size_bytes
;
// last_rpn = (naca->physicalMemorySize-1) >> PAGE_SHIFT;
last_rpn
=
0xfffff
;
printf
(
"
\n
Hardware Page Table Check
\n
-------------------
\n
"
);
printf
(
"htab base : %.16lx
\n
"
,
htab_data
.
htab
);
printf
(
"htab size : %.16lx
\n
"
,
htab_size_bytes
);
for
(
hpte1
=
htab_data
.
htab
;
hpte1
<
(
HPTE
*
)
htab_end
;
hpte1
++
)
{
if
(
hpte1
->
dw0
.
dw0
.
v
!=
0
)
{
if
(
hpte1
->
dw1
.
dw1
.
rpn
<=
last_rpn
)
{
dup_count
=
0
;
for
(
hpte2
=
hpte1
+
1
;
hpte2
<
(
HPTE
*
)
htab_end
;
hpte2
++
)
{
if
(
hpte2
->
dw0
.
dw0
.
v
!=
0
)
{
if
(
hpte1
->
dw1
.
dw1
.
rpn
==
hpte2
->
dw1
.
dw1
.
rpn
)
{
dup_count
++
;
}
}
}
if
(
dup_count
>
5
)
{
printf
(
" Duplicate rpn: %.13lx
\n
"
,
(
hpte1
->
dw1
.
dw1
.
rpn
));
printf
(
" mem map array entry %p count = %d
\n
"
,
(
mem_map
+
(
hpte1
->
dw1
.
dw1
.
rpn
)),
(
mem_map
+
(
hpte1
->
dw1
.
dw1
.
rpn
))
->
count
);
for
(
hpte2
=
hpte1
+
1
;
hpte2
<
(
HPTE
*
)
htab_end
;
hpte2
++
)
{
if
(
hpte2
->
dw0
.
dw0
.
v
!=
0
)
{
if
(
hpte1
->
dw1
.
dw1
.
rpn
==
hpte2
->
dw1
.
dw1
.
rpn
)
{
printf
(
" hpte2: %16.16lx *hpte2: %16.16lx %16.16lx
\n
"
,
hpte2
,
hpte2
->
dw0
.
dword0
,
hpte2
->
dw1
.
dword1
);
}
}
}
}
}
else
{
printf
(
" Bogus rpn: %.13lx
\n
"
,
(
hpte1
->
dw1
.
dw1
.
rpn
));
printf
(
" hpte: %16.16lx *hpte: %16.16lx %16.16lx
\n
"
,
hpte1
,
hpte1
->
dw0
.
dword0
,
hpte1
->
dw1
.
dword1
);
}
}
if
(
xmon_interrupted
())
return
;
}
// print the kernel vsids
kernel_vsid_c0
=
get_kernel_vsid
(
0xC000000000000000
);
kernel_vsid_c1
=
get_kernel_vsid
(
0xC000000010000000
);
kernel_vsid_c2
=
get_kernel_vsid
(
0xC000000020000000
);
kernel_vsid_c3
=
get_kernel_vsid
(
0xC000000030000000
);
kernel_vsid_c4
=
get_kernel_vsid
(
0xC000000040000000
);
kernel_vsid_c5
=
get_kernel_vsid
(
0xC000000050000000
);
kernel_vsid_d
=
get_kernel_vsid
(
0xD000000000000000
);
kernel_vsid_e
=
get_kernel_vsid
(
0xE000000000000000
);
kernel_vsid_f
=
get_kernel_vsid
(
0xF000000000000000
);
printf
(
" kernel vsid - seg c0 = %lx
\n
"
,
kernel_vsid_c0
);
printf
(
" kernel vsid - seg c1 = %lx
\n
"
,
kernel_vsid_c1
);
printf
(
" kernel vsid - seg c2 = %lx
\n
"
,
kernel_vsid_c2
);
printf
(
" kernel vsid - seg c3 = %lx
\n
"
,
kernel_vsid_c3
);
printf
(
" kernel vsid - seg c4 = %lx
\n
"
,
kernel_vsid_c4
);
printf
(
" kernel vsid - seg c5 = %lx
\n
"
,
kernel_vsid_c5
);
printf
(
" kernel vsid - seg d = %lx
\n
"
,
kernel_vsid_d
);
printf
(
" kernel vsid - seg e = %lx
\n
"
,
kernel_vsid_e
);
printf
(
" kernel vsid - seg f = %lx
\n
"
,
kernel_vsid_f
);
// print a list of valid vsids for the tasks
read_lock
(
&
tasklist_lock
);
for_each_task
(
p
)
if
(
p
->
mm
)
{
struct
mm_struct
*
mm
=
p
->
mm
;
printf
(
" task = %p mm = %lx pgd %lx
\n
"
,
p
,
mm
,
mm
->
pgd
);
vsid0
=
get_vsid
(
mm
->
context
,
0
);
vsid1
=
get_vsid
(
mm
->
context
,
0x10000000
);
vsid2
=
get_vsid
(
mm
->
context
,
0x20000000
);
vsidB
=
get_vsid
(
mm
->
context
,
0xB0000000
);
printf
(
" context = %lx vsid seg 0 = %lx
\n
"
,
mm
->
context
,
vsid0
);
printf
(
" vsid seg 1 = %lx
\n
"
,
vsid1
);
printf
(
" vsid seg 2 = %lx
\n
"
,
vsid2
);
printf
(
" vsid seg 2 = %lx
\n
"
,
vsidB
);
printf
(
"
\n
"
);
};
read_unlock
(
&
tasklist_lock
);
printf
(
"
\n
Done -------------------
\n
"
);
}
void
mem_check_pagetable_vsids
()
{
unsigned
long
htab_size_bytes
;
unsigned
long
htab_end
;
unsigned
long
last_rpn
;
struct
task_struct
*
p
;
unsigned
long
valid_table_count
,
invalid_table_count
,
bogus_rpn_count
;
int
found
;
unsigned
long
user_address_table_count
,
kernel_page_table_count
;
unsigned
long
pt_vsid
;
HPTE
*
hpte1
;
htab_size_bytes
=
htab_data
.
htab_num_ptegs
*
128
;
// 128B / PTEG
htab_end
=
(
unsigned
long
)
htab_data
.
htab
+
htab_size_bytes
;
// last_rpn = (naca->physicalMemorySize-1) >> PAGE_SHIFT;
last_rpn
=
0xfffff
;
printf
(
"
\n
Hardware Page Table Check
\n
-------------------
\n
"
);
printf
(
"htab base : %.16lx
\n
"
,
htab_data
.
htab
);
printf
(
"htab size : %.16lx
\n
"
,
htab_size_bytes
);
valid_table_count
=
0
;
invalid_table_count
=
0
;
bogus_rpn_count
=
0
;
user_address_table_count
=
0
;
kernel_page_table_count
=
0
;
for
(
hpte1
=
htab_data
.
htab
;
hpte1
<
(
HPTE
*
)
htab_end
;
hpte1
++
)
{
if
(
hpte1
->
dw0
.
dw0
.
v
!=
0
)
{
valid_table_count
++
;
if
(
hpte1
->
dw1
.
dw1
.
rpn
<=
last_rpn
)
{
pt_vsid
=
(
hpte1
->
dw0
.
dw0
.
avpn
)
>>
5
;
if
((
pt_vsid
==
get_kernel_vsid
(
0xC000000000000000
))
|
(
pt_vsid
==
get_kernel_vsid
(
0xC000000010000000
))
|
(
pt_vsid
==
get_kernel_vsid
(
0xC000000020000000
))
|
(
pt_vsid
==
get_kernel_vsid
(
0xC000000030000000
))
|
(
pt_vsid
==
get_kernel_vsid
(
0xC000000040000000
))
|
(
pt_vsid
==
get_kernel_vsid
(
0xC000000050000000
))
|
(
pt_vsid
==
get_kernel_vsid
(
0xD000000000000000
))
|
(
pt_vsid
==
get_kernel_vsid
(
0xE000000000000000
))
|
(
pt_vsid
==
get_kernel_vsid
(
0xF000000000000000
))
)
{
kernel_page_table_count
++
;
}
else
{
read_lock
(
&
tasklist_lock
);
found
=
0
;
for_each_task
(
p
)
{
if
(
p
->
mm
&&
(
found
==
0
))
{
struct
mm_struct
*
mm
=
p
->
mm
;
if
((
pt_vsid
==
get_vsid
(
mm
->
context
,
0
))
|
(
pt_vsid
==
get_vsid
(
mm
->
context
,
0x10000000
))
|
(
pt_vsid
==
get_vsid
(
mm
->
context
,
0x20000000
))
|
(
pt_vsid
==
get_vsid
(
mm
->
context
,
0x30000000
))
|
(
pt_vsid
==
get_vsid
(
mm
->
context
,
0x40000000
))
|
(
pt_vsid
==
get_vsid
(
mm
->
context
,
0x50000000
))
|
(
pt_vsid
==
get_vsid
(
mm
->
context
,
0x60000000
))
|
(
pt_vsid
==
get_vsid
(
mm
->
context
,
0x70000000
))
|
(
pt_vsid
==
get_vsid
(
mm
->
context
,
0x80000000
))
|
(
pt_vsid
==
get_vsid
(
mm
->
context
,
0x90000000
))
|
(
pt_vsid
==
get_vsid
(
mm
->
context
,
0xA0000000
))
|
(
pt_vsid
==
get_vsid
(
mm
->
context
,
0xB0000000
)))
{
user_address_table_count
++
;
found
=
1
;
}
}
}
read_unlock
(
&
tasklist_lock
);
if
(
found
==
0
)
{
printf
(
" vsid not found vsid = %lx, hpte = %p
\n
"
,
pt_vsid
,
hpte1
);
printf
(
" rpn in entry = %lx
\n
"
,
hpte1
->
dw1
.
dw1
.
rpn
);
printf
(
" mem map address = %lx
\n
"
,
mem_map
+
(
hpte1
->
dw1
.
dw1
.
rpn
));
}
else
// found
{
}
}
// good rpn
}
else
{
bogus_rpn_count
++
;
}
}
else
{
invalid_table_count
++
;
}
}
printf
(
" page table valid counts - valid entries = %lx invalid entries = %lx
\n
"
,
valid_table_count
,
invalid_table_count
);
printf
(
" bogus rpn entries ( probably io) = %lx
\n
"
,
bogus_rpn_count
);
printf
(
" page table counts - kernel entries = %lx user entries = %lx
\n
"
,
kernel_page_table_count
,
user_address_table_count
);
printf
(
"
\n
Done -------------------
\n
"
);
}
static
void
debug_trace
(
void
)
{
unsigned
long
val
,
cmd
,
on
;
...
...
include/asm-ppc64/bitops.h
View file @
c9195267
...
...
@@ -259,6 +259,12 @@ static __inline__ int ffs(int x)
return
__ilog2
(
i
&
-
i
)
+
1
;
}
/*
* fls: find last (most-significant) bit set.
* Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
*/
#define fls(x) generic_fls(x)
/*
* hweightN: returns the hamming weight (i.e. the number
* of bits set) of a N-bit word
...
...
include/asm-ppc64/cache.h
View file @
c9195267
...
...
@@ -8,6 +8,7 @@
#define __ARCH_PPC64_CACHE_H
/* bytes per L1 cache line */
#define L1_CACHE_BYTES 128
#define L1_CACHE_SHIFT 7
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
#endif
include/asm-ppc64/iSeries/HvCall.h
View file @
c9195267
...
...
@@ -130,6 +130,9 @@ enum HvCall_VaryOffChunkRc
#define HvCallBaseRouter28 HvCallBase + 28
#define HvCallBaseRouter29 HvCallBase + 29
#define HvCallBaseRouter30 HvCallBase + 30
#define HvCallCcSetDABR HvCallCc + 7
//=====================================================================================
static
inline
void
HvCall_setVirtualDecr
(
void
)
{
...
...
@@ -197,6 +200,10 @@ static inline void HvCall_terminateMachineSrc(void)
HvCall0
(
HvCallBaseTerminateMachineSrc
);
}
static
inline
void
HvCall_setDABR
(
unsigned
long
val
)
{
HvCall1
(
HvCallCcSetDABR
,
val
);
}
#endif // _HVCALL_H
include/asm-ppc64/iSeries/HvCallHpt.h
View file @
c9195267
...
...
@@ -106,21 +106,21 @@ static inline u64 HvCallHpt_invalidateSetSwBitsGet(u32 hpteIndex, u8 bitson, u8
return
compressedStatus
;
}
//=============================================================================
static
inline
u64
HvCallHpt_findValid
(
struct
HPTE
*
hpte
,
u64
vpn
)
static
inline
u64
HvCallHpt_findValid
(
HPTE
*
hpte
,
u64
vpn
)
{
u64
retIndex
=
HvCall3Ret16
(
HvCallHptFindValid
,
hpte
,
vpn
,
0
,
0
);
// getPaca()->adjustHmtForNoOfSpinLocksHeld();
return
retIndex
;
}
//=============================================================================
static
inline
u64
HvCallHpt_findNextValid
(
struct
HPTE
*
hpte
,
u32
hpteIndex
,
u8
bitson
,
u8
bitsoff
)
static
inline
u64
HvCallHpt_findNextValid
(
HPTE
*
hpte
,
u32
hpteIndex
,
u8
bitson
,
u8
bitsoff
)
{
u64
retIndex
=
HvCall3Ret16
(
HvCallHptFindNextValid
,
hpte
,
hpteIndex
,
bitson
,
bitsoff
);
// getPaca()->adjustHmtForNoOfSpinLocksHeld();
return
retIndex
;
}
//=============================================================================
static
inline
void
HvCallHpt_get
(
struct
HPTE
*
hpte
,
u32
hpteIndex
)
static
inline
void
HvCallHpt_get
(
HPTE
*
hpte
,
u32
hpteIndex
)
{
HvCall2Ret16
(
HvCallHptGet
,
hpte
,
hpteIndex
,
0
);
// getPaca()->adjustHmtForNoOfSpinLocksHeld();
...
...
@@ -128,7 +128,7 @@ static inline void HvCallHpt_get( struct HPTE *hpte, u32 hpteIndex )
//============================================================================
static
inline
void
HvCallHpt_addValidate
(
u32
hpteIndex
,
u32
hBit
,
struct
HPTE
*
hpte
)
HPTE
*
hpte
)
{
HvCall4
(
HvCallHptAddValidate
,
hpteIndex
,
...
...
include/asm-ppc64/iSeries/HvCallSc.h
View file @
c9195267
...
...
@@ -25,6 +25,7 @@
#define _HVCALLSC_H
#define HvCallBase 0x8000000000000000
#define HvCallCc 0x8001000000000000
#define HvCallCfg 0x8002000000000000
#define HvCallEvent 0x8003000000000000
#define HvCallHpt 0x8004000000000000
...
...
include/asm-ppc64/init.h
View file @
c9195267
#ifndef _PPC64_INIT_H
#define _PPC64_INIT_H
#include <linux/init.h>
#if __GNUC__ > 2 || __GNUC_MINOR__ >= 90
/* egcs */
/* DRENG add back in when we get section attribute support */
#define __chrp __attribute__ ((__section__ (".text.chrp")))
#define __chrpdata __attribute__ ((__section__ (".data.chrp")))
#define __chrpfunc(__argchrp) \
__argchrp __chrp; \
__argchrp
/* this is actually just common chrp/pmac code, not OF code -- Cort */
#define __openfirmware __attribute__ ((__section__ (".text.openfirmware")))
#define __openfirmwaredata __attribute__ ((__section__ (".data.openfirmware")))
#define __openfirmwarefunc(__argopenfirmware) \
__argopenfirmware __openfirmware; \
__argopenfirmware
#else
/* not egcs */
#define __openfirmware
#define __openfirmwaredata
#define __openfirmwarefunc(x) x
#endif
/* egcs */
#endif
/* _PPC64_INIT_H */
#error "<asm/init.h> should never be used - use <linux/init.h> instead"
include/asm-ppc64/lmb.h
View file @
c9195267
...
...
@@ -13,6 +13,7 @@
* 2 of the License, or (at your option) any later version.
*/
#include <linux/config.h>
#include <asm/prom.h>
extern
unsigned
long
reloc_offset
(
void
);
...
...
include/asm-ppc64/md.h
deleted
100644 → 0
View file @
278b098b
/*
* md.h: High speed xor_block operation for RAID4/5
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef __ASM_MD_H
#define __ASM_MD_H
/* #define HAVE_ARCH_XORBLOCK */
#define MD_XORBLOCK_ALIGNMENT sizeof(long)
#endif
/* __ASM_MD_H */
include/asm-ppc64/mmzone.h
0 → 100644
View file @
c9195267
/*
* Written by Kanoj Sarcar (kanoj@sgi.com) Aug 99
*
* PowerPC64 port:
* Copyright (C) 2002 Anton Blanchard, IBM Corp.
*/
#ifndef _ASM_MMZONE_H_
#define _ASM_MMZONE_H_
#include <linux/config.h>
typedef
struct
plat_pglist_data
{
pg_data_t
gendata
;
}
plat_pg_data_t
;
/*
* Following are macros that are specific to this numa platform.
*/
extern
plat_pg_data_t
plat_node_data
[];
#define MAX_NUMNODES 4
/* XXX grab this from the device tree - Anton */
#define PHYSADDR_TO_NID(pa) ((pa) >> 36)
#define PLAT_NODE_DATA(n) (&plat_node_data[(n)])
#define PLAT_NODE_DATA_STARTNR(n) \
(PLAT_NODE_DATA(n)->gendata.node_start_mapnr)
#define PLAT_NODE_DATA_SIZE(n) (PLAT_NODE_DATA(n)->gendata.node_size)
#define PLAT_NODE_DATA_LOCALNR(p, n) \
(((p) - PLAT_NODE_DATA(n)->gendata.node_start_paddr) >> PAGE_SHIFT)
#ifdef CONFIG_DISCONTIGMEM
/*
* Following are macros that each numa implmentation must define.
*/
/*
* Given a kernel address, find the home node of the underlying memory.
*/
#define KVADDR_TO_NID(kaddr) PHYSADDR_TO_NID(__pa(kaddr))
/*
* Return a pointer to the node data for node n.
*/
#define NODE_DATA(n) (&((PLAT_NODE_DATA(n))->gendata))
/*
* NODE_MEM_MAP gives the kaddr for the mem_map of the node.
*/
#define NODE_MEM_MAP(nid) (NODE_DATA(nid)->node_mem_map)
/*
* Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
* and returns the mem_map of that node.
*/
#define ADDR_TO_MAPBASE(kaddr) \
NODE_MEM_MAP(KVADDR_TO_NID((unsigned long)(kaddr)))
/*
* Given a kaddr, LOCAL_BASE_ADDR finds the owning node of the memory
* and returns the kaddr corresponding to first physical page in the
* node's mem_map.
*/
#define LOCAL_BASE_ADDR(kaddr) \
((unsigned long)__va(NODE_DATA(KVADDR_TO_NID(kaddr))->node_start_paddr))
#define LOCAL_MAP_NR(kvaddr) \
(((unsigned long)(kvaddr)-LOCAL_BASE_ADDR(kvaddr)) >> PAGE_SHIFT)
#if 0
/* XXX fix - Anton */
#define kern_addr_valid(kaddr) test_bit(LOCAL_MAP_NR(kaddr), \
NODE_DATA(KVADDR_TO_NID(kaddr))->valid_addr_bitmap)
#endif
#define discontigmem_pfn_to_page(pfn) \
({ \
unsigned long kaddr = (unsigned long)__va(pfn << PAGE_SHIFT); \
(ADDR_TO_MAPBASE(kaddr) + LOCAL_MAP_NR(kaddr)); \
})
#ifdef CONFIG_NUMA
/* XXX grab this from the device tree - Anton */
#define cputonode(cpu) ((cpu) >> 3)
#define numa_node_id() cputonode(smp_processor_id())
#endif
/* CONFIG_NUMA */
#endif
/* CONFIG_DISCONTIGMEM */
#endif
/* _ASM_MMZONE_H_ */
include/asm-ppc64/page.h
View file @
c9195267
...
...
@@ -33,24 +33,13 @@
#ifndef __ASSEMBLY__
#include <asm/naca.h>
#
define
STRICT_MM_TYPECHECKS
#
undef
STRICT_MM_TYPECHECKS
#define REGION_SIZE 4UL
#define OFFSET_SIZE 60UL
#define REGION_SHIFT 60UL
#define OFFSET_SHIFT 0UL
#define REGION_MASK (((1UL<<REGION_SIZE)-1UL)<<REGION_SHIFT)
#define REGION_STRIDE (1UL << REGION_SHIFT)
typedef
union
ppc64_va
{
struct
{
unsigned
long
off
:
OFFSET_SIZE
;
/* intra-region offset */
unsigned
long
reg
:
REGION_SIZE
;
/* region number */
}
f
;
unsigned
long
l
;
void
*
p
;
}
ppc64_va
;
static
__inline__
void
clear_page
(
void
*
addr
)
{
unsigned
long
lines
,
line_size
;
...
...
@@ -70,8 +59,8 @@ static __inline__ void clear_page(void *addr)
extern
void
copy_page
(
void
*
to
,
void
*
from
);
struct
page
;
extern
void
clear_user_page
(
void
*
page
,
unsigned
long
vaddr
);
extern
void
copy_user_page
(
void
*
to
,
void
*
from
,
unsigned
long
vaddr
);
extern
void
clear_user_page
(
void
*
page
,
unsigned
long
vaddr
,
struct
page
*
pg
);
extern
void
copy_user_page
(
void
*
to
,
void
*
from
,
unsigned
long
vaddr
,
struct
page
*
p
);
#ifdef STRICT_MM_TYPECHECKS
/*
...
...
@@ -215,8 +204,15 @@ static inline int get_order(unsigned long size)
#define __a2p(x) ((void *) absolute_to_phys(x))
#define __a2v(x) ((void *) __va(absolute_to_phys(x)))
#ifdef CONFIG_DISCONTIGMEM
#define page_to_pfn(page) \
((page) - page_zone(page)->zone_mem_map + \
(page_zone(page)->zone_start_paddr >> PAGE_SHIFT))
#define pfn_to_page(pfn) discontigmem_pfn_to_page(pfn)
#else
#define pfn_to_page(pfn) (mem_map + (pfn))
#define page_to_pfn(pfn) ((unsigned long)((pfn) - mem_map))
#define page_to_pfn(page) ((unsigned long)((page) - mem_map))
#endif
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
#define pfn_valid(pfn) ((pfn) < max_mapnr)
...
...
include/asm-ppc64/pgalloc.h
View file @
c9195267
...
...
@@ -53,6 +53,8 @@ pmd_free(pmd_t *pmd)
free_page
((
unsigned
long
)
pmd
);
}
#define pmd_free_tlb(tlb, pmd) pmd_free(pmd)
#define pmd_populate_kernel(mm, pmd, pte) pmd_set(pmd, pte)
#define pmd_populate(mm, pmd, pte_page) \
pmd_populate_kernel(mm, pmd, page_address(pte_page))
...
...
@@ -86,6 +88,7 @@ pte_free_kernel(pte_t *pte)
}
#define pte_free(pte_page) pte_free_kernel(page_address(pte_page))
#define pte_free_tlb(tlb, pte) pte_free(pte)
#define check_pgt_cache() do { } while (0)
...
...
include/asm-ppc64/pgtable.h
View file @
c9195267
...
...
@@ -12,11 +12,6 @@
#include <asm/page.h>
#endif
/* __ASSEMBLY__ */
/* Certain architectures need to do special things when pte's
* within a page table are directly modified. Thus, the following
* hook is made available.
*/
/* PMD_SHIFT determines what a second-level page table entry can map */
#define PMD_SHIFT (PAGE_SHIFT + PAGE_SHIFT - 3)
#define PMD_SIZE (1UL << PMD_SHIFT)
...
...
@@ -107,9 +102,9 @@
/* preserving _PAGE_SECONDARY | _PAGE_GROUP_IX */
#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_HPTEFLAGS)
#define _PAGE_BASE
_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_COHERENT
#define _PAGE_BASE
(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_COHERENT)
#define _PAGE_WRENABLE
_PAGE_RW | _PAGE_DIRTY
#define _PAGE_WRENABLE
(_PAGE_RW | _PAGE_DIRTY)
/* __pgprot defined in asm-ppc64/page.h */
#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
...
...
@@ -330,8 +325,6 @@ static inline void pte_clear(pte_t * ptep)
pte_update
(
ptep
,
~
_PAGE_HPTEFLAGS
,
0
);
}
extern
unsigned
long
va_to_phys
(
unsigned
long
address
);
extern
pte_t
*
va_to_pte
(
unsigned
long
address
);
extern
unsigned
long
ioremap_bot
,
ioremap_base
;
#define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
...
...
@@ -356,6 +349,7 @@ extern void paging_init(void);
* ahead of time, instead of waiting for the inevitable extra
* hash-table miss exception.
*/
struct
vm_area_struct
;
extern
void
update_mmu_cache
(
struct
vm_area_struct
*
,
unsigned
long
,
pte_t
);
/* Encode and de-code a swap entry */
...
...
@@ -380,12 +374,8 @@ extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
*/
#define pgtable_cache_init() do { } while (0)
extern
void
updateBoltedHptePP
(
unsigned
long
newpp
,
unsigned
long
ea
);
extern
void
hpte_init_pSeries
(
void
);
extern
void
hpte_init_iSeries
(
void
);
extern
void
make_pte
(
HPTE
*
htab
,
unsigned
long
va
,
unsigned
long
pa
,
int
mode
,
unsigned
long
hash_mask
,
int
large
);
#endif
/* __ASSEMBLY__ */
#endif
/* _PPC64_PGTABLE_H */
include/asm-ppc64/prom.h
View file @
c9195267
...
...
@@ -195,8 +195,5 @@ extern void print_properties(struct device_node *node);
extern
int
prom_n_addr_cells
(
struct
device_node
*
np
);
extern
int
prom_n_size_cells
(
struct
device_node
*
np
);
extern
void
prom_get_irq_senses
(
unsigned
char
*
senses
,
int
off
,
int
max
);
extern
void
prom_drawstring
(
const
char
*
c
);
extern
void
prom_drawhex
(
unsigned
long
v
);
extern
void
prom_drawchar
(
char
c
);
#endif
/* _PPC64_PROM_H */
include/asm-ppc64/ptrace-common.h
0 → 100644
View file @
c9195267
/*
* linux/arch/ppc64/kernel/ptrace-common.h
*
* Copyright (c) 2002 Stephen Rothwell, IBM Coproration
* Extracted from ptrace.c and ptrace32.c
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file README.legal in the main directory of
* this archive for more details.
*/
/*
* Set of msr bits that gdb can change on behalf of a process.
*/
#define MSR_DEBUGCHANGE (MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1)
/*
* Get contents of register REGNO in task TASK.
*/
static
inline
unsigned
long
get_reg
(
struct
task_struct
*
task
,
int
regno
)
{
if
(
regno
<
(
sizeof
(
struct
pt_regs
)
/
sizeof
(
unsigned
long
)))
return
((
unsigned
long
*
)
task
->
thread
.
regs
)[
regno
];
return
0
;
}
/*
* Write contents of register REGNO in task TASK.
*/
static
inline
int
put_reg
(
struct
task_struct
*
task
,
int
regno
,
unsigned
long
data
)
{
if
(
regno
<
PT_SOFTE
)
{
if
(
regno
==
PT_MSR
)
data
=
(
data
&
MSR_DEBUGCHANGE
)
|
(
task
->
thread
.
regs
->
msr
&
~
MSR_DEBUGCHANGE
);
((
unsigned
long
*
)
task
->
thread
.
regs
)[
regno
]
=
data
;
return
0
;
}
return
-
EIO
;
}
static
inline
void
set_single_step
(
struct
task_struct
*
task
)
{
struct
pt_regs
*
regs
=
task
->
thread
.
regs
;
if
(
regs
!=
NULL
)
regs
->
msr
|=
MSR_SE
;
}
static
inline
void
clear_single_step
(
struct
task_struct
*
task
)
{
struct
pt_regs
*
regs
=
task
->
thread
.
regs
;
if
(
regs
!=
NULL
)
regs
->
msr
&=
~
MSR_SE
;
}
include/asm-ppc64/rtas.h
View file @
c9195267
...
...
@@ -2,6 +2,7 @@
#define _PPC64_RTAS_H
#include <linux/spinlock.h>
#include <asm/page.h>
/*
* Definitions for talking to the RTAS on CHRP machines.
...
...
@@ -128,6 +129,29 @@ struct rtas_error_log {
unsigned
char
buffer
[
1
];
/* allocated by klimit bump */
};
struct
flash_block
{
char
*
data
;
unsigned
long
length
;
};
/* This struct is very similar but not identical to
* that needed by the rtas flash update.
* All we need to do for rtas is rewrite num_blocks
* into a version/length and translate the pointers
* to absolute.
*/
#define FLASH_BLOCKS_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct flash_block))
struct
flash_block_list
{
unsigned
long
num_blocks
;
struct
flash_block_list
*
next
;
struct
flash_block
blocks
[
FLASH_BLOCKS_PER_NODE
];
};
struct
flash_block_list_header
{
/* just the header of flash_block_list */
unsigned
long
num_blocks
;
struct
flash_block_list
*
next
;
};
extern
struct
flash_block_list_header
rtas_firmware_flash_list
;
extern
struct
rtas_t
rtas
;
extern
void
enter_rtas
(
struct
rtas_args
*
);
...
...
@@ -140,4 +164,7 @@ extern void rtas_restart(char *cmd);
extern
void
rtas_power_off
(
void
);
extern
void
rtas_halt
(
void
);
extern
struct
proc_dir_entry
*
rtas_proc_dir
;
#endif
/* _PPC64_RTAS_H */
include/asm-ppc64/softirq.h
View file @
c9195267
...
...
@@ -8,22 +8,20 @@
* 2 of the License, or (at your option) any later version.
*/
#include <asm/atomic.h>
#include <asm/hardirq.h>
#define local_bh_disable() do { local_bh_count(smp_processor_id())++; barrier(); } while (0)
#define __local_bh_enable() do { barrier(); local_bh_count(smp_processor_id())--; } while (0)
#define local_bh_enable() \
do { \
barrier(); \
if (!--local_bh_count(smp_processor_id()) \
&& softirq_pending(smp_processor_id())) { \
do_softirq(); \
} \
} while (0)
#define in_softirq() (local_bh_count(smp_processor_id()) != 0)
#endif
/* __ASM_SOFTIRQ_H */
include/asm-ppc64/system.h
View file @
c9195267
...
...
@@ -9,19 +9,11 @@
*/
#include <linux/config.h>
#include <linux/kdev_t.h>
#include <asm/page.h>
#include <asm/processor.h>
#include <asm/hw_irq.h>
#include <asm/memory.h>
/*
* System defines.
*/
#define KERNEL_START_PHYS 0x800000
#define KERNEL_START (PAGE_OFFSET+KERNEL_START_PHYS)
#define START_ADDR (PAGE_OFFSET+KERNEL_START_PHYS+0x00000)
/*
* Memory barrier.
* The sync instruction guarantees that all memory accesses initiated
...
...
@@ -85,24 +77,13 @@ extern void (*xmon_fault_handler)(struct pt_regs *regs);
extern
void
print_backtrace
(
unsigned
long
*
);
extern
void
show_regs
(
struct
pt_regs
*
regs
);
extern
void
flush_instruction_cache
(
void
);
extern
void
hard_reset_now
(
void
);
extern
void
poweroff_now
(
void
);
extern
int
_get_PVR
(
void
);
extern
long
_get_L2CR
(
void
);
extern
void
_set_L2CR
(
unsigned
long
);
extern
void
via_cuda_init
(
void
);
extern
void
pmac_nvram_init
(
void
);
extern
void
pmac_find_display
(
void
);
extern
void
giveup_fpu
(
struct
task_struct
*
);
extern
void
enable_kernel_fp
(
void
);
extern
void
giveup_altivec
(
struct
task_struct
*
);
extern
void
load_up_altivec
(
struct
task_struct
*
);
extern
void
cvt_fd
(
float
*
from
,
double
*
to
,
unsigned
long
*
fpscr
);
extern
void
cvt_df
(
double
*
from
,
float
*
to
,
unsigned
long
*
fpscr
);
extern
int
abs
(
int
);
struct
device_node
;
struct
task_struct
;
#define prepare_to_switch() do { } while(0)
#define switch_to(prev,next) _switch_to((prev),(next))
...
...
include/asm-ppc64/time.h
View file @
c9195267
...
...
@@ -14,6 +14,7 @@
#define __PPC64_TIME_H
#ifdef __KERNEL__
#include <linux/config.h>
#include <linux/types.h>
#include <linux/mc146818rtc.h>
...
...
include/asm-ppc64/tlb.h
View file @
c9195267
/*
* TLB shootdown specifics for PPC64
*
* Copyright (C) 2002 Anton Blanchard, IBM Corp.
* Copyright (C) 2002 Paul Mackerras, IBM Corp.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _PPC64_TLB_H
#define _PPC64_TLB_H
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
#include <asm/page.h>
#include <asm/mmu.h>
struct
free_pte_ctx
;
static
inline
void
tlb_flush
(
struct
free_pte_ctx
*
tlb
);
/* Get the generic bits... */
#include <asm-generic/tlb.h>
/* Nothing needed here in fact... */
#define tlb_start_vma(tlb, vma) do { } while (0)
#define tlb_end_vma(tlb, vma) do { } while (0)
/* Should make this at least as large as the generic batch size, but it
* takes up too much space */
#define PPC64_TLB_BATCH_NR 192
struct
ppc64_tlb_batch
{
unsigned
long
index
;
pte_t
pte
[
PPC64_TLB_BATCH_NR
];
unsigned
long
addr
[
PPC64_TLB_BATCH_NR
];
unsigned
long
vaddr
[
PPC64_TLB_BATCH_NR
];
};
extern
struct
ppc64_tlb_batch
ppc64_tlb_batch
[
NR_CPUS
];
static
inline
void
tlb_remove_tlb_entry
(
mmu_gather_t
*
tlb
,
pte_t
*
ptep
,
unsigned
long
address
)
{
int
cpu
=
smp_processor_id
();
struct
ppc64_tlb_batch
*
batch
=
&
ppc64_tlb_batch
[
cpu
];
unsigned
long
i
=
batch
->
index
;
pte_t
pte
;
if
(
pte_val
(
*
ptep
)
&
_PAGE_HASHPTE
)
{
pte
=
__pte
(
pte_update
(
ptep
,
_PAGE_HPTEFLAGS
,
0
));
if
(
pte_val
(
pte
)
&
_PAGE_HASHPTE
)
{
int
local
=
0
;
if
(
tlb
->
mm
->
cpu_vm_mask
==
(
1
<<
cpu
))
local
=
1
;
batch
->
pte
[
i
]
=
pte
;
batch
->
addr
[
i
]
=
address
;
i
++
;
if
(
i
==
PPC64_TLB_BATCH_NR
)
{
flush_hash_range
(
tlb
->
mm
->
context
,
i
,
local
);
i
=
0
;
}
}
}
batch
->
index
=
i
;
}
static
inline
void
tlb_flush
(
struct
free_pte_ctx
*
tlb
)
{
int
cpu
=
smp_processor_id
();
struct
ppc64_tlb_batch
*
batch
=
&
ppc64_tlb_batch
[
cpu
];
int
local
=
0
;
if
(
tlb
->
mm
->
cpu_vm_mask
==
(
1
<<
smp_processor_id
()))
local
=
1
;
flush_hash_range
(
tlb
->
mm
->
context
,
batch
->
index
,
local
);
batch
->
index
=
0
;
}
#endif
/* _PPC64_TLB_H */
include/asm-ppc64/tlbflush.h
View file @
c9195267
...
...
@@ -35,12 +35,4 @@ extern void flush_hash_page(unsigned long context, unsigned long ea, pte_t pte,
int
local
);
void
flush_hash_range
(
unsigned
long
context
,
unsigned
long
number
,
int
local
);
/* TLB flush batching */
#define MAX_BATCH_FLUSH 128
struct
tlb_batch_data
{
pte_t
pte
;
unsigned
long
addr
;
};
extern
struct
tlb_batch_data
tlb_batch_array
[
NR_CPUS
][
MAX_BATCH_FLUSH
];
#endif
/* _PPC64_TLBFLUSH_H */
include/asm-ppc64/uaccess.h
View file @
c9195267
...
...
@@ -124,9 +124,6 @@ do { \
} \
} while (0)
struct
__large_struct
{
unsigned
long
buf
[
100
];
};
#define __m(x) (*(struct __large_struct *)(x))
/*
* We don't tell gcc that we are accessing memory, but this is OK
* because we do not write to any memory gcc knows about, so there
...
...
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