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
nexedi
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