Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
96d803da
Commit
96d803da
authored
Nov 02, 2002
by
Richard Henderson
Browse files
Options
Browse Files
Download
Plain Diff
Merge are.twiddle.net:/home/rth/BK/linus-2.5
into are.twiddle.net:/home/rth/BK/axp-2.5
parents
37e093c1
353cc80d
Changes
18
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
1209 additions
and
470 deletions
+1209
-470
arch/alpha/Kconfig
arch/alpha/Kconfig
+3
-0
arch/alpha/defconfig
arch/alpha/defconfig
+1
-0
arch/alpha/kernel/Makefile
arch/alpha/kernel/Makefile
+1
-1
arch/alpha/kernel/core_cia.c
arch/alpha/kernel/core_cia.c
+5
-3
arch/alpha/kernel/entry.S
arch/alpha/kernel/entry.S
+5
-3
arch/alpha/kernel/err_common.c
arch/alpha/kernel/err_common.c
+772
-0
arch/alpha/kernel/err_impl.h
arch/alpha/kernel/err_impl.h
+148
-0
arch/alpha/kernel/irq_alpha.c
arch/alpha/kernel/irq_alpha.c
+2
-2
arch/alpha/kernel/osf_sys.c
arch/alpha/kernel/osf_sys.c
+19
-4
arch/alpha/kernel/process.c
arch/alpha/kernel/process.c
+5
-2
arch/alpha/kernel/signal.c
arch/alpha/kernel/signal.c
+20
-4
arch/alpha/kernel/sys_nautilus.c
arch/alpha/kernel/sys_nautilus.c
+11
-342
arch/alpha/kernel/traps.c
arch/alpha/kernel/traps.c
+148
-58
arch/alpha/math-emu/math.c
arch/alpha/math-emu/math.c
+25
-13
arch/alpha/mm/fault.c
arch/alpha/mm/fault.c
+34
-17
include/asm-alpha/hwrpb.h
include/asm-alpha/hwrpb.h
+3
-0
include/asm-alpha/siginfo.h
include/asm-alpha/siginfo.h
+3
-18
include/asm-alpha/system.h
include/asm-alpha/system.h
+4
-3
No files found.
arch/alpha/Kconfig
View file @
96d803da
...
...
@@ -522,6 +522,9 @@ config ALPHA_LARGE_VMALLOC
Say N unless you know you need gobs and gobs of vmalloc space.
config VERBOSE_MCHECK
bool "Verbose Machine Checks"
source "drivers/pci/Kconfig"
config HOTPLUG
...
...
arch/alpha/defconfig
View file @
96d803da
...
...
@@ -59,6 +59,7 @@ CONFIG_ALPHA_GENERIC=y
# CONFIG_ALPHA_TAKARA is not set
# CONFIG_ALPHA_TITAN is not set
# CONFIG_ALPHA_WILDFIRE is not set
CONFIG_VERBOSE_MCHECK=y
CONFIG_ISA=y
CONFIG_EISA=y
# CONFIG_SBUS is not set
...
...
arch/alpha/kernel/Makefile
View file @
96d803da
...
...
@@ -10,7 +10,7 @@ export-objs := alpha_ksyms.o
obj-y
:=
entry.o traps.o process.o init_task.o osf_sys.o irq.o
\
irq_alpha.o signal.o setup.o ptrace.o time.o semaphore.o
\
alpha_ksyms.o systbls.o
alpha_ksyms.o systbls.o
err_common.o
#
# FIXME!
...
...
arch/alpha/kernel/core_cia.c
View file @
96d803da
...
...
@@ -755,6 +755,7 @@ cia_pci_clr_err(void)
*
(
vip
)
CIA_IOC_CIA_ERR
;
/* re-read to force write. */
}
#ifdef CONFIG_VERBOSE_MCHECK
static
void
cia_decode_pci_error
(
struct
el_CIA_sysdata_mcheck
*
cia
,
const
char
*
msg
)
{
...
...
@@ -1022,13 +1023,13 @@ cia_decode_parity_error(struct el_CIA_sysdata_mcheck *cia)
printk
(
KERN_CRIT
" Command: %s, Parity bit: %d
\n
"
,
cmd
,
par
);
printk
(
KERN_CRIT
" Address: %#010lx, Mask: %#lx
\n
"
,
addr
,
mask
);
}
#endif
static
int
cia_decode_mchk
(
unsigned
long
la_ptr
)
{
struct
el_common
*
com
;
struct
el_CIA_sysdata_mcheck
*
cia
;
int
which
;
com
=
(
void
*
)
la_ptr
;
cia
=
(
void
*
)(
la_ptr
+
com
->
sys_offset
);
...
...
@@ -1036,8 +1037,8 @@ cia_decode_mchk(unsigned long la_ptr)
if
((
cia
->
cia_err
&
CIA_ERR_VALID
)
==
0
)
return
0
;
which
=
cia
->
cia_err
&
0xfff
;
switch
(
ffs
(
which
)
-
1
)
{
#ifdef CONFIG_VERBOSE_MCHECK
switch
(
ffs
(
cia
->
cia_err
&
0xfff
)
-
1
)
{
case
0
:
/* CIA_ERR_COR_ERR */
cia_decode_ecc_error
(
cia
,
"Corrected ECC error"
);
break
;
...
...
@@ -1109,6 +1110,7 @@ cia_decode_mchk(unsigned long la_ptr)
if
(
cia
->
cia_err
&
CIA_ERR_LOST_IOA_TIMEOUT
)
printk
(
KERN_CRIT
"CIA lost machine check: "
"I/O timeout
\n
"
);
#endif
return
1
;
}
...
...
arch/alpha/kernel/entry.S
View file @
96d803da
...
...
@@ -452,7 +452,8 @@ sys_fork:
bsr
$
1
,
do_switch_stack
bis
$
31
,
SIGCHLD
,
$
16
mov
$
31
,
$
17
mov
$
30
,
$
18
mov
$
31
,
$
18
mov
$
30
,
$
19
jsr
$
26
,
alpha_clone
bsr
$
1
,
undo_switch_stack
ret
$
31
,(
$
26
),
1
...
...
@@ -463,8 +464,9 @@ sys_fork:
.
ent
sys_clone
sys_clone
:
bsr
$
1
,
do_switch_stack
/
*
arg1
and
arg2
come
from
the
user
*/
mov
$
30
,
$
18
/
*
$
16
,
$
17
,
$
18
,
$
19
come
from
the
user
; $19 is used later
via
pt_regs
->
r19
.
*/
mov
$
30
,
$
19
jsr
$
26
,
alpha_clone
bsr
$
1
,
undo_switch_stack
ret
$
31
,(
$
26
),
1
...
...
arch/alpha/kernel/err_common.c
0 → 100644
View file @
96d803da
/*
* linux/arch/alpha/kernel/err_common.c
*
* Copyright (C) 2000 Jeff Wiedemeier (Compaq Computer Corporation)
*
* Error handling code supporting Alpha systems
*/
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/sched.h>
#include <asm/io.h>
#include <asm/hwrpb.h>
#include <asm/smp.h>
#include "err_impl.h"
#include "proto.h"
/*
* err_print_prefix -- error handling print routines should prefix
* all prints with this
*/
char
*
err_print_prefix
=
KERN_NOTICE
;
/*
* Forward references
*/
static
void
el_print_timestamp
(
union
el_timestamp
);
static
void
el_process_subpackets
(
struct
el_subpacket
*
,
int
);
/*
* Generic
*/
void
mchk_dump_mem
(
void
*
data
,
int
length
,
char
**
annotation
)
{
unsigned
long
*
ldata
=
data
;
int
i
;
for
(
i
=
0
;
(
i
*
sizeof
(
*
ldata
))
<
length
;
i
++
)
{
if
(
annotation
&&
!
annotation
[
i
])
annotation
=
NULL
;
printk
(
"%s %08x: %016lx %s
\n
"
,
err_print_prefix
,
(
unsigned
)(
i
*
sizeof
(
*
ldata
)),
ldata
[
i
],
annotation
?
annotation
[
i
]
:
""
);
}
}
void
mchk_dump_logout_frame
(
struct
el_common
*
mchk_header
)
{
printk
(
"%s -- Frame Header --
\n
"
" Frame Size: %d (0x%x) bytes
\n
"
" Flags: %s%s
\n
"
" MCHK Code: 0x%x
\n
"
" Frame Rev: %d
\n
"
" Proc Offset: 0x%08x
\n
"
" Sys Offset: 0x%08x
\n
"
" -- Processor Region --
\n
"
,
err_print_prefix
,
mchk_header
->
size
,
mchk_header
->
size
,
mchk_header
->
retry
?
"RETRY "
:
""
,
mchk_header
->
err2
?
"SECOND_ERR "
:
""
,
mchk_header
->
code
,
mchk_header
->
frame_rev
,
mchk_header
->
proc_offset
,
mchk_header
->
sys_offset
);
mchk_dump_mem
((
void
*
)
((
unsigned
long
)
mchk_header
+
mchk_header
->
proc_offset
),
mchk_header
->
sys_offset
-
mchk_header
->
proc_offset
,
NULL
);
printk
(
"%s -- System Region --
\n
"
,
err_print_prefix
);
mchk_dump_mem
((
void
*
)
((
unsigned
long
)
mchk_header
+
mchk_header
->
sys_offset
),
mchk_header
->
size
-
mchk_header
->
sys_offset
,
NULL
);
printk
(
"%s -- End of Frame --
\n
"
,
err_print_prefix
);
}
/*
* EV7 generic
*/
#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EV7)
void
ev7_machine_check
(
u64
vector
,
u64
la_ptr
,
struct
pt_regs
*
regs
)
{
/*
* Sync the processor
*/
mb
();
draina
();
/*
* Parse the logout frame without printing first. If the only error(s)
* found are have a disposition of "dismiss", then just dismiss them
* and don't print any message
*/
printk
(
"%sEV7 MACHINE CHECK vector %lx
\n
"
,
err_print_prefix
,
vector
);
/*
* Release the logout frame
*/
wrmces
(
0x7
);
mb
();
}
struct
ev7_pal_subpacket
{
union
{
struct
{
u32
mchk_code
;
u32
subpacket_count
;
u64
whami
;
u64
rbox_whami
;
u64
rbox_int
;
u64
exc_addr
;
union
el_timestamp
timestamp
;
u64
halt_code
;
u64
reserved
;
}
logout
;
}
by_type
;
};
static
char
*
el_ev7_processor_subpacket_annotation
[]
=
{
"Subpacket Header"
,
"I_STAT"
,
"DC_STAT"
,
"C_ADDR"
,
"C_SYNDROME_1"
,
"C_SYNDROME_0"
,
"C_STAT"
,
"C_STS"
,
"MM_STAT"
,
"EXC_ADDR"
,
"IER_CM"
,
"ISUM"
,
"PAL_BASE"
,
"I_CTL"
,
"PROCESS_CONTEXT"
,
"CBOX_CTL"
,
"CBOX_STP_CTL"
,
"CBOX_ACC_CTL"
,
"CBOX_LCL_SET"
,
"CBOX_GLB_SET"
,
"BBOX_CTL"
,
"BBOX_ERR_STS"
,
"BBOX_ERR_IDX"
,
"CBOX_DDP_ERR_STS"
,
"BBOX_DAT_RMP"
,
NULL
};
static
char
*
el_ev7_zbox_subpacket_annotation
[]
=
{
"Subpacket Header"
,
"ZBOX(0): DRAM_ERR_STATUS_2 / DRAM_ERR_STATUS_1"
,
"ZBOX(0): DRAM_ERROR_CTL / DRAM_ERR_STATUS_3"
,
"ZBOX(0): DIFT_TIMEOUT / DRAM_ERR_ADR"
,
"ZBOX(0): FRC_ERR_ADR / DRAM_MAPPER_CTL"
,
"ZBOX(0): reserved / DIFT_ERR_STATUS"
,
"ZBOX(1): DRAM_ERR_STATUS_2 / DRAM_ERR_STATUS_1"
,
"ZBOX(1): DRAM_ERROR_CTL / DRAM_ERR_STATUS_3"
,
"ZBOX(1): DIFT_TIMEOUT / DRAM_ERR_ADR"
,
"ZBOX(1): FRC_ERR_ADR / DRAM_MAPPER_CTL"
,
"ZBOX(1): reserved / DIFT_ERR_STATUS"
,
"CBOX_CTL"
,
"CBOX_STP_CTL"
,
"ZBOX(0)_ERROR_PA"
,
"ZBOX(1)_ERROR_PA"
,
"ZBOX(0)_ORED_SYNDROME"
,
"ZBOX(1)_ORED_SYNDROME"
,
NULL
};
static
char
*
el_ev7_rbox_subpacket_annotation
[]
=
{
"Subpacket Header"
,
"RBOX_CFG"
,
"RBOX_N_CFG"
,
"RBOX_S_CFG"
,
"RBOX_E_CFG"
,
"RBOX_W_CFG"
,
"RBOX_N_ERR"
,
"RBOX_S_ERR"
,
"RBOX_E_ERR"
,
"RBOX_W_ERR"
,
"RBOX_IO_CFG"
,
"RBOX_IO_ERR"
,
"RBOX_L_ERR"
,
"RBOX_WHOAMI"
,
"RBOX_IMASL"
,
"RBOX_INTQ"
,
"RBOX_INT"
,
NULL
};
static
char
*
el_ev7_io_subpacket_annotation
[]
=
{
"Subpacket Header"
,
"IO_ASIC_REV"
,
"IO_SYS_REV"
,
"IO7_UPH"
,
"HPI_CTL"
,
"CRD_CTL"
,
"HEI_CTL"
,
"PO7_ERROR_SUM"
,
"PO7_UNCRR_SYM"
,
"PO7_CRRCT_SYM"
,
"PO7_UGBGE_SYM"
,
"PO7_ERR_PKT0"
,
"PO7_ERR_PKT1"
,
"reserved"
,
"reserved"
,
"PO0_ERR_SUM"
,
"PO0_TLB_ERR"
,
"PO0_SPL_COMPLT"
,
"PO0_TRANS_SUM"
,
"PO0_FIRST_ERR"
,
"PO0_MULT_ERR"
,
"DM CSR PH"
,
"DM CSR PH"
,
"DM CSR PH"
,
"DM CSR PH"
,
"reserved"
,
"PO1_ERR_SUM"
,
"PO1_TLB_ERR"
,
"PO1_SPL_COMPLT"
,
"PO1_TRANS_SUM"
,
"PO1_FIRST_ERR"
,
"PO1_MULT_ERR"
,
"DM CSR PH"
,
"DM CSR PH"
,
"DM CSR PH"
,
"DM CSR PH"
,
"reserved"
,
"PO2_ERR_SUM"
,
"PO2_TLB_ERR"
,
"PO2_SPL_COMPLT"
,
"PO2_TRANS_SUM"
,
"PO2_FIRST_ERR"
,
"PO2_MULT_ERR"
,
"DM CSR PH"
,
"DM CSR PH"
,
"DM CSR PH"
,
"DM CSR PH"
,
"reserved"
,
"PO3_ERR_SUM"
,
"PO3_TLB_ERR"
,
"PO3_SPL_COMPLT"
,
"PO3_TRANS_SUM"
,
"PO3_FIRST_ERR"
,
"PO3_MULT_ERR"
,
"DM CSR PH"
,
"DM CSR PH"
,
"DM CSR PH"
,
"DM CSR PH"
,
"reserved"
,
NULL
};
static
struct
el_subpacket_annotation
el_ev7_pal_annotations
[]
=
{
SUBPACKET_ANNOTATION
(
EL_CLASS__PAL
,
EL_TYPE__PAL__EV7_PROCESSOR
,
1
,
"EV7 Processor Subpacket"
,
el_ev7_processor_subpacket_annotation
),
SUBPACKET_ANNOTATION
(
EL_CLASS__PAL
,
EL_TYPE__PAL__EV7_ZBOX
,
1
,
"EV7 ZBOX Subpacket"
,
el_ev7_zbox_subpacket_annotation
),
SUBPACKET_ANNOTATION
(
EL_CLASS__PAL
,
EL_TYPE__PAL__EV7_RBOX
,
1
,
"EV7 RBOX Subpacket"
,
el_ev7_rbox_subpacket_annotation
),
SUBPACKET_ANNOTATION
(
EL_CLASS__PAL
,
EL_TYPE__PAL__EV7_IO
,
1
,
"EV7 IO Subpacket"
,
el_ev7_io_subpacket_annotation
)
};
static
struct
el_subpacket
*
ev7_process_pal_subpacket
(
struct
el_subpacket
*
header
)
{
struct
ev7_pal_subpacket
*
packet
;
if
(
header
->
class
!=
EL_CLASS__PAL
)
{
printk
(
"%s ** Unexpected header CLASS %d TYPE %d, aborting
\n
"
,
err_print_prefix
,
header
->
class
,
header
->
type
);
return
NULL
;
}
packet
=
(
struct
ev7_pal_subpacket
*
)
header
->
by_type
.
raw
.
data_start
;
switch
(
header
->
type
)
{
case
EL_TYPE__PAL__LOGOUT_FRAME
:
printk
(
"%s*** MCHK occurred on LPID %ld (RBOX %lx)
\n
"
,
err_print_prefix
,
packet
->
by_type
.
logout
.
whami
,
packet
->
by_type
.
logout
.
rbox_whami
);
el_print_timestamp
(
packet
->
by_type
.
logout
.
timestamp
);
printk
(
"%s EXC_ADDR: %016lx
\n
"
" HALT_CODE: %lx
\n
"
,
err_print_prefix
,
packet
->
by_type
.
logout
.
exc_addr
,
packet
->
by_type
.
logout
.
halt_code
);
el_process_subpackets
(
header
,
packet
->
by_type
.
logout
.
subpacket_count
);
break
;
default:
printk
(
"%s ** PAL TYPE %d SUBPACKET
\n
"
,
err_print_prefix
,
header
->
type
);
el_annotate_subpacket
(
header
);
break
;
}
return
(
struct
el_subpacket
*
)((
unsigned
long
)
header
+
header
->
length
);
}
struct
el_subpacket_handler
ev7_pal_subpacket_handler
=
SUBPACKET_HANDLER_INIT
(
EL_CLASS__PAL
,
ev7_process_pal_subpacket
);
void
ev7_register_error_handlers
(
void
)
{
int
i
;
for
(
i
=
0
;
i
<
sizeof
(
el_ev7_pal_annotations
)
/
sizeof
(
el_ev7_pal_annotations
[
1
]);
i
++
)
{
cdl_register_subpacket_annotation
(
&
el_ev7_pal_annotations
[
i
]);
}
cdl_register_subpacket_handler
(
&
ev7_pal_subpacket_handler
);
}
#endif
/* CONFIG_ALPHA_GENERIC || CONFIG_ALPHA_EV7 */
/*
* EV6 generic
*/
#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EV6)
static
int
ev6_parse_ibox
(
u64
i_stat
,
int
print
)
{
int
status
=
MCHK_DISPOSITION_REPORT
;
#define EV6__I_STAT__PAR (1UL << 29)
#define EV6__I_STAT__ERRMASK (EV6__I_STAT__PAR)
if
(
!
(
i_stat
&
EV6__I_STAT__ERRMASK
))
return
MCHK_DISPOSITION_UNKNOWN_ERROR
;
if
(
!
print
)
return
status
;
if
(
i_stat
&
EV6__I_STAT__PAR
)
printk
(
"%s Icache parity error
\n
"
,
err_print_prefix
);
return
status
;
}
static
int
ev6_parse_mbox
(
u64
mm_stat
,
u64
d_stat
,
u64
c_stat
,
int
print
)
{
int
status
=
MCHK_DISPOSITION_REPORT
;
#define EV6__MM_STAT__DC_TAG_PERR (1UL << 10)
#define EV6__MM_STAT__ERRMASK (EV6__MM_STAT__DC_TAG_PERR)
#define EV6__D_STAT__TPERR_P0 (1UL << 0)
#define EV6__D_STAT__TPERR_P1 (1UL << 1)
#define EV6__D_STAT__ECC_ERR_ST (1UL << 2)
#define EV6__D_STAT__ECC_ERR_LD (1UL << 3)
#define EV6__D_STAT__SEO (1UL << 4)
#define EV6__D_STAT__ERRMASK (EV6__D_STAT__TPERR_P0 | \
EV6__D_STAT__TPERR_P1 | \
EV6__D_STAT__ECC_ERR_ST | \
EV6__D_STAT__ECC_ERR_LD | \
EV6__D_STAT__SEO)
if
(
!
(
d_stat
&
EV6__D_STAT__ERRMASK
)
&&
!
(
mm_stat
&
EV6__MM_STAT__ERRMASK
))
return
MCHK_DISPOSITION_UNKNOWN_ERROR
;
if
(
!
print
)
return
status
;
if
(
mm_stat
&
EV6__MM_STAT__DC_TAG_PERR
)
printk
(
"%s Dcache tag parity error on probe
\n
"
,
err_print_prefix
);
if
(
d_stat
&
EV6__D_STAT__TPERR_P0
)
printk
(
"%s Dcache tag parity error - pipe 0
\n
"
,
err_print_prefix
);
if
(
d_stat
&
EV6__D_STAT__TPERR_P1
)
printk
(
"%s Dcache tag parity error - pipe 1
\n
"
,
err_print_prefix
);
if
(
d_stat
&
EV6__D_STAT__ECC_ERR_ST
)
printk
(
"%s ECC error occurred on a store
\n
"
,
err_print_prefix
);
if
(
d_stat
&
EV6__D_STAT__ECC_ERR_LD
)
printk
(
"%s ECC error occurred on a %s load
\n
"
,
err_print_prefix
,
c_stat
?
""
:
"speculative "
);
if
(
d_stat
&
EV6__D_STAT__SEO
)
printk
(
"%s Dcache second error
\n
"
,
err_print_prefix
);
return
status
;
}
static
int
ev6_parse_cbox
(
u64
c_addr
,
u64
c1_syn
,
u64
c2_syn
,
u64
c_stat
,
u64
c_sts
,
int
print
)
{
char
*
sourcename
[]
=
{
"UNKNOWN"
,
"UNKNOWN"
,
"UNKNOWN"
,
"MEMORY"
,
"BCACHE"
,
"DCACHE"
,
"BCACHE PROBE"
,
"BCACHE PROBE"
};
char
*
streamname
[]
=
{
"D"
,
"I"
};
char
*
bitsname
[]
=
{
"SINGLE"
,
"DOUBLE"
};
int
status
=
MCHK_DISPOSITION_REPORT
;
int
source
=
-
1
,
stream
=
-
1
,
bits
=
-
1
;
#define EV6__C_STAT__BC_PERR (0x01)
#define EV6__C_STAT__DC_PERR (0x02)
#define EV6__C_STAT__DSTREAM_MEM_ERR (0x03)
#define EV6__C_STAT__DSTREAM_BC_ERR (0x04)
#define EV6__C_STAT__DSTREAM_DC_ERR (0x05)
#define EV6__C_STAT__PROBE_BC_ERR0 (0x06)
/* both 6 and 7 indicate... */
#define EV6__C_STAT__PROBE_BC_ERR1 (0x07)
/* ...probe bc error. */
#define EV6__C_STAT__ISTREAM_MEM_ERR (0x0B)
#define EV6__C_STAT__ISTREAM_BC_ERR (0x0C)
#define EV6__C_STAT__DSTREAM_MEM_DBL (0x13)
#define EV6__C_STAT__DSTREAM_BC_DBL (0x14)
#define EV6__C_STAT__ISTREAM_MEM_DBL (0x1B)
#define EV6__C_STAT__ISTREAM_BC_DBL (0x1C)
#define EV6__C_STAT__SOURCE_MEMORY (0x03)
#define EV6__C_STAT__SOURCE_BCACHE (0x04)
#define EV6__C_STAT__SOURCE__S (0)
#define EV6__C_STAT__SOURCE__M (0x07)
#define EV6__C_STAT__ISTREAM__S (3)
#define EV6__C_STAT__ISTREAM__M (0x01)
#define EV6__C_STAT__DOUBLE__S (4)
#define EV6__C_STAT__DOUBLE__M (0x01)
#define EV6__C_STAT__ERRMASK (0x1F)
#define EV6__C_STS__SHARED (1 << 0)
#define EV6__C_STS__DIRTY (1 << 1)
#define EV6__C_STS__VALID (1 << 2)
#define EV6__C_STS__PARITY (1 << 3)
if
(
!
(
c_stat
&
EV6__C_STAT__ERRMASK
))
return
MCHK_DISPOSITION_UNKNOWN_ERROR
;
if
(
!
print
)
return
status
;
source
=
EXTRACT
(
c_stat
,
EV6__C_STAT__SOURCE
);
stream
=
EXTRACT
(
c_stat
,
EV6__C_STAT__ISTREAM
);
bits
=
EXTRACT
(
c_stat
,
EV6__C_STAT__DOUBLE
);
if
(
c_stat
&
EV6__C_STAT__BC_PERR
)
{
printk
(
"%s Bcache tag parity error
\n
"
,
err_print_prefix
);
source
=
-
1
;
}
if
(
c_stat
&
EV6__C_STAT__DC_PERR
)
{
printk
(
"%s Dcache tag parity error
\n
"
,
err_print_prefix
);
source
=
-
1
;
}
if
(
c_stat
==
EV6__C_STAT__PROBE_BC_ERR0
||
c_stat
==
EV6__C_STAT__PROBE_BC_ERR1
)
{
printk
(
"%s Bcache single-bit error on a probe hit
\n
"
,
err_print_prefix
);
source
=
-
1
;
}
if
(
source
!=
-
1
)
printk
(
"%s %s-STREAM %s-BIT ECC error from %s
\n
"
,
err_print_prefix
,
streamname
[
stream
],
bitsname
[
bits
],
sourcename
[
source
]);
printk
(
"%s Address: 0x%016lx
\n
"
" Syndrome[upper.lower]: %02lx.%02lx
\n
"
,
err_print_prefix
,
c_addr
,
c2_syn
,
c1_syn
);
if
(
source
==
EV6__C_STAT__SOURCE_MEMORY
||
source
==
EV6__C_STAT__SOURCE_BCACHE
)
printk
(
"%s Block status: %s%s%s%s
\n
"
,
err_print_prefix
,
(
c_sts
&
EV6__C_STS__SHARED
)
?
"SHARED "
:
""
,
(
c_sts
&
EV6__C_STS__DIRTY
)
?
"DIRTY "
:
""
,
(
c_sts
&
EV6__C_STS__VALID
)
?
"VALID "
:
""
,
(
c_sts
&
EV6__C_STS__PARITY
)
?
"PARITY "
:
""
);
return
status
;
}
int
ev6_process_logout_frame
(
struct
el_common
*
mchk_header
,
int
print
)
{
struct
el_common_EV6_mcheck
*
ev6mchk
=
(
struct
el_common_EV6_mcheck
*
)
mchk_header
;
int
status
=
MCHK_DISPOSITION_UNKNOWN_ERROR
;
status
|=
ev6_parse_ibox
(
ev6mchk
->
I_STAT
,
print
);
status
|=
ev6_parse_mbox
(
ev6mchk
->
MM_STAT
,
ev6mchk
->
DC_STAT
,
ev6mchk
->
C_STAT
,
print
);
status
|=
ev6_parse_cbox
(
ev6mchk
->
C_ADDR
,
ev6mchk
->
DC1_SYNDROME
,
ev6mchk
->
DC0_SYNDROME
,
ev6mchk
->
C_STAT
,
ev6mchk
->
C_STS
,
print
);
if
(
!
print
)
return
status
;
if
(
status
!=
MCHK_DISPOSITION_DISMISS
)
{
char
*
saved_err_prefix
=
err_print_prefix
;
/*
* Dump some additional information from the frame
*/
printk
(
"%s EXC_ADDR: 0x%016lx IER_CM: 0x%016lx"
" ISUM: 0x%016lx
\n
"
" PAL_BASE: 0x%016lx I_CTL: 0x%016lx"
" PCTX: 0x%016lx
\n
"
,
err_print_prefix
,
ev6mchk
->
EXC_ADDR
,
ev6mchk
->
IER_CM
,
ev6mchk
->
ISUM
,
ev6mchk
->
PAL_BASE
,
ev6mchk
->
I_CTL
,
ev6mchk
->
PCTX
);
if
(
status
==
MCHK_DISPOSITION_UNKNOWN_ERROR
)
{
printk
(
"%s UNKNOWN error, frame follows:
\n
"
,
err_print_prefix
);
}
else
{
/* had decode -- downgrade print level for frame */
err_print_prefix
=
KERN_NOTICE
;
}
mchk_dump_logout_frame
(
mchk_header
);
err_print_prefix
=
saved_err_prefix
;
}
return
status
;
}
void
ev6_machine_check
(
u64
vector
,
u64
la_ptr
,
struct
pt_regs
*
regs
)
{
struct
el_common
*
mchk_header
=
(
struct
el_common
*
)
la_ptr
;
/*
* Sync the processor
*/
mb
();
draina
();
/*
* Parse the logout frame without printing first. If the only error(s)
* found are have a disposition of "dismiss", then just dismiss them
* and don't print any message
*/
if
(
ev6_process_logout_frame
(
mchk_header
,
0
)
!=
MCHK_DISPOSITION_DISMISS
)
{
char
*
saved_err_prefix
=
err_print_prefix
;
err_print_prefix
=
KERN_CRIT
;
/*
* Either a nondismissable error was detected or no
* recognized error was detected in the logout frame
* -- report the error in either case
*/
printk
(
"%s*CPU %s Error (Vector 0x%x) reported on CPU %d:
\n
"
,
err_print_prefix
,
(
vector
==
SCB_Q_PROCERR
)
?
"Correctable"
:
"Uncorrectable"
,
(
unsigned
int
)
vector
,
(
int
)
smp_processor_id
());
ev6_process_logout_frame
(
mchk_header
,
1
);
dik_show_regs
(
regs
,
NULL
);
err_print_prefix
=
saved_err_prefix
;
}
/*
* Release the logout frame
*/
wrmces
(
0x7
);
mb
();
}
#endif
/* CONFIG_ALPHA_GENERIC || CONFIG_ALPHA_EV6 */
/*
* Console Data Log
*/
/* Data */
static
struct
el_subpacket_handler
*
subpacket_handler_list
=
NULL
;
static
struct
el_subpacket_annotation
*
subpacket_annotation_list
=
NULL
;
static
void
el_print_timestamp
(
union
el_timestamp
timestamp
)
{
if
(
timestamp
.
as_int
)
printk
(
"%s TIMESTAMP: %d/%d/%02d %d:%02d:%0d
\n
"
,
err_print_prefix
,
timestamp
.
b
.
month
,
timestamp
.
b
.
day
,
timestamp
.
b
.
year
,
timestamp
.
b
.
hour
,
timestamp
.
b
.
minute
,
timestamp
.
b
.
second
);
}
static
struct
el_subpacket
*
el_process_header_subpacket
(
struct
el_subpacket
*
header
)
{
union
el_timestamp
timestamp
;
char
*
name
=
"UNKNOWN EVENT"
;
int
packet_count
=
0
;
int
length
=
0
;
if
(
header
->
class
!=
EL_CLASS__HEADER
)
{
printk
(
"%s** Unexpected header CLASS %d TYPE %d, aborting
\n
"
,
err_print_prefix
,
header
->
class
,
header
->
type
);
return
NULL
;
}
switch
(
header
->
type
)
{
case
EL_TYPE__HEADER__SYSTEM_ERROR_FRAME
:
name
=
"SYSTEM ERROR"
;
length
=
header
->
by_type
.
sys_err
.
frame_length
;
packet_count
=
header
->
by_type
.
sys_err
.
frame_packet_count
;
timestamp
.
as_int
=
0
;
break
;
case
EL_TYPE__HEADER__SYSTEM_EVENT_FRAME
:
name
=
"SYSTEM EVENT"
;
length
=
header
->
by_type
.
sys_event
.
frame_length
;
packet_count
=
header
->
by_type
.
sys_event
.
frame_packet_count
;
timestamp
=
header
->
by_type
.
sys_event
.
timestamp
;
break
;
case
EL_TYPE__HEADER__HALT_FRAME
:
name
=
"ERROR HALT"
;
length
=
header
->
by_type
.
err_halt
.
frame_length
;
packet_count
=
header
->
by_type
.
err_halt
.
frame_packet_count
;
timestamp
=
header
->
by_type
.
err_halt
.
timestamp
;
break
;
case
EL_TYPE__HEADER__LOGOUT_FRAME
:
name
=
"LOGOUT FRAME"
;
length
=
header
->
by_type
.
logout_header
.
frame_length
;
packet_count
=
1
;
timestamp
.
as_int
=
0
;
break
;
default:
/* Unknown */
printk
(
"%s** Unknown header - CLASS %d TYPE %d, aborting
\n
"
,
err_print_prefix
,
header
->
class
,
header
->
type
);
return
NULL
;
}
printk
(
"%s*** %s:
\n
"
" CLASS %d, TYPE %d
\n
"
,
err_print_prefix
,
name
,
header
->
class
,
header
->
type
);
el_print_timestamp
(
timestamp
);
/*
* Process the subpackets
*/
el_process_subpackets
(
header
,
packet_count
);
/* return the next header */
header
=
(
struct
el_subpacket
*
)
((
unsigned
long
)
header
+
header
->
length
+
length
);
return
header
;
}
static
void
el_process_subpackets
(
struct
el_subpacket
*
header
,
int
packet_count
)
{
struct
el_subpacket
*
subpacket
;
int
i
;
subpacket
=
(
struct
el_subpacket
*
)
((
unsigned
long
)
header
+
header
->
length
);
for
(
i
=
0
;
subpacket
&&
i
<
packet_count
;
i
++
)
{
printk
(
"%sPROCESSING SUBPACKET %d
\n
"
,
err_print_prefix
,
i
);
subpacket
=
el_process_subpacket
(
subpacket
);
}
}
static
struct
el_subpacket
*
el_process_subpacket_reg
(
struct
el_subpacket
*
header
)
{
struct
el_subpacket
*
next
=
NULL
;
struct
el_subpacket_handler
*
h
=
subpacket_handler_list
;
for
(;
h
&&
h
->
class
!=
header
->
class
;
h
=
h
->
next
);
if
(
h
)
next
=
h
->
handler
(
header
);
return
next
;
}
struct
el_subpacket
*
el_process_subpacket
(
struct
el_subpacket
*
header
)
{
struct
el_subpacket
*
next
=
NULL
;
switch
(
header
->
class
)
{
case
EL_CLASS__TERMINATION
:
/* Termination packet, there are no more */
break
;
case
EL_CLASS__HEADER
:
next
=
el_process_header_subpacket
(
header
);
break
;
default:
if
(
NULL
==
(
next
=
el_process_subpacket_reg
(
header
)))
{
printk
(
"%s** Unexpected header CLASS %d TYPE %d"
" -- aborting.
\n
"
,
err_print_prefix
,
header
->
class
,
header
->
type
);
}
break
;
}
return
next
;
}
void
el_annotate_subpacket
(
struct
el_subpacket
*
header
)
{
struct
el_subpacket_annotation
*
a
;
char
**
annotation
=
NULL
;
for
(
a
=
subpacket_annotation_list
;
a
;
a
=
a
->
next
)
{
if
(
a
->
class
==
header
->
class
&&
a
->
type
==
header
->
type
&&
a
->
revision
==
header
->
revision
)
{
/*
* We found the annotation
*/
annotation
=
a
->
annotation
;
printk
(
"%s %s
\n
"
,
err_print_prefix
,
a
->
description
);
break
;
}
}
mchk_dump_mem
(
header
,
header
->
length
,
annotation
);
}
static
void
__init
cdl_process_console_data_log
(
int
cpu
,
struct
percpu_struct
*
pcpu
)
{
struct
el_subpacket
*
header
=
(
struct
el_subpacket
*
)
(
IDENT_ADDR
|
pcpu
->
console_data_log_pa
);
int
err
;
printk
(
"%s******* CONSOLE DATA LOG FOR CPU %d. *******
\n
"
"*** Error(s) were logged on a previous boot
\n
"
,
err_print_prefix
,
cpu
);
for
(
err
=
0
;
header
&&
(
header
->
class
!=
EL_CLASS__TERMINATION
);
err
++
)
header
=
el_process_subpacket
(
header
);
/* let the console know it's ok to clear the error(s) at restart */
pcpu
->
console_data_log_pa
=
0
;
printk
(
"%s*** %d total error(s) logged
\n
"
"**** END OF CONSOLE DATA LOG FOR CPU %d ****
\n
"
,
err_print_prefix
,
err
,
cpu
);
}
void
__init
cdl_check_console_data_log
(
void
)
{
struct
percpu_struct
*
pcpu
;
int
cpu
;
for
(
cpu
=
0
;
cpu
<
hwrpb
->
nr_processors
;
cpu
++
)
{
pcpu
=
(
struct
percpu_struct
*
)
((
unsigned
long
)
hwrpb
+
hwrpb
->
processor_offset
+
cpu
*
hwrpb
->
processor_size
);
if
(
pcpu
->
console_data_log_pa
)
cdl_process_console_data_log
(
cpu
,
pcpu
);
}
}
int
__init
cdl_register_subpacket_annotation
(
struct
el_subpacket_annotation
*
new
)
{
struct
el_subpacket_annotation
*
a
=
subpacket_annotation_list
;
if
(
a
==
NULL
)
subpacket_annotation_list
=
new
;
else
{
for
(;
a
->
next
!=
NULL
;
a
=
a
->
next
)
{
if
((
a
->
class
==
new
->
class
&&
a
->
type
==
new
->
type
)
||
a
==
new
)
{
printk
(
"Attempted to re-register "
"subpacket annotation
\n
"
);
return
-
EINVAL
;
}
}
a
->
next
=
new
;
}
new
->
next
=
NULL
;
return
0
;
}
int
__init
cdl_register_subpacket_handler
(
struct
el_subpacket_handler
*
new
)
{
struct
el_subpacket_handler
*
h
=
subpacket_handler_list
;
if
(
h
==
NULL
)
subpacket_handler_list
=
new
;
else
{
for
(;
h
->
next
!=
NULL
;
h
=
h
->
next
)
{
if
(
h
->
class
==
new
->
class
||
h
==
new
)
{
printk
(
"Attempted to re-register "
"subpacket handler
\n
"
);
return
-
EINVAL
;
}
}
h
->
next
=
new
;
}
new
->
next
=
NULL
;
return
0
;
}
arch/alpha/kernel/err_impl.h
0 → 100644
View file @
96d803da
/*
* linux/arch/alpha/kernel/err_impl.h
*
* Copyright (C) 2000 Jeff Wiedemeier (Compaq Computer Corporation)
*
* Contains declarations and macros to support Alpha error handling
* implementations.
*/
/*
* SCB Vector definitions
*/
#define SCB_Q_SYSERR 0x620
#define SCB_Q_PROCERR 0x630
#define SCB_Q_SYSMCHK 0x660
#define SCB_Q_PROCMCHK 0x670
#define SCB_Q_SYSEVENT 0x680
/*
* Disposition definitions for logout frame parser
*/
#define MCHK_DISPOSITION_UNKNOWN_ERROR 0x00
#define MCHK_DISPOSITION_REPORT 0x01
#define MCHK_DISPOSITION_DISMISS 0x02
/*
* Error Log definitions
*/
/*
* Types
*/
#define EL_CLASS__TERMINATION (0)
# define EL_TYPE__TERMINATION__TERMINATION (0)
#define EL_CLASS__HEADER (5)
# define EL_TYPE__HEADER__SYSTEM_ERROR_FRAME (1)
# define EL_TYPE__HEADER__SYSTEM_EVENT_FRAME (2)
# define EL_TYPE__HEADER__HALT_FRAME (3)
# define EL_TYPE__HEADER__LOGOUT_FRAME (19)
#define EL_CLASS__GENERAL_NOTIFICATION (9)
#define EL_CLASS__PCI_ERROR_FRAME (11)
#define EL_CLASS__REGATTA_FAMILY (12)
# define EL_TYPE__REGATTA__PROCESSOR_ERROR_FRAME (1)
# define EL_TYPE__REGATTA__SYSTEM_ERROR_FRAME (2)
# define EL_TYPE__REGATTA__ENVIRONMENTAL_FRAME (3)
# define EL_TYPE__REGATTA__TITAN_PCHIP0_EXTENDED (8)
# define EL_TYPE__REGATTA__TITAN_PCHIP1_EXTENDED (9)
# define EL_TYPE__REGATTA__TITAN_MEMORY_EXTENDED (10)
# define EL_TYPE__REGATTA__PROCESSOR_DBL_ERROR_HALT (11)
# define EL_TYPE__REGATTA__SYSTEM_DBL_ERROR_HALT (12)
#define EL_CLASS__PAL (14)
# define EL_TYPE__PAL__LOGOUT_FRAME (1)
# define EL_TYPE__PAL__EV7_PROCESSOR (4)
# define EL_TYPE__PAL__EV7_ZBOX (5)
# define EL_TYPE__PAL__EV7_RBOX (6)
# define EL_TYPE__PAL__EV7_IO (7)
union
el_timestamp
{
struct
{
u8
second
;
u8
minute
;
u8
hour
;
u8
day
;
u8
month
;
u8
year
;
}
b
;
u64
as_int
;
};
struct
el_subpacket
{
u16
length
;
/* length of header (in bytes) */
u16
class
;
/* header class and type... */
u16
type
;
/* ...determine content */
u16
revision
;
/* header revision */
union
{
struct
{
/* Class 5, Type 1 - System Error */
u32
frame_length
;
u32
frame_packet_count
;
}
sys_err
;
struct
{
/* Class 5, Type 2 - System Event */
union
el_timestamp
timestamp
;
u32
frame_length
;
u32
frame_packet_count
;
}
sys_event
;
struct
{
/* Class 5, Type 3 - Double Error Halt */
u16
halt_code
;
u16
reserved
;
union
el_timestamp
timestamp
;
u32
frame_length
;
u32
frame_packet_count
;
}
err_halt
;
struct
{
/* Clasee 5, Type 19 - Logout Frame Header */
u32
frame_length
;
u32
frame_flags
;
u32
cpu_offset
;
u32
system_offset
;
}
logout_header
;
struct
{
/* Class 12 - Regatta */
u64
cpuid
;
u64
data_start
[
1
];
}
regatta_frame
;
struct
{
/* Raw */
u64
data_start
[
1
];
}
raw
;
}
by_type
;
};
struct
el_subpacket_annotation
{
struct
el_subpacket_annotation
*
next
;
u16
class
;
u16
type
;
u16
revision
;
char
*
description
;
char
**
annotation
;
};
#define SUBPACKET_ANNOTATION(c, t, r, d, a) {NULL, (c), (t), (r), (d), (a)}
struct
el_subpacket_handler
{
struct
el_subpacket_handler
*
next
;
u16
class
;
struct
el_subpacket
*
(
*
handler
)(
struct
el_subpacket
*
);
};
#define SUBPACKET_HANDLER_INIT(c, h) {NULL, (c), (h)}
/*
* Extract a field from a register given it's name. defines
* for the LSB (__S - shift count) and bitmask (__M) are required
*/
#define EXTRACT(u, f) (((u) >> f##__S) & f##__M)
/*
* err_common.c
*/
extern
char
*
err_print_prefix
;
extern
void
mchk_dump_mem
(
void
*
,
int
,
char
**
);
extern
void
mchk_dump_logout_frame
(
struct
el_common
*
);
extern
void
ev7_register_error_handlers
(
void
);
extern
void
ev7_machine_check
(
u64
,
u64
,
struct
pt_regs
*
);
extern
void
ev6_register_error_handlers
(
void
);
extern
int
ev6_process_logout_frame
(
struct
el_common
*
,
int
);
extern
void
ev6_machine_check
(
u64
,
u64
,
struct
pt_regs
*
);
extern
struct
el_subpacket
*
el_process_subpacket
(
struct
el_subpacket
*
);
extern
void
el_annotate_subpacket
(
struct
el_subpacket
*
);
extern
void
cdl_check_console_data_log
(
void
);
extern
int
cdl_register_subpacket_annotation
(
struct
el_subpacket_annotation
*
);
extern
int
cdl_register_subpacket_handler
(
struct
el_subpacket_handler
*
);
arch/alpha/kernel/irq_alpha.c
View file @
96d803da
...
...
@@ -147,10 +147,10 @@ process_mcheck_info(unsigned long vector, unsigned long la_ptr,
mchk_header
=
(
struct
el_common
*
)
la_ptr
;
printk
(
KERN_CRIT
"%s machine check: vector=0x%lx pc=0x%lx code=0x%
l
x
\n
"
,
printk
(
KERN_CRIT
"%s machine check: vector=0x%lx pc=0x%lx code=0x%x
\n
"
,
machine
,
vector
,
regs
->
pc
,
mchk_header
->
code
);
switch
(
(
unsigned
int
)
mchk_header
->
code
)
{
switch
(
mchk_header
->
code
)
{
/* Machine check reasons. Defined according to PALcode sources. */
case
0x80
:
reason
=
"tag parity error"
;
break
;
case
0x82
:
reason
=
"tag control parity error"
;
break
;
...
...
arch/alpha/kernel/osf_sys.c
View file @
96d803da
...
...
@@ -844,7 +844,7 @@ osf_setsysinfo(unsigned long op, void *buffer, unsigned long nbytes,
{
switch
(
op
)
{
case
SSI_IEEE_FP_CONTROL
:
{
unsigned
long
swcr
,
fpcr
;
unsigned
long
swcr
,
fpcr
,
fex
;
/*
* Alpha Architecture Handbook 4.7.7.3:
...
...
@@ -867,9 +867,24 @@ osf_setsysinfo(unsigned long op, void *buffer, unsigned long nbytes,
wrfpcr
(
fpcr
);
/* If any exceptions are now unmasked, send a signal. */
if
(((
swcr
&
IEEE_STATUS_MASK
)
>>
IEEE_STATUS_TO_EXCSUM_SHIFT
)
&
swcr
)
{
send_sig
(
SIGFPE
,
current
,
1
);
fex
=
((
swcr
&
IEEE_STATUS_MASK
)
>>
IEEE_STATUS_TO_EXCSUM_SHIFT
)
&
swcr
;
if
(
fex
)
{
siginfo_t
info
;
int
si_code
=
0
;
if
(
fex
&
IEEE_TRAP_ENABLE_DNO
)
si_code
=
FPE_FLTUND
;
if
(
fex
&
IEEE_TRAP_ENABLE_INE
)
si_code
=
FPE_FLTRES
;
if
(
fex
&
IEEE_TRAP_ENABLE_UNF
)
si_code
=
FPE_FLTUND
;
if
(
fex
&
IEEE_TRAP_ENABLE_OVF
)
si_code
=
FPE_FLTOVF
;
if
(
fex
&
IEEE_TRAP_ENABLE_DZE
)
si_code
=
FPE_FLTDIV
;
if
(
fex
&
IEEE_TRAP_ENABLE_INV
)
si_code
=
FPE_FLTINV
;
info
.
si_signo
=
SIGFPE
;
info
.
si_errno
=
0
;
info
.
si_code
=
si_code
;
info
.
si_addr
=
0
;
/* FIXME */
send_sig_info
(
SIGFPE
,
&
info
,
current
);
}
return
0
;
...
...
arch/alpha/kernel/process.c
View file @
96d803da
...
...
@@ -245,11 +245,10 @@ release_thread(struct task_struct *dead_task)
*/
int
alpha_clone
(
unsigned
long
clone_flags
,
unsigned
long
usp
,
struct
switch_stack
*
swstack
)
int
*
user_tid
,
struct
switch_stack
*
swstack
)
{
struct
task_struct
*
p
;
struct
pt_regs
*
u_regs
=
(
struct
pt_regs
*
)
(
swstack
+
1
);
int
*
user_tid
=
(
int
*
)
u_regs
->
r19
;
if
(
!
usp
)
usp
=
rdusp
();
...
...
@@ -314,6 +313,10 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
childti
->
pcb
.
ksp
=
(
unsigned
long
)
childstack
;
childti
->
pcb
.
flags
=
1
;
/* set FEN, clear everything else */
/* Set a new TLS for the child thread? Peek back into the
syscall arguments that we saved on syscall entry. */
childti
->
pcb
.
unique
=
(
clone_flags
&
CLONE_SETTLS
?
regs
->
r19
:
0
);
return
0
;
}
...
...
arch/alpha/kernel/signal.c
View file @
96d803da
...
...
@@ -293,8 +293,16 @@ do_sigreturn(struct sigframe *frame, struct pt_regs *regs,
goto
give_sigsegv
;
/* Send SIGTRAP if we're single-stepping: */
if
(
ptrace_cancel_bpt
(
current
))
send_sig
(
SIGTRAP
,
current
,
1
);
if
(
ptrace_cancel_bpt
(
current
))
{
siginfo_t
info
;
info
.
si_signo
=
SIGTRAP
;
info
.
si_errno
=
0
;
info
.
si_code
=
TRAP_BRKPT
;
info
.
si_addr
=
(
void
*
)
regs
->
pc
;
info
.
si_trapno
=
0
;
send_sig_info
(
SIGTRAP
,
&
info
,
current
);
}
return
;
give_sigsegv:
...
...
@@ -330,8 +338,16 @@ do_rt_sigreturn(struct rt_sigframe *frame, struct pt_regs *regs,
do_sigaltstack
(
&
st
,
NULL
,
rdusp
());
/* Send SIGTRAP if we're single-stepping: */
if
(
ptrace_cancel_bpt
(
current
))
send_sig
(
SIGTRAP
,
current
,
1
);
if
(
ptrace_cancel_bpt
(
current
))
{
siginfo_t
info
;
info
.
si_signo
=
SIGTRAP
;
info
.
si_errno
=
0
;
info
.
si_code
=
TRAP_BRKPT
;
info
.
si_addr
=
(
void
*
)
regs
->
pc
;
info
.
si_trapno
=
0
;
send_sig_info
(
SIGTRAP
,
&
info
,
current
);
}
return
;
give_sigsegv:
...
...
arch/alpha/kernel/sys_nautilus.c
View file @
96d803da
...
...
@@ -46,6 +46,7 @@
#include <asm/tlbflush.h>
#include "proto.h"
#include "err_impl.h"
#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"
...
...
@@ -100,317 +101,6 @@ nautilus_kill_arch(int mode)
}
}
/* Machine check handler code
*
* Perform analysis of a machine check that was triggered by the EV6
* CPU's fault-detection mechanism.
*/
/* IPR structures for EV6, containing the necessary data for the
* machine check handler to unpick the logout frame
*/
/* I_STAT */
#define EV6__I_STAT__PAR ( 1 << 29 )
/* MM_STAT */
#define EV6__MM_STAT__DC_TAG_PERR ( 1 << 10 )
/* DC_STAT */
#define EV6__DC_STAT__SEO ( 1 << 4 )
#define EV6__DC_STAT__ECC_ERR_LD ( 1 << 3 )
#define EV6__DC_STAT__ECC_ERR_ST ( 1 << 2 )
#define EV6__DC_STAT__TPERR_P1 ( 1 << 1 )
#define EV6__DC_STAT__TPERR_P0 ( 1 )
/* C_STAT */
#define EV6__C_STAT__BC_PERR ( 0x01 )
#define EV6__C_STAT__DC_PERR ( 0x02 )
#define EV6__C_STAT__DSTREAM_MEM_ERR ( 0x03 )
#define EV6__C_STAT__DSTREAM_BC_ERR ( 0x04 )
#define EV6__C_STAT__DSTREAM_DC_ERR ( 0x05 )
#define EV6__C_STAT__PROBE_BC_ERR0 ( 0x06 )
#define EV6__C_STAT__PROBE_BC_ERR1 ( 0x07 )
#define EV6__C_STAT__ISTREAM_MEM_ERR ( 0x0B )
#define EV6__C_STAT__ISTREAM_BC_ERR ( 0x0C )
#define EV6__C_STAT__DSTREAM_MEM_DBL ( 0x13 )
#define EV6__C_STAT__DSTREAM_BC_DBL ( 0x14 )
#define EV6__C_STAT__ISTREAM_MEM_DBL ( 0x1B )
#define EV6__C_STAT__ISTREAM_BC_DBL ( 0x1C )
/* Take the two syndromes from the CBOX error chain and convert them
* into a bit number. */
/* NOTE - since I don't know of any difference between C0 and C1 I
just ignore C1, since in all cases I've seen so far they are
identical. */
static
const
unsigned
char
ev6_bit_to_syndrome
[
72
]
=
{
0xce
,
0xcb
,
0xd3
,
0xd5
,
0xd6
,
0xd9
,
0xda
,
0xdc
,
/* 0 */
0x23
,
0x25
,
0x26
,
0x29
,
0x2a
,
0x2c
,
0x31
,
0x34
,
/* 8 */
0x0e
,
0x0b
,
0x13
,
0x15
,
0x16
,
0x19
,
0x1a
,
0x1c
,
/* 16 */
0xe3
,
0xe5
,
0xe6
,
0xe9
,
0xea
,
0xec
,
0xf1
,
0xf4
,
/* 24 */
0x4f
,
0x4a
,
0x52
,
0x54
,
0x57
,
0x58
,
0x5b
,
0x5d
,
/* 32 */
0xa2
,
0xa4
,
0xa7
,
0xa8
,
0xab
,
0xad
,
0xb0
,
0xb5
,
/* 40 */
0x8f
,
0x8a
,
0x92
,
0x94
,
0x97
,
0x98
,
0x9b
,
0x9d
,
/* 48 */
0x62
,
0x64
,
0x67
,
0x68
,
0x6b
,
0x6d
,
0x70
,
0x75
,
/* 56 */
0x01
,
0x02
,
0x04
,
0x08
,
0x10
,
0x20
,
0x40
,
0x80
/* 64 */
};
static
int
ev6_syn2bit
(
unsigned
long
c0
,
unsigned
long
c1
)
{
int
bit
;
for
(
bit
=
0
;
bit
<
72
;
bit
++
)
if
(
ev6_bit_to_syndrome
[
bit
]
==
c0
)
return
bit
;
for
(
bit
=
0
;
bit
<
72
;
bit
++
)
if
(
ev6_bit_to_syndrome
[
bit
]
==
c1
)
return
bit
+
64
;
return
-
1
;
/* not found */
}
/* Single bit ECC errors are categorized here. */
#if 0
static const char *interr = "CPU internal error";
static const char *slotb= "Slot-B error";
static const char *membus= "Memory/EV6-bus error";
#else
static
const
char
*
interr
=
""
;
static
const
char
*
slotb
=
""
;
static
const
char
*
membus
=
""
;
#endif
static
void
ev6_crd_interp
(
char
*
interp
,
struct
el_common_EV6_mcheck
*
L
)
{
/* Icache data or tag parity error. */
if
(
L
->
I_STAT
&
EV6__I_STAT__PAR
)
{
sprintf
(
interp
,
"%s: I_STAT[PAR]
\n
"
"Icache data or tag parity error"
,
interr
);
return
;
}
/* Dcache tag parity error (on issue) (DFAULT). */
if
(
L
->
MM_STAT
&
EV6__MM_STAT__DC_TAG_PERR
)
{
sprintf
(
interp
,
"%s: MM_STAT[DC_TAG_PERR]
\n
"
"Dcache tag parity error(on issue)"
,
interr
);
return
;
}
/* Errors relating to D-stream set non-zero DC_STAT.
Mask CRD bits. */
switch
(
L
->
DC_STAT
&
(
EV6__DC_STAT__ECC_ERR_ST
|
EV6__DC_STAT__ECC_ERR_LD
))
{
case
EV6__DC_STAT__ECC_ERR_ST
:
/* Dcache single-bit ECC error on small store */
sprintf
(
interp
,
"%s: DC_STAT[ECC_ERR_ST]
\n
"
"Dcache single-bit ECC error on small store"
,
interr
);
return
;
case
EV6__DC_STAT__ECC_ERR_LD
:
switch
(
L
->
C_STAT
)
{
case
0
:
/* Dcache single-bit error on speculative load */
/* Bcache victim read on Dcache/Bcache miss */
sprintf
(
interp
,
"%s: DC_STAT[ECC_ERR_LD] C_STAT=0
\n
"
"Dcache single-bit ECC error on speculative load"
,
slotb
);
return
;
case
EV6__C_STAT__DSTREAM_DC_ERR
:
/* Dcache single bit error on load */
sprintf
(
interp
,
"%s: DC_STAT[ECC_ERR_LD] C_STAT[DSTREAM_DC_ERR]
\n
"
" Dcache single-bit ECC error on speculative load, bit %d"
,
interr
,
ev6_syn2bit
(
L
->
DC0_SYNDROME
,
L
->
DC1_SYNDROME
));
return
;
case
EV6__C_STAT__DSTREAM_BC_ERR
:
/* Bcache single-bit error on Dcache fill */
sprintf
(
interp
,
"%s: DC_STAT[ECC_ERR_LD] C_STAT[DSTREAM_BC_ERR]
\n
"
" Bcache single-bit error on Dcache fill, bit %d"
,
slotb
,
ev6_syn2bit
(
L
->
DC0_SYNDROME
,
L
->
DC1_SYNDROME
));
return
;
case
EV6__C_STAT__DSTREAM_MEM_ERR
:
/* Memory single-bit error on Dcache fill */
sprintf
(
interp
,
"%s (to Dcache): DC_STAT[ECC_ERR_LD] "
"C_STAT[DSTREAM_MEM_ERR]
\n
"
"Memory single-bit error on Dcache fill, "
"Address 0x%lX, bit %d"
,
membus
,
L
->
C_ADDR
,
ev6_syn2bit
(
L
->
DC0_SYNDROME
,
L
->
DC1_SYNDROME
));
return
;
}
}
/* I-stream, other misc errors go on C_STAT alone */
switch
(
L
->
C_STAT
)
{
case
EV6__C_STAT__ISTREAM_BC_ERR
:
/* Bcache single-bit error on Icache fill (also MCHK) */
sprintf
(
interp
,
"%s: C_STAT[ISTREAM_BC_ERR]
\n
"
"Bcache single-bit error on Icache fill, bit %d"
,
slotb
,
ev6_syn2bit
(
L
->
DC0_SYNDROME
,
L
->
DC1_SYNDROME
));
return
;
case
EV6__C_STAT__ISTREAM_MEM_ERR
:
/* Memory single-bit error on Icache fill (also MCHK) */
sprintf
(
interp
,
"%s : C_STATISTREAM_MEM_ERR]
\n
"
"Memory single-bit error on Icache fill "
"addr 0x%lX, bit %d"
,
membus
,
L
->
C_ADDR
,
ev6_syn2bit
(
L
->
DC0_SYNDROME
,
L
->
DC1_SYNDROME
));
return
;
case
EV6__C_STAT__PROBE_BC_ERR0
:
case
EV6__C_STAT__PROBE_BC_ERR1
:
/* Bcache single-bit error on a probe hit */
sprintf
(
interp
,
"%s: C_STAT[PROBE_BC_ERR]
\n
"
"Bcache single-bit error on a probe hit, "
"addr 0x%lx, bit %d"
,
slotb
,
L
->
C_ADDR
,
ev6_syn2bit
(
L
->
DC0_SYNDROME
,
L
->
DC1_SYNDROME
));
return
;
}
}
static
void
ev6_mchk_interp
(
char
*
interp
,
struct
el_common_EV6_mcheck
*
L
)
{
/* Machine check errors described by DC_STAT */
switch
(
L
->
DC_STAT
)
{
case
EV6__DC_STAT__TPERR_P0
:
case
EV6__DC_STAT__TPERR_P1
:
/* Dcache tag parity error (on retry) */
sprintf
(
interp
,
"%s: DC_STAT[TPERR_P0|TPERR_P1]
\n
"
"Dcache tag parity error(on retry)"
,
interr
);
return
;
case
EV6__DC_STAT__SEO
:
/* Dcache second error on store */
sprintf
(
interp
,
"%s: DC_STAT[SEO]
\n
"
"Dcache second error during mcheck"
,
interr
);
return
;
}
/* Machine check errors described by C_STAT */
switch
(
L
->
C_STAT
)
{
case
EV6__C_STAT__DC_PERR
:
/* Dcache duplicate tag parity error */
sprintf
(
interp
,
"%s: C_STAT[DC_PERR]
\n
"
"Dcache duplicate tag parity error at 0x%lX"
,
interr
,
L
->
C_ADDR
);
return
;
case
EV6__C_STAT__BC_PERR
:
/* Bcache tag parity error */
sprintf
(
interp
,
"%s: C_STAT[BC_PERR]
\n
"
"Bcache tag parity error at 0x%lX"
,
slotb
,
L
->
C_ADDR
);
return
;
case
EV6__C_STAT__ISTREAM_BC_ERR
:
/* Bcache single-bit error on Icache fill (also CRD) */
sprintf
(
interp
,
"%s: C_STAT[ISTREAM_BC_ERR]
\n
"
"Bcache single-bit error on Icache fill 0x%lX bit %d"
,
slotb
,
L
->
C_ADDR
,
ev6_syn2bit
(
L
->
DC0_SYNDROME
,
L
->
DC1_SYNDROME
));
return
;
case
EV6__C_STAT__ISTREAM_MEM_ERR
:
/* Memory single-bit error on Icache fill (also CRD) */
sprintf
(
interp
,
"%s: C_STAT[ISTREAM_MEM_ERR]
\n
"
"Memory single-bit error on Icache fill 0x%lX, bit %d"
,
membus
,
L
->
C_ADDR
,
ev6_syn2bit
(
L
->
DC0_SYNDROME
,
L
->
DC1_SYNDROME
));
return
;
case
EV6__C_STAT__ISTREAM_BC_DBL
:
/* Bcache double-bit error on Icache fill */
sprintf
(
interp
,
"%s: C_STAT[ISTREAM_BC_DBL]
\n
"
"Bcache double-bit error on Icache fill at 0x%lX"
,
slotb
,
L
->
C_ADDR
);
return
;
case
EV6__C_STAT__DSTREAM_BC_DBL
:
/* Bcache double-bit error on Dcache fill */
sprintf
(
interp
,
"%s: C_STAT[DSTREAM_BC_DBL]
\n
"
"Bcache double-bit error on Dcache fill at 0x%lX"
,
slotb
,
L
->
C_ADDR
);
return
;
case
EV6__C_STAT__ISTREAM_MEM_DBL
:
/* Memory double-bit error on Icache fill */
sprintf
(
interp
,
"%s: C_STAT[ISTREAM_MEM_DBL]
\n
"
"Memory double-bit error on Icache fill at 0x%lX"
,
membus
,
L
->
C_ADDR
);
return
;
case
EV6__C_STAT__DSTREAM_MEM_DBL
:
/* Memory double-bit error on Dcache fill */
sprintf
(
interp
,
"%s: C_STAT[DSTREAM_MEM_DBL]
\n
"
"Memory double-bit error on Dcache fill at 0x%lX"
,
membus
,
L
->
C_ADDR
);
return
;
}
}
static
void
ev6_cpu_machine_check
(
unsigned
long
vector
,
struct
el_common_EV6_mcheck
*
L
,
struct
pt_regs
*
regs
)
{
char
interp
[
80
];
/* This is verbose and looks intimidating. Should it be printed for
corrected (CRD) machine checks? */
printk
(
KERN_CRIT
"PALcode logout frame: "
"MCHK_Code %d "
"MCHK_Frame_Rev %d
\n
"
"I_STAT %016lx "
"DC_STAT %016lx "
"C_ADDR %016lx
\n
"
"SYND1 %016lx "
"SYND0 %016lx "
"C_STAT %016lx
\n
"
"C_STS %016lx "
"RES %016lx "
"EXC_ADDR%016lx
\n
"
"IER_CM %016lx "
"ISUM %016lx "
"MM_STAT %016lx
\n
"
"PALBASE %016lx "
"I_CTL %016lx "
"PCTX %016lx
\n
"
"CPU registers: "
"PC %016lx "
"Return %016lx
\n
"
,
L
->
MCHK_Code
,
L
->
MCHK_Frame_Rev
,
L
->
I_STAT
,
L
->
DC_STAT
,
L
->
C_ADDR
,
L
->
DC1_SYNDROME
,
L
->
DC0_SYNDROME
,
L
->
C_STAT
,
L
->
C_STS
,
L
->
RESERVED0
,
L
->
EXC_ADDR
,
L
->
IER_CM
,
L
->
ISUM
,
L
->
MM_STAT
,
L
->
PAL_BASE
,
L
->
I_CTL
,
L
->
PCTX
,
regs
->
pc
,
regs
->
r26
);
/* Attempt an interpretation on the meanings of the fields above. */
sprintf
(
interp
,
"No interpretation available!"
);
if
(
vector
==
SCB_Q_PROCERR
)
ev6_crd_interp
(
interp
,
L
);
else
if
(
vector
==
SCB_Q_PROCMCHK
)
ev6_mchk_interp
(
interp
,
L
);
printk
(
KERN_CRIT
"interpretation: %s
\n\n
"
,
interp
);
}
/* Perform analysis of a machine check that arrived from the system (NMI) */
static
void
...
...
@@ -430,7 +120,6 @@ nautilus_machine_check(unsigned long vector, unsigned long la_ptr,
struct
pt_regs
*
regs
)
{
char
*
mchk_class
;
unsigned
cpu_analysis
=
0
,
sys_analysis
=
0
;
/* Now for some analysis. Machine checks fall into two classes --
those picked up by the system, and those picked up by the CPU.
...
...
@@ -463,39 +152,20 @@ nautilus_machine_check(unsigned long vector, unsigned long la_ptr,
return
;
}
switch
(
vector
)
{
case
SCB_Q_SYSERR
:
mchk_class
=
"Correctable System Machine Check (NMI)"
;
sys_analysis
=
1
;
break
;
case
SCB_Q_SYSMCHK
:
mchk_class
=
"Fatal System Machine Check (NMI)"
;
sys_analysis
=
1
;
break
;
case
SCB_Q_PROCERR
:
mchk_class
=
"Correctable Processor Machine Check"
;
cpu_analysis
=
1
;
break
;
case
SCB_Q_PROCMCHK
:
mchk_class
=
"Fatal Processor Machine Check"
;
cpu_analysis
=
1
;
break
;
default:
mchk_class
=
"Unknown vector!"
;
break
;
if
(
vector
==
SCB_Q_SYSERR
)
mchk_class
=
"Correctable"
;
else
if
(
vector
==
SCB_Q_SYSMCHK
)
mchk_class
=
"Fatal"
;
else
{
ev6_machine_check
(
vector
,
la_ptr
,
regs
);
return
;
}
printk
(
KERN_CRIT
"NAUTILUS Machine check 0x%lx [%s]
\n
"
,
printk
(
KERN_CRIT
"NAUTILUS Machine check 0x%lx "
"[%s System Machine Check (NMI)]
\n
"
,
vector
,
mchk_class
);
if
(
cpu_analysis
)
ev6_cpu_machine_check
(
vector
,
(
struct
el_common_EV6_mcheck
*
)
la_ptr
,
regs
);
if
(
sys_analysis
)
naut_sys_machine_check
(
vector
,
la_ptr
,
regs
);
naut_sys_machine_check
(
vector
,
la_ptr
,
regs
);
/* Tell the PALcode to clear the machine check */
draina
();
...
...
@@ -504,7 +174,6 @@ nautilus_machine_check(unsigned long vector, unsigned long la_ptr,
}
/*
* The System Vectors
*/
...
...
arch/alpha/kernel/traps.c
View file @
96d803da
...
...
@@ -213,25 +213,25 @@ do_entArith(unsigned long summary, unsigned long write_mask,
unsigned
long
a2
,
unsigned
long
a3
,
unsigned
long
a4
,
unsigned
long
a5
,
struct
pt_regs
regs
)
{
long
si_code
=
FPE_FLTINV
;
siginfo_t
info
;
if
(
summary
&
1
)
{
/* Software-completion summary bit is set, so try to
emulate the instruction. */
if
(
!
amask
(
AMASK_PRECISE_TRAP
))
{
/* 21264 (except pass 1) has precise exceptions. */
if
(
alpha_fp_emul
(
regs
.
pc
-
4
))
return
;
}
else
{
if
(
alpha_fp_emul_imprecise
(
&
regs
,
write_mask
))
return
;
}
emulate the instruction. If the processor supports
precise exceptions, we don't have to search. */
if
(
!
amask
(
AMASK_PRECISE_TRAP
))
si_code
=
alpha_fp_emul
(
regs
.
pc
-
4
);
else
si_code
=
alpha_fp_emul_imprecise
(
&
regs
,
write_mask
);
}
#if 0
printk("%s: arithmetic trap at %016lx: %02lx %016lx\n",
current->comm, regs.pc, summary, write_mask);
#endif
die_if_kernel
(
"Arithmetic fault"
,
&
regs
,
0
,
0
);
send_sig
(
SIGFPE
,
current
,
1
);
info
.
si_signo
=
SIGFPE
;
info
.
si_errno
=
0
;
info
.
si_code
=
si_code
;
info
.
si_addr
=
(
void
*
)
regs
.
pc
;
send_sig_info
(
SIGFPE
,
&
info
,
current
);
}
asmlinkage
void
...
...
@@ -239,6 +239,9 @@ do_entIF(unsigned long type, unsigned long a1,
unsigned
long
a2
,
unsigned
long
a3
,
unsigned
long
a4
,
unsigned
long
a5
,
struct
pt_regs
regs
)
{
siginfo_t
info
;
int
signo
,
code
;
if
(
!
opDEC_testing
||
type
!=
4
)
{
if
(
type
==
1
)
{
const
unsigned
int
*
data
...
...
@@ -253,55 +256,99 @@ do_entIF(unsigned long type, unsigned long a1,
switch
(
type
)
{
case
0
:
/* breakpoint */
info
.
si_signo
=
SIGTRAP
;
info
.
si_errno
=
0
;
info
.
si_code
=
TRAP_BRKPT
;
info
.
si_trapno
=
0
;
info
.
si_addr
=
(
void
*
)
regs
.
pc
;
if
(
ptrace_cancel_bpt
(
current
))
{
regs
.
pc
-=
4
;
/* make pc point to former bpt */
}
send_sig
(
SIGTRAP
,
current
,
1
);
send_sig_info
(
SIGTRAP
,
&
info
,
current
);
return
;
case
1
:
/* bugcheck */
send_sig
(
SIGTRAP
,
current
,
1
);
info
.
si_signo
=
SIGTRAP
;
info
.
si_errno
=
0
;
info
.
si_code
=
__SI_FAULT
;
info
.
si_addr
=
(
void
*
)
regs
.
pc
;
info
.
si_trapno
=
0
;
send_sig_info
(
SIGTRAP
,
&
info
,
current
);
return
;
case
2
:
/* gentrap */
/*
* The exception code should be passed on to the signal
* handler as the second argument. Linux doesn't do that
* yet (also notice that Linux *always* behaves like
* DEC Unix with SA_SIGINFO off; see DEC Unix man page
* for sigaction(2)).
*/
info
.
si_addr
=
(
void
*
)
regs
.
pc
;
info
.
si_trapno
=
regs
.
r16
;
switch
((
long
)
regs
.
r16
)
{
case
GEN_INTOVF
:
case
GEN_INTDIV
:
case
GEN_FLTOVF
:
case
GEN_FLTDIV
:
case
GEN_FLTUND
:
case
GEN_FLTINV
:
case
GEN_FLTINE
:
case
GEN_ROPRAND
:
send_sig
(
SIGFPE
,
current
,
1
);
return
;
case
GEN_DECOVF
:
case
GEN_DECDIV
:
case
GEN_DECINV
:
case
GEN_ASSERTERR
:
case
GEN_NULPTRERR
:
case
GEN_STKOVF
:
case
GEN_STRLENERR
:
case
GEN_SUBSTRERR
:
case
GEN_RANGERR
:
case
GEN_SUBRNG
:
case
GEN_SUBRNG1
:
case
GEN_SUBRNG2
:
case
GEN_SUBRNG3
:
case
GEN_SUBRNG4
:
case
GEN_SUBRNG5
:
case
GEN_SUBRNG6
:
case
GEN_SUBRNG7
:
send_sig
(
SIGTRAP
,
current
,
1
);
return
;
case
GEN_INTOVF
:
signo
=
SIGFPE
;
code
=
FPE_INTOVF
;
break
;
case
GEN_INTDIV
:
signo
=
SIGFPE
;
code
=
FPE_INTDIV
;
break
;
case
GEN_FLTOVF
:
signo
=
SIGFPE
;
code
=
FPE_FLTOVF
;
break
;
case
GEN_FLTDIV
:
signo
=
SIGFPE
;
code
=
FPE_FLTDIV
;
break
;
case
GEN_FLTUND
:
signo
=
SIGFPE
;
code
=
FPE_FLTUND
;
break
;
case
GEN_FLTINV
:
signo
=
SIGFPE
;
code
=
FPE_FLTINV
;
break
;
case
GEN_FLTINE
:
signo
=
SIGFPE
;
code
=
FPE_FLTRES
;
break
;
case
GEN_ROPRAND
:
signo
=
SIGFPE
;
code
=
__SI_FAULT
;
break
;
case
GEN_DECOVF
:
case
GEN_DECDIV
:
case
GEN_DECINV
:
case
GEN_ASSERTERR
:
case
GEN_NULPTRERR
:
case
GEN_STKOVF
:
case
GEN_STRLENERR
:
case
GEN_SUBSTRERR
:
case
GEN_RANGERR
:
case
GEN_SUBRNG
:
case
GEN_SUBRNG1
:
case
GEN_SUBRNG2
:
case
GEN_SUBRNG3
:
case
GEN_SUBRNG4
:
case
GEN_SUBRNG5
:
case
GEN_SUBRNG6
:
case
GEN_SUBRNG7
:
default:
signo
=
SIGTRAP
;
code
=
__SI_FAULT
;
break
;
}
break
;
info
.
si_signo
=
signo
;
info
.
si_errno
=
0
;
info
.
si_code
=
code
;
info
.
si_addr
=
(
void
*
)
regs
.
pc
;
send_sig_info
(
signo
,
&
info
,
current
);
return
;
case
4
:
/* opDEC */
if
(
implver
()
==
IMPLVER_EV4
)
{
long
si_code
;
/* The some versions of SRM do not handle
the opDEC properly - they return the PC of the
opDEC fault, not the instruction after as the
...
...
@@ -309,8 +356,7 @@ do_entIF(unsigned long type, unsigned long a1,
We do this by intentionally causing an opDEC
fault during the boot sequence and testing if
we get the correct PC. If not, we set a flag
to correct it every time through.
*/
to correct it every time through. */
if
(
opDEC_testing
)
{
if
(
regs
.
pc
==
opDEC_test_pc
)
{
opDEC_fix
=
4
;
...
...
@@ -324,8 +370,17 @@ do_entIF(unsigned long type, unsigned long a1,
/* EV4 does not implement anything except normal
rounding. Everything else will come here as
an illegal instruction. Emulate them. */
if
(
alpha_fp_emul
(
regs
.
pc
-
4
))
si_code
=
alpha_fp_emul
(
regs
.
pc
-
4
);
if
(
si_code
==
0
)
return
;
if
(
si_code
>
0
)
{
info
.
si_signo
=
SIGFPE
;
info
.
si_errno
=
0
;
info
.
si_code
=
si_code
;
info
.
si_addr
=
(
void
*
)
regs
.
pc
;
send_sig_info
(
SIGFPE
,
&
info
,
current
);
return
;
}
}
break
;
...
...
@@ -347,7 +402,12 @@ do_entIF(unsigned long type, unsigned long a1,
default:
/* unexpected instruction-fault type */
;
}
send_sig
(
SIGILL
,
current
,
1
);
info
.
si_signo
=
SIGILL
;
info
.
si_errno
=
0
;
info
.
si_code
=
ILL_ILLOPC
;
info
.
si_addr
=
regs
.
pc
;
send_sig_info
(
SIGILL
,
&
info
,
current
);
}
/* There is an ifdef in the PALcode in MILO that enables a
...
...
@@ -362,8 +422,15 @@ do_entDbg(unsigned long type, unsigned long a1,
unsigned
long
a2
,
unsigned
long
a3
,
unsigned
long
a4
,
unsigned
long
a5
,
struct
pt_regs
regs
)
{
siginfo_t
info
;
die_if_kernel
(
"Instruction fault"
,
&
regs
,
type
,
0
);
force_sig
(
SIGILL
,
current
);
info
.
si_signo
=
SIGILL
;
info
.
si_errno
=
0
;
info
.
si_code
=
ILL_ILLOPC
;
info
.
si_addr
=
regs
.
pc
;
force_sig_info
(
SIGILL
,
&
info
,
current
);
}
...
...
@@ -720,6 +787,7 @@ do_entUnaUser(void * va, unsigned long opcode,
unsigned
long
tmp1
,
tmp2
,
tmp3
,
tmp4
;
unsigned
long
fake_reg
,
*
reg_addr
=
&
fake_reg
;
siginfo_t
info
;
long
error
;
/* Check the UAC bits to decide what the user wants us to do
...
...
@@ -984,12 +1052,34 @@ do_entUnaUser(void * va, unsigned long opcode,
give_sigsegv:
regs
->
pc
-=
4
;
/* make pc point to faulting insn */
send_sig
(
SIGSEGV
,
current
,
1
);
info
.
si_signo
=
SIGSEGV
;
info
.
si_errno
=
0
;
/* We need to replicate some of the logic in mm/fault.c,
since we don't have access to the fault code in the
exception handling return path. */
if
(
!
__access_ok
((
unsigned
long
)
va
,
0
,
USER_DS
))
info
.
si_code
=
SEGV_ACCERR
;
else
{
struct
mm_struct
*
mm
=
current
->
mm
;
down_read
(
&
mm
->
mmap_sem
);
if
(
find_vma
(
mm
,
(
unsigned
long
)
va
))
info
.
si_code
=
SEGV_ACCERR
;
else
info
.
si_code
=
SEGV_MAPERR
;
up_read
(
&
mm
->
mmap_sem
);
}
info
.
si_addr
=
va
;
send_sig_info
(
SIGSEGV
,
&
info
,
current
);
return
;
give_sigbus:
regs
->
pc
-=
4
;
send_sig
(
SIGBUS
,
current
,
1
);
info
.
si_signo
=
SIGBUS
;
info
.
si_errno
=
0
;
info
.
si_code
=
BUS_ADRALN
;
info
.
si_addr
=
va
;
send_sig_info
(
SIGBUS
,
&
info
,
current
);
return
;
}
...
...
arch/alpha/math-emu/math.c
View file @
96d803da
...
...
@@ -86,11 +86,13 @@ void cleanup_module(void)
/*
* Emulate the floating point instruction at address PC. Returns 0 if
* emulation fails. Notice that the kernel does not and cannot use FP
* regs. This is good because it means that instead of
* saving/restoring all fp regs, we simply stick the result of the
* operation into the appropriate register.
* Emulate the floating point instruction at address PC. Returns -1 if the
* instruction to be emulated is illegal (such as with the opDEC trap), else
* the SI_CODE for a SIGFPE signal, else 0 if everything's ok.
*
* Notice that the kernel does not and cannot use FP regs. This is good
* because it means that instead of saving/restoring all fp regs, we simply
* stick the result of the operation into the appropriate register.
*/
long
alpha_fp_emul
(
unsigned
long
pc
)
...
...
@@ -102,6 +104,7 @@ alpha_fp_emul (unsigned long pc)
unsigned
long
fa
,
fb
,
fc
,
func
,
mode
,
src
;
unsigned
long
res
,
va
,
vb
,
vc
,
swcr
,
fpcr
;
__u32
insn
;
long
si_code
;
MOD_INC_USE_COUNT
;
...
...
@@ -306,10 +309,19 @@ alpha_fp_emul (unsigned long pc)
wrfpcr
(
fpcr
);
/* Do we generate a signal? */
if
(
_fex
&
swcr
&
IEEE_TRAP_ENABLE_MASK
)
{
MOD_DEC_USE_COUNT
;
return
0
;
_fex
=
_fex
&
swcr
&
IEEE_TRAP_ENABLE_MASK
;
si_code
=
0
;
if
(
_fex
)
{
if
(
_fex
&
IEEE_TRAP_ENABLE_DNO
)
si_code
=
FPE_FLTUND
;
if
(
_fex
&
IEEE_TRAP_ENABLE_INE
)
si_code
=
FPE_FLTRES
;
if
(
_fex
&
IEEE_TRAP_ENABLE_UNF
)
si_code
=
FPE_FLTUND
;
if
(
_fex
&
IEEE_TRAP_ENABLE_OVF
)
si_code
=
FPE_FLTOVF
;
if
(
_fex
&
IEEE_TRAP_ENABLE_DZE
)
si_code
=
FPE_FLTDIV
;
if
(
_fex
&
IEEE_TRAP_ENABLE_INV
)
si_code
=
FPE_FLTINV
;
}
MOD_DEC_USE_COUNT
;
return
si_code
;
}
/* We used to write the destination register here, but DEC FORTRAN
...
...
@@ -317,20 +329,20 @@ alpha_fp_emul (unsigned long pc)
immediately after the operations above. */
MOD_DEC_USE_COUNT
;
return
1
;
return
0
;
bad_insn:
printk
(
KERN_ERR
"alpha_fp_emul: Invalid FP insn %#x at %#lx
\n
"
,
insn
,
pc
);
MOD_DEC_USE_COUNT
;
return
0
;
return
-
1
;
}
long
alpha_fp_emul_imprecise
(
struct
pt_regs
*
regs
,
unsigned
long
write_mask
)
{
unsigned
long
trigger_pc
=
regs
->
pc
-
4
;
unsigned
long
insn
,
opcode
,
rc
,
no_signal
=
0
;
unsigned
long
insn
,
opcode
,
rc
,
si_code
=
0
;
MOD_INC_USE_COUNT
;
...
...
@@ -384,7 +396,7 @@ alpha_fp_emul_imprecise (struct pt_regs *regs, unsigned long write_mask)
if
(
!
write_mask
)
{
/* Re-execute insns in the trap-shadow. */
regs
->
pc
=
trigger_pc
+
4
;
no_signal
=
alpha_fp_emul
(
trigger_pc
);
si_code
=
alpha_fp_emul
(
trigger_pc
);
goto
egress
;
}
trigger_pc
-=
4
;
...
...
@@ -392,5 +404,5 @@ alpha_fp_emul_imprecise (struct pt_regs *regs, unsigned long write_mask)
egress:
MOD_DEC_USE_COUNT
;
return
no_signal
;
return
si_code
;
}
arch/alpha/mm/fault.c
View file @
96d803da
...
...
@@ -89,7 +89,8 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
struct
vm_area_struct
*
vma
;
struct
mm_struct
*
mm
=
current
->
mm
;
unsigned
int
fixup
;
int
fault
;
int
fault
,
si_code
=
SEGV_MAPERR
;
siginfo_t
info
;
/* As of EV6, a load into $31/$f31 is a prefetch, and never faults
(or is suppressed by the PALcode). Support that for older CPUs
...
...
@@ -129,6 +130,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
/* Ok, we have a good vm_area for this memory access, so
we can handle it. */
good_area:
si_code
=
SEGV_ACCERR
;
if
(
cause
<
0
)
{
if
(
!
(
vma
->
vm_flags
&
VM_EXEC
))
goto
bad_area
;
...
...
@@ -148,10 +150,20 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
fault
=
handle_mm_fault
(
mm
,
vma
,
address
,
cause
>
0
);
up_read
(
&
mm
->
mmap_sem
);
if
(
fault
<
0
)
goto
out_of_memory
;
if
(
fault
==
0
)
switch
(
fault
)
{
case
VM_FAULT_MINOR
:
current
->
min_flt
++
;
break
;
case
VM_FAULT_MAJOR
:
current
->
maj_flt
++
;
break
;
case
VM_FAULT_SIGBUS
:
goto
do_sigbus
;
case
VM_FAULT_OOM
:
goto
out_of_memory
;
default:
BUG
();
}
return
;
/* Something tried to access memory that isn't in our memory map.
...
...
@@ -159,20 +171,14 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
bad_area:
up_read
(
&
mm
->
mmap_sem
);
if
(
user_mode
(
regs
))
{
force_sig
(
SIGSEGV
,
current
);
return
;
}
if
(
user_mode
(
regs
))
goto
do_sigsegv
;
no_context:
/* Are we prepared to handle this fault as an exception? */
if
((
fixup
=
search_exception_table
(
regs
->
pc
,
regs
->
gp
))
!=
0
)
{
unsigned
long
newpc
;
newpc
=
fixup_exception
(
dpf_reg
,
fixup
,
regs
->
pc
);
#if 0
printk("%s: Exception at [<%lx>] (%lx) handled successfully\n",
current->comm, regs->pc, newpc);
#endif
regs
->
pc
=
newpc
;
return
;
}
...
...
@@ -201,17 +207,28 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
do_sigbus:
/* Send a sigbus, regardless of whether we were in kernel
or user mode. */
force_sig
(
SIGBUS
,
current
);
info
.
si_signo
=
SIGBUS
;
info
.
si_errno
=
0
;
info
.
si_code
=
BUS_ADRERR
;
info
.
si_addr
=
(
void
*
)
address
;
force_sig_info
(
SIGBUS
,
&
info
,
current
);
if
(
!
user_mode
(
regs
))
goto
no_context
;
return
;
do_sigsegv:
info
.
si_signo
=
SIGSEGV
;
info
.
si_errno
=
0
;
info
.
si_code
=
si_code
;
info
.
si_addr
=
(
void
*
)
address
;
force_sig_info
(
SIGSEGV
,
&
info
,
current
);
return
;
#ifdef CONFIG_ALPHA_LARGE_VMALLOC
vmalloc_fault:
if
(
user_mode
(
regs
))
{
force_sig
(
SIGSEGV
,
current
);
return
;
}
else
{
if
(
user_mode
(
regs
))
goto
do_sigsegv
;
else
{
/* Synchronize this task's top level page-table
with the "reference" page table from init. */
long
offset
=
__pgd_offset
(
address
);
...
...
include/asm-alpha/hwrpb.h
View file @
96d803da
...
...
@@ -109,6 +109,9 @@ struct percpu_struct {
unsigned
long
ipc_buffer
[
21
];
unsigned
long
palcode_avail
[
16
];
unsigned
long
compatibility
;
unsigned
long
console_data_log_pa
;
unsigned
long
console_data_log_length
;
unsigned
long
bcache_info
;
};
struct
procdesc_struct
{
...
...
include/asm-alpha/siginfo.h
View file @
96d803da
#ifndef _ALPHA_SIGINFO_H
#define _ALPHA_SIGINFO_H
#define SI_PAD_SIZE ((SI_MAX_SIZE/sizeof(int)) - 4)
#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))
#define __ARCH_SI_TRAPNO
#define SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE/sizeof(int)) - 4)
#define HAVE_ARCH_COPY_SIGINFO
#define SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE/sizeof(int)) - 4)
#include <asm-generic/siginfo.h>
#ifdef __KERNEL__
#include <linux/string.h>
extern
inline
void
copy_siginfo
(
siginfo_t
*
to
,
siginfo_t
*
from
)
{
if
(
from
->
si_code
<
0
)
memcpy
(
to
,
from
,
sizeof
(
siginfo_t
));
else
/* _sigchld is currently the largest know union member */
memcpy
(
to
,
from
,
4
*
sizeof
(
int
)
+
sizeof
(
from
->
_sifields
.
_sigchld
));
}
#endif
/* __KERNEL__ */
#endif
include/asm-alpha/system.h
View file @
96d803da
...
...
@@ -61,7 +61,8 @@ struct el_common {
int
retry
:
1
;
/* retry flag */
unsigned
int
proc_offset
;
/* processor-specific offset */
unsigned
int
sys_offset
;
/* system-specific offset */
unsigned
long
code
;
/* machine check code */
unsigned
int
code
;
/* machine check code */
unsigned
int
frame_rev
;
/* frame revision */
};
/* Machine Check Frame for uncorrectable errors (Large format)
...
...
@@ -117,11 +118,11 @@ struct el_common_EV6_mcheck {
unsigned
long
DC0_SYNDROME
;
unsigned
long
C_STAT
;
unsigned
long
C_STS
;
unsigned
long
RESERVED0
;
unsigned
long
MM_STAT
;
unsigned
long
EXC_ADDR
;
unsigned
long
IER_CM
;
unsigned
long
ISUM
;
unsigned
long
MM_STAT
;
unsigned
long
RESERVED0
;
unsigned
long
PAL_BASE
;
unsigned
long
I_CTL
;
unsigned
long
PCTX
;
...
...
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