Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
adam.huang
Arm Trusted Firmware
Commits
eef90a77
Unverified
Commit
eef90a77
authored
Jul 27, 2018
by
Soby Mathew
Committed by
GitHub
Jul 27, 2018
Browse files
Merge pull request #1497 from SNG-ARM/master
RAS changes for SGI575 platform
parents
128dad9a
f29d1828
Changes
10
Hide whitespace changes
Inline
Side-by-side
include/plat/arm/common/arm_spm_def.h
View file @
eef90a77
...
@@ -7,7 +7,6 @@
...
@@ -7,7 +7,6 @@
#define __ARM_SPM_DEF_H__
#define __ARM_SPM_DEF_H__
#include <arm_def.h>
#include <arm_def.h>
#include <platform_def.h>
#include <utils_def.h>
#include <utils_def.h>
#include <xlat_tables_defs.h>
#include <xlat_tables_defs.h>
...
@@ -73,12 +72,11 @@
...
@@ -73,12 +72,11 @@
/*
/*
* RW memory, which uses the remaining Trusted DRAM. Placed after the memory
* RW memory, which uses the remaining Trusted DRAM. Placed after the memory
* shared between Secure and Non-secure worlds
. First there is the stack memory
* shared between Secure and Non-secure worlds
, or after the platform specific
*
for all CPUs and then there is the common heap memory. Both are mapped with
*
buffers, if defined. First there is the stack memory for all CPUs and then
* RW permissions.
*
there is the common heap memory. Both are mapped with
RW permissions.
*/
*/
#define PLAT_SP_IMAGE_STACK_BASE (ARM_SP_IMAGE_NS_BUF_BASE + \
#define PLAT_SP_IMAGE_STACK_BASE PLAT_ARM_SP_IMAGE_STACK_BASE
ARM_SP_IMAGE_NS_BUF_SIZE)
#define PLAT_SP_IMAGE_STACK_PCPU_SIZE ULL(0x2000)
#define PLAT_SP_IMAGE_STACK_PCPU_SIZE ULL(0x2000)
#define ARM_SP_IMAGE_STACK_TOTAL_SIZE (PLATFORM_CORE_COUNT * \
#define ARM_SP_IMAGE_STACK_TOTAL_SIZE (PLATFORM_CORE_COUNT * \
PLAT_SP_IMAGE_STACK_PCPU_SIZE)
PLAT_SP_IMAGE_STACK_PCPU_SIZE)
...
...
lib/extensions/ras/ras_common.c
View file @
eef90a77
...
@@ -114,9 +114,10 @@ static int ras_interrupt_handler(uint32_t intr_raw, uint32_t flags,
...
@@ -114,9 +114,10 @@ static int ras_interrupt_handler(uint32_t intr_raw, uint32_t flags,
panic
();
panic
();
}
}
if
(
selected
->
err_record
->
probe
)
{
ret
=
selected
->
err_record
->
probe
(
selected
->
err_record
,
&
probe_data
);
ret
=
selected
->
err_record
->
probe
(
selected
->
err_record
,
&
probe_data
);
assert
(
ret
!=
0
);
assert
(
ret
!=
0
);
}
/* Call error handler for the record group */
/* Call error handler for the record group */
assert
(
selected
->
err_record
->
handler
!=
NULL
);
assert
(
selected
->
err_record
->
handler
!=
NULL
);
...
...
plat/arm/board/fvp/include/platform_def.h
View file @
eef90a77
...
@@ -163,4 +163,7 @@
...
@@ -163,4 +163,7 @@
#define PLAT_ARM_PRIVATE_SDEI_EVENTS ARM_SDEI_PRIVATE_EVENTS
#define PLAT_ARM_PRIVATE_SDEI_EVENTS ARM_SDEI_PRIVATE_EVENTS
#define PLAT_ARM_SHARED_SDEI_EVENTS ARM_SDEI_SHARED_EVENTS
#define PLAT_ARM_SHARED_SDEI_EVENTS ARM_SDEI_SHARED_EVENTS
#define PLAT_ARM_SP_IMAGE_STACK_BASE (ARM_SP_IMAGE_NS_BUF_BASE + \
ARM_SP_IMAGE_NS_BUF_SIZE)
#endif
/* __PLATFORM_DEF_H__ */
#endif
/* __PLATFORM_DEF_H__ */
plat/arm/common/arm_err.c
View file @
eef90a77
...
@@ -5,12 +5,12 @@
...
@@ -5,12 +5,12 @@
*/
*/
#include <arch_helpers.h>
#include <arch_helpers.h>
#include <board_arm_def.h>
#include <console.h>
#include <console.h>
#include <debug.h>
#include <debug.h>
#include <errno.h>
#include <errno.h>
#include <norflash.h>
#include <norflash.h>
#include <platform.h>
#include <platform.h>
#include <platform_def.h>
#include <stdint.h>
#include <stdint.h>
/*
/*
...
...
plat/arm/css/sgi/include/platform_def.h
View file @
eef90a77
...
@@ -8,12 +8,14 @@
...
@@ -8,12 +8,14 @@
#define PLATFORM_DEF_H
#define PLATFORM_DEF_H
#include <arm_def.h>
#include <arm_def.h>
#include <arm_spm_def.h>
#include <board_arm_def.h>
#include <board_arm_def.h>
#include <board_css_def.h>
#include <board_css_def.h>
#include <common_def.h>
#include <common_def.h>
#include <css_def.h>
#include <css_def.h>
#include <soc_css_def.h>
#include <soc_css_def.h>
#include <utils_def.h>
#include <utils_def.h>
#include <xlat_tables_defs.h>
#define CSS_SGI_MAX_CPUS_PER_CLUSTER 4
#define CSS_SGI_MAX_CPUS_PER_CLUSTER 4
...
@@ -85,6 +87,55 @@
...
@@ -85,6 +87,55 @@
#define PLAT_ARM_GICC_BASE 0x2C000000
#define PLAT_ARM_GICC_BASE 0x2C000000
#define PLAT_ARM_GICR_BASE 0x300C0000
#define PLAT_ARM_GICR_BASE 0x300C0000
/* Map the secure region for access from S-EL0 */
#define PLAT_ARM_SECURE_MAP_DEVICE MAP_REGION_FLAT( \
SOC_CSS_DEVICE_BASE, \
SOC_CSS_DEVICE_SIZE, \
MT_DEVICE | MT_RW | MT_SECURE | MT_USER)
#if RAS_EXTENSION
/* Allocate 128KB for CPER buffers */
#define PLAT_SP_BUF_BASE ULL(0x20000)
#define PLAT_ARM_SP_IMAGE_STACK_BASE (ARM_SP_IMAGE_NS_BUF_BASE + \
ARM_SP_IMAGE_NS_BUF_SIZE + \
PLAT_SP_BUF_BASE)
/* Platform specific SMC FID's used for RAS */
#define SP_DMC_ERROR_INJECT_EVENT_AARCH64 0xC4000042
#define SP_DMC_ERROR_INJECT_EVENT_AARCH32 0x84000042
#define SP_DMC_ERROR_OVERFLOW_EVENT_AARCH64 0xC4000043
#define SP_DMC_ERROR_OVERFLOW_EVENT_AARCH32 0x84000043
#define SP_DMC_ERROR_ECC_EVENT_AARCH64 0xC4000044
#define SP_DMC_ERROR_ECC_EVENT_AARCH32 0x84000044
/* ARM SDEI dynamic shared event numbers */
#define SGI_SDEI_DS_EVENT_0 804
#define SGI_SDEI_DS_EVENT_1 805
#define PLAT_ARM_PRIVATE_SDEI_EVENTS \
SDEI_DEFINE_EVENT_0(ARM_SDEI_SGI), \
SDEI_EXPLICIT_EVENT(SGI_SDEI_DS_EVENT_0, SDEI_MAPF_CRITICAL), \
SDEI_EXPLICIT_EVENT(SGI_SDEI_DS_EVENT_1, SDEI_MAPF_CRITICAL),
#define PLAT_ARM_SHARED_SDEI_EVENTS
#define ARM_SP_CPER_BUF_BASE (ARM_SP_IMAGE_NS_BUF_BASE + \
ARM_SP_IMAGE_NS_BUF_SIZE)
#define ARM_SP_CPER_BUF_SIZE ULL(0x20000)
#define ARM_SP_CPER_BUF_MMAP MAP_REGION2( \
ARM_SP_CPER_BUF_BASE, \
ARM_SP_CPER_BUF_BASE, \
ARM_SP_CPER_BUF_SIZE, \
MT_RW_DATA | MT_NS | MT_USER, \
PAGE_SIZE)
#else
#define PLAT_ARM_SP_IMAGE_STACK_BASE (ARM_SP_IMAGE_NS_BUF_BASE + \
ARM_SP_IMAGE_NS_BUF_SIZE)
#endif
/* RAS_EXTENSION */
/* Platform ID address */
/* Platform ID address */
#define SSC_VERSION (SSC_REG_BASE + SSC_VERSION_OFFSET)
#define SSC_VERSION (SSC_REG_BASE + SSC_VERSION_OFFSET)
#ifndef __ASSEMBLY__
#ifndef __ASSEMBLY__
...
...
plat/arm/css/sgi/include/sgi_ras.h
0 → 100644
View file @
eef90a77
/*
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __SGI_RAS__
#define __SGI_RAS__
/*
* Mapping the RAS interrupt with SDEI event number and the event
* id used with Standalone MM code
*/
struct
sgi_ras_ev_map
{
int
ras_ev_num
;
/* RAS Event number */
int
sdei_ev_num
;
/* SDEI Event number */
int
intr
;
/* Physical intr number */
};
int
sgi_ras_intr_handler_setup
(
void
);
#endif
/* __SGI_RAS__ */
plat/arm/css/sgi/sgi-common.mk
View file @
eef90a77
...
@@ -8,6 +8,16 @@ ENABLE_PLAT_COMPAT := 0
...
@@ -8,6 +8,16 @@ ENABLE_PLAT_COMPAT := 0
CSS_ENT_BASE
:=
plat/arm/css/sgi
CSS_ENT_BASE
:=
plat/arm/css/sgi
RAS_EXTENSION
:=
0
ENABLE_SPM
:=
0
SDEI_SUPPORT
:=
0
EL3_EXCEPTION_HANDLING
:=
0
HANDLE_EA_EL3_FIRST
:=
0
INTERCONNECT_SOURCES
:=
${CSS_ENT_BASE}
/sgi_interconnect.c
INTERCONNECT_SOURCES
:=
${CSS_ENT_BASE}
/sgi_interconnect.c
PLAT_INCLUDES
+=
-I
${CSS_ENT_BASE}
/include
PLAT_INCLUDES
+=
-I
${CSS_ENT_BASE}
/include
...
@@ -40,6 +50,10 @@ BL31_SOURCES += ${ENT_CPU_SOURCES} \
...
@@ -40,6 +50,10 @@ BL31_SOURCES += ${ENT_CPU_SOURCES} \
${CSS_ENT_BASE}
/sgi_topology.c
\
${CSS_ENT_BASE}
/sgi_topology.c
\
${CSS_ENT_BASE}
/sgi_plat_config.c
${CSS_ENT_BASE}
/sgi_plat_config.c
ifeq
(${RAS_EXTENSION},1)
BL31_SOURCES
+=
${CSS_ENT_BASE}
/sgi_ras.c
endif
# Add the FDT_SOURCES and options for Dynamic Config
# Add the FDT_SOURCES and options for Dynamic Config
FDT_SOURCES
+=
${CSS_ENT_BASE}
/fdts/
${PLAT}
_tb_fw_config.dts
FDT_SOURCES
+=
${CSS_ENT_BASE}
/fdts/
${PLAT}
_tb_fw_config.dts
TB_FW_CONFIG
:=
${BUILD_PLAT}
/fdts/
${PLAT}
_tb_fw_config.dtb
TB_FW_CONFIG
:=
${BUILD_PLAT}
/fdts/
${PLAT}
_tb_fw_config.dtb
...
...
plat/arm/css/sgi/sgi_bl31_setup.c
View file @
eef90a77
...
@@ -8,6 +8,7 @@
...
@@ -8,6 +8,7 @@
#include <debug.h>
#include <debug.h>
#include <plat_arm.h>
#include <plat_arm.h>
#include <sgi_plat_config.h>
#include <sgi_plat_config.h>
#include <sgi_ras.h>
void
bl31_early_platform_setup2
(
u_register_t
arg0
,
u_register_t
arg1
,
void
bl31_early_platform_setup2
(
u_register_t
arg0
,
u_register_t
arg1
,
u_register_t
arg2
,
u_register_t
arg3
)
u_register_t
arg2
,
u_register_t
arg3
)
...
@@ -17,3 +18,12 @@ void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
...
@@ -17,3 +18,12 @@ void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
arm_bl31_early_platform_setup
((
void
*
)
arg0
,
arg1
,
arg2
,
(
void
*
)
arg3
);
arm_bl31_early_platform_setup
((
void
*
)
arg0
,
arg1
,
arg2
,
(
void
*
)
arg3
);
}
}
void
bl31_platform_setup
(
void
)
{
arm_bl31_platform_setup
();
#if RAS_EXTENSION
sgi_ras_intr_handler_setup
();
#endif
}
plat/arm/css/sgi/sgi_plat.c
View file @
eef90a77
...
@@ -5,11 +5,14 @@
...
@@ -5,11 +5,14 @@
*/
*/
#include <arm_def.h>
#include <arm_def.h>
#include <arm_spm_def.h>
#include <bl_common.h>
#include <bl_common.h>
#include <ccn.h>
#include <ccn.h>
#include <debug.h>
#include <debug.h>
#include <plat_arm.h>
#include <plat_arm.h>
#include <platform_def.h>
#include <platform.h>
#include <platform.h>
#include <secure_partition.h>
#include "../../../../bl1/bl1_private.h"
#include "../../../../bl1/bl1_private.h"
#if USE_COHERENT_MEM
#if USE_COHERENT_MEM
...
@@ -57,6 +60,9 @@ const mmap_region_t plat_arm_mmap[] = {
...
@@ -57,6 +60,9 @@ const mmap_region_t plat_arm_mmap[] = {
ARM_MAP_NS_DRAM1
,
ARM_MAP_NS_DRAM1
,
#if ARM_BL31_IN_DRAM
#if ARM_BL31_IN_DRAM
ARM_MAP_BL31_SEC_DRAM
,
ARM_MAP_BL31_SEC_DRAM
,
#endif
#if ENABLE_SPM
ARM_SP_IMAGE_MMAP
,
#endif
#endif
{
0
}
{
0
}
};
};
...
@@ -67,8 +73,73 @@ const mmap_region_t plat_arm_mmap[] = {
...
@@ -67,8 +73,73 @@ const mmap_region_t plat_arm_mmap[] = {
V2M_MAP_IOFPGA
,
V2M_MAP_IOFPGA
,
CSS_SGI_MAP_DEVICE
,
CSS_SGI_MAP_DEVICE
,
SOC_CSS_MAP_DEVICE
,
SOC_CSS_MAP_DEVICE
,
#if ENABLE_SPM
ARM_SPM_BUF_EL3_MMAP
,
#endif
{
0
}
{
0
}
};
};
#if ENABLE_SPM && defined(IMAGE_BL31)
const
mmap_region_t
plat_arm_secure_partition_mmap
[]
=
{
PLAT_ARM_SECURE_MAP_DEVICE
,
ARM_SP_IMAGE_MMAP
,
ARM_SP_IMAGE_NS_BUF_MMAP
,
ARM_SP_CPER_BUF_MMAP
,
ARM_SP_IMAGE_RW_MMAP
,
ARM_SPM_BUF_EL0_MMAP
,
{
0
}
};
#endif
/* ENABLE_SPM && defined(IMAGE_BL31) */
#endif
#endif
ARM_CASSERT_MMAP
ARM_CASSERT_MMAP
#if ENABLE_SPM && defined(IMAGE_BL31)
/*
* Boot information passed to a secure partition during initialisation. Linear
* indices in MP information will be filled at runtime.
*/
static
secure_partition_mp_info_t
sp_mp_info
[]
=
{
[
0
]
=
{
0x81000000
,
0
},
[
1
]
=
{
0x81000100
,
0
},
[
2
]
=
{
0x81000200
,
0
},
[
3
]
=
{
0x81000300
,
0
},
[
4
]
=
{
0x81010000
,
0
},
[
5
]
=
{
0x81010100
,
0
},
[
6
]
=
{
0x81010200
,
0
},
[
7
]
=
{
0x81010300
,
0
},
};
const
secure_partition_boot_info_t
plat_arm_secure_partition_boot_info
=
{
.
h
.
type
=
PARAM_SP_IMAGE_BOOT_INFO
,
.
h
.
version
=
VERSION_1
,
.
h
.
size
=
sizeof
(
secure_partition_boot_info_t
),
.
h
.
attr
=
0
,
.
sp_mem_base
=
ARM_SP_IMAGE_BASE
,
.
sp_mem_limit
=
ARM_SP_IMAGE_LIMIT
,
.
sp_image_base
=
ARM_SP_IMAGE_BASE
,
.
sp_stack_base
=
PLAT_SP_IMAGE_STACK_BASE
,
.
sp_heap_base
=
ARM_SP_IMAGE_HEAP_BASE
,
.
sp_ns_comm_buf_base
=
ARM_SP_IMAGE_NS_BUF_BASE
,
.
sp_shared_buf_base
=
PLAT_SPM_BUF_BASE
,
.
sp_image_size
=
ARM_SP_IMAGE_SIZE
,
.
sp_pcpu_stack_size
=
PLAT_SP_IMAGE_STACK_PCPU_SIZE
,
.
sp_heap_size
=
ARM_SP_IMAGE_HEAP_SIZE
,
.
sp_ns_comm_buf_size
=
ARM_SP_IMAGE_NS_BUF_SIZE
,
.
sp_shared_buf_size
=
PLAT_SPM_BUF_SIZE
,
.
num_sp_mem_regions
=
ARM_SP_IMAGE_NUM_MEM_REGIONS
,
.
num_cpus
=
PLATFORM_CORE_COUNT
,
.
mp_info
=
&
sp_mp_info
[
0
],
};
const
struct
mmap_region
*
plat_get_secure_partition_mmap
(
void
*
cookie
)
{
return
plat_arm_secure_partition_mmap
;
}
const
struct
secure_partition_boot_info
*
plat_get_secure_partition_boot_info
(
void
*
cookie
)
{
return
&
plat_arm_secure_partition_boot_info
;
}
#endif
/* ENABLE_SPM && defined(IMAGE_BL31) */
plat/arm/css/sgi/sgi_ras.c
0 → 100644
View file @
eef90a77
/*
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arm_spm_def.h>
#include <assert.h>
#include <context_mgmt.h>
#include <interrupt_mgmt.h>
#include <mm_svc.h>
#include <ras.h>
#include <sgi_ras.h>
#include <platform.h>
#include <spm_svc.h>
#include <sdei.h>
#include <string.h>
static
int
sgi_ras_intr_handler
(
const
struct
err_record_info
*
err_rec
,
int
probe_data
,
const
struct
err_handler_data
*
const
data
);
struct
efi_guid
{
uint32_t
data1
;
uint16_t
data2
;
uint16_t
data3
;
uint8_t
data4
[
8
];
};
typedef
struct
mm_communicate_header
{
struct
efi_guid
header_guid
;
size_t
message_len
;
uint8_t
data
[
8
];
}
mm_communicate_header_t
;
struct
sgi_ras_ev_map
sgi575_ras_map
[]
=
{
/* DMC620 error overflow interrupt*/
{
SP_DMC_ERROR_OVERFLOW_EVENT_AARCH64
,
SGI_SDEI_DS_EVENT_1
,
33
},
/* DMC620 error ECC error interrupt*/
{
SP_DMC_ERROR_ECC_EVENT_AARCH64
,
SGI_SDEI_DS_EVENT_0
,
35
},
};
#define SGI575_RAS_MAP_SIZE ARRAY_SIZE(sgi575_ras_map)
struct
err_record_info
sgi_err_records
[]
=
{
{
.
handler
=
&
sgi_ras_intr_handler
,
},
};
struct
ras_interrupt
sgi_ras_interrupts
[]
=
{
{
.
intr_number
=
33
,
.
err_record
=
&
sgi_err_records
[
0
],
},
{
.
intr_number
=
35
,
.
err_record
=
&
sgi_err_records
[
0
],
}
};
REGISTER_ERR_RECORD_INFO
(
sgi_err_records
);
REGISTER_RAS_INTERRUPTS
(
sgi_ras_interrupts
);
static
struct
sgi_ras_ev_map
*
plat_sgi_get_ras_ev_map
(
void
)
{
return
sgi575_ras_map
;
}
static
int
plat_sgi_get_ras_ev_map_size
(
void
)
{
return
SGI575_RAS_MAP_SIZE
;
}
/*
* Find event mapping for a given interrupt number: On success, returns pointer
* to the event mapping. On error, returns NULL.
*/
static
struct
sgi_ras_ev_map
*
find_ras_event_map_by_intr
(
uint32_t
intr_num
)
{
struct
sgi_ras_ev_map
*
map
=
plat_sgi_get_ras_ev_map
();
int
i
;
int
size
=
plat_sgi_get_ras_ev_map_size
();
for
(
i
=
0
;
i
<
size
;
i
++
)
{
if
(
map
->
intr
==
intr_num
)
return
map
;
map
++
;
}
return
NULL
;
}
static
void
sgi_ras_intr_configure
(
int
intr
)
{
plat_ic_set_interrupt_type
(
intr
,
INTR_TYPE_EL3
);
plat_ic_set_interrupt_priority
(
intr
,
PLAT_RAS_PRI
);
plat_ic_clear_interrupt_pending
(
intr
);
plat_ic_set_spi_routing
(
intr
,
INTR_ROUTING_MODE_ANY
,
(
u_register_t
)
read_mpidr_el1
());
plat_ic_enable_interrupt
(
intr
);
}
static
int
sgi_ras_intr_handler
(
const
struct
err_record_info
*
err_rec
,
int
probe_data
,
const
struct
err_handler_data
*
const
data
)
{
struct
sgi_ras_ev_map
*
ras_map
;
mm_communicate_header_t
*
header
;
uint32_t
intr
;
cm_el1_sysregs_context_save
(
NON_SECURE
);
intr
=
data
->
interrupt
;
/*
* Find if this is a RAS interrupt. There must be an event against
* this interrupt
*/
ras_map
=
find_ras_event_map_by_intr
(
intr
);
assert
(
ras_map
);
/*
* Populate the MM_COMMUNICATE payload to share the
* event info with StandaloneMM code. This allows us to use
* MM_COMMUNICATE as a common entry mechanism into S-EL0. The
* header data will be parsed in StandaloneMM to process the
* corresponding event.
*
* TBD - Currently, the buffer allocated by SPM for communication
* between EL3 and S-EL0 is being used(PLAT_SPM_BUF_BASE). But this
* should happen via a dynamic mem allocation, which should be
* managed by SPM -- the individual platforms then call the mem
* alloc api to get memory for the payload.
*/
header
=
(
void
*
)
PLAT_SPM_BUF_BASE
;
memset
(
header
,
0
,
sizeof
(
*
header
));
memcpy
(
&
header
->
data
,
&
ras_map
->
ras_ev_num
,
sizeof
(
ras_map
->
ras_ev_num
));
header
->
message_len
=
4
;
spm_sp_call
(
MM_COMMUNICATE_AARCH64
,
(
uint64_t
)
header
,
0
,
plat_my_core_pos
());
/*
* Do an EOI of the RAS interuupt. This allows the
* sdei event to be dispatched at the SDEI event's
* priority.
*/
plat_ic_end_of_interrupt
(
intr
);
/* Dispatch the event to the SDEI client */
sdei_dispatch_event
(
ras_map
->
sdei_ev_num
);
return
0
;
}
int
sgi_ras_intr_handler_setup
(
void
)
{
int
i
;
struct
sgi_ras_ev_map
*
map
=
plat_sgi_get_ras_ev_map
();
int
size
=
plat_sgi_get_ras_ev_map_size
();
for
(
i
=
0
;
i
<
size
;
i
++
)
{
sgi_ras_intr_configure
(
map
->
intr
);
map
++
;
}
INFO
(
"SGI: RAS Interrupt Handler successfully registered
\n
"
);
return
0
;
}
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