Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
26cda988
K
Kernel
项目概览
openeuler
/
Kernel
大约 1 年 前同步成功
通知
5
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
26cda988
编写于
9月 12, 2005
作者:
L
Linus Torvalds
浏览文件
操作
浏览文件
下载
差异文件
Merge master.kernel.org:/pub/scm/linux/kernel/git/paulus/ppc64-2.6
上级
1df5c10a
2d909d08
变更
28
隐藏空白更改
内联
并排
Showing
28 changed file
with
795 addition
and
273 deletion
+795
-273
arch/ppc64/kernel/iSeries_pci.c
arch/ppc64/kernel/iSeries_pci.c
+1
-1
arch/ppc64/kernel/maple_pci.c
arch/ppc64/kernel/maple_pci.c
+28
-28
arch/ppc64/kernel/pSeries_setup.c
arch/ppc64/kernel/pSeries_setup.c
+8
-0
arch/ppc64/kernel/pSeries_smp.c
arch/ppc64/kernel/pSeries_smp.c
+11
-2
arch/ppc64/kernel/pci.c
arch/ppc64/kernel/pci.c
+335
-90
arch/ppc64/kernel/pmac_pci.c
arch/ppc64/kernel/pmac_pci.c
+30
-30
arch/ppc64/kernel/pmac_setup.c
arch/ppc64/kernel/pmac_setup.c
+13
-0
arch/ppc64/kernel/process.c
arch/ppc64/kernel/process.c
+34
-0
arch/ppc64/kernel/ptrace.c
arch/ppc64/kernel/ptrace.c
+28
-0
arch/ppc64/kernel/ptrace32.c
arch/ppc64/kernel/ptrace32.c
+31
-3
arch/ppc64/kernel/ras.c
arch/ppc64/kernel/ras.c
+0
-2
arch/ppc64/kernel/setup.c
arch/ppc64/kernel/setup.c
+0
-16
arch/ppc64/kernel/signal.c
arch/ppc64/kernel/signal.c
+9
-0
arch/ppc64/kernel/signal32.c
arch/ppc64/kernel/signal32.c
+8
-0
arch/ppc64/kernel/xics.c
arch/ppc64/kernel/xics.c
+22
-22
arch/ppc64/mm/fault.c
arch/ppc64/mm/fault.c
+25
-6
arch/ppc64/xmon/privinst.h
arch/ppc64/xmon/privinst.h
+0
-1
arch/ppc64/xmon/xmon.c
arch/ppc64/xmon/xmon.c
+4
-16
include/asm-powerpc/siginfo.h
include/asm-powerpc/siginfo.h
+8
-0
include/asm-ppc/ptrace.h
include/asm-ppc/ptrace.h
+7
-0
include/asm-ppc64/hvcall.h
include/asm-ppc64/hvcall.h
+6
-0
include/asm-ppc64/machdep.h
include/asm-ppc64/machdep.h
+1
-4
include/asm-ppc64/pci-bridge.h
include/asm-ppc64/pci-bridge.h
+5
-0
include/asm-ppc64/plpar_wrappers.h
include/asm-ppc64/plpar_wrappers.h
+9
-0
include/asm-ppc64/processor.h
include/asm-ppc64/processor.h
+1
-0
include/asm-ppc64/ptrace-common.h
include/asm-ppc64/ptrace-common.h
+92
-0
include/asm-ppc64/ptrace.h
include/asm-ppc64/ptrace.h
+76
-52
include/asm-ppc64/system.h
include/asm-ppc64/system.h
+3
-0
未找到文件。
arch/ppc64/kernel/iSeries_pci.c
浏览文件 @
26cda988
...
@@ -252,7 +252,7 @@ unsigned long __init find_and_init_phbs(void)
...
@@ -252,7 +252,7 @@ unsigned long __init find_and_init_phbs(void)
phb
=
(
struct
pci_controller
*
)
kmalloc
(
sizeof
(
struct
pci_controller
),
GFP_KERNEL
);
phb
=
(
struct
pci_controller
*
)
kmalloc
(
sizeof
(
struct
pci_controller
),
GFP_KERNEL
);
if
(
phb
==
NULL
)
if
(
phb
==
NULL
)
return
-
ENOMEM
;
return
-
ENOMEM
;
pci_setup_pci_controller
(
phb
);
pci_setup_pci_controller
(
phb
);
phb
->
pci_mem_offset
=
phb
->
local_number
=
bus
;
phb
->
pci_mem_offset
=
phb
->
local_number
=
bus
;
phb
->
first_busno
=
bus
;
phb
->
first_busno
=
bus
;
...
...
arch/ppc64/kernel/maple_pci.c
浏览文件 @
26cda988
...
@@ -283,7 +283,7 @@ static void __init setup_u3_agp(struct pci_controller* hose)
...
@@ -283,7 +283,7 @@ static void __init setup_u3_agp(struct pci_controller* hose)
* the reg address cell, we shall fix that by killing struct
* the reg address cell, we shall fix that by killing struct
* reg_property and using some accessor functions instead
* reg_property and using some accessor functions instead
*/
*/
hose
->
first_busno
=
0xf0
;
hose
->
first_busno
=
0xf0
;
hose
->
last_busno
=
0xff
;
hose
->
last_busno
=
0xff
;
hose
->
ops
=
&
u3_agp_pci_ops
;
hose
->
ops
=
&
u3_agp_pci_ops
;
hose
->
cfg_addr
=
ioremap
(
0xf0000000
+
0x800000
,
0x1000
);
hose
->
cfg_addr
=
ioremap
(
0xf0000000
+
0x800000
,
0x1000
);
...
@@ -315,24 +315,24 @@ static int __init add_bridge(struct device_node *dev)
...
@@ -315,24 +315,24 @@ static int __init add_bridge(struct device_node *dev)
char
*
disp_name
;
char
*
disp_name
;
int
*
bus_range
;
int
*
bus_range
;
int
primary
=
1
;
int
primary
=
1
;
struct
property
*
of_prop
;
struct
property
*
of_prop
;
DBG
(
"Adding PCI host bridge %s
\n
"
,
dev
->
full_name
);
DBG
(
"Adding PCI host bridge %s
\n
"
,
dev
->
full_name
);
bus_range
=
(
int
*
)
get_property
(
dev
,
"bus-range"
,
&
len
);
bus_range
=
(
int
*
)
get_property
(
dev
,
"bus-range"
,
&
len
);
if
(
bus_range
==
NULL
||
len
<
2
*
sizeof
(
int
))
{
if
(
bus_range
==
NULL
||
len
<
2
*
sizeof
(
int
))
{
printk
(
KERN_WARNING
"Can't get bus-range for %s, assume bus 0
\n
"
,
printk
(
KERN_WARNING
"Can't get bus-range for %s, assume bus 0
\n
"
,
dev
->
full_name
);
dev
->
full_name
);
}
}
hose
=
alloc_bootmem
(
sizeof
(
struct
pci_controller
));
hose
=
alloc_bootmem
(
sizeof
(
struct
pci_controller
));
if
(
hose
==
NULL
)
if
(
hose
==
NULL
)
return
-
ENOMEM
;
return
-
ENOMEM
;
pci_setup_pci_controller
(
hose
);
pci_setup_pci_controller
(
hose
);
hose
->
arch_data
=
dev
;
hose
->
arch_data
=
dev
;
hose
->
first_busno
=
bus_range
?
bus_range
[
0
]
:
0
;
hose
->
first_busno
=
bus_range
?
bus_range
[
0
]
:
0
;
hose
->
last_busno
=
bus_range
?
bus_range
[
1
]
:
0xff
;
hose
->
last_busno
=
bus_range
?
bus_range
[
1
]
:
0xff
;
of_prop
=
alloc_bootmem
(
sizeof
(
struct
property
)
+
of_prop
=
alloc_bootmem
(
sizeof
(
struct
property
)
+
sizeof
(
hose
->
global_number
));
sizeof
(
hose
->
global_number
));
...
@@ -346,25 +346,25 @@ static int __init add_bridge(struct device_node *dev)
...
@@ -346,25 +346,25 @@ static int __init add_bridge(struct device_node *dev)
}
}
disp_name
=
NULL
;
disp_name
=
NULL
;
if
(
device_is_compatible
(
dev
,
"u3-agp"
))
{
if
(
device_is_compatible
(
dev
,
"u3-agp"
))
{
setup_u3_agp
(
hose
);
setup_u3_agp
(
hose
);
disp_name
=
"U3-AGP"
;
disp_name
=
"U3-AGP"
;
primary
=
0
;
primary
=
0
;
}
else
if
(
device_is_compatible
(
dev
,
"u3-ht"
))
{
}
else
if
(
device_is_compatible
(
dev
,
"u3-ht"
))
{
setup_u3_ht
(
hose
);
setup_u3_ht
(
hose
);
disp_name
=
"U3-HT"
;
disp_name
=
"U3-HT"
;
primary
=
1
;
primary
=
1
;
}
}
printk
(
KERN_INFO
"Found %s PCI host bridge. Firmware bus number: %d->%d
\n
"
,
printk
(
KERN_INFO
"Found %s PCI host bridge. Firmware bus number: %d->%d
\n
"
,
disp_name
,
hose
->
first_busno
,
hose
->
last_busno
);
disp_name
,
hose
->
first_busno
,
hose
->
last_busno
);
/* Interpret the "ranges" property */
/* Interpret the "ranges" property */
/* This also maps the I/O region and sets isa_io/mem_base */
/* This also maps the I/O region and sets isa_io/mem_base */
pci_process_bridge_OF_ranges
(
hose
,
dev
);
pci_process_bridge_OF_ranges
(
hose
,
dev
);
pci_setup_phb_io
(
hose
,
primary
);
pci_setup_phb_io
(
hose
,
primary
);
/* Fixup "bus-range" OF property */
/* Fixup "bus-range" OF property */
fixup_bus_range
(
dev
);
fixup_bus_range
(
dev
);
return
0
;
return
0
;
}
}
...
...
arch/ppc64/kernel/pSeries_setup.c
浏览文件 @
26cda988
...
@@ -590,6 +590,13 @@ static int pseries_shared_idle(void)
...
@@ -590,6 +590,13 @@ static int pseries_shared_idle(void)
return
0
;
return
0
;
}
}
static
int
pSeries_pci_probe_mode
(
struct
pci_bus
*
bus
)
{
if
(
systemcfg
->
platform
&
PLATFORM_LPAR
)
return
PCI_PROBE_DEVTREE
;
return
PCI_PROBE_NORMAL
;
}
struct
machdep_calls
__initdata
pSeries_md
=
{
struct
machdep_calls
__initdata
pSeries_md
=
{
.
probe
=
pSeries_probe
,
.
probe
=
pSeries_probe
,
.
setup_arch
=
pSeries_setup_arch
,
.
setup_arch
=
pSeries_setup_arch
,
...
@@ -597,6 +604,7 @@ struct machdep_calls __initdata pSeries_md = {
...
@@ -597,6 +604,7 @@ struct machdep_calls __initdata pSeries_md = {
.
get_cpuinfo
=
pSeries_get_cpuinfo
,
.
get_cpuinfo
=
pSeries_get_cpuinfo
,
.
log_error
=
pSeries_log_error
,
.
log_error
=
pSeries_log_error
,
.
pcibios_fixup
=
pSeries_final_fixup
,
.
pcibios_fixup
=
pSeries_final_fixup
,
.
pci_probe_mode
=
pSeries_pci_probe_mode
,
.
irq_bus_setup
=
pSeries_irq_bus_setup
,
.
irq_bus_setup
=
pSeries_irq_bus_setup
,
.
restart
=
rtas_restart
,
.
restart
=
rtas_restart
,
.
power_off
=
rtas_power_off
,
.
power_off
=
rtas_power_off
,
...
...
arch/ppc64/kernel/pSeries_smp.c
浏览文件 @
26cda988
...
@@ -272,6 +272,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
...
@@ -272,6 +272,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
unsigned
long
start_here
=
__pa
((
u32
)
*
((
unsigned
long
*
)
unsigned
long
start_here
=
__pa
((
u32
)
*
((
unsigned
long
*
)
pSeries_secondary_smp_init
));
pSeries_secondary_smp_init
));
unsigned
int
pcpu
;
unsigned
int
pcpu
;
int
start_cpu
;
if
(
cpu_isset
(
lcpu
,
of_spin_map
))
if
(
cpu_isset
(
lcpu
,
of_spin_map
))
/* Already started by OF and sitting in spin loop */
/* Already started by OF and sitting in spin loop */
...
@@ -282,12 +283,20 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
...
@@ -282,12 +283,20 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
/* Fixup atomic count: it exited inside IRQ handler. */
/* Fixup atomic count: it exited inside IRQ handler. */
paca
[
lcpu
].
__current
->
thread_info
->
preempt_count
=
0
;
paca
[
lcpu
].
__current
->
thread_info
->
preempt_count
=
0
;
status
=
rtas_call
(
rtas_token
(
"start-cpu"
),
3
,
1
,
NULL
,
/*
pcpu
,
start_here
,
lcpu
);
* If the RTAS start-cpu token does not exist then presume the
* cpu is already spinning.
*/
start_cpu
=
rtas_token
(
"start-cpu"
);
if
(
start_cpu
==
RTAS_UNKNOWN_SERVICE
)
return
1
;
status
=
rtas_call
(
start_cpu
,
3
,
1
,
NULL
,
pcpu
,
start_here
,
lcpu
);
if
(
status
!=
0
)
{
if
(
status
!=
0
)
{
printk
(
KERN_ERR
"start-cpu failed: %i
\n
"
,
status
);
printk
(
KERN_ERR
"start-cpu failed: %i
\n
"
,
status
);
return
0
;
return
0
;
}
}
return
1
;
return
1
;
}
}
...
...
arch/ppc64/kernel/pci.c
浏览文件 @
26cda988
...
@@ -51,6 +51,10 @@ unsigned long io_page_mask;
...
@@ -51,6 +51,10 @@ unsigned long io_page_mask;
EXPORT_SYMBOL
(
io_page_mask
);
EXPORT_SYMBOL
(
io_page_mask
);
#ifdef CONFIG_PPC_MULTIPLATFORM
static
void
fixup_resource
(
struct
resource
*
res
,
struct
pci_dev
*
dev
);
static
void
do_bus_setup
(
struct
pci_bus
*
bus
);
#endif
unsigned
int
pcibios_assign_all_busses
(
void
)
unsigned
int
pcibios_assign_all_busses
(
void
)
{
{
...
@@ -225,10 +229,287 @@ static void __init pcibios_claim_of_setup(void)
...
@@ -225,10 +229,287 @@ static void __init pcibios_claim_of_setup(void)
}
}
#endif
#endif
#ifdef CONFIG_PPC_MULTIPLATFORM
static
u32
get_int_prop
(
struct
device_node
*
np
,
const
char
*
name
,
u32
def
)
{
u32
*
prop
;
int
len
;
prop
=
(
u32
*
)
get_property
(
np
,
name
,
&
len
);
if
(
prop
&&
len
>=
4
)
return
*
prop
;
return
def
;
}
static
unsigned
int
pci_parse_of_flags
(
u32
addr0
)
{
unsigned
int
flags
=
0
;
if
(
addr0
&
0x02000000
)
{
flags
|=
IORESOURCE_MEM
;
if
(
addr0
&
0x40000000
)
flags
|=
IORESOURCE_PREFETCH
;
}
else
if
(
addr0
&
0x01000000
)
flags
|=
IORESOURCE_IO
;
return
flags
;
}
#define GET_64BIT(prop, i) ((((u64) (prop)[(i)]) << 32) | (prop)[(i)+1])
static
void
pci_parse_of_addrs
(
struct
device_node
*
node
,
struct
pci_dev
*
dev
)
{
u64
base
,
size
;
unsigned
int
flags
;
struct
resource
*
res
;
u32
*
addrs
,
i
;
int
proplen
;
addrs
=
(
u32
*
)
get_property
(
node
,
"assigned-addresses"
,
&
proplen
);
if
(
!
addrs
)
return
;
for
(;
proplen
>=
20
;
proplen
-=
20
,
addrs
+=
5
)
{
flags
=
pci_parse_of_flags
(
addrs
[
0
]);
if
(
!
flags
)
continue
;
base
=
GET_64BIT
(
addrs
,
1
);
size
=
GET_64BIT
(
addrs
,
3
);
if
(
!
size
)
continue
;
i
=
addrs
[
0
]
&
0xff
;
if
(
PCI_BASE_ADDRESS_0
<=
i
&&
i
<=
PCI_BASE_ADDRESS_5
)
{
res
=
&
dev
->
resource
[(
i
-
PCI_BASE_ADDRESS_0
)
>>
2
];
}
else
if
(
i
==
dev
->
rom_base_reg
)
{
res
=
&
dev
->
resource
[
PCI_ROM_RESOURCE
];
flags
|=
IORESOURCE_READONLY
|
IORESOURCE_CACHEABLE
;
}
else
{
printk
(
KERN_ERR
"PCI: bad cfg reg num 0x%x
\n
"
,
i
);
continue
;
}
res
->
start
=
base
;
res
->
end
=
base
+
size
-
1
;
res
->
flags
=
flags
;
res
->
name
=
pci_name
(
dev
);
fixup_resource
(
res
,
dev
);
}
}
static
struct
pci_dev
*
of_create_pci_dev
(
struct
device_node
*
node
,
struct
pci_bus
*
bus
,
int
devfn
)
{
struct
pci_dev
*
dev
;
const
char
*
type
;
dev
=
kmalloc
(
sizeof
(
struct
pci_dev
),
GFP_KERNEL
);
if
(
!
dev
)
return
NULL
;
type
=
get_property
(
node
,
"device_type"
,
NULL
);
if
(
type
==
NULL
)
type
=
""
;
memset
(
dev
,
0
,
sizeof
(
struct
pci_dev
));
dev
->
bus
=
bus
;
dev
->
sysdata
=
node
;
dev
->
dev
.
parent
=
bus
->
bridge
;
dev
->
dev
.
bus
=
&
pci_bus_type
;
dev
->
devfn
=
devfn
;
dev
->
multifunction
=
0
;
/* maybe a lie? */
dev
->
vendor
=
get_int_prop
(
node
,
"vendor-id"
,
0xffff
);
dev
->
device
=
get_int_prop
(
node
,
"device-id"
,
0xffff
);
dev
->
subsystem_vendor
=
get_int_prop
(
node
,
"subsystem-vendor-id"
,
0
);
dev
->
subsystem_device
=
get_int_prop
(
node
,
"subsystem-id"
,
0
);
dev
->
cfg_size
=
256
;
/*pci_cfg_space_size(dev);*/
sprintf
(
pci_name
(
dev
),
"%04x:%02x:%02x.%d"
,
pci_domain_nr
(
bus
),
dev
->
bus
->
number
,
PCI_SLOT
(
devfn
),
PCI_FUNC
(
devfn
));
dev
->
class
=
get_int_prop
(
node
,
"class-code"
,
0
);
dev
->
current_state
=
4
;
/* unknown power state */
if
(
!
strcmp
(
type
,
"pci"
))
{
/* a PCI-PCI bridge */
dev
->
hdr_type
=
PCI_HEADER_TYPE_BRIDGE
;
dev
->
rom_base_reg
=
PCI_ROM_ADDRESS1
;
}
else
if
(
!
strcmp
(
type
,
"cardbus"
))
{
dev
->
hdr_type
=
PCI_HEADER_TYPE_CARDBUS
;
}
else
{
dev
->
hdr_type
=
PCI_HEADER_TYPE_NORMAL
;
dev
->
rom_base_reg
=
PCI_ROM_ADDRESS
;
dev
->
irq
=
NO_IRQ
;
if
(
node
->
n_intrs
>
0
)
{
dev
->
irq
=
node
->
intrs
[
0
].
line
;
pci_write_config_byte
(
dev
,
PCI_INTERRUPT_LINE
,
dev
->
irq
);
}
}
pci_parse_of_addrs
(
node
,
dev
);
pci_device_add
(
dev
,
bus
);
/* XXX pci_scan_msi_device(dev); */
return
dev
;
}
static
void
of_scan_pci_bridge
(
struct
device_node
*
node
,
struct
pci_dev
*
dev
);
static
void
__devinit
of_scan_bus
(
struct
device_node
*
node
,
struct
pci_bus
*
bus
)
{
struct
device_node
*
child
=
NULL
;
u32
*
reg
;
int
reglen
,
devfn
;
struct
pci_dev
*
dev
;
while
((
child
=
of_get_next_child
(
node
,
child
))
!=
NULL
)
{
reg
=
(
u32
*
)
get_property
(
child
,
"reg"
,
&
reglen
);
if
(
reg
==
NULL
||
reglen
<
20
)
continue
;
devfn
=
(
reg
[
0
]
>>
8
)
&
0xff
;
/* create a new pci_dev for this device */
dev
=
of_create_pci_dev
(
child
,
bus
,
devfn
);
if
(
!
dev
)
continue
;
if
(
dev
->
hdr_type
==
PCI_HEADER_TYPE_BRIDGE
||
dev
->
hdr_type
==
PCI_HEADER_TYPE_CARDBUS
)
of_scan_pci_bridge
(
child
,
dev
);
}
do_bus_setup
(
bus
);
}
static
void
__devinit
of_scan_pci_bridge
(
struct
device_node
*
node
,
struct
pci_dev
*
dev
)
{
struct
pci_bus
*
bus
;
u32
*
busrange
,
*
ranges
;
int
len
,
i
,
mode
;
struct
resource
*
res
;
unsigned
int
flags
;
u64
size
;
/* parse bus-range property */
busrange
=
(
u32
*
)
get_property
(
node
,
"bus-range"
,
&
len
);
if
(
busrange
==
NULL
||
len
!=
8
)
{
printk
(
KERN_ERR
"Can't get bus-range for PCI-PCI bridge %s
\n
"
,
node
->
full_name
);
return
;
}
ranges
=
(
u32
*
)
get_property
(
node
,
"ranges"
,
&
len
);
if
(
ranges
==
NULL
)
{
printk
(
KERN_ERR
"Can't get ranges for PCI-PCI bridge %s
\n
"
,
node
->
full_name
);
return
;
}
bus
=
pci_add_new_bus
(
dev
->
bus
,
dev
,
busrange
[
0
]);
if
(
!
bus
)
{
printk
(
KERN_ERR
"Failed to create pci bus for %s
\n
"
,
node
->
full_name
);
return
;
}
bus
->
primary
=
dev
->
bus
->
number
;
bus
->
subordinate
=
busrange
[
1
];
bus
->
bridge_ctl
=
0
;
bus
->
sysdata
=
node
;
/* parse ranges property */
/* PCI #address-cells == 3 and #size-cells == 2 always */
res
=
&
dev
->
resource
[
PCI_BRIDGE_RESOURCES
];
for
(
i
=
0
;
i
<
PCI_NUM_RESOURCES
-
PCI_BRIDGE_RESOURCES
;
++
i
)
{
res
->
flags
=
0
;
bus
->
resource
[
i
]
=
res
;
++
res
;
}
i
=
1
;
for
(;
len
>=
32
;
len
-=
32
,
ranges
+=
8
)
{
flags
=
pci_parse_of_flags
(
ranges
[
0
]);
size
=
GET_64BIT
(
ranges
,
6
);
if
(
flags
==
0
||
size
==
0
)
continue
;
if
(
flags
&
IORESOURCE_IO
)
{
res
=
bus
->
resource
[
0
];
if
(
res
->
flags
)
{
printk
(
KERN_ERR
"PCI: ignoring extra I/O range"
" for bridge %s
\n
"
,
node
->
full_name
);
continue
;
}
}
else
{
if
(
i
>=
PCI_NUM_RESOURCES
-
PCI_BRIDGE_RESOURCES
)
{
printk
(
KERN_ERR
"PCI: too many memory ranges"
" for bridge %s
\n
"
,
node
->
full_name
);
continue
;
}
res
=
bus
->
resource
[
i
];
++
i
;
}
res
->
start
=
GET_64BIT
(
ranges
,
1
);
res
->
end
=
res
->
start
+
size
-
1
;
res
->
flags
=
flags
;
fixup_resource
(
res
,
dev
);
}
sprintf
(
bus
->
name
,
"PCI Bus %04x:%02x"
,
pci_domain_nr
(
bus
),
bus
->
number
);
mode
=
PCI_PROBE_NORMAL
;
if
(
ppc_md
.
pci_probe_mode
)
mode
=
ppc_md
.
pci_probe_mode
(
bus
);
if
(
mode
==
PCI_PROBE_DEVTREE
)
of_scan_bus
(
node
,
bus
);
else
if
(
mode
==
PCI_PROBE_NORMAL
)
pci_scan_child_bus
(
bus
);
}
#endif
/* CONFIG_PPC_MULTIPLATFORM */
static
void
__devinit
scan_phb
(
struct
pci_controller
*
hose
)
{
struct
pci_bus
*
bus
;
struct
device_node
*
node
=
hose
->
arch_data
;
int
i
,
mode
;
struct
resource
*
res
;
bus
=
pci_create_bus
(
NULL
,
hose
->
first_busno
,
hose
->
ops
,
node
);
if
(
bus
==
NULL
)
{
printk
(
KERN_ERR
"Failed to create bus for PCI domain %04x
\n
"
,
hose
->
global_number
);
return
;
}
bus
->
secondary
=
hose
->
first_busno
;
hose
->
bus
=
bus
;
bus
->
resource
[
0
]
=
res
=
&
hose
->
io_resource
;
if
(
res
->
flags
&&
request_resource
(
&
ioport_resource
,
res
))
printk
(
KERN_ERR
"Failed to request PCI IO region "
"on PCI domain %04x
\n
"
,
hose
->
global_number
);
for
(
i
=
0
;
i
<
3
;
++
i
)
{
res
=
&
hose
->
mem_resources
[
i
];
bus
->
resource
[
i
+
1
]
=
res
;
if
(
res
->
flags
&&
request_resource
(
&
iomem_resource
,
res
))
printk
(
KERN_ERR
"Failed to request PCI memory region "
"on PCI domain %04x
\n
"
,
hose
->
global_number
);
}
mode
=
PCI_PROBE_NORMAL
;
#ifdef CONFIG_PPC_MULTIPLATFORM
if
(
ppc_md
.
pci_probe_mode
)
mode
=
ppc_md
.
pci_probe_mode
(
bus
);
if
(
mode
==
PCI_PROBE_DEVTREE
)
{
bus
->
subordinate
=
hose
->
last_busno
;
of_scan_bus
(
node
,
bus
);
}
#endif
/* CONFIG_PPC_MULTIPLATFORM */
if
(
mode
==
PCI_PROBE_NORMAL
)
hose
->
last_busno
=
bus
->
subordinate
=
pci_scan_child_bus
(
bus
);
pci_bus_add_devices
(
bus
);
}
static
int
__init
pcibios_init
(
void
)
static
int
__init
pcibios_init
(
void
)
{
{
struct
pci_controller
*
hose
,
*
tmp
;
struct
pci_controller
*
hose
,
*
tmp
;
struct
pci_bus
*
bus
;
/* For now, override phys_mem_access_prot. If we need it,
/* For now, override phys_mem_access_prot. If we need it,
* later, we may move that initialization to each ppc_md
* later, we may move that initialization to each ppc_md
...
@@ -242,13 +523,8 @@ static int __init pcibios_init(void)
...
@@ -242,13 +523,8 @@ static int __init pcibios_init(void)
printk
(
"PCI: Probing PCI hardware
\n
"
);
printk
(
"PCI: Probing PCI hardware
\n
"
);
/* Scan all of the recorded PCI controllers. */
/* Scan all of the recorded PCI controllers. */
list_for_each_entry_safe
(
hose
,
tmp
,
&
hose_list
,
list_node
)
{
list_for_each_entry_safe
(
hose
,
tmp
,
&
hose_list
,
list_node
)
hose
->
last_busno
=
0xff
;
scan_phb
(
hose
);
bus
=
pci_scan_bus
(
hose
->
first_busno
,
hose
->
ops
,
hose
->
arch_data
);
hose
->
bus
=
bus
;
hose
->
last_busno
=
bus
->
subordinate
;
}
#ifndef CONFIG_PPC_ISERIES
#ifndef CONFIG_PPC_ISERIES
if
(
pci_probe_only
)
if
(
pci_probe_only
)
...
@@ -820,120 +1096,89 @@ void phbs_remap_io(void)
...
@@ -820,120 +1096,89 @@ void phbs_remap_io(void)
/*
/*
* ppc64 can have multifunction devices that do not respond to function 0.
* ppc64 can have multifunction devices that do not respond to function 0.
* In this case we must scan all functions.
* In this case we must scan all functions.
* XXX this can go now, we use the OF device tree in all the
* cases that caused problems. -- paulus
*/
*/
int
pcibios_scan_all_fns
(
struct
pci_bus
*
bus
,
int
devfn
)
int
pcibios_scan_all_fns
(
struct
pci_bus
*
bus
,
int
devfn
)
{
{
struct
device_node
*
busdn
,
*
dn
;
if
(
bus
->
self
)
busdn
=
pci_device_to_OF_node
(
bus
->
self
);
else
busdn
=
bus
->
sysdata
;
/* must be a phb */
if
(
busdn
==
NULL
)
return
0
;
/*
* Check to see if there is any of the 8 functions are in the
* device tree. If they are then we need to scan all the
* functions of this slot.
*/
for
(
dn
=
busdn
->
child
;
dn
;
dn
=
dn
->
sibling
)
{
struct
pci_dn
*
pdn
=
dn
->
data
;
if
(
pdn
&&
(
pdn
->
devfn
>>
3
)
==
(
devfn
>>
3
))
return
1
;
}
return
0
;
return
0
;
}
}
static
void
__devinit
fixup_resource
(
struct
resource
*
res
,
struct
pci_dev
*
dev
)
{
struct
pci_controller
*
hose
=
pci_bus_to_host
(
dev
->
bus
);
unsigned
long
start
,
end
,
mask
,
offset
;
if
(
res
->
flags
&
IORESOURCE_IO
)
{
offset
=
(
unsigned
long
)
hose
->
io_base_virt
-
pci_io_base
;
start
=
res
->
start
+=
offset
;
end
=
res
->
end
+=
offset
;
/* Need to allow IO access to pages that are in the
ISA range */
if
(
start
<
MAX_ISA_PORT
)
{
if
(
end
>
MAX_ISA_PORT
)
end
=
MAX_ISA_PORT
;
start
>>=
PAGE_SHIFT
;
end
>>=
PAGE_SHIFT
;
/* get the range of pages for the map */
mask
=
((
1
<<
(
end
+
1
))
-
1
)
^
((
1
<<
start
)
-
1
);
io_page_mask
|=
mask
;
}
}
else
if
(
res
->
flags
&
IORESOURCE_MEM
)
{
res
->
start
+=
hose
->
pci_mem_offset
;
res
->
end
+=
hose
->
pci_mem_offset
;
}
}
void
__devinit
pcibios_fixup_device_resources
(
struct
pci_dev
*
dev
,
void
__devinit
pcibios_fixup_device_resources
(
struct
pci_dev
*
dev
,
struct
pci_bus
*
bus
)
struct
pci_bus
*
bus
)
{
{
/* Update device resources. */
/* Update device resources. */
struct
pci_controller
*
hose
=
pci_bus_to_host
(
bus
);
int
i
;
int
i
;
for
(
i
=
0
;
i
<
PCI_NUM_RESOURCES
;
i
++
)
{
for
(
i
=
0
;
i
<
PCI_NUM_RESOURCES
;
i
++
)
if
(
dev
->
resource
[
i
].
flags
&
IORESOURCE_IO
)
{
if
(
dev
->
resource
[
i
].
flags
)
unsigned
long
offset
=
(
unsigned
long
)
hose
->
io_base_virt
fixup_resource
(
&
dev
->
resource
[
i
],
dev
);
-
pci_io_base
;
unsigned
long
start
,
end
,
mask
;
start
=
dev
->
resource
[
i
].
start
+=
offset
;
end
=
dev
->
resource
[
i
].
end
+=
offset
;
/* Need to allow IO access to pages that are in the
ISA range */
if
(
start
<
MAX_ISA_PORT
)
{
if
(
end
>
MAX_ISA_PORT
)
end
=
MAX_ISA_PORT
;
start
>>=
PAGE_SHIFT
;
end
>>=
PAGE_SHIFT
;
/* get the range of pages for the map */
mask
=
((
1
<<
(
end
+
1
))
-
1
)
^
((
1
<<
start
)
-
1
);
io_page_mask
|=
mask
;
}
}
else
if
(
dev
->
resource
[
i
].
flags
&
IORESOURCE_MEM
)
{
dev
->
resource
[
i
].
start
+=
hose
->
pci_mem_offset
;
dev
->
resource
[
i
].
end
+=
hose
->
pci_mem_offset
;
}
}
}
}
EXPORT_SYMBOL
(
pcibios_fixup_device_resources
);
EXPORT_SYMBOL
(
pcibios_fixup_device_resources
);
void
__devinit
pcibios_fixup_bus
(
struct
pci_bus
*
bus
)
static
void
__devinit
do_bus_setup
(
struct
pci_bus
*
bus
)
{
{
struct
pci_controller
*
hose
=
pci_bus_to_host
(
bus
);
struct
pci_dev
*
dev
;
struct
pci_dev
*
dev
=
bus
->
self
;
struct
resource
*
res
;
int
i
;
if
(
!
dev
)
{
ppc_md
.
iommu_bus_setup
(
bus
);
/* Root bus. */
hose
->
bus
=
bus
;
list_for_each_entry
(
dev
,
&
bus
->
devices
,
bus_list
)
bus
->
resource
[
0
]
=
res
=
&
hose
->
io_resource
;
ppc_md
.
iommu_dev_setup
(
dev
)
;
if
(
res
->
flags
&&
request_resource
(
&
ioport_resource
,
res
)
)
if
(
ppc_md
.
irq_bus_setup
)
printk
(
KERN_ERR
"Failed to request IO on "
ppc_md
.
irq_bus_setup
(
bus
);
"PCI domain %d
\n
"
,
pci_domain_nr
(
bus
));
}
for
(
i
=
0
;
i
<
3
;
++
i
)
{
void
__devinit
pcibios_fixup_bus
(
struct
pci_bus
*
bus
)
res
=
&
hose
->
mem_resources
[
i
];
{
bus
->
resource
[
i
+
1
]
=
res
;
struct
pci_dev
*
dev
=
bus
->
self
;
if
(
res
->
flags
&&
request_resource
(
&
iomem_resource
,
res
))
printk
(
KERN_ERR
"Failed to request MEM on "
if
(
dev
&&
pci_probe_only
&&
"PCI domain %d
\n
"
,
(
dev
->
class
>>
8
)
==
PCI_CLASS_BRIDGE_PCI
)
{
pci_domain_nr
(
bus
));
}
}
else
if
(
pci_probe_only
&&
(
dev
->
class
>>
8
)
==
PCI_CLASS_BRIDGE_PCI
)
{
/* This is a subordinate bridge */
/* This is a subordinate bridge */
pci_read_bridge_bases
(
bus
);
pci_read_bridge_bases
(
bus
);
pcibios_fixup_device_resources
(
dev
,
bus
);
pcibios_fixup_device_resources
(
dev
,
bus
);
}
}
ppc_md
.
iommu_bus_setup
(
bus
);
do_bus_setup
(
bus
);
list_for_each_entry
(
dev
,
&
bus
->
devices
,
bus_list
)
ppc_md
.
iommu_dev_setup
(
dev
);
if
(
ppc_md
.
irq_bus_setup
)
ppc_md
.
irq_bus_setup
(
bus
);
if
(
!
pci_probe_only
)
if
(
!
pci_probe_only
)
return
;
return
;
list_for_each_entry
(
dev
,
&
bus
->
devices
,
bus_list
)
{
list_for_each_entry
(
dev
,
&
bus
->
devices
,
bus_list
)
if
((
dev
->
class
>>
8
)
!=
PCI_CLASS_BRIDGE_PCI
)
if
((
dev
->
class
>>
8
)
!=
PCI_CLASS_BRIDGE_PCI
)
pcibios_fixup_device_resources
(
dev
,
bus
);
pcibios_fixup_device_resources
(
dev
,
bus
);
}
}
}
EXPORT_SYMBOL
(
pcibios_fixup_bus
);
EXPORT_SYMBOL
(
pcibios_fixup_bus
);
...
...
arch/ppc64/kernel/pmac_pci.c
浏览文件 @
26cda988
...
@@ -388,7 +388,7 @@ static void __init setup_u3_agp(struct pci_controller* hose)
...
@@ -388,7 +388,7 @@ static void __init setup_u3_agp(struct pci_controller* hose)
* the reg address cell, we shall fix that by killing struct
* the reg address cell, we shall fix that by killing struct
* reg_property and using some accessor functions instead
* reg_property and using some accessor functions instead
*/
*/
hose
->
first_busno
=
0xf0
;
hose
->
first_busno
=
0xf0
;
hose
->
last_busno
=
0xff
;
hose
->
last_busno
=
0xff
;
has_uninorth
=
1
;
has_uninorth
=
1
;
hose
->
ops
=
&
macrisc_pci_ops
;
hose
->
ops
=
&
macrisc_pci_ops
;
...
@@ -473,7 +473,7 @@ static void __init setup_u3_ht(struct pci_controller* hose)
...
@@ -473,7 +473,7 @@ static void __init setup_u3_ht(struct pci_controller* hose)
continue
;
continue
;
}
}
cur
++
;
cur
++
;
DBG
(
"U3/HT: hole, %d end at %08lx, %d start at %08lx
\n
"
,
DBG
(
"U3/HT: hole, %d end at %08lx, %d start at %08lx
\n
"
,
cur
-
1
,
res
->
start
-
1
,
cur
,
res
->
end
+
1
);
cur
-
1
,
res
->
start
-
1
,
cur
,
res
->
end
+
1
);
hose
->
mem_resources
[
cur
].
name
=
np
->
full_name
;
hose
->
mem_resources
[
cur
].
name
=
np
->
full_name
;
hose
->
mem_resources
[
cur
].
flags
=
IORESOURCE_MEM
;
hose
->
mem_resources
[
cur
].
flags
=
IORESOURCE_MEM
;
...
@@ -603,24 +603,24 @@ static int __init add_bridge(struct device_node *dev)
...
@@ -603,24 +603,24 @@ static int __init add_bridge(struct device_node *dev)
char
*
disp_name
;
char
*
disp_name
;
int
*
bus_range
;
int
*
bus_range
;
int
primary
=
1
;
int
primary
=
1
;
struct
property
*
of_prop
;
struct
property
*
of_prop
;
DBG
(
"Adding PCI host bridge %s
\n
"
,
dev
->
full_name
);
DBG
(
"Adding PCI host bridge %s
\n
"
,
dev
->
full_name
);
bus_range
=
(
int
*
)
get_property
(
dev
,
"bus-range"
,
&
len
);
bus_range
=
(
int
*
)
get_property
(
dev
,
"bus-range"
,
&
len
);
if
(
bus_range
==
NULL
||
len
<
2
*
sizeof
(
int
))
{
if
(
bus_range
==
NULL
||
len
<
2
*
sizeof
(
int
))
{
printk
(
KERN_WARNING
"Can't get bus-range for %s, assume bus 0
\n
"
,
printk
(
KERN_WARNING
"Can't get bus-range for %s, assume bus 0
\n
"
,
dev
->
full_name
);
dev
->
full_name
);
}
}
hose
=
alloc_bootmem
(
sizeof
(
struct
pci_controller
));
hose
=
alloc_bootmem
(
sizeof
(
struct
pci_controller
));
if
(
hose
==
NULL
)
if
(
hose
==
NULL
)
return
-
ENOMEM
;
return
-
ENOMEM
;
pci_setup_pci_controller
(
hose
);
pci_setup_pci_controller
(
hose
);
hose
->
arch_data
=
dev
;
hose
->
arch_data
=
dev
;
hose
->
first_busno
=
bus_range
?
bus_range
[
0
]
:
0
;
hose
->
first_busno
=
bus_range
?
bus_range
[
0
]
:
0
;
hose
->
last_busno
=
bus_range
?
bus_range
[
1
]
:
0xff
;
hose
->
last_busno
=
bus_range
?
bus_range
[
1
]
:
0xff
;
of_prop
=
alloc_bootmem
(
sizeof
(
struct
property
)
+
of_prop
=
alloc_bootmem
(
sizeof
(
struct
property
)
+
sizeof
(
hose
->
global_number
));
sizeof
(
hose
->
global_number
));
...
@@ -634,24 +634,24 @@ static int __init add_bridge(struct device_node *dev)
...
@@ -634,24 +634,24 @@ static int __init add_bridge(struct device_node *dev)
}
}
disp_name
=
NULL
;
disp_name
=
NULL
;
if
(
device_is_compatible
(
dev
,
"u3-agp"
))
{
if
(
device_is_compatible
(
dev
,
"u3-agp"
))
{
setup_u3_agp
(
hose
);
setup_u3_agp
(
hose
);
disp_name
=
"U3-AGP"
;
disp_name
=
"U3-AGP"
;
primary
=
0
;
primary
=
0
;
}
else
if
(
device_is_compatible
(
dev
,
"u3-ht"
))
{
}
else
if
(
device_is_compatible
(
dev
,
"u3-ht"
))
{
setup_u3_ht
(
hose
);
setup_u3_ht
(
hose
);
disp_name
=
"U3-HT"
;
disp_name
=
"U3-HT"
;
primary
=
1
;
primary
=
1
;
}
}
printk
(
KERN_INFO
"Found %s PCI host bridge. Firmware bus number: %d->%d
\n
"
,
printk
(
KERN_INFO
"Found %s PCI host bridge. Firmware bus number: %d->%d
\n
"
,
disp_name
,
hose
->
first_busno
,
hose
->
last_busno
);
disp_name
,
hose
->
first_busno
,
hose
->
last_busno
);
/* Interpret the "ranges" property */
/* Interpret the "ranges" property */
/* This also maps the I/O region and sets isa_io/mem_base */
/* This also maps the I/O region and sets isa_io/mem_base */
pmac_process_bridge_OF_ranges
(
hose
,
dev
,
primary
);
pmac_process_bridge_OF_ranges
(
hose
,
dev
,
primary
);
/* Fixup "bus-range" OF property */
/* Fixup "bus-range" OF property */
fixup_bus_range
(
dev
);
fixup_bus_range
(
dev
);
return
0
;
return
0
;
}
}
...
...
arch/ppc64/kernel/pmac_setup.c
浏览文件 @
26cda988
...
@@ -477,6 +477,18 @@ static int __init pmac_probe(int platform)
...
@@ -477,6 +477,18 @@ static int __init pmac_probe(int platform)
return
1
;
return
1
;
}
}
static
int
pmac_probe_mode
(
struct
pci_bus
*
bus
)
{
struct
device_node
*
node
=
bus
->
sysdata
;
/* We need to use normal PCI probing for the AGP bus,
since the device for the AGP bridge isn't in the tree. */
if
(
bus
->
self
==
NULL
&&
device_is_compatible
(
node
,
"u3-agp"
))
return
PCI_PROBE_NORMAL
;
return
PCI_PROBE_DEVTREE
;
}
struct
machdep_calls
__initdata
pmac_md
=
{
struct
machdep_calls
__initdata
pmac_md
=
{
#ifdef CONFIG_HOTPLUG_CPU
#ifdef CONFIG_HOTPLUG_CPU
.
cpu_die
=
generic_mach_cpu_die
,
.
cpu_die
=
generic_mach_cpu_die
,
...
@@ -488,6 +500,7 @@ struct machdep_calls __initdata pmac_md = {
...
@@ -488,6 +500,7 @@ struct machdep_calls __initdata pmac_md = {
.
init_IRQ
=
pmac_init_IRQ
,
.
init_IRQ
=
pmac_init_IRQ
,
.
get_irq
=
mpic_get_irq
,
.
get_irq
=
mpic_get_irq
,
.
pcibios_fixup
=
pmac_pcibios_fixup
,
.
pcibios_fixup
=
pmac_pcibios_fixup
,
.
pci_probe_mode
=
pmac_probe_mode
,
.
restart
=
pmac_restart
,
.
restart
=
pmac_restart
,
.
power_off
=
pmac_power_off
,
.
power_off
=
pmac_power_off
,
.
halt
=
pmac_halt
,
.
halt
=
pmac_halt
,
...
...
arch/ppc64/kernel/process.c
浏览文件 @
26cda988
...
@@ -54,6 +54,7 @@
...
@@ -54,6 +54,7 @@
#include <asm/sections.h>
#include <asm/sections.h>
#include <asm/tlbflush.h>
#include <asm/tlbflush.h>
#include <asm/time.h>
#include <asm/time.h>
#include <asm/plpar_wrappers.h>
#ifndef CONFIG_SMP
#ifndef CONFIG_SMP
struct
task_struct
*
last_task_used_math
=
NULL
;
struct
task_struct
*
last_task_used_math
=
NULL
;
...
@@ -163,7 +164,30 @@ int dump_task_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs)
...
@@ -163,7 +164,30 @@ int dump_task_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs)
#endif
/* CONFIG_ALTIVEC */
#endif
/* CONFIG_ALTIVEC */
static
void
set_dabr_spr
(
unsigned
long
val
)
{
mtspr
(
SPRN_DABR
,
val
);
}
int
set_dabr
(
unsigned
long
dabr
)
{
int
ret
=
0
;
if
(
firmware_has_feature
(
FW_FEATURE_XDABR
))
{
/* We want to catch accesses from kernel and userspace */
unsigned
long
flags
=
H_DABRX_KERNEL
|
H_DABRX_USER
;
ret
=
plpar_set_xdabr
(
dabr
,
flags
);
}
else
if
(
firmware_has_feature
(
FW_FEATURE_DABR
))
{
ret
=
plpar_set_dabr
(
dabr
);
}
else
{
set_dabr_spr
(
dabr
);
}
return
ret
;
}
DEFINE_PER_CPU
(
struct
cpu_usage
,
cpu_usage_array
);
DEFINE_PER_CPU
(
struct
cpu_usage
,
cpu_usage_array
);
static
DEFINE_PER_CPU
(
unsigned
long
,
current_dabr
);
struct
task_struct
*
__switch_to
(
struct
task_struct
*
prev
,
struct
task_struct
*
__switch_to
(
struct
task_struct
*
prev
,
struct
task_struct
*
new
)
struct
task_struct
*
new
)
...
@@ -198,6 +222,11 @@ struct task_struct *__switch_to(struct task_struct *prev,
...
@@ -198,6 +222,11 @@ struct task_struct *__switch_to(struct task_struct *prev,
new
->
thread
.
regs
->
msr
|=
MSR_VEC
;
new
->
thread
.
regs
->
msr
|=
MSR_VEC
;
#endif
/* CONFIG_ALTIVEC */
#endif
/* CONFIG_ALTIVEC */
if
(
unlikely
(
__get_cpu_var
(
current_dabr
)
!=
new
->
thread
.
dabr
))
{
set_dabr
(
new
->
thread
.
dabr
);
__get_cpu_var
(
current_dabr
)
=
new
->
thread
.
dabr
;
}
flush_tlb_pending
();
flush_tlb_pending
();
new_thread
=
&
new
->
thread
;
new_thread
=
&
new
->
thread
;
...
@@ -334,6 +363,11 @@ void flush_thread(void)
...
@@ -334,6 +363,11 @@ void flush_thread(void)
last_task_used_altivec
=
NULL
;
last_task_used_altivec
=
NULL
;
#endif
/* CONFIG_ALTIVEC */
#endif
/* CONFIG_ALTIVEC */
#endif
/* CONFIG_SMP */
#endif
/* CONFIG_SMP */
if
(
current
->
thread
.
dabr
)
{
current
->
thread
.
dabr
=
0
;
set_dabr
(
0
);
}
}
}
void
void
...
...
arch/ppc64/kernel/ptrace.c
浏览文件 @
26cda988
...
@@ -17,6 +17,7 @@
...
@@ -17,6 +17,7 @@
* this archive for more details.
* this archive for more details.
*/
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/mm.h>
...
@@ -206,6 +207,19 @@ int sys_ptrace(long request, long pid, long addr, long data)
...
@@ -206,6 +207,19 @@ int sys_ptrace(long request, long pid, long addr, long data)
break
;
break
;
}
}
case
PTRACE_GET_DEBUGREG
:
{
ret
=
-
EINVAL
;
/* We only support one DABR and no IABRS at the moment */
if
(
addr
>
0
)
break
;
ret
=
put_user
(
child
->
thread
.
dabr
,
(
unsigned
long
__user
*
)
data
);
break
;
}
case
PTRACE_SET_DEBUGREG
:
ret
=
ptrace_set_debugreg
(
child
,
addr
,
data
);
case
PTRACE_DETACH
:
case
PTRACE_DETACH
:
ret
=
ptrace_detach
(
child
,
data
);
ret
=
ptrace_detach
(
child
,
data
);
break
;
break
;
...
@@ -274,6 +288,20 @@ int sys_ptrace(long request, long pid, long addr, long data)
...
@@ -274,6 +288,20 @@ int sys_ptrace(long request, long pid, long addr, long data)
break
;
break
;
}
}
#ifdef CONFIG_ALTIVEC
case
PTRACE_GETVRREGS
:
/* Get the child altivec register state. */
flush_altivec_to_thread
(
child
);
ret
=
get_vrregs
((
unsigned
long
__user
*
)
data
,
child
);
break
;
case
PTRACE_SETVRREGS
:
/* Set the child altivec register state. */
flush_altivec_to_thread
(
child
);
ret
=
set_vrregs
(
child
,
(
unsigned
long
__user
*
)
data
);
break
;
#endif
default:
default:
ret
=
ptrace_request
(
child
,
request
,
addr
,
data
);
ret
=
ptrace_request
(
child
,
request
,
addr
,
data
);
break
;
break
;
...
...
arch/ppc64/kernel/ptrace32.c
浏览文件 @
26cda988
...
@@ -17,6 +17,7 @@
...
@@ -17,6 +17,7 @@
* this archive for more details.
* this archive for more details.
*/
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/mm.h>
...
@@ -337,6 +338,19 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
...
@@ -337,6 +338,19 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
break
;
break
;
}
}
case
PTRACE_GET_DEBUGREG
:
{
ret
=
-
EINVAL
;
/* We only support one DABR and no IABRS at the moment */
if
(
addr
>
0
)
break
;
ret
=
put_user
(
child
->
thread
.
dabr
,
(
u32
__user
*
)
data
);
break
;
}
case
PTRACE_SET_DEBUGREG
:
ret
=
ptrace_set_debugreg
(
child
,
addr
,
data
);
break
;
case
PTRACE_DETACH
:
case
PTRACE_DETACH
:
ret
=
ptrace_detach
(
child
,
data
);
ret
=
ptrace_detach
(
child
,
data
);
break
;
break
;
...
@@ -405,9 +419,23 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
...
@@ -405,9 +419,23 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
break
;
break
;
}
}
case
PTRACE_GETEVENTMSG
:
case
PTRACE_GETEVENTMSG
:
ret
=
put_user
(
child
->
ptrace_message
,
(
unsigned
int
__user
*
)
data
);
ret
=
put_user
(
child
->
ptrace_message
,
(
unsigned
int
__user
*
)
data
);
break
;
break
;
#ifdef CONFIG_ALTIVEC
case
PTRACE_GETVRREGS
:
/* Get the child altivec register state. */
flush_altivec_to_thread
(
child
);
ret
=
get_vrregs
((
unsigned
long
__user
*
)
data
,
child
);
break
;
case
PTRACE_SETVRREGS
:
/* Set the child altivec register state. */
flush_altivec_to_thread
(
child
);
ret
=
set_vrregs
(
child
,
(
unsigned
long
__user
*
)
data
);
break
;
#endif
default:
default:
ret
=
ptrace_request
(
child
,
request
,
addr
,
data
);
ret
=
ptrace_request
(
child
,
request
,
addr
,
data
);
...
...
arch/ppc64/kernel/ras.c
浏览文件 @
26cda988
...
@@ -59,8 +59,6 @@ char mce_data_buf[RTAS_ERROR_LOG_MAX]
...
@@ -59,8 +59,6 @@ char mce_data_buf[RTAS_ERROR_LOG_MAX]
/* This is true if we are using the firmware NMI handler (typically LPAR) */
/* This is true if we are using the firmware NMI handler (typically LPAR) */
extern
int
fwnmi_active
;
extern
int
fwnmi_active
;
extern
void
_exception
(
int
signr
,
struct
pt_regs
*
regs
,
int
code
,
unsigned
long
addr
);
static
int
ras_get_sensor_state_token
;
static
int
ras_get_sensor_state_token
;
static
int
ras_check_exception_token
;
static
int
ras_check_exception_token
;
...
...
arch/ppc64/kernel/setup.c
浏览文件 @
26cda988
...
@@ -1064,8 +1064,6 @@ void __init setup_arch(char **cmdline_p)
...
@@ -1064,8 +1064,6 @@ void __init setup_arch(char **cmdline_p)
#define PPC64_LINUX_FUNCTION 0x0f000000
#define PPC64_LINUX_FUNCTION 0x0f000000
#define PPC64_IPL_MESSAGE 0xc0000000
#define PPC64_IPL_MESSAGE 0xc0000000
#define PPC64_TERM_MESSAGE 0xb0000000
#define PPC64_TERM_MESSAGE 0xb0000000
#define PPC64_ATTN_MESSAGE 0xa0000000
#define PPC64_DUMP_MESSAGE 0xd0000000
static
void
ppc64_do_msg
(
unsigned
int
src
,
const
char
*
msg
)
static
void
ppc64_do_msg
(
unsigned
int
src
,
const
char
*
msg
)
{
{
...
@@ -1093,20 +1091,6 @@ void ppc64_terminate_msg(unsigned int src, const char *msg)
...
@@ -1093,20 +1091,6 @@ void ppc64_terminate_msg(unsigned int src, const char *msg)
printk
(
"[terminate]%04x %s
\n
"
,
src
,
msg
);
printk
(
"[terminate]%04x %s
\n
"
,
src
,
msg
);
}
}
/* Print something that needs attention (device error, etc) */
void
ppc64_attention_msg
(
unsigned
int
src
,
const
char
*
msg
)
{
ppc64_do_msg
(
PPC64_LINUX_FUNCTION
|
PPC64_ATTN_MESSAGE
|
src
,
msg
);
printk
(
"[attention]%04x %s
\n
"
,
src
,
msg
);
}
/* Print a dump progress message. */
void
ppc64_dump_msg
(
unsigned
int
src
,
const
char
*
msg
)
{
ppc64_do_msg
(
PPC64_LINUX_FUNCTION
|
PPC64_DUMP_MESSAGE
|
src
,
msg
);
printk
(
"[dump]%04x %s
\n
"
,
src
,
msg
);
}
/* This should only be called on processor 0 during calibrate decr */
/* This should only be called on processor 0 during calibrate decr */
void
__init
setup_default_decr
(
void
)
void
__init
setup_default_decr
(
void
)
{
{
...
...
arch/ppc64/kernel/signal.c
浏览文件 @
26cda988
...
@@ -550,6 +550,15 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
...
@@ -550,6 +550,15 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
/* Whee! Actually deliver the signal. */
/* Whee! Actually deliver the signal. */
if
(
TRAP
(
regs
)
==
0x0C00
)
if
(
TRAP
(
regs
)
==
0x0C00
)
syscall_restart
(
regs
,
&
ka
);
syscall_restart
(
regs
,
&
ka
);
/*
* Reenable the DABR before delivering the signal to
* user space. The DABR will have been cleared if it
* triggered inside the kernel.
*/
if
(
current
->
thread
.
dabr
)
set_dabr
(
current
->
thread
.
dabr
);
return
handle_signal
(
signr
,
&
ka
,
&
info
,
oldset
,
regs
);
return
handle_signal
(
signr
,
&
ka
,
&
info
,
oldset
,
regs
);
}
}
...
...
arch/ppc64/kernel/signal32.c
浏览文件 @
26cda988
...
@@ -970,6 +970,14 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
...
@@ -970,6 +970,14 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
newsp
=
regs
->
gpr
[
1
];
newsp
=
regs
->
gpr
[
1
];
newsp
&=
~
0xfUL
;
newsp
&=
~
0xfUL
;
/*
* Reenable the DABR before delivering the signal to
* user space. The DABR will have been cleared if it
* triggered inside the kernel.
*/
if
(
current
->
thread
.
dabr
)
set_dabr
(
current
->
thread
.
dabr
);
/* Whee! Actually deliver the signal. */
/* Whee! Actually deliver the signal. */
if
(
ka
.
sa
.
sa_flags
&
SA_SIGINFO
)
if
(
ka
.
sa
.
sa_flags
&
SA_SIGINFO
)
ret
=
handle_rt_signal32
(
signr
,
&
ka
,
&
info
,
oldset
,
regs
,
newsp
);
ret
=
handle_rt_signal32
(
signr
,
&
ka
,
&
info
,
oldset
,
regs
,
newsp
);
...
...
arch/ppc64/kernel/xics.c
浏览文件 @
26cda988
...
@@ -38,7 +38,7 @@ static void xics_mask_and_ack_irq(unsigned int irq);
...
@@ -38,7 +38,7 @@ static void xics_mask_and_ack_irq(unsigned int irq);
static
void
xics_end_irq
(
unsigned
int
irq
);
static
void
xics_end_irq
(
unsigned
int
irq
);
static
void
xics_set_affinity
(
unsigned
int
irq_nr
,
cpumask_t
cpumask
);
static
void
xics_set_affinity
(
unsigned
int
irq_nr
,
cpumask_t
cpumask
);
struct
hw_interrupt_type
xics_pic
=
{
st
atic
st
ruct
hw_interrupt_type
xics_pic
=
{
.
typename
=
" XICS "
,
.
typename
=
" XICS "
,
.
startup
=
xics_startup
,
.
startup
=
xics_startup
,
.
enable
=
xics_enable_irq
,
.
enable
=
xics_enable_irq
,
...
@@ -48,7 +48,7 @@ struct hw_interrupt_type xics_pic = {
...
@@ -48,7 +48,7 @@ struct hw_interrupt_type xics_pic = {
.
set_affinity
=
xics_set_affinity
.
set_affinity
=
xics_set_affinity
};
};
struct
hw_interrupt_type
xics_8259_pic
=
{
st
atic
st
ruct
hw_interrupt_type
xics_8259_pic
=
{
.
typename
=
" XICS/8259"
,
.
typename
=
" XICS/8259"
,
.
ack
=
xics_mask_and_ack_irq
,
.
ack
=
xics_mask_and_ack_irq
,
};
};
...
@@ -89,9 +89,8 @@ static struct xics_ipl __iomem *xics_per_cpu[NR_CPUS];
...
@@ -89,9 +89,8 @@ static struct xics_ipl __iomem *xics_per_cpu[NR_CPUS];
static
int
xics_irq_8259_cascade
=
0
;
static
int
xics_irq_8259_cascade
=
0
;
static
int
xics_irq_8259_cascade_real
=
0
;
static
int
xics_irq_8259_cascade_real
=
0
;
static
unsigned
int
default_server
=
0xFF
;
static
unsigned
int
default_server
=
0xFF
;
/* also referenced in smp.c... */
static
unsigned
int
default_distrib_server
=
0
;
unsigned
int
default_distrib_server
=
0
;
static
unsigned
int
interrupt_server_size
=
8
;
unsigned
int
interrupt_server_size
=
8
;
/*
/*
* XICS only has a single IPI, so encode the messages per CPU
* XICS only has a single IPI, so encode the messages per CPU
...
@@ -99,10 +98,10 @@ unsigned int interrupt_server_size = 8;
...
@@ -99,10 +98,10 @@ unsigned int interrupt_server_size = 8;
struct
xics_ipi_struct
xics_ipi_message
[
NR_CPUS
]
__cacheline_aligned
;
struct
xics_ipi_struct
xics_ipi_message
[
NR_CPUS
]
__cacheline_aligned
;
/* RTAS service tokens */
/* RTAS service tokens */
int
ibm_get_xive
;
static
int
ibm_get_xive
;
int
ibm_set_xive
;
static
int
ibm_set_xive
;
int
ibm_int_on
;
static
int
ibm_int_on
;
int
ibm_int_off
;
static
int
ibm_int_off
;
typedef
struct
{
typedef
struct
{
int
(
*
xirr_info_get
)(
int
cpu
);
int
(
*
xirr_info_get
)(
int
cpu
);
...
@@ -284,16 +283,17 @@ static void xics_enable_irq(unsigned int virq)
...
@@ -284,16 +283,17 @@ static void xics_enable_irq(unsigned int virq)
call_status
=
rtas_call
(
ibm_set_xive
,
3
,
1
,
NULL
,
irq
,
server
,
call_status
=
rtas_call
(
ibm_set_xive
,
3
,
1
,
NULL
,
irq
,
server
,
DEFAULT_PRIORITY
);
DEFAULT_PRIORITY
);
if
(
call_status
!=
0
)
{
if
(
call_status
!=
0
)
{
printk
(
KERN_ERR
"xics_enable_irq: irq=%d: ibm_set_xive "
printk
(
KERN_ERR
"xics_enable_irq: irq=%u: ibm_set_xive "
"returned %x
\n
"
,
irq
,
call_status
);
"returned %d
\n
"
,
irq
,
call_status
);
printk
(
"set_xive %x, server %x
\n
"
,
ibm_set_xive
,
server
);
return
;
return
;
}
}
/* Now unmask the interrupt (often a no-op) */
/* Now unmask the interrupt (often a no-op) */
call_status
=
rtas_call
(
ibm_int_on
,
1
,
1
,
NULL
,
irq
);
call_status
=
rtas_call
(
ibm_int_on
,
1
,
1
,
NULL
,
irq
);
if
(
call_status
!=
0
)
{
if
(
call_status
!=
0
)
{
printk
(
KERN_ERR
"xics_enable_irq: irq=%
d
: ibm_int_on "
printk
(
KERN_ERR
"xics_enable_irq: irq=%
u
: ibm_int_on "
"returned %
x
\n
"
,
irq
,
call_status
);
"returned %
d
\n
"
,
irq
,
call_status
);
return
;
return
;
}
}
}
}
...
@@ -308,8 +308,8 @@ static void xics_disable_real_irq(unsigned int irq)
...
@@ -308,8 +308,8 @@ static void xics_disable_real_irq(unsigned int irq)
call_status
=
rtas_call
(
ibm_int_off
,
1
,
1
,
NULL
,
irq
);
call_status
=
rtas_call
(
ibm_int_off
,
1
,
1
,
NULL
,
irq
);
if
(
call_status
!=
0
)
{
if
(
call_status
!=
0
)
{
printk
(
KERN_ERR
"xics_disable_real_irq: irq=%
d
: "
printk
(
KERN_ERR
"xics_disable_real_irq: irq=%
u
: "
"ibm_int_off returned %
x
\n
"
,
irq
,
call_status
);
"ibm_int_off returned %
d
\n
"
,
irq
,
call_status
);
return
;
return
;
}
}
...
@@ -317,8 +317,8 @@ static void xics_disable_real_irq(unsigned int irq)
...
@@ -317,8 +317,8 @@ static void xics_disable_real_irq(unsigned int irq)
/* Have to set XIVE to 0xff to be able to remove a slot */
/* Have to set XIVE to 0xff to be able to remove a slot */
call_status
=
rtas_call
(
ibm_set_xive
,
3
,
1
,
NULL
,
irq
,
server
,
0xff
);
call_status
=
rtas_call
(
ibm_set_xive
,
3
,
1
,
NULL
,
irq
,
server
,
0xff
);
if
(
call_status
!=
0
)
{
if
(
call_status
!=
0
)
{
printk
(
KERN_ERR
"xics_disable_irq: irq=%
d
: ibm_set_xive(0xff)"
printk
(
KERN_ERR
"xics_disable_irq: irq=%
u
: ibm_set_xive(0xff)"
" returned %
x
\n
"
,
irq
,
call_status
);
" returned %
d
\n
"
,
irq
,
call_status
);
return
;
return
;
}
}
}
}
...
@@ -380,7 +380,7 @@ int xics_get_irq(struct pt_regs *regs)
...
@@ -380,7 +380,7 @@ int xics_get_irq(struct pt_regs *regs)
if
(
irq
==
NO_IRQ
)
if
(
irq
==
NO_IRQ
)
irq
=
real_irq_to_virt_slowpath
(
vec
);
irq
=
real_irq_to_virt_slowpath
(
vec
);
if
(
irq
==
NO_IRQ
)
{
if
(
irq
==
NO_IRQ
)
{
printk
(
KERN_ERR
"Interrupt %
d
(real) is invalid,"
printk
(
KERN_ERR
"Interrupt %
u
(real) is invalid,"
" disabling it.
\n
"
,
vec
);
" disabling it.
\n
"
,
vec
);
xics_disable_real_irq
(
vec
);
xics_disable_real_irq
(
vec
);
}
else
}
else
...
@@ -622,7 +622,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
...
@@ -622,7 +622,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
status
=
rtas_call
(
ibm_get_xive
,
1
,
3
,
xics_status
,
irq
);
status
=
rtas_call
(
ibm_get_xive
,
1
,
3
,
xics_status
,
irq
);
if
(
status
)
{
if
(
status
)
{
printk
(
KERN_ERR
"xics_set_affinity: irq=%
d
ibm,get-xive "
printk
(
KERN_ERR
"xics_set_affinity: irq=%
u
ibm,get-xive "
"returns %d
\n
"
,
irq
,
status
);
"returns %d
\n
"
,
irq
,
status
);
return
;
return
;
}
}
...
@@ -641,7 +641,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
...
@@ -641,7 +641,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
irq
,
newmask
,
xics_status
[
1
]);
irq
,
newmask
,
xics_status
[
1
]);
if
(
status
)
{
if
(
status
)
{
printk
(
KERN_ERR
"xics_set_affinity: irq=%
d
ibm,set-xive "
printk
(
KERN_ERR
"xics_set_affinity: irq=%
u
ibm,set-xive "
"returns %d
\n
"
,
irq
,
status
);
"returns %d
\n
"
,
irq
,
status
);
return
;
return
;
}
}
...
@@ -720,7 +720,7 @@ void xics_migrate_irqs_away(void)
...
@@ -720,7 +720,7 @@ void xics_migrate_irqs_away(void)
status
=
rtas_call
(
ibm_get_xive
,
1
,
3
,
xics_status
,
irq
);
status
=
rtas_call
(
ibm_get_xive
,
1
,
3
,
xics_status
,
irq
);
if
(
status
)
{
if
(
status
)
{
printk
(
KERN_ERR
"migrate_irqs_away: irq=%
d
"
printk
(
KERN_ERR
"migrate_irqs_away: irq=%
u
"
"ibm,get-xive returns %d
\n
"
,
"ibm,get-xive returns %d
\n
"
,
virq
,
status
);
virq
,
status
);
goto
unlock
;
goto
unlock
;
...
@@ -734,7 +734,7 @@ void xics_migrate_irqs_away(void)
...
@@ -734,7 +734,7 @@ void xics_migrate_irqs_away(void)
if
(
xics_status
[
0
]
!=
get_hard_smp_processor_id
(
cpu
))
if
(
xics_status
[
0
]
!=
get_hard_smp_processor_id
(
cpu
))
goto
unlock
;
goto
unlock
;
printk
(
KERN_WARNING
"IRQ %
d
affinity broken off cpu %u
\n
"
,
printk
(
KERN_WARNING
"IRQ %
u
affinity broken off cpu %u
\n
"
,
virq
,
cpu
);
virq
,
cpu
);
/* Reset affinity to all cpus */
/* Reset affinity to all cpus */
...
...
arch/ppc64/mm/fault.c
浏览文件 @
26cda988
...
@@ -77,6 +77,28 @@ static int store_updates_sp(struct pt_regs *regs)
...
@@ -77,6 +77,28 @@ static int store_updates_sp(struct pt_regs *regs)
return
0
;
return
0
;
}
}
static
void
do_dabr
(
struct
pt_regs
*
regs
,
unsigned
long
error_code
)
{
siginfo_t
info
;
if
(
notify_die
(
DIE_DABR_MATCH
,
"dabr_match"
,
regs
,
error_code
,
11
,
SIGSEGV
)
==
NOTIFY_STOP
)
return
;
if
(
debugger_dabr_match
(
regs
))
return
;
/* Clear the DABR */
set_dabr
(
0
);
/* Deliver the signal to userspace */
info
.
si_signo
=
SIGTRAP
;
info
.
si_errno
=
0
;
info
.
si_code
=
TRAP_HWBKPT
;
info
.
si_addr
=
(
void
__user
*
)
regs
->
nip
;
force_sig_info
(
SIGTRAP
,
&
info
,
current
);
}
/*
/*
* The error_code parameter is
* The error_code parameter is
* - DSISR for a non-SLB data access fault,
* - DSISR for a non-SLB data access fault,
...
@@ -111,12 +133,9 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
...
@@ -111,12 +133,9 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
if
(
!
user_mode
(
regs
)
&&
(
address
>=
TASK_SIZE
))
if
(
!
user_mode
(
regs
)
&&
(
address
>=
TASK_SIZE
))
return
SIGSEGV
;
return
SIGSEGV
;
if
(
error_code
&
DSISR_DABRMATCH
)
{
if
(
error_code
&
DSISR_DABRMATCH
)
{
if
(
notify_die
(
DIE_DABR_MATCH
,
"dabr_match"
,
regs
,
error_code
,
do_dabr
(
regs
,
error_code
);
11
,
SIGSEGV
)
==
NOTIFY_STOP
)
return
0
;
return
0
;
if
(
debugger_dabr_match
(
regs
))
return
0
;
}
}
if
(
in_atomic
()
||
mm
==
NULL
)
{
if
(
in_atomic
()
||
mm
==
NULL
)
{
...
...
arch/ppc64/xmon/privinst.h
浏览文件 @
26cda988
...
@@ -46,7 +46,6 @@ GSETSPR(287, pvr)
...
@@ -46,7 +46,6 @@ GSETSPR(287, pvr)
GSETSPR
(
1008
,
hid0
)
GSETSPR
(
1008
,
hid0
)
GSETSPR
(
1009
,
hid1
)
GSETSPR
(
1009
,
hid1
)
GSETSPR
(
1010
,
iabr
)
GSETSPR
(
1010
,
iabr
)
GSETSPR
(
1013
,
dabr
)
GSETSPR
(
1023
,
pir
)
GSETSPR
(
1023
,
pir
)
static
inline
void
store_inst
(
void
*
p
)
static
inline
void
store_inst
(
void
*
p
)
...
...
arch/ppc64/xmon/xmon.c
浏览文件 @
26cda988
...
@@ -586,6 +586,8 @@ int xmon_dabr_match(struct pt_regs *regs)
...
@@ -586,6 +586,8 @@ int xmon_dabr_match(struct pt_regs *regs)
{
{
if
((
regs
->
msr
&
(
MSR_IR
|
MSR_PR
|
MSR_SF
))
!=
(
MSR_IR
|
MSR_SF
))
if
((
regs
->
msr
&
(
MSR_IR
|
MSR_PR
|
MSR_SF
))
!=
(
MSR_IR
|
MSR_SF
))
return
0
;
return
0
;
if
(
dabr
.
enabled
==
0
)
return
0
;
xmon_core
(
regs
,
0
);
xmon_core
(
regs
,
0
);
return
1
;
return
1
;
}
}
...
@@ -628,20 +630,6 @@ int xmon_fault_handler(struct pt_regs *regs)
...
@@ -628,20 +630,6 @@ int xmon_fault_handler(struct pt_regs *regs)
return
0
;
return
0
;
}
}
/* On systems with a hypervisor, we can't set the DABR
(data address breakpoint register) directly. */
static
void
set_controlled_dabr
(
unsigned
long
val
)
{
#ifdef CONFIG_PPC_PSERIES
if
(
systemcfg
->
platform
==
PLATFORM_PSERIES_LPAR
)
{
int
rc
=
plpar_hcall_norets
(
H_SET_DABR
,
val
);
if
(
rc
!=
H_Success
)
xmon_printf
(
"Warning: setting DABR failed (%d)
\n
"
,
rc
);
}
else
#endif
set_dabr
(
val
);
}
static
struct
bpt
*
at_breakpoint
(
unsigned
long
pc
)
static
struct
bpt
*
at_breakpoint
(
unsigned
long
pc
)
{
{
int
i
;
int
i
;
...
@@ -728,7 +716,7 @@ static void insert_bpts(void)
...
@@ -728,7 +716,7 @@ static void insert_bpts(void)
static
void
insert_cpu_bpts
(
void
)
static
void
insert_cpu_bpts
(
void
)
{
{
if
(
dabr
.
enabled
)
if
(
dabr
.
enabled
)
set_
controlled_
dabr
(
dabr
.
address
|
(
dabr
.
enabled
&
7
));
set_dabr
(
dabr
.
address
|
(
dabr
.
enabled
&
7
));
if
(
iabr
&&
cpu_has_feature
(
CPU_FTR_IABR
))
if
(
iabr
&&
cpu_has_feature
(
CPU_FTR_IABR
))
set_iabr
(
iabr
->
address
set_iabr
(
iabr
->
address
|
(
iabr
->
enabled
&
(
BP_IABR
|
BP_IABR_TE
)));
|
(
iabr
->
enabled
&
(
BP_IABR
|
BP_IABR_TE
)));
...
@@ -756,7 +744,7 @@ static void remove_bpts(void)
...
@@ -756,7 +744,7 @@ static void remove_bpts(void)
static
void
remove_cpu_bpts
(
void
)
static
void
remove_cpu_bpts
(
void
)
{
{
set_
controlled_
dabr
(
0
);
set_dabr
(
0
);
if
(
cpu_has_feature
(
CPU_FTR_IABR
))
if
(
cpu_has_feature
(
CPU_FTR_IABR
))
set_iabr
(
0
);
set_iabr
(
0
);
}
}
...
...
include/asm-powerpc/siginfo.h
浏览文件 @
26cda988
...
@@ -15,4 +15,12 @@
...
@@ -15,4 +15,12 @@
#include <asm-generic/siginfo.h>
#include <asm-generic/siginfo.h>
/*
* SIGTRAP si_codes
*/
#define TRAP_BRANCH (__SI_FAULT|3)
/* process taken branch trap */
#define TRAP_HWBKPT (__SI_FAULT|4)
/* hardware breakpoint or watchpoint */
#undef NSIGTRAP
#define NSIGTRAP 4
#endif
/* _ASM_POWERPC_SIGINFO_H */
#endif
/* _ASM_POWERPC_SIGINFO_H */
include/asm-ppc/ptrace.h
浏览文件 @
26cda988
...
@@ -142,4 +142,11 @@ do { \
...
@@ -142,4 +142,11 @@ do { \
#define PTRACE_GETEVRREGS 20
#define PTRACE_GETEVRREGS 20
#define PTRACE_SETEVRREGS 21
#define PTRACE_SETEVRREGS 21
/*
* Get or set a debug register. The first 16 are DABR registers and the
* second 16 are IABR registers.
*/
#define PTRACE_GET_DEBUGREG 25
#define PTRACE_SET_DEBUGREG 26
#endif
#endif
include/asm-ppc64/hvcall.h
浏览文件 @
26cda988
...
@@ -56,6 +56,11 @@
...
@@ -56,6 +56,11 @@
#define H_PP1 (1UL<<(63-62))
#define H_PP1 (1UL<<(63-62))
#define H_PP2 (1UL<<(63-63))
#define H_PP2 (1UL<<(63-63))
/* DABRX flags */
#define H_DABRX_HYPERVISOR (1UL<<(63-61))
#define H_DABRX_KERNEL (1UL<<(63-62))
#define H_DABRX_USER (1UL<<(63-63))
/* pSeries hypervisor opcodes */
/* pSeries hypervisor opcodes */
#define H_REMOVE 0x04
#define H_REMOVE 0x04
#define H_ENTER 0x08
#define H_ENTER 0x08
...
@@ -101,6 +106,7 @@
...
@@ -101,6 +106,7 @@
#define H_VIO_SIGNAL 0x104
#define H_VIO_SIGNAL 0x104
#define H_SEND_CRQ 0x108
#define H_SEND_CRQ 0x108
#define H_COPY_RDMA 0x110
#define H_COPY_RDMA 0x110
#define H_SET_XDABR 0x134
#define H_STUFF_TCE 0x138
#define H_STUFF_TCE 0x138
#define H_PUT_TCE_INDIRECT 0x13C
#define H_PUT_TCE_INDIRECT 0x13C
#define H_VTERM_PARTNER_INFO 0x150
#define H_VTERM_PARTNER_INFO 0x150
...
...
include/asm-ppc64/machdep.h
浏览文件 @
26cda988
...
@@ -88,6 +88,7 @@ struct machdep_calls {
...
@@ -88,6 +88,7 @@ struct machdep_calls {
/* PCI stuff */
/* PCI stuff */
void
(
*
pcibios_fixup
)(
void
);
void
(
*
pcibios_fixup
)(
void
);
int
(
*
pci_probe_mode
)(
struct
pci_bus
*
);
void
(
*
restart
)(
char
*
cmd
);
void
(
*
restart
)(
char
*
cmd
);
void
(
*
power_off
)(
void
);
void
(
*
power_off
)(
void
);
...
@@ -173,10 +174,6 @@ extern sys_ctrler_t sys_ctrler;
...
@@ -173,10 +174,6 @@ extern sys_ctrler_t sys_ctrler;
void
ppc64_boot_msg
(
unsigned
int
src
,
const
char
*
msg
);
void
ppc64_boot_msg
(
unsigned
int
src
,
const
char
*
msg
);
/* Print a termination message (print only -- does not stop the kernel) */
/* Print a termination message (print only -- does not stop the kernel) */
void
ppc64_terminate_msg
(
unsigned
int
src
,
const
char
*
msg
);
void
ppc64_terminate_msg
(
unsigned
int
src
,
const
char
*
msg
);
/* Print something that needs attention (device error, etc) */
void
ppc64_attention_msg
(
unsigned
int
src
,
const
char
*
msg
);
/* Print a dump progress message. */
void
ppc64_dump_msg
(
unsigned
int
src
,
const
char
*
msg
);
static
inline
void
log_error
(
char
*
buf
,
unsigned
int
err_type
,
int
fatal
)
static
inline
void
log_error
(
char
*
buf
,
unsigned
int
err_type
,
int
fatal
)
{
{
...
...
include/asm-ppc64/pci-bridge.h
浏览文件 @
26cda988
...
@@ -119,5 +119,10 @@ static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus)
...
@@ -119,5 +119,10 @@ static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus)
return
PCI_DN
(
busdn
)
->
phb
;
return
PCI_DN
(
busdn
)
->
phb
;
}
}
/* Return values for ppc_md.pci_probe_mode function */
#define PCI_PROBE_NONE -1
/* Don't look at this bus at all */
#define PCI_PROBE_NORMAL 0
/* Do normal PCI probing */
#define PCI_PROBE_DEVTREE 1
/* Instantiate from device tree */
#endif
#endif
#endif
/* __KERNEL__ */
#endif
/* __KERNEL__ */
include/asm-ppc64/plpar_wrappers.h
浏览文件 @
26cda988
...
@@ -107,5 +107,14 @@ static inline long plpar_put_term_char(unsigned long termno,
...
@@ -107,5 +107,14 @@ static inline long plpar_put_term_char(unsigned long termno,
lbuf
[
1
]);
lbuf
[
1
]);
}
}
static
inline
long
plpar_set_xdabr
(
unsigned
long
address
,
unsigned
long
flags
)
{
return
plpar_hcall_norets
(
H_SET_XDABR
,
address
,
flags
);
}
static
inline
long
plpar_set_dabr
(
unsigned
long
val
)
{
return
plpar_hcall_norets
(
H_SET_DABR
,
val
);
}
#endif
/* _PPC64_PLPAR_WRAPPERS_H */
#endif
/* _PPC64_PLPAR_WRAPPERS_H */
include/asm-ppc64/processor.h
浏览文件 @
26cda988
...
@@ -433,6 +433,7 @@ struct thread_struct {
...
@@ -433,6 +433,7 @@ struct thread_struct {
unsigned
long
start_tb
;
/* Start purr when proc switched in */
unsigned
long
start_tb
;
/* Start purr when proc switched in */
unsigned
long
accum_tb
;
/* Total accumilated purr for process */
unsigned
long
accum_tb
;
/* Total accumilated purr for process */
unsigned
long
vdso_base
;
/* base of the vDSO library */
unsigned
long
vdso_base
;
/* base of the vDSO library */
unsigned
long
dabr
;
/* Data address breakpoint register */
#ifdef CONFIG_ALTIVEC
#ifdef CONFIG_ALTIVEC
/* Complete AltiVec register set */
/* Complete AltiVec register set */
vector128
vr
[
32
]
__attribute
((
aligned
(
16
)));
vector128
vr
[
32
]
__attribute
((
aligned
(
16
)));
...
...
include/asm-ppc64/ptrace-common.h
浏览文件 @
26cda988
...
@@ -11,6 +11,10 @@
...
@@ -11,6 +11,10 @@
#ifndef _PPC64_PTRACE_COMMON_H
#ifndef _PPC64_PTRACE_COMMON_H
#define _PPC64_PTRACE_COMMON_H
#define _PPC64_PTRACE_COMMON_H
#include <linux/config.h>
#include <asm/system.h>
/*
/*
* Set of msr bits that gdb can change on behalf of a process.
* Set of msr bits that gdb can change on behalf of a process.
*/
*/
...
@@ -69,4 +73,92 @@ static inline void clear_single_step(struct task_struct *task)
...
@@ -69,4 +73,92 @@ static inline void clear_single_step(struct task_struct *task)
clear_ti_thread_flag
(
task
->
thread_info
,
TIF_SINGLESTEP
);
clear_ti_thread_flag
(
task
->
thread_info
,
TIF_SINGLESTEP
);
}
}
#ifdef CONFIG_ALTIVEC
/*
* Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
* The transfer totals 34 quadword. Quadwords 0-31 contain the
* corresponding vector registers. Quadword 32 contains the vscr as the
* last word (offset 12) within that quadword. Quadword 33 contains the
* vrsave as the first word (offset 0) within the quadword.
*
* This definition of the VMX state is compatible with the current PPC32
* ptrace interface. This allows signal handling and ptrace to use the
* same structures. This also simplifies the implementation of a bi-arch
* (combined (32- and 64-bit) gdb.
*/
/*
* Get contents of AltiVec register state in task TASK
*/
static
inline
int
get_vrregs
(
unsigned
long
__user
*
data
,
struct
task_struct
*
task
)
{
unsigned
long
regsize
;
/* copy AltiVec registers VR[0] .. VR[31] */
regsize
=
32
*
sizeof
(
vector128
);
if
(
copy_to_user
(
data
,
task
->
thread
.
vr
,
regsize
))
return
-
EFAULT
;
data
+=
(
regsize
/
sizeof
(
unsigned
long
));
/* copy VSCR */
regsize
=
1
*
sizeof
(
vector128
);
if
(
copy_to_user
(
data
,
&
task
->
thread
.
vscr
,
regsize
))
return
-
EFAULT
;
data
+=
(
regsize
/
sizeof
(
unsigned
long
));
/* copy VRSAVE */
if
(
put_user
(
task
->
thread
.
vrsave
,
(
u32
__user
*
)
data
))
return
-
EFAULT
;
return
0
;
}
/*
* Write contents of AltiVec register state into task TASK.
*/
static
inline
int
set_vrregs
(
struct
task_struct
*
task
,
unsigned
long
__user
*
data
)
{
unsigned
long
regsize
;
/* copy AltiVec registers VR[0] .. VR[31] */
regsize
=
32
*
sizeof
(
vector128
);
if
(
copy_from_user
(
task
->
thread
.
vr
,
data
,
regsize
))
return
-
EFAULT
;
data
+=
(
regsize
/
sizeof
(
unsigned
long
));
/* copy VSCR */
regsize
=
1
*
sizeof
(
vector128
);
if
(
copy_from_user
(
&
task
->
thread
.
vscr
,
data
,
regsize
))
return
-
EFAULT
;
data
+=
(
regsize
/
sizeof
(
unsigned
long
));
/* copy VRSAVE */
if
(
get_user
(
task
->
thread
.
vrsave
,
(
u32
__user
*
)
data
))
return
-
EFAULT
;
return
0
;
}
#endif
static
inline
int
ptrace_set_debugreg
(
struct
task_struct
*
task
,
unsigned
long
addr
,
unsigned
long
data
)
{
/* We only support one DABR and no IABRS at the moment */
if
(
addr
>
0
)
return
-
EINVAL
;
/* The bottom 3 bits are flags */
if
((
data
&
~
0x7UL
)
>=
TASK_SIZE
)
return
-
EIO
;
/* Ensure translation is on */
if
(
data
&&
!
(
data
&
DABR_TRANSLATION
))
return
-
EIO
;
task
->
thread
.
dabr
=
data
;
return
0
;
}
#endif
/* _PPC64_PTRACE_COMMON_H */
#endif
/* _PPC64_PTRACE_COMMON_H */
include/asm-ppc64/ptrace.h
浏览文件 @
26cda988
...
@@ -25,56 +25,49 @@
...
@@ -25,56 +25,49 @@
*/
*/
#ifndef __ASSEMBLY__
#ifndef __ASSEMBLY__
#define PPC_REG unsigned long
struct
pt_regs
{
struct
pt_regs
{
PPC_REG
gpr
[
32
];
unsigned
long
gpr
[
32
];
PPC_REG
nip
;
unsigned
long
nip
;
PPC_REG
msr
;
unsigned
long
msr
;
PPC_REG
orig_gpr3
;
/* Used for restarting system calls */
unsigned
long
orig_gpr3
;
/* Used for restarting system calls */
PPC_REG
ctr
;
unsigned
long
ctr
;
PPC_REG
link
;
unsigned
long
link
;
PPC_REG
xer
;
unsigned
long
xer
;
PPC_REG
ccr
;
unsigned
long
ccr
;
PPC_REG
softe
;
/* Soft enabled/disabled */
unsigned
long
softe
;
/* Soft enabled/disabled */
PPC_REG
trap
;
/* Reason for being here */
unsigned
long
trap
;
/* Reason for being here */
PPC_REG
dar
;
/* Fault registers */
unsigned
long
dar
;
/* Fault registers */
PPC_REG
dsisr
;
unsigned
long
dsisr
;
PPC_REG
result
;
/* Result of a system call */
unsigned
long
result
;
/* Result of a system call */
};
};
#define PPC_REG_32 unsigned int
struct
pt_regs32
{
struct
pt_regs32
{
PPC_REG_32
gpr
[
32
];
unsigned
int
gpr
[
32
];
PPC_REG_32
nip
;
unsigned
int
nip
;
PPC_REG_32
msr
;
unsigned
int
msr
;
PPC_REG_32
orig_gpr3
;
/* Used for restarting system calls */
unsigned
int
orig_gpr3
;
/* Used for restarting system calls */
PPC_REG_32
ctr
;
unsigned
int
ctr
;
PPC_REG_32
link
;
unsigned
int
link
;
PPC_REG_32
xer
;
unsigned
int
xer
;
PPC_REG_32
ccr
;
unsigned
int
ccr
;
PPC_REG_32
mq
;
/* 601 only (not used at present) */
unsigned
int
mq
;
/* 601 only (not used at present) */
/* Used on APUS to hold IPL value. */
unsigned
int
trap
;
/* Reason for being here */
PPC_REG_32
trap
;
/* Reason for being here */
unsigned
int
dar
;
/* Fault registers */
PPC_REG_32
dar
;
/* Fault registers */
unsigned
int
dsisr
;
PPC_REG_32
dsisr
;
unsigned
int
result
;
/* Result of a system call */
PPC_REG_32
result
;
/* Result of a system call */
};
};
#ifdef __KERNEL__
#define instruction_pointer(regs) ((regs)->nip)
#define instruction_pointer(regs) ((regs)->nip)
#ifdef CONFIG_SMP
#ifdef CONFIG_SMP
extern
unsigned
long
profile_pc
(
struct
pt_regs
*
regs
);
extern
unsigned
long
profile_pc
(
struct
pt_regs
*
regs
);
#else
#else
#define profile_pc(regs) instruction_pointer(regs)
#define profile_pc(regs) instruction_pointer(regs)
#endif
#endif
#endif
/* __ASSEMBLY__ */
#define STACK_FRAME_OVERHEAD 112
/* size of minimum stack frame */
/* Size of dummy stack frame allocated when calling signal handler. */
#define __SIGNAL_FRAMESIZE 128
#define __SIGNAL_FRAMESIZE32 64
#define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1)
#define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1)
#define force_successful_syscall_return() \
#define force_successful_syscall_return() \
...
@@ -89,6 +82,16 @@ extern unsigned long profile_pc(struct pt_regs *regs);
...
@@ -89,6 +82,16 @@ extern unsigned long profile_pc(struct pt_regs *regs);
#define TRAP(regs) ((regs)->trap & ~0xF)
#define TRAP(regs) ((regs)->trap & ~0xF)
#define CHECK_FULL_REGS(regs) BUG_ON(regs->trap & 1)
#define CHECK_FULL_REGS(regs) BUG_ON(regs->trap & 1)
#endif
/* __KERNEL__ */
#endif
/* __ASSEMBLY__ */
#define STACK_FRAME_OVERHEAD 112
/* size of minimum stack frame */
/* Size of dummy stack frame allocated when calling signal handler. */
#define __SIGNAL_FRAMESIZE 128
#define __SIGNAL_FRAMESIZE32 64
/*
/*
* Offsets used by 'ptrace' system call interface.
* Offsets used by 'ptrace' system call interface.
*/
*/
...
@@ -135,17 +138,21 @@ extern unsigned long profile_pc(struct pt_regs *regs);
...
@@ -135,17 +138,21 @@ extern unsigned long profile_pc(struct pt_regs *regs);
#define PT_XER 37
#define PT_XER 37
#define PT_CCR 38
#define PT_CCR 38
#define PT_SOFTE 39
#define PT_SOFTE 39
#define PT_TRAP 40
#define PT_DAR 41
#define PT_DSISR 42
#define PT_RESULT 43
#define PT_RESULT 43
#define PT_FPR0 48
#define PT_FPR0 48
/* Kernel and userspace will both use this PT_FPSCR value. 32-bit apps will have
/*
* visibility to the asm-ppc/ptrace.h header instead of this one.
* Kernel and userspace will both use this PT_FPSCR value. 32-bit apps will
* have visibility to the asm-ppc/ptrace.h header instead of this one.
*/
*/
#define PT_FPSCR (PT_FPR0 + 32)
/* each FP reg occupies 1 slot in 64-bit space */
#define PT_FPSCR (PT_FPR0 + 32)
/* each FP reg occupies 1 slot in 64-bit space */
#ifdef __KERNEL__
#ifdef __KERNEL__
#define PT_FPSCR32 (PT_FPR0 + 2*32 + 1)
/* each FP reg occupies 2 32-bit userspace slots */
#define PT_FPSCR32 (PT_FPR0 + 2*32 + 1)
/* each FP reg occupies 2 32-bit userspace slots */
#endif
#endif
#define PT_VR0 82
/* each Vector reg occupies 2 slots in 64-bit */
#define PT_VR0 82
/* each Vector reg occupies 2 slots in 64-bit */
...
@@ -173,17 +180,34 @@ extern unsigned long profile_pc(struct pt_regs *regs);
...
@@ -173,17 +180,34 @@ extern unsigned long profile_pc(struct pt_regs *regs);
#define PTRACE_GETVRREGS 18
#define PTRACE_GETVRREGS 18
#define PTRACE_SETVRREGS 19
#define PTRACE_SETVRREGS 19
/* Additional PTRACE requests implemented on PowerPC. */
/*
#define PPC_PTRACE_GETREGS 0x99
/* Get GPRs 0 - 31 */
* While we dont have 64bit book E processors, we need to reserve the
#define PPC_PTRACE_SETREGS 0x98
/* Set GPRs 0 - 31 */
* relevant ptrace calls for 32bit compatibility.
#define PPC_PTRACE_GETFPREGS 0x97
/* Get FPRs 0 - 31 */
*/
#define PPC_PTRACE_SETFPREGS 0x96
/* Set FPRs 0 - 31 */
#if 0
#define PPC_PTRACE_PEEKTEXT_3264 0x95
/* Read word at location ADDR on a 64-bit process from a 32-bit process. */
#define PTRACE_GETEVRREGS 20
#define PPC_PTRACE_PEEKDATA_3264 0x94
/* Read word at location ADDR on a 64-bit process from a 32-bit process. */
#define PTRACE_SETEVRREGS 21
#define PPC_PTRACE_POKETEXT_3264 0x93
/* Write word at location ADDR on a 64-bit process from a 32-bit process. */
#endif
#define PPC_PTRACE_POKEDATA_3264 0x92
/* Write word at location ADDR on a 64-bit process from a 32-bit process. */
#define PPC_PTRACE_PEEKUSR_3264 0x91
/* Read a register (specified by ADDR) out of the "user area" on a 64-bit process from a 32-bit process. */
#define PPC_PTRACE_POKEUSR_3264 0x90
/* Write DATA into location ADDR within the "user area" on a 64-bit process from a 32-bit process. */
/*
* Get or set a debug register. The first 16 are DABR registers and the
* second 16 are IABR registers.
*/
#define PTRACE_GET_DEBUGREG 25
#define PTRACE_SET_DEBUGREG 26
/* Additional PTRACE requests implemented on PowerPC. */
#define PPC_PTRACE_GETREGS 0x99
/* Get GPRs 0 - 31 */
#define PPC_PTRACE_SETREGS 0x98
/* Set GPRs 0 - 31 */
#define PPC_PTRACE_GETFPREGS 0x97
/* Get FPRs 0 - 31 */
#define PPC_PTRACE_SETFPREGS 0x96
/* Set FPRs 0 - 31 */
/* Calls to trace a 64bit program from a 32bit program */
#define PPC_PTRACE_PEEKTEXT_3264 0x95
#define PPC_PTRACE_PEEKDATA_3264 0x94
#define PPC_PTRACE_POKETEXT_3264 0x93
#define PPC_PTRACE_POKEDATA_3264 0x92
#define PPC_PTRACE_PEEKUSR_3264 0x91
#define PPC_PTRACE_POKEUSR_3264 0x90
#endif
/* _PPC64_PTRACE_H */
#endif
/* _PPC64_PTRACE_H */
include/asm-ppc64/system.h
浏览文件 @
26cda988
...
@@ -101,6 +101,9 @@ static inline int debugger_dabr_match(struct pt_regs *regs) { return 0; }
...
@@ -101,6 +101,9 @@ static inline int debugger_dabr_match(struct pt_regs *regs) { return 0; }
static
inline
int
debugger_fault_handler
(
struct
pt_regs
*
regs
)
{
return
0
;
}
static
inline
int
debugger_fault_handler
(
struct
pt_regs
*
regs
)
{
return
0
;
}
#endif
#endif
extern
int
set_dabr
(
unsigned
long
dabr
);
extern
void
_exception
(
int
signr
,
struct
pt_regs
*
regs
,
int
code
,
unsigned
long
addr
);
extern
int
fix_alignment
(
struct
pt_regs
*
regs
);
extern
int
fix_alignment
(
struct
pt_regs
*
regs
);
extern
void
bad_page_fault
(
struct
pt_regs
*
regs
,
unsigned
long
address
,
extern
void
bad_page_fault
(
struct
pt_regs
*
regs
,
unsigned
long
address
,
int
sig
);
int
sig
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录