Re: [PATCH v7 22/25] ACPI / APEI: Kick the memory_failure() queue for synchronous errors

2018-12-04 Thread Xie XiuQi
 is no return value check for memory_failure() in 
memory_failure_work_func(),
I'm not sure whether we need to check the return value.

static void memory_failure_work_func(struct work_struct *work)
{
struct memory_failure_cpu *mf_cpu;
struct memory_failure_entry entry = { 0, };
unsigned long proc_flags;
int gotten;

mf_cpu = container_of(work, struct memory_failure_cpu, work);
for (;;) {
spin_lock_irqsave(&mf_cpu->lock, proc_flags);
gotten = kfifo_get(&mf_cpu->fifo, &entry);
spin_unlock_irqrestore(&mf_cpu->lock, proc_flags);
if (!gotten)
break;
if (entry.flags & MF_SOFT_OFFLINE)
soft_offline_page(pfn_to_page(entry.pfn), entry.flags);
else
memory_failure(entry.pfn, entry.flags);
}
}

If the recovery fails here, we need to take other actions, such as force to 
send a SIGBUS signal.


> -#endif
> +
> + /*
> +  * If the notification indicates that it was the interrupted
> +  * instruction that caused the error, try to kick the
> +  * memory_failure() queue before returning to user-space.
> +  */
> + if (ghes_is_synchronous(ghes) && current->mm != &init_mm) {
> + callback = kzalloc(sizeof(*callback), GFP_ATOMIC);
> + if (!callback)
> + return;
> + callback->work.func = ghes_kick_memory_failure;
> + callback->cpu = smp_processor_id();
> + ret = task_work_add(current, &callback->work, true);
> + if (ret)
> +     kfree(callback);
> + }
>  }
>  
>  /*
> @@ -480,7 +535,7 @@ static void ghes_do_proc(struct ghes *ghes,
>   ghes_edac_report_mem_error(sev, mem_err);
>  
>   arch_apei_report_mem_error(sev, mem_err);
> - ghes_handle_memory_failure(gdata, sev);
> + ghes_handle_memory_failure(ghes, gdata, sev);
>   }
>   else if (guid_equal(sec_type, &CPER_SEC_PCIE)) {
>   ghes_handle_aer(gdata);
> 

-- 
Thanks,
Xie XiuQi

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v3 1/8] trace: ras: add ARM processor error information trace event

2017-04-17 Thread Xie XiuQi
Hi Tyler,

On 2017/4/18 1:18, Baicar, Tyler wrote:
> On 4/16/2017 9:16 PM, Xie XiuQi wrote:
>> On 2017/4/17 11:08, Xie XiuQi wrote:
>>>> On 3/30/2017 4:31 AM, Xie XiuQi wrote:
>>>>> Add a new trace event for ARM processor error information, so that
>>>>> the user will know what error occurred. With this information the
>>>>> user may take appropriate action.
>>>>>
>>>>> These trace events are consistent with the ARM processor error
>>>>> information table which defined in UEFI 2.6 spec section N.2.4.4.1.
>>>>>
>>>>> ---
>>>>> v2: add trace enabled condition as Steven's suggestion.
>>>>>   fix a typo.
>>>>> ---
>>>>>
>>>>> Cc: Steven Rostedt 
>>>>> Cc: Tyler Baicar 
>>>>> Signed-off-by: Xie XiuQi 
>>>>> ---
>>>>
> ...
>>>>> +/*
>>>>> + * First define the enums in MM_ACTION_RESULT to be exported to userspace
>>>>> + * via TRACE_DEFINE_ENUM().
>>>>> + */
>>>>> +#undef EM
>>>>> +#undef EMe
>>>>> +#define EM(a, b) TRACE_DEFINE_ENUM(a);
>>>>> +#define EMe(a, b)TRACE_DEFINE_ENUM(a);
>>>>> +
>>>>> +ARM_PROC_ERR_TYPE
>>>>> +ARM_PROC_ERR_FLAGS
>>>> Are the above two lines supposed to be here?
>>>>> +
>>>>> +/*
>>>>> + * Now redefine the EM() and EMe() macros to map the enums to the strings
>>>>> + * that will be printed in the output.
>>>>> + */
>>>>> +#undef EM
>>>>> +#undef EMe
>>>>> +#define EM(a, b){ a, b },
>>>>> +#define EMe(a, b){ a, b }
>>>>> +
>>>>> +TRACE_EVENT(arm_proc_err,
>>>> I think it would be better to keep this similar to the naming of the 
>>>> current RAS trace events (right now we have mc_event, arm_event, 
>>>> aer_event, etc.). I would suggest using "arm_err_info_event" since this is 
>>>> handling the error information structures of the arm errors.
>>>>> +
>>>>> +TP_PROTO(const struct cper_arm_err_info *err),
>>>>> +
>>>>> +TP_ARGS(err),
>>>>> +
>>>>> +TP_STRUCT__entry(
>>>>> +__field(u8, type)
>>>>> +__field(u16, multiple_error)
>>>>> +__field(u8, flags)
>>>>> +__field(u64, error_info)
>>>>> +__field(u64, virt_fault_addr)
>>>>> +__field(u64, physical_fault_addr)
>>>> Validation bits should also be a part of this structure that way user 
>>>> space tools will know which of these fields are valid.
>>> Could we use the default value to check the validation which we have 
>>> checked in TP_fast_assign?
> Yes, true...I guess we really don't need the validation bits then.
>>>>> +),
>>>>> +
>>>>> +TP_fast_assign(
>>>>> +__entry->type = err->type;
>>>>> +
>>>>> +if (err->validation_bits & CPER_ARM_INFO_VALID_MULTI_ERR)
>>>>> +__entry->multiple_error = err->multiple_error;
>>>>> +else
>>>>> +__entry->multiple_error = ~0;
>>>>> +
>>>>> +if (err->validation_bits & CPER_ARM_INFO_VALID_FLAGS)
>>>>> +__entry->flags = err->flags;
>>>>> +else
>>>>> +__entry->flags = ~0;
>>>>> +
>>>>> +if (err->validation_bits & CPER_ARM_INFO_VALID_ERR_INFO)
>>>>> +__entry->error_info = err->error_info;
>>>>> +else
>>>>> +__entry->error_info = 0ULL;
>>>>> +
>>>>> +if (err->validation_bits & CPER_ARM_INFO_VALID_VIRT_ADDR)
>>>>> +__entry->virt_fault_addr = err->virt_fault_addr;
>>>>> +else
>>>>> +__entry->virt_fault_addr = 0ULL;
>>>>> +
>>>>> +if (err->validation_bits & CPER_ARM_INFO_VALID_PHYSICAL_ADDR)
>>>>> +__entry->physical_fault_addr = err->physical_fault_addr;
>>>>> +else
>>>>> +__entry->physical_fault_addr = 0ULL;
>

Re: [PATCH v3 1/8] trace: ras: add ARM processor error information trace event

2017-04-16 Thread Xie XiuQi
Hi Tyler,

On 2017/4/17 11:08, Xie XiuQi wrote:
> Hi Tyler,
> 
> Thanks for your comments and testing.
> 
> On 2017/4/15 4:36, Baicar, Tyler wrote:
>> On 3/30/2017 4:31 AM, Xie XiuQi wrote:
>>> Add a new trace event for ARM processor error information, so that
>>> the user will know what error occurred. With this information the
>>> user may take appropriate action.
>>>
>>> These trace events are consistent with the ARM processor error
>>> information table which defined in UEFI 2.6 spec section N.2.4.4.1.
>>>
>>> ---
>>> v2: add trace enabled condition as Steven's suggestion.
>>>  fix a typo.
>>> ---
>>>
>>> Cc: Steven Rostedt 
>>> Cc: Tyler Baicar 
>>> Signed-off-by: Xie XiuQi 
>>> ---
>> ...
>>>   +#define ARM_PROC_ERR_TYPE\
>>> +EM ( CPER_ARM_INFO_TYPE_CACHE, "cache error" )\
>>> +EM ( CPER_ARM_INFO_TYPE_TLB,  "TLB error" )\
>>> +EM ( CPER_ARM_INFO_TYPE_BUS, "bus error" )\
>>> +EMe ( CPER_ARM_INFO_TYPE_UARCH, "micro-architectural error" )
>>> +
>>> +#define ARM_PROC_ERR_FLAGS\
>>> +EM ( CPER_ARM_INFO_FLAGS_FIRST, "First error captured" )\
>>> +EM ( CPER_ARM_INFO_FLAGS_LAST,  "Last error captured" )\
>>> +EM ( CPER_ARM_INFO_FLAGS_PROPAGATED, "Propagated" )\
>>> +EMe ( CPER_ARM_INFO_FLAGS_OVERFLOW, "Overflow" )
>>> +
>> Hello Xie XiuQi,
>>
>> This isn't compiling for me because of these definitions. Here you are using 
>> ARM_*, but below in the TP_printk you are using ARCH_*. The compiler 
>> complains the ARCH_* ones are undefined:
>>
>> ./include/trace/../../include/ras/ras_event.h:278:37: error: 
>> 'ARCH_PROC_ERR_TYPE' undeclared (first use in this function)
>>  __print_symbolic(__entry->type, ARCH_PROC_ERR_TYPE),
>> ./include/trace/../../include/ras/ras_event.h:280:38: error: 
>> 'ARCH_PROC_ERR_FLAGS' undeclared (first use in this function)
>>  __print_symbolic(__entry->flags, ARCH_PROC_ERR_FLAGS),
> 
> Sorry, it's a typo. It should be ARM_xxx.
> 
>>
>>> +/*
>>> + * First define the enums in MM_ACTION_RESULT to be exported to userspace
>>> + * via TRACE_DEFINE_ENUM().
>>> + */
>>> +#undef EM
>>> +#undef EMe
>>> +#define EM(a, b) TRACE_DEFINE_ENUM(a);
>>> +#define EMe(a, b)TRACE_DEFINE_ENUM(a);
>>> +
>>> +ARM_PROC_ERR_TYPE
>>> +ARM_PROC_ERR_FLAGS
>> Are the above two lines supposed to be here?
>>> +
>>> +/*
>>> + * Now redefine the EM() and EMe() macros to map the enums to the strings
>>> + * that will be printed in the output.
>>> + */
>>> +#undef EM
>>> +#undef EMe
>>> +#define EM(a, b){ a, b },
>>> +#define EMe(a, b){ a, b }
>>> +
>>> +TRACE_EVENT(arm_proc_err,
>> I think it would be better to keep this similar to the naming of the current 
>> RAS trace events (right now we have mc_event, arm_event, aer_event, etc.). I 
>> would suggest using "arm_err_info_event" since this is handling the error 
>> information structures of the arm errors.
>>> +
>>> +TP_PROTO(const struct cper_arm_err_info *err),
>>> +
>>> +TP_ARGS(err),
>>> +
>>> +TP_STRUCT__entry(
>>> +__field(u8, type)
>>> +__field(u16, multiple_error)
>>> +__field(u8, flags)
>>> +__field(u64, error_info)
>>> +__field(u64, virt_fault_addr)
>>> +__field(u64, physical_fault_addr)
>> Validation bits should also be a part of this structure that way user space 
>> tools will know which of these fields are valid.
> 
> Could we use the default value to check the validation which we have checked 
> in TP_fast_assign?
> 
>>> +),
>>> +
>>> +TP_fast_assign(
>>> +__entry->type = err->type;
>>> +
>>> +if (err->validation_bits & CPER_ARM_INFO_VALID_MULTI_ERR)
>>> +__entry->multiple_error = err->multiple_error;
>>> +else
>>> +__entry->multiple_error = ~0;
>>> +
>>> +if (err->validation_bits & CPER_ARM_INFO_VALID_FLAGS)
>>> +__entry->flags = err->flags;
>>> +else
>>> +__entry->flags = ~0;
>>> +
>>

Re: [PATCH v3 1/8] trace: ras: add ARM processor error information trace event

2017-04-16 Thread Xie XiuQi
Hi Tyler,

Thanks for your comments and testing.

On 2017/4/15 4:36, Baicar, Tyler wrote:
> On 3/30/2017 4:31 AM, Xie XiuQi wrote:
>> Add a new trace event for ARM processor error information, so that
>> the user will know what error occurred. With this information the
>> user may take appropriate action.
>>
>> These trace events are consistent with the ARM processor error
>> information table which defined in UEFI 2.6 spec section N.2.4.4.1.
>>
>> ---
>> v2: add trace enabled condition as Steven's suggestion.
>>  fix a typo.
>> ---
>>
>> Cc: Steven Rostedt 
>> Cc: Tyler Baicar 
>> Signed-off-by: Xie XiuQi 
>> ---
> ...
>>   +#define ARM_PROC_ERR_TYPE\
>> +EM ( CPER_ARM_INFO_TYPE_CACHE, "cache error" )\
>> +EM ( CPER_ARM_INFO_TYPE_TLB,  "TLB error" )\
>> +EM ( CPER_ARM_INFO_TYPE_BUS, "bus error" )\
>> +EMe ( CPER_ARM_INFO_TYPE_UARCH, "micro-architectural error" )
>> +
>> +#define ARM_PROC_ERR_FLAGS\
>> +EM ( CPER_ARM_INFO_FLAGS_FIRST, "First error captured" )\
>> +EM ( CPER_ARM_INFO_FLAGS_LAST,  "Last error captured" )\
>> +EM ( CPER_ARM_INFO_FLAGS_PROPAGATED, "Propagated" )\
>> +EMe ( CPER_ARM_INFO_FLAGS_OVERFLOW, "Overflow" )
>> +
> Hello Xie XiuQi,
> 
> This isn't compiling for me because of these definitions. Here you are using 
> ARM_*, but below in the TP_printk you are using ARCH_*. The compiler 
> complains the ARCH_* ones are undefined:
> 
> ./include/trace/../../include/ras/ras_event.h:278:37: error: 
> 'ARCH_PROC_ERR_TYPE' undeclared (first use in this function)
>  __print_symbolic(__entry->type, ARCH_PROC_ERR_TYPE),
> ./include/trace/../../include/ras/ras_event.h:280:38: error: 
> 'ARCH_PROC_ERR_FLAGS' undeclared (first use in this function)
>  __print_symbolic(__entry->flags, ARCH_PROC_ERR_FLAGS),

Sorry, it's a typo. It should be ARM_xxx.

> 
>> +/*
>> + * First define the enums in MM_ACTION_RESULT to be exported to userspace
>> + * via TRACE_DEFINE_ENUM().
>> + */
>> +#undef EM
>> +#undef EMe
>> +#define EM(a, b) TRACE_DEFINE_ENUM(a);
>> +#define EMe(a, b)TRACE_DEFINE_ENUM(a);
>> +
>> +ARM_PROC_ERR_TYPE
>> +ARM_PROC_ERR_FLAGS
> Are the above two lines supposed to be here?
>> +
>> +/*
>> + * Now redefine the EM() and EMe() macros to map the enums to the strings
>> + * that will be printed in the output.
>> + */
>> +#undef EM
>> +#undef EMe
>> +#define EM(a, b){ a, b },
>> +#define EMe(a, b){ a, b }
>> +
>> +TRACE_EVENT(arm_proc_err,
> I think it would be better to keep this similar to the naming of the current 
> RAS trace events (right now we have mc_event, arm_event, aer_event, etc.). I 
> would suggest using "arm_err_info_event" since this is handling the error 
> information structures of the arm errors.
>> +
>> +TP_PROTO(const struct cper_arm_err_info *err),
>> +
>> +TP_ARGS(err),
>> +
>> +TP_STRUCT__entry(
>> +__field(u8, type)
>> +__field(u16, multiple_error)
>> +__field(u8, flags)
>> +__field(u64, error_info)
>> +__field(u64, virt_fault_addr)
>> +__field(u64, physical_fault_addr)
> Validation bits should also be a part of this structure that way user space 
> tools will know which of these fields are valid.

Could we use the default value to check the validation which we have checked in 
TP_fast_assign?

>> +),
>> +
>> +TP_fast_assign(
>> +__entry->type = err->type;
>> +
>> +if (err->validation_bits & CPER_ARM_INFO_VALID_MULTI_ERR)
>> +__entry->multiple_error = err->multiple_error;
>> +else
>> +__entry->multiple_error = ~0;
>> +
>> +if (err->validation_bits & CPER_ARM_INFO_VALID_FLAGS)
>> +__entry->flags = err->flags;
>> +else
>> +__entry->flags = ~0;
>> +
>> +if (err->validation_bits & CPER_ARM_INFO_VALID_ERR_INFO)
>> +__entry->error_info = err->error_info;
>> +else
>> +__entry->error_info = 0ULL;
>> +
>> +if (err->validation_bits & CPER_ARM_INFO_VALID_VIRT_ADDR)
>> +__entry->virt_fault_addr = err->virt_fault_addr;
>> +else
>> +__entry->virt_fault_addr = 0ULL;
>> +
>> +if (

Re: [PATCH v3 7/8] arm64: exception: handle asynchronous SError interrupt

2017-04-14 Thread Xie XiuQi
Hi Mark,

Thanks for your comments.

On 2017/4/13 18:51, Mark Rutland wrote:
> Hi,
>
> On Thu, Mar 30, 2017 at 06:31:07PM +0800, Xie XiuQi wrote:
>> diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
>> index f20c64a..22f9c90 100644
>> --- a/arch/arm64/include/asm/esr.h
>> +++ b/arch/arm64/include/asm/esr.h
>> @@ -106,6 +106,20 @@
>>  #define ESR_ELx_AR  (UL(1) << 14)
>>  #define ESR_ELx_CM  (UL(1) << 8)
>>
>> +#define ESR_Elx_DFSC_SEI(0x11)
>
> We should probably have a definition for the uncategorized DFSC value,
> too.
>

Will do, thanks.

How about "#define ESR_Elx_DFSC_UNCATEGORIZED   (0)" ?

> [...]
>
>> index 43512d4..d8a7306 100644
>> --- a/arch/arm64/kernel/entry.S
>> +++ b/arch/arm64/kernel/entry.S
>> @@ -69,7 +69,14 @@
>>  #define BAD_FIQ 2
>>  #define BAD_ERROR   3
>>
>> +.arch_extension ras
>
> Generally, arch_extension is a warning sign that code isn't going to
> work with contemporary assemblers, which we likely need to support.
>
>> +
>>  .macro  kernel_entry, el, regsize = 64
>> +#ifdef CONFIG_ARM64_ESB
>> +.if \el == 0
>> +esb
>
> Here, I think that we'll need to macro this such that we can build with
> existing toolchains.
>
> e.g. in  we need something like:
>
>   #define HINT_IMM_ESB16
>
>   .macro ESB
>   hint#HINT_IMM_ESB
>   .endm
>

Good, thanks for your suggestion. I'll use this macro in next versin.

>> +.endif
>> +#endif
>>  sub sp, sp, #S_FRAME_SIZE
>>  .if \regsize == 32
>>  mov w0, w0  // zero upper 32 bits of x0
>> @@ -208,6 +215,7 @@ alternative_else_nop_endif
>>  #endif
>>
>>  .if \el == 0
>> +msr daifset, #0xF   // Set flags
>
> Elsewhere in head.S we use helpers to fiddle with DAIF bits.
>
> Please be consistent with that. Add an enable_all macro if we need one.

OK, I'll do it refer to head.S.

>
>>  ldr x23, [sp, #S_SP]// load return stack pointer
>>  msr sp_el0, x23
>>  #ifdef CONFIG_ARM64_ERRATUM_845719
>> @@ -226,6 +234,15 @@ alternative_else_nop_endif
>>
>>  msr elr_el1, x21// set up the return data
>>  msr spsr_el1, x22
>> +
>> +#ifdef CONFIG_ARM64_ESB
>> +.if \el == 0
>> +esb // Error Synchronization Barrier
>> +mrs x21, disr_el1   // Check for deferred error
>
> We'll need an  definition for this register. With that, we
> can use mrs_s here.

OK, thanks.

>
>> +tbnzx21, #31, el1_sei
>> +.endif
>> +#endif
>> +
>>  ldp x0, x1, [sp, #16 * 0]
>>  ldp x2, x3, [sp, #16 * 1]
>>  ldp x4, x5, [sp, #16 * 2]
>> @@ -318,7 +335,7 @@ ENTRY(vectors)
>>  ventry  el1_sync_invalid// Synchronous EL1t
>>  ventry  el1_irq_invalid // IRQ EL1t
>>  ventry  el1_fiq_invalid // FIQ EL1t
>> -ventry  el1_error_invalid   // Error EL1t
>> +ventry  el1_error   // Error EL1t
>>
>>  ventry  el1_sync// Synchronous EL1h
>>  ventry  el1_irq // IRQ EL1h
>> @@ -328,7 +345,7 @@ ENTRY(vectors)
>>  ventry  el0_sync// Synchronous 64-bit EL0
>>  ventry  el0_irq // IRQ 64-bit EL0
>>  ventry  el0_fiq_invalid // FIQ 64-bit EL0
>> -ventry  el0_error_invalid   // Error 64-bit EL0
>> +ventry  el0_error   // Error 64-bit EL0
>>
>>  #ifdef CONFIG_COMPAT
>>  ventry  el0_sync_compat // Synchronous 32-bit EL0
>> @@ -508,12 +525,31 @@ el1_preempt:
>>  ret x24
>>  #endif
>>
>> +.align  6
>> +el1_error:
>> +kernel_entry 1
>> +el1_sei:
>> +/*
>> + * asynchronous SError interrupt from kernel
>> + */
>> +mov x0, sp
>> +mrs x1, esr_el1
>
> I don't think this is correct if we branched here from kernel_exit.
> Surely we want the DISR_EL1 value, and ESR_EL1 is unrelated?

Yes, indeed. I'll change it in next version.

>
>> +mov x2, #1  // exception level of SEI 
>> generated
>> +b   do_sei
>
> You don't need to figure out the EL h

Re: [PATCH v3 4/8] APEI: GHES: reserve a virtual page for SEI context

2017-04-06 Thread Xie XiuQi
Hi James,

Thanks for your comments.

On 2017/4/1 0:22, James Morse wrote:
> Hi Xie XiuQi,
> 
> On 30/03/17 11:31, Xie XiuQi wrote:
>> On arm64 platform, SEI may interrupt code which had interrupts masked.
>> But SEI could be masked, so it's not treated as NMI, however SEA is
>> treated as NMI.
>>
>> So, the  memory area used to transfer hardware error information from
>> BIOS to Linux can be determined only in NMI, SEI(arm64), IRQ or timer
>> handler.
>>
>> In this patch, we add a virtual page for SEI context.
> 
> I don't think this is the best way of solving the interaction problem. If we
> ever need to add another notification method this gets even more complicated,
> and the ioremap code has to know how these methods can interact.
> 
> 
>> diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
>> index 045d101..b1f9b1f 100644
>> --- a/drivers/acpi/apei/ghes.c
>> +++ b/drivers/acpi/apei/ghes.c
>> @@ -155,54 +162,55 @@ static void ghes_ioremap_exit(void)
> 
>> -static void __iomem *ghes_ioremap_pfn_irq(u64 pfn)
>> -{
>> -unsigned long vaddr, paddr;
>> -pgprot_t prot;
>> -
>> -vaddr = (unsigned long)GHES_IOREMAP_IRQ_PAGE(ghes_ioremap_area->addr);
>> +if (in_nmi()) {
>> +raw_spin_lock(&ghes_ioremap_lock_nmi);
>> +vaddr = (unsigned 
>> long)GHES_IOREMAP_NMI_PAGE(ghes_ioremap_area->addr);
>> +} else if (this_cpu_read(sei_in_process)) {
> 
>> +spin_lock_irqsave(&ghes_ioremap_lock_sei, flags);
> 
> I think this one should be a raw_spin_lock. I'm pretty sure this is for 
> RT-linux
> where spin_lock() on a contented lock will call schedule() in the same way
> mutex_lock() does. If interrupts were masked by arch code then you need to use
> raw_spin_lock.
> So now we need to know how we got in here, we interrupted the SError handler 
> so
> this should only be Synchronous External Abort. Having to know how we got here
> is another problem with this approach.
> 
> 
> As suggested earlier[0], I think the best way is to allocate one page of 
> virtual
> address space per struct ghes, and move the locks out to the notify calls, 
> which
> can know how they are called.
> 
> I've pushed a branch to:
> http://www.linux-arm.org/git?p=linux-jm.git;a=commit;h=refs/heads/apei_ioremap_rework/v1
> 

Good! I could rebase on your patch next time.

> I intend to post those patches as an RFC series later in the cycle, I've only
> build tested it so far.
> 
> 
> Thanks,
> 
> James
> 
>> +vaddr = (unsigned 
>> long)GHES_IOREMAP_SEI_PAGE(ghes_ioremap_area->addr);
>> +} else {
>> +spin_lock_irqsave(&ghes_ioremap_lock_irq, flags);
>> +vaddr = (unsigned 
>> long)GHES_IOREMAP_IRQ_PAGE(ghes_ioremap_area->addr);
>> +}
> 
> 
> [0] https://lkml.org/lkml/2017/3/20/434
> 
> 
> .
> 

-- 
Thanks,
Xie XiuQi

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v3 2/8] acpi: apei: handle SEI notification type for ARMv8

2017-04-06 Thread Xie XiuQi
Hi James,

Sorry for reply late, and thanks for your comments.

On 2017/4/1 0:20, James Morse wrote:
> Hi Xie XiuQi,
> 
> On 30/03/17 11:31, Xie XiuQi wrote:
>> ARM APEI extension proposal added SEI (asynchronous SError interrupt)
>> notification type for ARMv8.
>>
>> Add a new GHES error source handling function for SEI. In firmware
>> first mode, if an error source's notification type is SEI. Then GHES
>> could parse and report the detail error information.
> 
> The APEI additions are unsafe until patch 4 as SEA can interrupt SEI and
> deadlock while trying to take the same set of locks. This patch needs to be
> after that interaction is fixed/prevented, or we should prevent it by adding a
> depends-on-not to the Kconfig to prevent SEI and SEA being registered at the
> same time. (as a short term fix).

Will fix later.

> 
> (more comments on this on that later patch)
> 
> 
>> diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
>> index e52be6a..53710a2 100644
>> --- a/arch/arm64/kernel/traps.c
>> +++ b/arch/arm64/kernel/traps.c
> 
>> @@ -625,6 +627,14 @@ asmlinkage void bad_mode(struct pt_regs *regs, int 
>> reason, unsigned int esr)
> 
> bad_mode() is called in other scenarios too, for example executing an 
> undefined
> instruction at EL1. You split the SError path out of the vectors in patch 7, I
> think we should do that here.
> 
> 
>>  handler[reason], smp_processor_id(), esr,
>>  esr_get_class_string(esr));
>>  
>> +/*
>> + * In firmware first mode, we could assume firmware will only generate 
>> one
>> + * of cper records at a time. There is no risk for one cpu to parse 
>> ghes table.
>> + */
> 
> I don't follow this comment, is this saying SError can't interrupt SError? We
> already get this guarantee as the CPU masks SError when it takes an exception.
> 
> Firmware can generate multiple CPER records for a single 'event'. The CPER
> records are the 'Data' in ACPI:Table 18-343 Generic Error Data Entry, and 
> there
> are 'zero or more' of these with a 'Generic Error Status Block' header that
> describes the overall event. (Table 18-342).
> 
> I don't think we need this comment.

Thanks for your explanation, OK, I'll remove this comment.

> 
> 
>> +if (IS_ENABLED(CONFIG_ACPI_APEI_SEI) && ESR_ELx_EC(esr) == 
>> ESR_ELx_EC_SERROR) {
>> +ghes_notify_sei();
>> +}
> 
>>  die("Oops - bad mode", regs, 0);
>>  local_irq_disable();
>>  panic("bad mode");
> 
> Thanks,
> 
> James
> 
> 
> .
> 

-- 
Thanks,
Xie XiuQi

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v3 1/8] trace: ras: add ARM processor error information trace event

2017-04-06 Thread Xie XiuQi
Hi Steve,

Sorry for reply late.

On 2017/3/31 0:02, Steven Rostedt wrote:
> On Thu, 30 Mar 2017 18:31:01 +0800
> Xie XiuQi  wrote:
> 
>> Add a new trace event for ARM processor error information, so that
>> the user will know what error occurred. With this information the
>> user may take appropriate action.
>>
>> These trace events are consistent with the ARM processor error
>> information table which defined in UEFI 2.6 spec section N.2.4.4.1.
>>
>> ---
>> v2: add trace enabled condition as Steven's suggestion.
>> fix a typo.
>> ---
>>
>> Cc: Steven Rostedt 
>> Cc: Tyler Baicar 
>> Signed-off-by: Xie XiuQi 
>> ---
>>  drivers/acpi/apei/ghes.c | 10 ++
>>  include/linux/cper.h |  5 +++
>>  include/ras/ras_event.h  | 87 
>> 
>>  3 files changed, 102 insertions(+)
>>
>> diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
>> index 81eabc6..6be0333 100644
>> --- a/drivers/acpi/apei/ghes.c
>> +++ b/drivers/acpi/apei/ghes.c
>> @@ -518,9 +518,19 @@ static void ghes_do_proc(struct ghes *ghes,
>>  else if (!uuid_le_cmp(sec_type, CPER_SEC_PROC_ARM) &&
>>   trace_arm_event_enabled()) {
>>  struct cper_sec_proc_arm *arm_err;
>> +struct cper_arm_err_info *err_info;
>> +int i;
>>  
>>  arm_err = acpi_hest_generic_data_payload(gdata);
>>  trace_arm_event(arm_err);
>> +
>> +if (trace_arm_proc_err_enabled()) {
>> +err_info = (struct cper_arm_err_info *)(arm_err 
>> + 1);
>> +for (i = 0; i < arm_err->err_info_num; i++) {
>> +trace_arm_proc_err(err_info);
>> +err_info += 1;
>> +}
>> +}
>>  } else if (trace_unknown_sec_event_enabled()) {
>>  void *unknown_err = 
>> acpi_hest_generic_data_payload(gdata);
>>  trace_unknown_sec_event(&sec_type,
>> diff --git a/include/linux/cper.h b/include/linux/cper.h
>> index 85450f3..0cae900 100644
>> --- a/include/linux/cper.h
>> +++ b/include/linux/cper.h
>> @@ -270,6 +270,11 @@ enum {
>>  #define CPER_ARM_INFO_VALID_VIRT_ADDR   0x0008
>>  #define CPER_ARM_INFO_VALID_PHYSICAL_ADDR   0x0010
>>  
>> +#define CPER_ARM_INFO_TYPE_CACHE0
>> +#define CPER_ARM_INFO_TYPE_TLB  1
>> +#define CPER_ARM_INFO_TYPE_BUS  2
>> +#define CPER_ARM_INFO_TYPE_UARCH3
>> +
>>  #define CPER_ARM_INFO_FLAGS_FIRST   0x0001
>>  #define CPER_ARM_INFO_FLAGS_LAST0x0002
>>  #define CPER_ARM_INFO_FLAGS_PROPAGATED  0x0004
>> diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h
>> index 13befad..026b094 100644
>> --- a/include/ras/ras_event.h
>> +++ b/include/ras/ras_event.h
>> @@ -206,6 +206,93 @@
>>__entry->running_state, __entry->psci_state)
>>  );
>>  
>> +#define ARM_PROC_ERR_TYPE   \
>> +EM ( CPER_ARM_INFO_TYPE_CACHE, "cache error" )  \
>> +EM ( CPER_ARM_INFO_TYPE_TLB,  "TLB error" ) \
>> +EM ( CPER_ARM_INFO_TYPE_BUS, "bus error" )  \
>> +EMe ( CPER_ARM_INFO_TYPE_UARCH, "micro-architectural error" )
>> +
>> +#define ARM_PROC_ERR_FLAGS  \
>> +EM ( CPER_ARM_INFO_FLAGS_FIRST, "First error captured" )\
>> +EM ( CPER_ARM_INFO_FLAGS_LAST,  "Last error captured" ) \
>> +EM ( CPER_ARM_INFO_FLAGS_PROPAGATED, "Propagated" ) \
>> +EMe ( CPER_ARM_INFO_FLAGS_OVERFLOW, "Overflow" )
>> +
> 
> Can flags have more than one bit set?

Yes, indeed. ARM_PROC_ERR_FLAGS might have more than on bit set.
Could we use __print_flags instead? like:

#define show_proc_err_flags(flags) __print_flags(flags, "|",
\
{ CPER_ARM_INFO_FLAGS_FIRST,"First error captured" },   
\
{ CPER_ARM_INFO_FLAGS_LAST, "Last error captured" },
\
{ CPER_ARM_INFO_FLAGS_PROPAGATED,   "Propagated" }, 
\
{ CPER_ARM_INFO_FLAGS_OVERFLOW, "Overflow" }}

> 
>> +/*
>> + * First define the enums in MM_ACTION_RESULT to be exported to userspace
>> + * vi

[PATCH v3 1/8] trace: ras: add ARM processor error information trace event

2017-03-30 Thread Xie XiuQi
Add a new trace event for ARM processor error information, so that
the user will know what error occurred. With this information the
user may take appropriate action.

These trace events are consistent with the ARM processor error
information table which defined in UEFI 2.6 spec section N.2.4.4.1.

---
v2: add trace enabled condition as Steven's suggestion.
fix a typo.
---

Cc: Steven Rostedt 
Cc: Tyler Baicar 
Signed-off-by: Xie XiuQi 
---
 drivers/acpi/apei/ghes.c | 10 ++
 include/linux/cper.h |  5 +++
 include/ras/ras_event.h  | 87 
 3 files changed, 102 insertions(+)

diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 81eabc6..6be0333 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -518,9 +518,19 @@ static void ghes_do_proc(struct ghes *ghes,
else if (!uuid_le_cmp(sec_type, CPER_SEC_PROC_ARM) &&
 trace_arm_event_enabled()) {
struct cper_sec_proc_arm *arm_err;
+   struct cper_arm_err_info *err_info;
+   int i;
 
arm_err = acpi_hest_generic_data_payload(gdata);
trace_arm_event(arm_err);
+
+   if (trace_arm_proc_err_enabled()) {
+   err_info = (struct cper_arm_err_info *)(arm_err 
+ 1);
+   for (i = 0; i < arm_err->err_info_num; i++) {
+   trace_arm_proc_err(err_info);
+   err_info += 1;
+   }
+   }
} else if (trace_unknown_sec_event_enabled()) {
void *unknown_err = 
acpi_hest_generic_data_payload(gdata);
trace_unknown_sec_event(&sec_type,
diff --git a/include/linux/cper.h b/include/linux/cper.h
index 85450f3..0cae900 100644
--- a/include/linux/cper.h
+++ b/include/linux/cper.h
@@ -270,6 +270,11 @@ enum {
 #define CPER_ARM_INFO_VALID_VIRT_ADDR  0x0008
 #define CPER_ARM_INFO_VALID_PHYSICAL_ADDR  0x0010
 
+#define CPER_ARM_INFO_TYPE_CACHE   0
+#define CPER_ARM_INFO_TYPE_TLB 1
+#define CPER_ARM_INFO_TYPE_BUS 2
+#define CPER_ARM_INFO_TYPE_UARCH   3
+
 #define CPER_ARM_INFO_FLAGS_FIRST  0x0001
 #define CPER_ARM_INFO_FLAGS_LAST   0x0002
 #define CPER_ARM_INFO_FLAGS_PROPAGATED 0x0004
diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h
index 13befad..026b094 100644
--- a/include/ras/ras_event.h
+++ b/include/ras/ras_event.h
@@ -206,6 +206,93 @@
  __entry->running_state, __entry->psci_state)
 );
 
+#define ARM_PROC_ERR_TYPE  \
+   EM ( CPER_ARM_INFO_TYPE_CACHE, "cache error" )  \
+   EM ( CPER_ARM_INFO_TYPE_TLB,  "TLB error" ) \
+   EM ( CPER_ARM_INFO_TYPE_BUS, "bus error" )  \
+   EMe ( CPER_ARM_INFO_TYPE_UARCH, "micro-architectural error" )
+
+#define ARM_PROC_ERR_FLAGS \
+   EM ( CPER_ARM_INFO_FLAGS_FIRST, "First error captured" )\
+   EM ( CPER_ARM_INFO_FLAGS_LAST,  "Last error captured" ) \
+   EM ( CPER_ARM_INFO_FLAGS_PROPAGATED, "Propagated" ) \
+   EMe ( CPER_ARM_INFO_FLAGS_OVERFLOW, "Overflow" )
+
+/*
+ * First define the enums in MM_ACTION_RESULT to be exported to userspace
+ * via TRACE_DEFINE_ENUM().
+ */
+#undef EM
+#undef EMe
+#define EM(a, b) TRACE_DEFINE_ENUM(a);
+#define EMe(a, b)  TRACE_DEFINE_ENUM(a);
+
+ARM_PROC_ERR_TYPE
+ARM_PROC_ERR_FLAGS
+
+/*
+ * Now redefine the EM() and EMe() macros to map the enums to the strings
+ * that will be printed in the output.
+ */
+#undef EM
+#undef EMe
+#define EM(a, b)   { a, b },
+#define EMe(a, b)  { a, b }
+
+TRACE_EVENT(arm_proc_err,
+
+   TP_PROTO(const struct cper_arm_err_info *err),
+
+   TP_ARGS(err),
+
+   TP_STRUCT__entry(
+   __field(u8, type)
+   __field(u16, multiple_error)
+   __field(u8, flags)
+   __field(u64, error_info)
+   __field(u64, virt_fault_addr)
+   __field(u64, physical_fault_addr)
+   ),
+
+   TP_fast_assign(
+   __entry->type = err->type;
+
+   if (err->validation_bits & CPER_ARM_INFO_VALID_MULTI_ERR)
+   __entry->multiple_error = err->multiple_error;
+   else
+   __entry->multiple_error = ~0;
+
+   if (err->validation_bits & CPER_ARM_INFO_VALID_FLAGS)
+   __entry->flags = err->flags;
+   else
+   __entry->flags = ~0;
+
+   if (err->validation_bits & CPER_ARM_INFO_VALID_ERR_INFO)
+   

[PATCH v3 7/8] arm64: exception: handle asynchronous SError interrupt

2017-03-30 Thread Xie XiuQi
Error Synchronization Barrier (ESB; part of the ARMv8.2 Extensions)
is used to synchronize Unrecoverable errors. That is, containable errors
architecturally consumed by the PE and not silently propagated.

With ESB it is generally possible to isolate an unrecoverable error
between two ESB instructions. So, it's possible to recovery from
unrecoverable errors reported by asynchronous SError interrupt.

If ARMv8.2 RAS Extension is not support, ESB is treated as a NOP.

Signed-off-by: Xie XiuQi 
Signed-off-by: Wang Xiongfeng 
---
 arch/arm64/Kconfig   | 16 ++
 arch/arm64/include/asm/esr.h | 14 +
 arch/arm64/kernel/entry.S| 70 ++--
 arch/arm64/kernel/traps.c| 54 --
 4 files changed, 150 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 859a90e..7402175 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -911,6 +911,22 @@ endmenu
 
 menu "ARMv8.2 architectural features"
 
+config ARM64_ESB
+   bool "Enable support for Error Synchronization Barrier (ESB)"
+   default n
+   help
+ Error Synchronization Barrier (ESB; part of the ARMv8.2 Extensions)
+ is used to synchronize Unrecoverable errors. That is, containable 
errors
+ architecturally consumed by the PE and not silently propagated.
+
+ Without ESB it is not generally possible to isolate an Unrecoverable
+ error because it is not known which instruction generated the error.
+
+ Selecting this option allows inject esb instruction before the 
exception
+ change. If ARMv8.2 RAS Extension is not support, ESB is treated as a 
NOP.
+
+ Note that ESB instruction can introduce slight overhead, so say N if 
unsure.
+
 config ARM64_UAO
bool "Enable support for User Access Override (UAO)"
default y
diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
index f20c64a..22f9c90 100644
--- a/arch/arm64/include/asm/esr.h
+++ b/arch/arm64/include/asm/esr.h
@@ -106,6 +106,20 @@
 #define ESR_ELx_AR (UL(1) << 14)
 #define ESR_ELx_CM (UL(1) << 8)
 
+#define ESR_Elx_DFSC_SEI   (0x11)
+
+#define ESR_ELx_AET_SHIFT  (10)
+#define ESR_ELx_AET_MAX(7)
+#define ESR_ELx_AET_MASK   (UL(7) << ESR_ELx_AET_SHIFT)
+#define ESR_ELx_AET(esr)   (((esr) & ESR_ELx_AET_MASK) >> 
ESR_ELx_AET_SHIFT)
+
+#define ESR_ELx_AET_UC (0)
+#define ESR_ELx_AET_UEU(1)
+#define ESR_ELx_AET_UEO(2)
+#define ESR_ELx_AET_UER(3)
+#define ESR_ELx_AET_CE (6)
+
+
 /* ISS field definitions for exceptions taken in to Hyp */
 #define ESR_ELx_CV (UL(1) << 24)
 #define ESR_ELx_COND_SHIFT (20)
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 43512d4..d8a7306 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -69,7 +69,14 @@
 #define BAD_FIQ2
 #define BAD_ERROR  3
 
+   .arch_extension ras
+
.macro  kernel_entry, el, regsize = 64
+#ifdef CONFIG_ARM64_ESB
+   .if \el == 0
+   esb
+   .endif
+#endif
sub sp, sp, #S_FRAME_SIZE
.if \regsize == 32
mov w0, w0  // zero upper 32 bits of x0
@@ -208,6 +215,7 @@ alternative_else_nop_endif
 #endif
 
.if \el == 0
+   msr daifset, #0xF   // Set flags
ldr x23, [sp, #S_SP]// load return stack pointer
msr sp_el0, x23
 #ifdef CONFIG_ARM64_ERRATUM_845719
@@ -226,6 +234,15 @@ alternative_else_nop_endif
 
msr elr_el1, x21// set up the return data
msr spsr_el1, x22
+
+#ifdef CONFIG_ARM64_ESB
+   .if \el == 0
+   esb // Error Synchronization Barrier
+   mrs x21, disr_el1   // Check for deferred error
+   tbnzx21, #31, el1_sei
+   .endif
+#endif
+
ldp x0, x1, [sp, #16 * 0]
ldp x2, x3, [sp, #16 * 1]
ldp x4, x5, [sp, #16 * 2]
@@ -318,7 +335,7 @@ ENTRY(vectors)
ventry  el1_sync_invalid// Synchronous EL1t
ventry  el1_irq_invalid // IRQ EL1t
ventry  el1_fiq_invalid // FIQ EL1t
-   ventry  el1_error_invalid   // Error EL1t
+   ventry  el1_error   // Error EL1t
 
ventry  el1_sync// Synchronous EL1h
ventry  el1_irq // IRQ EL1h
@@ -328,7 +345,7 @@ ENTRY(vectors)
ventry  el0_sync// Synchronous 64-bit EL0
ventry  el0_irq // IRQ 64-bit EL0
ventry  el0_fiq_invalid // FIQ 64-bit EL0
-   ventry  el0_erro

[PATCH v3 8/8] arm64: exception: check shared writable page in SEI handler

2017-03-30 Thread Xie XiuQi
From: Wang Xiongfeng 

Since SEI is asynchronous, the error data has been consumed. So we must
suppose that all the memory data current process can write are
contaminated. If the process doesn't have shared writable pages, the
process will be killed, and the system will continue running normally.
Otherwise, the system must be terminated, because the error has been
propagated to other processes running on other cores, and recursively
the error may be propagated to several another processes.

Signed-off-by: Wang Xiongfeng 
Signed-off-by: Xie XiuQi 
---
 arch/arm64/kernel/traps.c | 149 --
 1 file changed, 144 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 99be6d8..b222589 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -34,6 +34,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include 
 #include 
@@ -662,7 +664,144 @@ asmlinkage void bad_mode(struct pt_regs *regs, int 
reason, unsigned int esr)
[ESR_ELx_AET_CE]=   "Corrected",
 };
 
+static void shared_writable_pte_entry(pte_t *pte, unsigned long addr,
+   struct mm_walk *walk)
+{
+   int *is_shared_writable = walk->private;
+   struct vm_area_struct *vma = walk->vma;
+   struct page *page = NULL;
+   int mapcount = -1;
+
+   if (!pte_write(__pte(pgprot_val(vma->vm_page_prot
+   return;
+
+   if (pte_present(*pte)) {
+   page = vm_normal_page(vma, addr, *pte);
+   } else if (is_swap_pte(*pte)) {
+   swp_entry_t swpent = pte_to_swp_entry(*pte);
+
+   if (!non_swap_entry(swpent))
+   mapcount = swp_swapcount(swpent);
+   else if (is_migration_entry(swpent))
+   page = migration_entry_to_page(swpent);
+   }
+
+   if (mapcount == -1 && page)
+   mapcount = page_mapcount(page);
+   if (mapcount >= 2)
+   *is_shared_writable = 1;
+}
+
+static void shared_writable_pmd_entry(pmd_t *pmd, unsigned long addr,
+   struct mm_walk *walk)
+{
+   struct page *page;
+   int mapcount;
+   int *is_shared_writable = walk->private;
+
+   if (!pmd_write(*pmd))
+   return;
+
+   page = pmd_page(*pmd);
+   if (page) {
+   mapcount = page_mapcount(page);
+   if (mapcount >= 2)
+   *is_shared_writable = 1;
+   }
+}
+
+static int shared_writable_pte_range(pmd_t *pmd, unsigned long addr,
+   unsigned long end, struct mm_walk *walk)
+{
+   pte_t *pte;
+
+   if (pmd_trans_huge(*pmd)) {
+   shared_writable_pmd_entry(pmd, addr, walk);
+   return 0;
+   }
+
+   if (pmd_trans_unstable(pmd))
+   return 0;
+
+   pte = pte_offset_map(pmd, addr);
+   for (; addr != end; pte++, addr += PAGE_SIZE)
+   shared_writable_pte_entry(pte, addr, walk);
+   return 0;
+}
+
+#ifdef CONFIG_HUGETLB_PAGE
+static int shared_writable_hugetlb_range(pte_t *pte, unsigned long hmask,
+   unsigned long addr, unsigned long end,
+   struct mm_walk *walk)
+{
+   struct vm_area_struct *vma = walk->vma;
+   int *is_shared_writable = walk->private;
+   struct page *page = NULL;
+   int mapcount;
+
+   if (!pte_write(*pte))
+   return 0;
+
+   if (pte_present(*pte)) {
+   page = vm_normal_page(vma, addr, *pte);
+   } else if (is_swap_pte(*pte)) {
+   swp_entry_t swpent = pte_to_swp_entry(*pte);
+
+   if (is_migration_entry(swpent))
+   page = migration_entry_to_page(swpent);
+   }
+
+   if (page) {
+   mapcount = page_mapcount(page);
+
+   if (mapcount >= 2)
+   *is_shared_writable = 1;
+   }
+   return 0;
+}
+#endif
+
+/*
+ *Check whether there exists a page in mm_struct which is shared with other
+ process and writable (not COW) at the same time. 0 means existing such a page.
+ */
+int mm_shared_writable(struct mm_struct *mm)
+{
+   struct vm_area_struct *vma;
+   int is_shared_writable = 0;
+   struct mm_walk shared_writable_walk = {
+   .pmd_entry = shared_writable_pte_range,
+#ifdef CONFIG_HUGETLB_PAGE
+   .hugetlb_entry = shared_writable_hugetlb_range,
+#endif
+   .mm = mm,
+   .private = &is_shared_writable,
+   };
+
+   if (!mm)
+   return -EPERM;
+
+   vma = mm->mmap;
+   while (vma) {
+   walk_page_vma(vma, &shared_writable_walk);
+   if (is_shared_writable)
+   return 1;
+   vma = vma->vm_next;
+   }
+   return 0;
+

[PATCH v3 7/8] arm64: exception: handle asynchronous SError interrupt

2017-03-30 Thread Xie XiuQi
Error Synchronization Barrier (ESB; part of the ARMv8.2 Extensions)
is used to synchronize Unrecoverable errors. That is, containable errors
architecturally consumed by the PE and not silently propagated.

With ESB it is generally possible to isolate an unrecoverable error
between two ESB instructions. So, it's possible to recovery from
unrecoverable errors reported by asynchronous SError interrupt.

If ARMv8.2 RAS Extension is not support, ESB is treated as a NOP.

Signed-off-by: Xie XiuQi 
Signed-off-by: Wang Xiongfeng 
---
 arch/arm64/Kconfig   | 16 ++
 arch/arm64/include/asm/esr.h | 14 +
 arch/arm64/kernel/entry.S| 70 ++--
 arch/arm64/kernel/traps.c| 54 --
 4 files changed, 150 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 859a90e..7402175 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -911,6 +911,22 @@ endmenu
 
 menu "ARMv8.2 architectural features"
 
+config ARM64_ESB
+   bool "Enable support for Error Synchronization Barrier (ESB)"
+   default n
+   help
+ Error Synchronization Barrier (ESB; part of the ARMv8.2 Extensions)
+ is used to synchronize Unrecoverable errors. That is, containable 
errors
+ architecturally consumed by the PE and not silently propagated.
+
+ Without ESB it is not generally possible to isolate an Unrecoverable
+ error because it is not known which instruction generated the error.
+
+ Selecting this option allows inject esb instruction before the 
exception
+ change. If ARMv8.2 RAS Extension is not support, ESB is treated as a 
NOP.
+
+ Note that ESB instruction can introduce slight overhead, so say N if 
unsure.
+
 config ARM64_UAO
bool "Enable support for User Access Override (UAO)"
default y
diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
index f20c64a..22f9c90 100644
--- a/arch/arm64/include/asm/esr.h
+++ b/arch/arm64/include/asm/esr.h
@@ -106,6 +106,20 @@
 #define ESR_ELx_AR (UL(1) << 14)
 #define ESR_ELx_CM (UL(1) << 8)
 
+#define ESR_Elx_DFSC_SEI   (0x11)
+
+#define ESR_ELx_AET_SHIFT  (10)
+#define ESR_ELx_AET_MAX(7)
+#define ESR_ELx_AET_MASK   (UL(7) << ESR_ELx_AET_SHIFT)
+#define ESR_ELx_AET(esr)   (((esr) & ESR_ELx_AET_MASK) >> 
ESR_ELx_AET_SHIFT)
+
+#define ESR_ELx_AET_UC (0)
+#define ESR_ELx_AET_UEU(1)
+#define ESR_ELx_AET_UEO(2)
+#define ESR_ELx_AET_UER(3)
+#define ESR_ELx_AET_CE (6)
+
+
 /* ISS field definitions for exceptions taken in to Hyp */
 #define ESR_ELx_CV (UL(1) << 24)
 #define ESR_ELx_COND_SHIFT (20)
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 43512d4..d8a7306 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -69,7 +69,14 @@
 #define BAD_FIQ2
 #define BAD_ERROR  3
 
+   .arch_extension ras
+
.macro  kernel_entry, el, regsize = 64
+#ifdef CONFIG_ARM64_ESB
+   .if \el == 0
+   esb
+   .endif
+#endif
sub sp, sp, #S_FRAME_SIZE
.if \regsize == 32
mov w0, w0  // zero upper 32 bits of x0
@@ -208,6 +215,7 @@ alternative_else_nop_endif
 #endif
 
.if \el == 0
+   msr daifset, #0xF   // Set flags
ldr x23, [sp, #S_SP]// load return stack pointer
msr sp_el0, x23
 #ifdef CONFIG_ARM64_ERRATUM_845719
@@ -226,6 +234,15 @@ alternative_else_nop_endif
 
msr elr_el1, x21// set up the return data
msr spsr_el1, x22
+
+#ifdef CONFIG_ARM64_ESB
+   .if \el == 0
+   esb // Error Synchronization Barrier
+   mrs x21, disr_el1   // Check for deferred error
+   tbnzx21, #31, el1_sei
+   .endif
+#endif
+
ldp x0, x1, [sp, #16 * 0]
ldp x2, x3, [sp, #16 * 1]
ldp x4, x5, [sp, #16 * 2]
@@ -318,7 +335,7 @@ ENTRY(vectors)
ventry  el1_sync_invalid// Synchronous EL1t
ventry  el1_irq_invalid // IRQ EL1t
ventry  el1_fiq_invalid // FIQ EL1t
-   ventry  el1_error_invalid   // Error EL1t
+   ventry  el1_error   // Error EL1t
 
ventry  el1_sync// Synchronous EL1h
ventry  el1_irq // IRQ EL1h
@@ -328,7 +345,7 @@ ENTRY(vectors)
ventry  el0_sync// Synchronous 64-bit EL0
ventry  el0_irq // IRQ 64-bit EL0
ventry  el0_fiq_invalid // FIQ 64-bit EL0
-   ventry  el0_erro

[PATCH v3 8/8] arm64: exception: check shared writable page in SEI handler

2017-03-30 Thread Xie XiuQi
From: Wang Xiongfeng 

Since SEI is asynchronous, the error data has been consumed. So we must
suppose that all the memory data current process can write are
contaminated. If the process doesn't have shared writable pages, the
process will be killed, and the system will continue running normally.
Otherwise, the system must be terminated, because the error has been
propagated to other processes running on other cores, and recursively
the error may be propagated to several another processes.

Signed-off-by: Wang Xiongfeng 
Signed-off-by: Xie XiuQi 
---
 arch/arm64/kernel/traps.c | 149 --
 1 file changed, 144 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 99be6d8..b222589 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -34,6 +34,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include 
 #include 
@@ -662,7 +664,144 @@ asmlinkage void bad_mode(struct pt_regs *regs, int 
reason, unsigned int esr)
[ESR_ELx_AET_CE]=   "Corrected",
 };
 
+static void shared_writable_pte_entry(pte_t *pte, unsigned long addr,
+   struct mm_walk *walk)
+{
+   int *is_shared_writable = walk->private;
+   struct vm_area_struct *vma = walk->vma;
+   struct page *page = NULL;
+   int mapcount = -1;
+
+   if (!pte_write(__pte(pgprot_val(vma->vm_page_prot
+   return;
+
+   if (pte_present(*pte)) {
+   page = vm_normal_page(vma, addr, *pte);
+   } else if (is_swap_pte(*pte)) {
+   swp_entry_t swpent = pte_to_swp_entry(*pte);
+
+   if (!non_swap_entry(swpent))
+   mapcount = swp_swapcount(swpent);
+   else if (is_migration_entry(swpent))
+   page = migration_entry_to_page(swpent);
+   }
+
+   if (mapcount == -1 && page)
+   mapcount = page_mapcount(page);
+   if (mapcount >= 2)
+   *is_shared_writable = 1;
+}
+
+static void shared_writable_pmd_entry(pmd_t *pmd, unsigned long addr,
+   struct mm_walk *walk)
+{
+   struct page *page;
+   int mapcount;
+   int *is_shared_writable = walk->private;
+
+   if (!pmd_write(*pmd))
+   return;
+
+   page = pmd_page(*pmd);
+   if (page) {
+   mapcount = page_mapcount(page);
+   if (mapcount >= 2)
+   *is_shared_writable = 1;
+   }
+}
+
+static int shared_writable_pte_range(pmd_t *pmd, unsigned long addr,
+   unsigned long end, struct mm_walk *walk)
+{
+   pte_t *pte;
+
+   if (pmd_trans_huge(*pmd)) {
+   shared_writable_pmd_entry(pmd, addr, walk);
+   return 0;
+   }
+
+   if (pmd_trans_unstable(pmd))
+   return 0;
+
+   pte = pte_offset_map(pmd, addr);
+   for (; addr != end; pte++, addr += PAGE_SIZE)
+   shared_writable_pte_entry(pte, addr, walk);
+   return 0;
+}
+
+#ifdef CONFIG_HUGETLB_PAGE
+static int shared_writable_hugetlb_range(pte_t *pte, unsigned long hmask,
+   unsigned long addr, unsigned long end,
+   struct mm_walk *walk)
+{
+   struct vm_area_struct *vma = walk->vma;
+   int *is_shared_writable = walk->private;
+   struct page *page = NULL;
+   int mapcount;
+
+   if (!pte_write(*pte))
+   return 0;
+
+   if (pte_present(*pte)) {
+   page = vm_normal_page(vma, addr, *pte);
+   } else if (is_swap_pte(*pte)) {
+   swp_entry_t swpent = pte_to_swp_entry(*pte);
+
+   if (is_migration_entry(swpent))
+   page = migration_entry_to_page(swpent);
+   }
+
+   if (page) {
+   mapcount = page_mapcount(page);
+
+   if (mapcount >= 2)
+   *is_shared_writable = 1;
+   }
+   return 0;
+}
+#endif
+
+/*
+ *Check whether there exists a page in mm_struct which is shared with other
+ process and writable (not COW) at the same time. 0 means existing such a page.
+ */
+int mm_shared_writable(struct mm_struct *mm)
+{
+   struct vm_area_struct *vma;
+   int is_shared_writable = 0;
+   struct mm_walk shared_writable_walk = {
+   .pmd_entry = shared_writable_pte_range,
+#ifdef CONFIG_HUGETLB_PAGE
+   .hugetlb_entry = shared_writable_hugetlb_range,
+#endif
+   .mm = mm,
+   .private = &is_shared_writable,
+   };
+
+   if (!mm)
+   return -EPERM;
+
+   vma = mm->mmap;
+   while (vma) {
+   walk_page_vma(vma, &shared_writable_walk);
+   if (is_shared_writable)
+   return 1;
+   vma = vma->vm_next;
+   }
+   return 0;
+

[PATCH v3 1/8] trace: ras: add ARM processor error information trace event

2017-03-30 Thread Xie XiuQi
Add a new trace event for ARM processor error information, so that
the user will know what error occurred. With this information the
user may take appropriate action.

These trace events are consistent with the ARM processor error
information table which defined in UEFI 2.6 spec section N.2.4.4.1.

---
v2: add trace enabled condition as Steven's suggestion.
fix a typo.
---

Cc: Steven Rostedt 
Cc: Tyler Baicar 
Signed-off-by: Xie XiuQi 
---
 drivers/acpi/apei/ghes.c | 10 ++
 include/linux/cper.h |  5 +++
 include/ras/ras_event.h  | 87 
 3 files changed, 102 insertions(+)

diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 81eabc6..6be0333 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -518,9 +518,19 @@ static void ghes_do_proc(struct ghes *ghes,
else if (!uuid_le_cmp(sec_type, CPER_SEC_PROC_ARM) &&
 trace_arm_event_enabled()) {
struct cper_sec_proc_arm *arm_err;
+   struct cper_arm_err_info *err_info;
+   int i;
 
arm_err = acpi_hest_generic_data_payload(gdata);
trace_arm_event(arm_err);
+
+   if (trace_arm_proc_err_enabled()) {
+   err_info = (struct cper_arm_err_info *)(arm_err 
+ 1);
+   for (i = 0; i < arm_err->err_info_num; i++) {
+   trace_arm_proc_err(err_info);
+   err_info += 1;
+   }
+   }
} else if (trace_unknown_sec_event_enabled()) {
void *unknown_err = 
acpi_hest_generic_data_payload(gdata);
trace_unknown_sec_event(&sec_type,
diff --git a/include/linux/cper.h b/include/linux/cper.h
index 85450f3..0cae900 100644
--- a/include/linux/cper.h
+++ b/include/linux/cper.h
@@ -270,6 +270,11 @@ enum {
 #define CPER_ARM_INFO_VALID_VIRT_ADDR  0x0008
 #define CPER_ARM_INFO_VALID_PHYSICAL_ADDR  0x0010
 
+#define CPER_ARM_INFO_TYPE_CACHE   0
+#define CPER_ARM_INFO_TYPE_TLB 1
+#define CPER_ARM_INFO_TYPE_BUS 2
+#define CPER_ARM_INFO_TYPE_UARCH   3
+
 #define CPER_ARM_INFO_FLAGS_FIRST  0x0001
 #define CPER_ARM_INFO_FLAGS_LAST   0x0002
 #define CPER_ARM_INFO_FLAGS_PROPAGATED 0x0004
diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h
index 13befad..026b094 100644
--- a/include/ras/ras_event.h
+++ b/include/ras/ras_event.h
@@ -206,6 +206,93 @@
  __entry->running_state, __entry->psci_state)
 );
 
+#define ARM_PROC_ERR_TYPE  \
+   EM ( CPER_ARM_INFO_TYPE_CACHE, "cache error" )  \
+   EM ( CPER_ARM_INFO_TYPE_TLB,  "TLB error" ) \
+   EM ( CPER_ARM_INFO_TYPE_BUS, "bus error" )  \
+   EMe ( CPER_ARM_INFO_TYPE_UARCH, "micro-architectural error" )
+
+#define ARM_PROC_ERR_FLAGS \
+   EM ( CPER_ARM_INFO_FLAGS_FIRST, "First error captured" )\
+   EM ( CPER_ARM_INFO_FLAGS_LAST,  "Last error captured" ) \
+   EM ( CPER_ARM_INFO_FLAGS_PROPAGATED, "Propagated" ) \
+   EMe ( CPER_ARM_INFO_FLAGS_OVERFLOW, "Overflow" )
+
+/*
+ * First define the enums in MM_ACTION_RESULT to be exported to userspace
+ * via TRACE_DEFINE_ENUM().
+ */
+#undef EM
+#undef EMe
+#define EM(a, b) TRACE_DEFINE_ENUM(a);
+#define EMe(a, b)  TRACE_DEFINE_ENUM(a);
+
+ARM_PROC_ERR_TYPE
+ARM_PROC_ERR_FLAGS
+
+/*
+ * Now redefine the EM() and EMe() macros to map the enums to the strings
+ * that will be printed in the output.
+ */
+#undef EM
+#undef EMe
+#define EM(a, b)   { a, b },
+#define EMe(a, b)  { a, b }
+
+TRACE_EVENT(arm_proc_err,
+
+   TP_PROTO(const struct cper_arm_err_info *err),
+
+   TP_ARGS(err),
+
+   TP_STRUCT__entry(
+   __field(u8, type)
+   __field(u16, multiple_error)
+   __field(u8, flags)
+   __field(u64, error_info)
+   __field(u64, virt_fault_addr)
+   __field(u64, physical_fault_addr)
+   ),
+
+   TP_fast_assign(
+   __entry->type = err->type;
+
+   if (err->validation_bits & CPER_ARM_INFO_VALID_MULTI_ERR)
+   __entry->multiple_error = err->multiple_error;
+   else
+   __entry->multiple_error = ~0;
+
+   if (err->validation_bits & CPER_ARM_INFO_VALID_FLAGS)
+   __entry->flags = err->flags;
+   else
+   __entry->flags = ~0;
+
+   if (err->validation_bits & CPER_ARM_INFO_VALID_ERR_INFO)
+   

[PATCH v3 3/8] arm64: apei: add a per-cpu variable to indecate sei is processing

2017-03-30 Thread Xie XiuQi
Add a per-cpu variable to indicate sei is processing, with which we could use to
reserve a separate virtual space address page for sei in next patch

Signed-off-by: Xie XiuQi 
---
 arch/arm64/kernel/traps.c | 4 
 include/acpi/ghes.h   | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 53710a2..955dc8c 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -615,6 +615,8 @@ const char *esr_get_class_string(u32 esr)
return esr_class_str[ESR_ELx_EC(esr)];
 }
 
+DEFINE_PER_CPU(int, sei_in_process);
+
 /*
  * bad_mode handles the impossible case in the exception vector. This is always
  * fatal.
@@ -632,7 +634,9 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, 
unsigned int esr)
 * of cper records at a time. There is no risk for one cpu to parse 
ghes table.
 */
if (IS_ENABLED(CONFIG_ACPI_APEI_SEI) && ESR_ELx_EC(esr) == 
ESR_ELx_EC_SERROR) {
+   this_cpu_inc(sei_in_process);
ghes_notify_sei();
+   this_cpu_dec(sei_in_process);
}
 
die("Oops - bad mode", regs, 0);
diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h
index 10d752e..eed79ea 100644
--- a/include/acpi/ghes.h
+++ b/include/acpi/ghes.h
@@ -102,4 +102,6 @@ static inline void *acpi_hest_generic_data_payload(struct 
acpi_hest_generic_data
 int ghes_notify_sea(void);
 int ghes_notify_sei(void);
 
+DECLARE_PER_CPU(int, sei_in_process);
+
 #endif /* GHES_H */
-- 
1.8.3.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH v3 5/8] arm64: KVM: add guest SEI support

2017-03-30 Thread Xie XiuQi
Add ghes handling for SEI so that the host kernel could parse and
report detailed error information for SEI which occur in the guest
kernel.

If there were no CPER records, (or the system doesn't support SEI as a GHES
notification mechanism), then yes we should still call kvm_inject_vabt().

Signed-off-by: Xie XiuQi 
---
 arch/arm64/include/asm/system_misc.h |  1 +
 arch/arm64/kernel/traps.c| 14 ++
 arch/arm64/kvm/handle_exit.c | 22 --
 3 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/system_misc.h 
b/arch/arm64/include/asm/system_misc.h
index 5b2cecd..d68d61f 100644
--- a/arch/arm64/include/asm/system_misc.h
+++ b/arch/arm64/include/asm/system_misc.h
@@ -59,5 +59,6 @@ void hook_debug_fault_code(int nr, int (*fn)(unsigned long, 
unsigned int,
 #endif /* __ASSEMBLY__ */
 
 int handle_guest_sea(unsigned long addr, unsigned int esr);
+int handle_guest_sei(unsigned long addr, unsigned int esr);
 
 #endif /* __ASM_SYSTEM_MISC_H */
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 955dc8c..b6d6727 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -618,6 +618,20 @@ const char *esr_get_class_string(u32 esr)
 DEFINE_PER_CPU(int, sei_in_process);
 
 /*
+ * Handle asynchronous SError interrupt that occur in a guest kernel.
+ */
+int handle_guest_sei(unsigned long addr, unsigned int esr)
+{
+int ret = -ENOENT;
+
+if(IS_ENABLED(CONFIG_ACPI_APEI_SEI)) {
+ret = ghes_notify_sei();
+}
+
+return ret;
+}
+
+/*
  * bad_mode handles the impossible case in the exception vector. This is always
  * fatal.
  */
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index fa1b18e..c89d83a 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define CREATE_TRACE_POINTS
 #include "trace.h"
@@ -177,6 +178,23 @@ static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu 
*vcpu)
return arm_exit_handlers[hsr_ec];
 }
 
+static int kvm_handle_guest_sei(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+   unsigned long fault_ipa = kvm_vcpu_get_fault_ipa(vcpu);
+
+   if (handle_guest_sei((unsigned long)fault_ipa,
+   kvm_vcpu_get_hsr(vcpu))) {
+   kvm_err("Failed to handle guest SEI, FSC: EC=%#x xFSC=%#lx 
ESR_EL2=%#lx\n",
+   kvm_vcpu_trap_get_class(vcpu),
+   (unsigned long)kvm_vcpu_trap_get_fault(vcpu),
+   (unsigned long)kvm_vcpu_get_hsr(vcpu));
+
+   kvm_inject_vabt(vcpu);
+   }
+
+   return 0;
+}
+
 /*
  * Return > 0 to return to guest, < 0 on error, 0 (and set exit_reason) on
  * proper exit to userspace.
@@ -200,7 +218,7 @@ int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
*vcpu_pc(vcpu) -= adj;
}
 
-   kvm_inject_vabt(vcpu);
+   kvm_handle_guest_sei(vcpu, run);
return 1;
}
 
@@ -210,7 +228,7 @@ int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
case ARM_EXCEPTION_IRQ:
return 1;
case ARM_EXCEPTION_EL1_SERROR:
-   kvm_inject_vabt(vcpu);
+   kvm_handle_guest_sei(vcpu, run);
return 1;
case ARM_EXCEPTION_TRAP:
/*
-- 
1.8.3.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH v3 2/8] acpi: apei: handle SEI notification type for ARMv8

2017-03-30 Thread Xie XiuQi
ARM APEI extension proposal added SEI (asynchronous SError interrupt)
notification type for ARMv8.

Add a new GHES error source handling function for SEI. In firmware
first mode, if an error source's notification type is SEI. Then GHES
could parse and report the detail error information.

Signed-off-by: Xie XiuQi 
---
 arch/arm64/kernel/traps.c | 10 
 drivers/acpi/apei/Kconfig | 14 
 drivers/acpi/apei/ghes.c  | 58 +++
 include/acpi/ghes.h   |  1 +
 4 files changed, 83 insertions(+)

diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index e52be6a..53710a2 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -47,6 +47,8 @@
 #include 
 #include 
 
+#include 
+
 static const char *handler[]= {
"Synchronous Abort",
"IRQ",
@@ -625,6 +627,14 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, 
unsigned int esr)
handler[reason], smp_processor_id(), esr,
esr_get_class_string(esr));
 
+   /*
+* In firmware first mode, we could assume firmware will only generate 
one
+* of cper records at a time. There is no risk for one cpu to parse 
ghes table.
+*/
+   if (IS_ENABLED(CONFIG_ACPI_APEI_SEI) && ESR_ELx_EC(esr) == 
ESR_ELx_EC_SERROR) {
+   ghes_notify_sei();
+   }
+
die("Oops - bad mode", regs, 0);
local_irq_disable();
panic("bad mode");
diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig
index b54bd33..c00c9d34 100644
--- a/drivers/acpi/apei/Kconfig
+++ b/drivers/acpi/apei/Kconfig
@@ -55,6 +55,20 @@ config ACPI_APEI_SEA
  option allows the OS to look for such hardware error record, and
  take appropriate action.
 
+config ACPI_APEI_SEI
+   bool "APEI Asynchronous SError Interrupt logging/recovering support"
+   depends on ARM64 && ACPI_APEI_GHES
+   help
+ This option should be enabled if the system supports
+ firmware first handling of SEI (asynchronous SError interrupt).
+
+ SEI happens with invalid instruction access or asynchronous exceptions
+ on ARMv8 systems. If a system supports firmware first handling of SEI,
+ the platform analyzes and handles hardware error notifications from
+ SEI, and it may then form a HW error record for the OS to parse and
+ handle. This option allows the OS to look for such hardware error
+ record, and take appropriate action.
+
 config ACPI_APEI_MEMORY_FAILURE
bool "APEI memory error recovering support"
depends on ACPI_APEI && MEMORY_FAILURE
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 6be0333..045d101 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -862,6 +862,51 @@ static inline void ghes_sea_remove(struct ghes *ghes)
 }
 #endif /* CONFIG_ACPI_APEI_SEA */
 
+#ifdef CONFIG_ACPI_APEI_SEI
+static LIST_HEAD(ghes_sei);
+
+int ghes_notify_sei(void)
+{
+   struct ghes *ghes;
+   int ret = -ENOENT;
+
+   rcu_read_lock();
+   list_for_each_entry_rcu(ghes, &ghes_sei, list) {
+   if(!ghes_proc(ghes))
+   ret = 0;
+   }
+   rcu_read_unlock();
+   return ret;
+}
+
+static void ghes_sei_add(struct ghes *ghes)
+{
+   mutex_lock(&ghes_list_mutex);
+   list_add_rcu(&ghes->list, &ghes_sei);
+   mutex_unlock(&ghes_list_mutex);
+}
+
+static void ghes_sei_remove(struct ghes *ghes)
+{
+   mutex_lock(&ghes_list_mutex);
+   list_del_rcu(&ghes->list);
+   mutex_unlock(&ghes_list_mutex);
+   synchronize_rcu();
+}
+#else /* CONFIG_ACPI_APEI_SEI */
+static inline void ghes_sei_add(struct ghes *ghes)
+{
+   pr_err(GHES_PFX "ID: %d, trying to add SEI notification which is not 
supported\n",
+  ghes->generic->header.source_id);
+}
+
+static inline void ghes_sei_remove(struct ghes *ghes)
+{
+   pr_err(GHES_PFX "ID: %d, trying to remove SEI notification which is not 
supported\n",
+  ghes->generic->header.source_id);
+}
+#endif /* CONFIG_HAVE_ACPI_APEI_SEI */
+
 #ifdef CONFIG_HAVE_ACPI_APEI_NMI
 /*
  * printk is not safe in NMI context.  So in NMI handler, we allocate
@@ -,6 +1156,13 @@ static int ghes_probe(struct platform_device *ghes_dev)
goto err;
}
break;
+   case ACPI_HEST_NOTIFY_SEI:
+   if (!IS_ENABLED(CONFIG_HAVE_ACPI_APEI_SEI)) {
+   pr_warn(GHES_PFX "Generic hardware error source: %d 
notified via SEI is not supported!\n",
+   generic->header.source_id);
+   goto err;
+   }
+   break;
case ACPI_HEST_NOTIFY_NMI:
if (!IS_EN

[PATCH v3 4/8] APEI: GHES: reserve a virtual page for SEI context

2017-03-30 Thread Xie XiuQi
On arm64 platform, SEI may interrupt code which had interrupts masked.
But SEI could be masked, so it's not treated as NMI, however SEA is
treated as NMI.

So, the  memory area used to transfer hardware error information from
BIOS to Linux can be determined only in NMI, SEI(arm64), IRQ or timer
handler.

In this patch, we add a virtual page for SEI context.

Signed-off-by: Xie XiuQi 
---
 drivers/acpi/apei/ghes.c | 98 +++-
 1 file changed, 47 insertions(+), 51 deletions(-)

diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 045d101..b1f9b1f 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -108,26 +108,33 @@
 
 /*
  * Because the memory area used to transfer hardware error information
- * from BIOS to Linux can be determined only in NMI, IRQ or timer
- * handler, but general ioremap can not be used in atomic context, so
- * a special version of atomic ioremap is implemented for that.
+ * from BIOS to Linux can be determined only in NMI, SEI (ARM64), IRQ or
+ * timer handler, but general ioremap can not be used in atomic context,
+ * so a special version of atomic ioremap is implemented for that.
  */
 
 /*
- * Two virtual pages are used, one for IRQ/PROCESS context, the other for
- * NMI context (optionally).
+ * 3 virtual pages are used, one for IRQ/PROCESS context, one for SEI
+ * (on ARM64 platform), and the other for NMI context (optionally).
  */
+#ifdef CONFIG_ACPI_APEI_SEI
+#define GHES_IOREMAP_PAGES   3
+#define GHES_IOREMAP_SEI_PAGE(base)((base) + PAGE_SIZE*2)
+#else
 #define GHES_IOREMAP_PAGES   2
+#endif
+
 #define GHES_IOREMAP_IRQ_PAGE(base)(base)
 #define GHES_IOREMAP_NMI_PAGE(base)((base) + PAGE_SIZE)
 
 /* virtual memory area for atomic ioremap */
 static struct vm_struct *ghes_ioremap_area;
 /*
- * These 2 spinlock is used to prevent atomic ioremap virtual memory
+ * These 3 spinlock is used to prevent atomic ioremap virtual memory
  * area from being mapped simultaneously.
  */
 static DEFINE_RAW_SPINLOCK(ghes_ioremap_lock_nmi);
+static DEFINE_SPINLOCK(ghes_ioremap_lock_sei);
 static DEFINE_SPINLOCK(ghes_ioremap_lock_irq);
 
 static struct gen_pool *ghes_estatus_pool;
@@ -155,54 +162,55 @@ static void ghes_ioremap_exit(void)
free_vm_area(ghes_ioremap_area);
 }
 
-static void __iomem *ghes_ioremap_pfn_nmi(u64 pfn)
+static void __iomem *ghes_ioremap_pfn(u64 pfn)
 {
-   unsigned long vaddr;
+   unsigned long vaddr, flags = 0;
phys_addr_t paddr;
pgprot_t prot;
 
-   vaddr = (unsigned long)GHES_IOREMAP_NMI_PAGE(ghes_ioremap_area->addr);
-
-   paddr = pfn << PAGE_SHIFT;
-   prot = arch_apei_get_mem_attribute(paddr);
-   ioremap_page_range(vaddr, vaddr + PAGE_SIZE, paddr, prot);
-
-   return (void __iomem *)vaddr;
-}
-
-static void __iomem *ghes_ioremap_pfn_irq(u64 pfn)
-{
-   unsigned long vaddr, paddr;
-   pgprot_t prot;
-
-   vaddr = (unsigned long)GHES_IOREMAP_IRQ_PAGE(ghes_ioremap_area->addr);
+   if (in_nmi()) {
+   raw_spin_lock(&ghes_ioremap_lock_nmi);
+   vaddr = (unsigned 
long)GHES_IOREMAP_NMI_PAGE(ghes_ioremap_area->addr);
+   } else if (this_cpu_read(sei_in_process)) {
+   spin_lock_irqsave(&ghes_ioremap_lock_sei, flags);
+   vaddr = (unsigned 
long)GHES_IOREMAP_SEI_PAGE(ghes_ioremap_area->addr);
+   } else {
+   spin_lock_irqsave(&ghes_ioremap_lock_irq, flags);
+   vaddr = (unsigned 
long)GHES_IOREMAP_IRQ_PAGE(ghes_ioremap_area->addr);
+   }
 
paddr = pfn << PAGE_SHIFT;
prot = arch_apei_get_mem_attribute(paddr);
-
ioremap_page_range(vaddr, vaddr + PAGE_SIZE, paddr, prot);
 
return (void __iomem *)vaddr;
 }
 
-static void ghes_iounmap_nmi(void __iomem *vaddr_ptr)
+static void ghes_iounmap(void __iomem *vaddr_ptr)
 {
unsigned long vaddr = (unsigned long __force)vaddr_ptr;
void *base = ghes_ioremap_area->addr;
+   unsigned long page, flags = 0;
+
+   if (in_nmi()) {
+   page = (unsigned long)GHES_IOREMAP_NMI_PAGE(base);
+   } else if (this_cpu_read(sei_in_process)) {
+   page = (unsigned long)GHES_IOREMAP_SEI_PAGE(base);
+   } else {
+   page = (unsigned long)GHES_IOREMAP_IRQ_PAGE(base);
+   }
 
-   BUG_ON(vaddr != (unsigned long)GHES_IOREMAP_NMI_PAGE(base));
+   BUG_ON(vaddr != page);
unmap_kernel_range_noflush(vaddr, PAGE_SIZE);
arch_apei_flush_tlb_one(vaddr);
-}
-
-static void ghes_iounmap_irq(void __iomem *vaddr_ptr)
-{
-   unsigned long vaddr = (unsigned long __force)vaddr_ptr;
-   void *base = ghes_ioremap_area->addr;
 
-   BUG_ON(vaddr != (unsigned long)GHES_IOREMAP_IRQ_PAGE(base));
-   unmap_kernel_range_noflush(vaddr, PAGE_SIZE);
-   arch_apei_flush_tlb_one(vaddr);
+   if (in_nmi()) {
+   raw_spin

[PATCH v3 6/8] arm64: RAS: add ras extension runtime detection

2017-03-30 Thread Xie XiuQi
According to <> document, we add RAS extension
feature runtime detection, which would be used for error recovery
in the future.

Signed-off-by: Xie XiuQi 
Reviewed-by: Kefeng Wang 
---
 arch/arm64/include/asm/cpucaps.h |  3 ++-
 arch/arm64/include/asm/sysreg.h  |  2 ++
 arch/arm64/kernel/cpufeature.c   | 11 +++
 3 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index fb78a5d..3847cf8 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -37,7 +37,8 @@
 #define ARM64_HAS_NO_FPSIMD16
 #define ARM64_WORKAROUND_REPEAT_TLBI   17
 #define ARM64_WORKAROUND_QCOM_FALKOR_E1003 18
+#define ARM64_HAS_RAS_EXTN 19
 
-#define ARM64_NCAPS19
+#define ARM64_NCAPS20
 
 #endif /* __ASM_CPUCAPS_H */
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index ac24b6e..32964c7 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -157,6 +157,7 @@
 #define ID_AA64ISAR0_AES_SHIFT 4
 
 /* id_aa64pfr0 */
+#define ID_AA64PFR0_RAS_SHIFT  28
 #define ID_AA64PFR0_GIC_SHIFT  24
 #define ID_AA64PFR0_ASIMD_SHIFT20
 #define ID_AA64PFR0_FP_SHIFT   16
@@ -165,6 +166,7 @@
 #define ID_AA64PFR0_EL1_SHIFT  4
 #define ID_AA64PFR0_EL0_SHIFT  0
 
+#define ID_AA64PFR0_RAS_V1 0x1
 #define ID_AA64PFR0_FP_NI  0xf
 #define ID_AA64PFR0_FP_SUPPORTED   0x0
 #define ID_AA64PFR0_ASIMD_NI   0xf
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index abda8e8..b0fb81e 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -98,6 +98,7 @@
 };
 
 static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = {
+   ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 
ID_AA64PFR0_RAS_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 
ID_AA64PFR0_GIC_SHIFT, 4, 0),
S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 
ID_AA64PFR0_ASIMD_SHIFT, 4, ID_AA64PFR0_ASIMD_NI),
S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 
ID_AA64PFR0_FP_SHIFT, 4, ID_AA64PFR0_FP_NI),
@@ -860,6 +861,16 @@ static bool has_no_fpsimd(const struct 
arm64_cpu_capabilities *entry, int __unus
.min_field_value = 0,
.matches = has_no_fpsimd,
},
+   {
+   .desc = "ARM64 RAS Extension Support",
+   .capability = ARM64_HAS_RAS_EXTN,
+   .def_scope = SCOPE_SYSTEM,
+   .matches = has_cpuid_feature,
+   .sys_reg = SYS_ID_AA64PFR0_EL1,
+   .sign = FTR_UNSIGNED,
+   .field_pos = ID_AA64PFR0_RAS_SHIFT,
+   .min_field_value = ID_AA64PFR0_RAS_V1,
+   },
{},
 };
 
-- 
1.8.3.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH v3 2/8] acpi: apei: handle SEI notification type for ARMv8

2017-03-30 Thread Xie XiuQi
ARM APEI extension proposal added SEI (asynchronous SError interrupt)
notification type for ARMv8.

Add a new GHES error source handling function for SEI. In firmware
first mode, if an error source's notification type is SEI. Then GHES
could parse and report the detail error information.

Signed-off-by: Xie XiuQi 
---
 arch/arm64/kernel/traps.c | 10 
 drivers/acpi/apei/Kconfig | 14 
 drivers/acpi/apei/ghes.c  | 58 +++
 include/acpi/ghes.h   |  1 +
 4 files changed, 83 insertions(+)

diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index e52be6a..53710a2 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -47,6 +47,8 @@
 #include 
 #include 
 
+#include 
+
 static const char *handler[]= {
"Synchronous Abort",
"IRQ",
@@ -625,6 +627,14 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, 
unsigned int esr)
handler[reason], smp_processor_id(), esr,
esr_get_class_string(esr));
 
+   /*
+* In firmware first mode, we could assume firmware will only generate 
one
+* of cper records at a time. There is no risk for one cpu to parse 
ghes table.
+*/
+   if (IS_ENABLED(CONFIG_ACPI_APEI_SEI) && ESR_ELx_EC(esr) == 
ESR_ELx_EC_SERROR) {
+   ghes_notify_sei();
+   }
+
die("Oops - bad mode", regs, 0);
local_irq_disable();
panic("bad mode");
diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig
index b54bd33..c00c9d34 100644
--- a/drivers/acpi/apei/Kconfig
+++ b/drivers/acpi/apei/Kconfig
@@ -55,6 +55,20 @@ config ACPI_APEI_SEA
  option allows the OS to look for such hardware error record, and
  take appropriate action.
 
+config ACPI_APEI_SEI
+   bool "APEI Asynchronous SError Interrupt logging/recovering support"
+   depends on ARM64 && ACPI_APEI_GHES
+   help
+ This option should be enabled if the system supports
+ firmware first handling of SEI (asynchronous SError interrupt).
+
+ SEI happens with invalid instruction access or asynchronous exceptions
+ on ARMv8 systems. If a system supports firmware first handling of SEI,
+ the platform analyzes and handles hardware error notifications from
+ SEI, and it may then form a HW error record for the OS to parse and
+ handle. This option allows the OS to look for such hardware error
+ record, and take appropriate action.
+
 config ACPI_APEI_MEMORY_FAILURE
bool "APEI memory error recovering support"
depends on ACPI_APEI && MEMORY_FAILURE
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 6be0333..045d101 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -862,6 +862,51 @@ static inline void ghes_sea_remove(struct ghes *ghes)
 }
 #endif /* CONFIG_ACPI_APEI_SEA */
 
+#ifdef CONFIG_ACPI_APEI_SEI
+static LIST_HEAD(ghes_sei);
+
+int ghes_notify_sei(void)
+{
+   struct ghes *ghes;
+   int ret = -ENOENT;
+
+   rcu_read_lock();
+   list_for_each_entry_rcu(ghes, &ghes_sei, list) {
+   if(!ghes_proc(ghes))
+   ret = 0;
+   }
+   rcu_read_unlock();
+   return ret;
+}
+
+static void ghes_sei_add(struct ghes *ghes)
+{
+   mutex_lock(&ghes_list_mutex);
+   list_add_rcu(&ghes->list, &ghes_sei);
+   mutex_unlock(&ghes_list_mutex);
+}
+
+static void ghes_sei_remove(struct ghes *ghes)
+{
+   mutex_lock(&ghes_list_mutex);
+   list_del_rcu(&ghes->list);
+   mutex_unlock(&ghes_list_mutex);
+   synchronize_rcu();
+}
+#else /* CONFIG_ACPI_APEI_SEI */
+static inline void ghes_sei_add(struct ghes *ghes)
+{
+   pr_err(GHES_PFX "ID: %d, trying to add SEI notification which is not 
supported\n",
+  ghes->generic->header.source_id);
+}
+
+static inline void ghes_sei_remove(struct ghes *ghes)
+{
+   pr_err(GHES_PFX "ID: %d, trying to remove SEI notification which is not 
supported\n",
+  ghes->generic->header.source_id);
+}
+#endif /* CONFIG_HAVE_ACPI_APEI_SEI */
+
 #ifdef CONFIG_HAVE_ACPI_APEI_NMI
 /*
  * printk is not safe in NMI context.  So in NMI handler, we allocate
@@ -,6 +1156,13 @@ static int ghes_probe(struct platform_device *ghes_dev)
goto err;
}
break;
+   case ACPI_HEST_NOTIFY_SEI:
+   if (!IS_ENABLED(CONFIG_HAVE_ACPI_APEI_SEI)) {
+   pr_warn(GHES_PFX "Generic hardware error source: %d 
notified via SEI is not supported!\n",
+   generic->header.source_id);
+   goto err;
+   }
+   break;
case ACPI_HEST_NOTIFY_NMI:
if (!IS_EN

[PATCH v3 3/8] arm64: apei: add a per-cpu variable to indecate sei is processing

2017-03-30 Thread Xie XiuQi
Add a per-cpu variable to indicate sei is processing, with which we could use to
reserve a separate virtual space address page for sei in next patch

Signed-off-by: Xie XiuQi 
---
 arch/arm64/kernel/traps.c | 4 
 include/acpi/ghes.h   | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 53710a2..955dc8c 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -615,6 +615,8 @@ const char *esr_get_class_string(u32 esr)
return esr_class_str[ESR_ELx_EC(esr)];
 }
 
+DEFINE_PER_CPU(int, sei_in_process);
+
 /*
  * bad_mode handles the impossible case in the exception vector. This is always
  * fatal.
@@ -632,7 +634,9 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, 
unsigned int esr)
 * of cper records at a time. There is no risk for one cpu to parse 
ghes table.
 */
if (IS_ENABLED(CONFIG_ACPI_APEI_SEI) && ESR_ELx_EC(esr) == 
ESR_ELx_EC_SERROR) {
+   this_cpu_inc(sei_in_process);
ghes_notify_sei();
+   this_cpu_dec(sei_in_process);
}
 
die("Oops - bad mode", regs, 0);
diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h
index 10d752e..eed79ea 100644
--- a/include/acpi/ghes.h
+++ b/include/acpi/ghes.h
@@ -102,4 +102,6 @@ static inline void *acpi_hest_generic_data_payload(struct 
acpi_hest_generic_data
 int ghes_notify_sea(void);
 int ghes_notify_sei(void);
 
+DECLARE_PER_CPU(int, sei_in_process);
+
 #endif /* GHES_H */
-- 
1.8.3.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH v3 0/8] arm64: acpi: apei: handle SEI notification type for ARMv8

2017-03-30 Thread Xie XiuQi
ARM APEI extension proposal added SEI (asynchronous SError interrupt)
notification type for ARMv8.

Add a new GHES error source handling function for SEI. In firmware
first mode, if an error source's notification type is SEI. Then GHES
could parse and report the detail error information.

In firmware first mode, we could assume:
1) The ghes for sei is a global table, firmware should report one sei at a time.
2) SEI is masked while exception is processing
3) SEI may interrupt while irq handler is running 
4) SEA may interrupt while SEI handler is running

So, the memory area used to transfer hardware error information from
BIOS to Linux can be determined only in NMI, SEI(arm64), IRQ or timer
handler. We add a virtual page for SEI context.

Error Synchronization Barrier (ESB; part of the ARMv8.2 Extensions)
is used to synchronize Unrecoverable errors. That is, containable errors
architecturally consumed by the PE and not silently propagated.

With ESB it is generally possible to isolate an unrecoverable error
between two ESB instructions. So, it's possible to recovery from
unrecoverable errors reported by asynchronous SError interrupt.

Since SEI is asynchronous, a SEI generated on user process may propagate
to another user process via shared memory, which may cause unrecoverable.
We have a idea which only recover sei from user process which has no
writable shared memory.

The idea is still in the discussion, any comments is welcome.

This series is based on Tyler's series "[PATCH V13 00/10] Add UEFI 2.6 and ACPI 
6.1 updates
for RAS on ARM64" and the latest mainline.

v3: add ARM processor error information trace event
add a per-cpu variable to indecate sei is processing
remove nmi_{enter/exit} protection for ghes_notify_sei()
reserve a virtual page for processing ghes table in SEI context
don't always inject vabt for sei
serprate do_sei from bad_mode
add esb which make recovery from sei possible
add an idea to recovery from sei for shared memory process

v2: add kvm guest SEI notification support
add nmi_{entry, exit} to protect ghes_notify_sei

https://lkml.org/lkml/2017/3/7/962
https://lkml.org/lkml/2017/3/3/189

Wang Xiongfeng (1):
  arm64: exception: check shared writable page in SEI handler

Xie XiuQi (7):
  trace: ras: add ARM processor error information trace event
  acpi: apei: handle SEI notification type for ARMv8
  arm64: apei: add a per-cpu variable to indecate sei is processing
  APEI: GHES: reserve a virtual page for SEI context
  arm64: KVM: add guest SEI support
  arm64: RAS: add ras extension runtime detection
  arm64: exception: handle asynchronous SError interrupt

 arch/arm64/Kconfig   |  16 +++
 arch/arm64/include/asm/cpucaps.h |   3 +-
 arch/arm64/include/asm/esr.h |  14 +++
 arch/arm64/include/asm/sysreg.h  |   2 +
 arch/arm64/include/asm/system_misc.h |   1 +
 arch/arm64/kernel/cpufeature.c   |  11 ++
 arch/arm64/kernel/entry.S|  70 ++-
 arch/arm64/kernel/traps.c| 217 +++
 arch/arm64/kvm/handle_exit.c |  22 +++-
 drivers/acpi/apei/Kconfig|  14 +++
 drivers/acpi/apei/ghes.c | 166 +++
 include/acpi/ghes.h  |   3 +
 include/linux/cper.h |   5 +
 include/ras/ras_event.h  |  87 ++
 14 files changed, 575 insertions(+), 56 deletions(-)

-- 
1.8.3.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH v3 6/8] arm64: RAS: add ras extension runtime detection

2017-03-30 Thread Xie XiuQi
According to <> document, we add RAS extension
feature runtime detection, which would be used for error recovery
in the future.

Signed-off-by: Xie XiuQi 
Reviewed-by: Kefeng Wang 
---
 arch/arm64/include/asm/cpucaps.h |  3 ++-
 arch/arm64/include/asm/sysreg.h  |  2 ++
 arch/arm64/kernel/cpufeature.c   | 11 +++
 3 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index fb78a5d..3847cf8 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -37,7 +37,8 @@
 #define ARM64_HAS_NO_FPSIMD16
 #define ARM64_WORKAROUND_REPEAT_TLBI   17
 #define ARM64_WORKAROUND_QCOM_FALKOR_E1003 18
+#define ARM64_HAS_RAS_EXTN 19
 
-#define ARM64_NCAPS19
+#define ARM64_NCAPS20
 
 #endif /* __ASM_CPUCAPS_H */
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index ac24b6e..32964c7 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -157,6 +157,7 @@
 #define ID_AA64ISAR0_AES_SHIFT 4
 
 /* id_aa64pfr0 */
+#define ID_AA64PFR0_RAS_SHIFT  28
 #define ID_AA64PFR0_GIC_SHIFT  24
 #define ID_AA64PFR0_ASIMD_SHIFT20
 #define ID_AA64PFR0_FP_SHIFT   16
@@ -165,6 +166,7 @@
 #define ID_AA64PFR0_EL1_SHIFT  4
 #define ID_AA64PFR0_EL0_SHIFT  0
 
+#define ID_AA64PFR0_RAS_V1 0x1
 #define ID_AA64PFR0_FP_NI  0xf
 #define ID_AA64PFR0_FP_SUPPORTED   0x0
 #define ID_AA64PFR0_ASIMD_NI   0xf
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index abda8e8..b0fb81e 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -98,6 +98,7 @@
 };
 
 static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = {
+   ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 
ID_AA64PFR0_RAS_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 
ID_AA64PFR0_GIC_SHIFT, 4, 0),
S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 
ID_AA64PFR0_ASIMD_SHIFT, 4, ID_AA64PFR0_ASIMD_NI),
S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 
ID_AA64PFR0_FP_SHIFT, 4, ID_AA64PFR0_FP_NI),
@@ -860,6 +861,16 @@ static bool has_no_fpsimd(const struct 
arm64_cpu_capabilities *entry, int __unus
.min_field_value = 0,
.matches = has_no_fpsimd,
},
+   {
+   .desc = "ARM64 RAS Extension Support",
+   .capability = ARM64_HAS_RAS_EXTN,
+   .def_scope = SCOPE_SYSTEM,
+   .matches = has_cpuid_feature,
+   .sys_reg = SYS_ID_AA64PFR0_EL1,
+   .sign = FTR_UNSIGNED,
+   .field_pos = ID_AA64PFR0_RAS_SHIFT,
+   .min_field_value = ID_AA64PFR0_RAS_V1,
+   },
{},
 };
 
-- 
1.8.3.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH v3 5/8] arm64: KVM: add guest SEI support

2017-03-30 Thread Xie XiuQi
Add ghes handling for SEI so that the host kernel could parse and
report detailed error information for SEI which occur in the guest
kernel.

If there were no CPER records, (or the system doesn't support SEI as a GHES
notification mechanism), then yes we should still call kvm_inject_vabt().

Signed-off-by: Xie XiuQi 
---
 arch/arm64/include/asm/system_misc.h |  1 +
 arch/arm64/kernel/traps.c| 14 ++
 arch/arm64/kvm/handle_exit.c | 22 --
 3 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/system_misc.h 
b/arch/arm64/include/asm/system_misc.h
index 5b2cecd..d68d61f 100644
--- a/arch/arm64/include/asm/system_misc.h
+++ b/arch/arm64/include/asm/system_misc.h
@@ -59,5 +59,6 @@ void hook_debug_fault_code(int nr, int (*fn)(unsigned long, 
unsigned int,
 #endif /* __ASSEMBLY__ */
 
 int handle_guest_sea(unsigned long addr, unsigned int esr);
+int handle_guest_sei(unsigned long addr, unsigned int esr);
 
 #endif /* __ASM_SYSTEM_MISC_H */
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 955dc8c..b6d6727 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -618,6 +618,20 @@ const char *esr_get_class_string(u32 esr)
 DEFINE_PER_CPU(int, sei_in_process);
 
 /*
+ * Handle asynchronous SError interrupt that occur in a guest kernel.
+ */
+int handle_guest_sei(unsigned long addr, unsigned int esr)
+{
+int ret = -ENOENT;
+
+if(IS_ENABLED(CONFIG_ACPI_APEI_SEI)) {
+ret = ghes_notify_sei();
+}
+
+return ret;
+}
+
+/*
  * bad_mode handles the impossible case in the exception vector. This is always
  * fatal.
  */
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index fa1b18e..c89d83a 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define CREATE_TRACE_POINTS
 #include "trace.h"
@@ -177,6 +178,23 @@ static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu 
*vcpu)
return arm_exit_handlers[hsr_ec];
 }
 
+static int kvm_handle_guest_sei(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+   unsigned long fault_ipa = kvm_vcpu_get_fault_ipa(vcpu);
+
+   if (handle_guest_sei((unsigned long)fault_ipa,
+   kvm_vcpu_get_hsr(vcpu))) {
+   kvm_err("Failed to handle guest SEI, FSC: EC=%#x xFSC=%#lx 
ESR_EL2=%#lx\n",
+   kvm_vcpu_trap_get_class(vcpu),
+   (unsigned long)kvm_vcpu_trap_get_fault(vcpu),
+   (unsigned long)kvm_vcpu_get_hsr(vcpu));
+
+   kvm_inject_vabt(vcpu);
+   }
+
+   return 0;
+}
+
 /*
  * Return > 0 to return to guest, < 0 on error, 0 (and set exit_reason) on
  * proper exit to userspace.
@@ -200,7 +218,7 @@ int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
*vcpu_pc(vcpu) -= adj;
}
 
-   kvm_inject_vabt(vcpu);
+   kvm_handle_guest_sei(vcpu, run);
return 1;
}
 
@@ -210,7 +228,7 @@ int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
case ARM_EXCEPTION_IRQ:
return 1;
case ARM_EXCEPTION_EL1_SERROR:
-   kvm_inject_vabt(vcpu);
+   kvm_handle_guest_sei(vcpu, run);
return 1;
case ARM_EXCEPTION_TRAP:
/*
-- 
1.8.3.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH v3 4/8] APEI: GHES: reserve a virtual page for SEI context

2017-03-30 Thread Xie XiuQi
On arm64 platform, SEI may interrupt code which had interrupts masked.
But SEI could be masked, so it's not treated as NMI, however SEA is
treated as NMI.

So, the  memory area used to transfer hardware error information from
BIOS to Linux can be determined only in NMI, SEI(arm64), IRQ or timer
handler.

In this patch, we add a virtual page for SEI context.

Signed-off-by: Xie XiuQi 
---
 drivers/acpi/apei/ghes.c | 98 +++-
 1 file changed, 47 insertions(+), 51 deletions(-)

diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 045d101..b1f9b1f 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -108,26 +108,33 @@
 
 /*
  * Because the memory area used to transfer hardware error information
- * from BIOS to Linux can be determined only in NMI, IRQ or timer
- * handler, but general ioremap can not be used in atomic context, so
- * a special version of atomic ioremap is implemented for that.
+ * from BIOS to Linux can be determined only in NMI, SEI (ARM64), IRQ or
+ * timer handler, but general ioremap can not be used in atomic context,
+ * so a special version of atomic ioremap is implemented for that.
  */
 
 /*
- * Two virtual pages are used, one for IRQ/PROCESS context, the other for
- * NMI context (optionally).
+ * 3 virtual pages are used, one for IRQ/PROCESS context, one for SEI
+ * (on ARM64 platform), and the other for NMI context (optionally).
  */
+#ifdef CONFIG_ACPI_APEI_SEI
+#define GHES_IOREMAP_PAGES   3
+#define GHES_IOREMAP_SEI_PAGE(base)((base) + PAGE_SIZE*2)
+#else
 #define GHES_IOREMAP_PAGES   2
+#endif
+
 #define GHES_IOREMAP_IRQ_PAGE(base)(base)
 #define GHES_IOREMAP_NMI_PAGE(base)((base) + PAGE_SIZE)
 
 /* virtual memory area for atomic ioremap */
 static struct vm_struct *ghes_ioremap_area;
 /*
- * These 2 spinlock is used to prevent atomic ioremap virtual memory
+ * These 3 spinlock is used to prevent atomic ioremap virtual memory
  * area from being mapped simultaneously.
  */
 static DEFINE_RAW_SPINLOCK(ghes_ioremap_lock_nmi);
+static DEFINE_SPINLOCK(ghes_ioremap_lock_sei);
 static DEFINE_SPINLOCK(ghes_ioremap_lock_irq);
 
 static struct gen_pool *ghes_estatus_pool;
@@ -155,54 +162,55 @@ static void ghes_ioremap_exit(void)
free_vm_area(ghes_ioremap_area);
 }
 
-static void __iomem *ghes_ioremap_pfn_nmi(u64 pfn)
+static void __iomem *ghes_ioremap_pfn(u64 pfn)
 {
-   unsigned long vaddr;
+   unsigned long vaddr, flags = 0;
phys_addr_t paddr;
pgprot_t prot;
 
-   vaddr = (unsigned long)GHES_IOREMAP_NMI_PAGE(ghes_ioremap_area->addr);
-
-   paddr = pfn << PAGE_SHIFT;
-   prot = arch_apei_get_mem_attribute(paddr);
-   ioremap_page_range(vaddr, vaddr + PAGE_SIZE, paddr, prot);
-
-   return (void __iomem *)vaddr;
-}
-
-static void __iomem *ghes_ioremap_pfn_irq(u64 pfn)
-{
-   unsigned long vaddr, paddr;
-   pgprot_t prot;
-
-   vaddr = (unsigned long)GHES_IOREMAP_IRQ_PAGE(ghes_ioremap_area->addr);
+   if (in_nmi()) {
+   raw_spin_lock(&ghes_ioremap_lock_nmi);
+   vaddr = (unsigned 
long)GHES_IOREMAP_NMI_PAGE(ghes_ioremap_area->addr);
+   } else if (this_cpu_read(sei_in_process)) {
+   spin_lock_irqsave(&ghes_ioremap_lock_sei, flags);
+   vaddr = (unsigned 
long)GHES_IOREMAP_SEI_PAGE(ghes_ioremap_area->addr);
+   } else {
+   spin_lock_irqsave(&ghes_ioremap_lock_irq, flags);
+   vaddr = (unsigned 
long)GHES_IOREMAP_IRQ_PAGE(ghes_ioremap_area->addr);
+   }
 
paddr = pfn << PAGE_SHIFT;
prot = arch_apei_get_mem_attribute(paddr);
-
ioremap_page_range(vaddr, vaddr + PAGE_SIZE, paddr, prot);
 
return (void __iomem *)vaddr;
 }
 
-static void ghes_iounmap_nmi(void __iomem *vaddr_ptr)
+static void ghes_iounmap(void __iomem *vaddr_ptr)
 {
unsigned long vaddr = (unsigned long __force)vaddr_ptr;
void *base = ghes_ioremap_area->addr;
+   unsigned long page, flags = 0;
+
+   if (in_nmi()) {
+   page = (unsigned long)GHES_IOREMAP_NMI_PAGE(base);
+   } else if (this_cpu_read(sei_in_process)) {
+   page = (unsigned long)GHES_IOREMAP_SEI_PAGE(base);
+   } else {
+   page = (unsigned long)GHES_IOREMAP_IRQ_PAGE(base);
+   }
 
-   BUG_ON(vaddr != (unsigned long)GHES_IOREMAP_NMI_PAGE(base));
+   BUG_ON(vaddr != page);
unmap_kernel_range_noflush(vaddr, PAGE_SIZE);
arch_apei_flush_tlb_one(vaddr);
-}
-
-static void ghes_iounmap_irq(void __iomem *vaddr_ptr)
-{
-   unsigned long vaddr = (unsigned long __force)vaddr_ptr;
-   void *base = ghes_ioremap_area->addr;
 
-   BUG_ON(vaddr != (unsigned long)GHES_IOREMAP_IRQ_PAGE(base));
-   unmap_kernel_range_noflush(vaddr, PAGE_SIZE);
-   arch_apei_flush_tlb_one(vaddr);
+   if (in_nmi()) {
+   raw_spin

[PATCH v3 0/8] arm64: acpi: apei: handle SEI notification type for ARMv8

2017-03-30 Thread Xie XiuQi
ARM APEI extension proposal added SEI (asynchronous SError interrupt)
notification type for ARMv8.

Add a new GHES error source handling function for SEI. In firmware
first mode, if an error source's notification type is SEI. Then GHES
could parse and report the detail error information.

In firmware first mode, we could assume:
1) The ghes for sei is a global table, firmware should report one sei at a time.
2) SEI is masked while exception is processing
3) SEI may interrupt while irq handler is running 
4) SEA may interrupt while SEI handler is running

So, the memory area used to transfer hardware error information from
BIOS to Linux can be determined only in NMI, SEI(arm64), IRQ or timer
handler. We add a virtual page for SEI context.

Error Synchronization Barrier (ESB; part of the ARMv8.2 Extensions)
is used to synchronize Unrecoverable errors. That is, containable errors
architecturally consumed by the PE and not silently propagated.

With ESB it is generally possible to isolate an unrecoverable error
between two ESB instructions. So, it's possible to recovery from
unrecoverable errors reported by asynchronous SError interrupt.

Since SEI is asynchronous, a SEI generated on user process may propagate
to another user process via shared memory, which may cause unrecoverable.
We have a idea which only recover sei from user process which has no
writable shared memory.

The idea is still in the discussion, any comments is welcome.

This series is based on Tyler's series "[PATCH V13 00/10] Add UEFI 2.6 and ACPI 
6.1 updates
for RAS on ARM64" and the latest mainline.

v3: add ARM processor error information trace event
add a per-cpu variable to indecate sei is processing
remove nmi_{enter/exit} protection for ghes_notify_sei()
reserve a virtual page for processing ghes table in SEI context
don't always inject vabt for sei
serprate do_sei from bad_mode
add esb which make recovery from sei possible
add an idea to recovery from sei for shared memory process

v2: add kvm guest SEI notification support
add nmi_{entry, exit} to protect ghes_notify_sei

https://lkml.org/lkml/2017/3/7/962
https://lkml.org/lkml/2017/3/3/189

Wang Xiongfeng (1):
  arm64: exception: check shared writable page in SEI handler

Xie XiuQi (7):
  trace: ras: add ARM processor error information trace event
  acpi: apei: handle SEI notification type for ARMv8
  arm64: apei: add a per-cpu variable to indecate sei is processing
  APEI: GHES: reserve a virtual page for SEI context
  arm64: KVM: add guest SEI support
  arm64: RAS: add ras extension runtime detection
  arm64: exception: handle asynchronous SError interrupt

 arch/arm64/Kconfig   |  16 +++
 arch/arm64/include/asm/cpucaps.h |   3 +-
 arch/arm64/include/asm/esr.h |  14 +++
 arch/arm64/include/asm/sysreg.h  |   2 +
 arch/arm64/include/asm/system_misc.h |   1 +
 arch/arm64/kernel/cpufeature.c   |  11 ++
 arch/arm64/kernel/entry.S|  70 ++-
 arch/arm64/kernel/traps.c| 217 +++
 arch/arm64/kvm/handle_exit.c |  22 +++-
 drivers/acpi/apei/Kconfig|  14 +++
 drivers/acpi/apei/ghes.c | 166 +++
 include/acpi/ghes.h  |   3 +
 include/linux/cper.h |   5 +
 include/ras/ras_event.h  |  87 ++
 14 files changed, 575 insertions(+), 56 deletions(-)

-- 
1.8.3.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH V11 10/10] arm/arm64: KVM: add guest SEA support

2017-03-22 Thread Xie XiuQi
Hi James,

On 2017/3/22 19:14, James Morse wrote:
> Hi Wang Xiongfeng,
> 
> On 22/03/17 02:46, Xiongfeng Wang wrote:
>>> Guests are a special case as QEMU may never access the faulty memory 
>>> itself, so
>>> it won't receive the 'late' signal. It looks like ARM/arm64 KVM lacks 
>>> support
>>> for KVM_PFN_ERR_HWPOISON which sends SIGBUS from KVM's fault-handling code. 
>>> I
>>> have patches to add support for this which I intend to send at rc1.
>>>
>>> [0] suggests 'KVM qemu' sets these MCE flags to take the 'early' path, but 
>>> given
>>> x86s KVM_PFN_ERR_HWPOISON, this may be out of date.
>>>
>>>
>>> Either way, once QEMU gets a signal indicating the virtual address, it can
>>> generate its own APEI CPER records and use the KVM APIs to mock up an
>>> Synchronous External Abort, (or inject an IRQ or run the vcpu waiting for 
>>> the
>>> guest's polling thread to come round, whichever was described to the guest 
>>> via
>>> the HEST/GHES tables).
>>>
>>
>> I have another confusion about the SIGBUS signal. Can QEMU always get a 
>> SIGBUS when needed.
>> I know one circumstance which will send SIGBUS. The 
>> ghes_handle_memory_failure() in
>> ghes_do_proc() will send SIGBUS to QEMU, but this only happens when there 
>> exists memory section
>> in ghes, that is the section type is CPER_SEC_PLATFORM_MEM.
>> Suppose this case, an load  error in guest application causes an SEA, and 
>> the firmware take it.
>> The firmware begin to scan the error record and fill the ghes. But the error 
>> record in memory node
>> has been read by other handler.
> 
> (this looks like a race)
> 
>> The firmware won't add memory section in ghes, so 
>> ghes_handle_memory_failure() won't be called.
> 
> I think this would be a firmware bug. Firmware can reserve as much memory as 
> it
> needs for writing CPER records, there should not be a case where 'the memory' 
> is
> currently being processed by another handler.

I have a question here:
Consider this case, the memory controller first detected a memory error,
but it has not been consumed. So it will not generate the SEA. Memory error
may be reported to the OS by IRQ with MEM section in CPER record; and
after for a while, the error data was loaded into the cache and consumed,
when the SEA is generated. Is it possible only processor section, and no
MEM section in CPER record?

Obviously there are two different GHES above, one for SEA and another for 
IRQ/GSIV.
Could we assume that there is mem section in the SEA ghes table?

> 
> The memory firmware uses to write CPER records too shouldn't be published to 
> the
> OS until it has finished. Once firmware has finished writing the CPER records 
> it
> can update the memory pointed to by GHES->ErrorStatusAddress with the location
> of the CPER records and invoke the Notification method for this GHES. (SEI, 
> SEA,
> IRQ etc). We should always get a complete set of CPER records to describe the 
> error.
> 

Does it mean that the BIOS has the responsibility to ensure that the GHES table 
has a
complete error info, including memory, bus, tlb, cache and other related error 
info?

-- 
Thanks,
Xie XiuQi

> It firmware uses GHESv2 it can get an 'ack' write from APEI once it has 
> finished
> processing the records. Once it gets this firmware knows it can re-use the 
> memory.
> 
> (Obviously each GHES entry can only process one error at a time. Firmware 
> should
> either handle this, or have one entry for each Error Source that can happen
> independently)
> 
> 
>> I mean that we may not rely on ghes_handle_memory_failure() to send SIGBUS 
>> to QEMU. Whether we should
>> add some other code to send SIGBUS in handle_guest_abort(). I don't know 
>> whether the ARM/arm64
>>  KVM_PFN_ERR_HWPOISON you mentioned above will cover all the cases.
> 
> The SIGBUS routine is part of the kernel's recovery method for memory errors. 
> It
> should cover all the errors reported with this CPER_SEC_PLATFORM_MEM.
> 
> Back to the race you describe. It shouldn't matter if one CPU processes an 
> error
> for guest memory while a vcpu is running on another. This may happen if the
> error was detected by DRAM's background scrub.
> If we don't treat KVM/Qemu as anything special the memory_failure()->SIGBUS 
> path
> will happen regardless of whether the fault interrupted the guest or not.
> 
> 
> There are other types of error such as PCIe, CPU, BUS error etc. If it's
> possible to recover from these we may need additional code in the kernel. This
> shouldn't necessarily treat KVM as a special case.
> 
> 
> Thanks,
> 
> James
> 
> 
> .
> 


___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH V13 09/10] trace, ras: add ARM processor error trace event

2017-03-21 Thread Xie XiuQi
Reviewed-by: Xie XiuQi 

On 2017/3/22 6:47, Tyler Baicar wrote:
> Currently there are trace events for the various RAS
> errors with the exception of ARM processor type errors.
> Add a new trace event for such errors so that the user
> will know when they occur. These trace events are
> consistent with the ARM processor error section type
> defined in UEFI 2.6 spec section N.2.4.4.
> 
> Signed-off-by: Tyler Baicar 
> Acked-by: Steven Rostedt 
> ---
>  drivers/acpi/apei/ghes.c|  8 +++-
>  drivers/firmware/efi/cper.c |  1 +
>  drivers/ras/ras.c   |  1 +
>  include/ras/ras_event.h | 45 
> +
>  4 files changed, 54 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
> index 3ecbacc..230b095 100644
> --- a/drivers/acpi/apei/ghes.c
> +++ b/drivers/acpi/apei/ghes.c
> @@ -515,7 +515,13 @@ static void ghes_do_proc(struct ghes *ghes,
>   }
>  #endif
>  #ifdef CONFIG_RAS
> - else if (trace_unknown_sec_event_enabled()) {
> + else if (!uuid_le_cmp(sec_type, CPER_SEC_PROC_ARM) &&
> +  trace_arm_event_enabled()) {
> + struct cper_sec_proc_arm *arm_err;
> +
> + arm_err = acpi_hest_generic_data_payload(gdata);
> + trace_arm_event(arm_err);
> + } else if (trace_unknown_sec_event_enabled()) {
>   void *unknown_err = 
> acpi_hest_generic_data_payload(gdata);
>   trace_unknown_sec_event(&sec_type,
>   fru_id, fru_text, sec_sev,
> diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
> index d263bc8..37a39af 100644
> --- a/drivers/firmware/efi/cper.c
> +++ b/drivers/firmware/efi/cper.c
> @@ -35,6 +35,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  #define INDENT_SP" "
>  
> diff --git a/drivers/ras/ras.c b/drivers/ras/ras.c
> index fb2500b..8ba5a94 100644
> --- a/drivers/ras/ras.c
> +++ b/drivers/ras/ras.c
> @@ -28,3 +28,4 @@ static int __init ras_init(void)
>  #endif
>  EXPORT_TRACEPOINT_SYMBOL_GPL(mc_event);
>  EXPORT_TRACEPOINT_SYMBOL_GPL(unknown_sec_event);
> +EXPORT_TRACEPOINT_SYMBOL_GPL(arm_event);
> diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h
> index 5861b6f..13befad 100644
> --- a/include/ras/ras_event.h
> +++ b/include/ras/ras_event.h
> @@ -162,6 +162,51 @@
>  );
>  
>  /*
> + * ARM Processor Events Report
> + *
> + * This event is generated when hardware detects an ARM processor error
> + * has occurred. UEFI 2.6 spec section N.2.4.4.
> + */
> +TRACE_EVENT(arm_event,
> +
> + TP_PROTO(const struct cper_sec_proc_arm *proc),
> +
> + TP_ARGS(proc),
> +
> + TP_STRUCT__entry(
> + __field(u64, mpidr)
> + __field(u64, midr)
> + __field(u32, running_state)
> + __field(u32, psci_state)
> + __field(u8, affinity)
> + ),
> +
> + TP_fast_assign(
> + if (proc->validation_bits & CPER_ARM_VALID_AFFINITY_LEVEL)
> + __entry->affinity = proc->affinity_level;
> + else
> + __entry->affinity = ~0;
> + if (proc->validation_bits & CPER_ARM_VALID_MPIDR)
> + __entry->mpidr = proc->mpidr;
> + else
> + __entry->mpidr = 0ULL;
> + __entry->midr = proc->midr;
> + if (proc->validation_bits & CPER_ARM_VALID_RUNNING_STATE) {
> + __entry->running_state = proc->running_state;
> + __entry->psci_state = proc->psci_state;
> + } else {
> + __entry->running_state = ~0;
> + __entry->psci_state = ~0;
> + }
> + ),
> +
> + TP_printk("affinity level: %d; MPIDR: %016llx; MIDR: %016llx; "
> +   "running state: %d; PSCI state: %d",
> +   __entry->affinity, __entry->mpidr, __entry->midr,
> +   __entry->running_state, __entry->psci_state)
> +);
> +
> +/*
>   * Unknown Section Report
>   *
>   * This event is generated when hardware detected a hardware
> 

-- 
Thanks,
Xie XiuQi

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH V12 09/10] trace, ras: add ARM processor error trace event

2017-03-14 Thread Xie XiuQi
Hi Steven,

Thanks for you comments. As your suggestion, I've changed it in v2.

>From c29c14c3b960f55beb4c4b22b7aced64fa7daf9a Mon Sep 17 00:00:00 2001
From: Xie XiuQi 
Date: Mon, 13 Mar 2017 15:46:06 +0800
Subject: [PATCH v2] trace: ras: add ARM processor error information trace event

Add a new trace event for ARM processor error information, so that
the user will know what error occurred. With this information the
user may take appropriate action.

These trace events are consistent with the ARM processor error
information table which defined in UEFI 2.6 spec section N.2.4.4.1.

---
v2: add trace enabled condition as Steven's suggestion.
fix a typo.

Signed-off-by: Xie XiuQi 
---
 drivers/acpi/apei/ghes.c | 10 ++
 include/linux/cper.h |  5 +++
 include/ras/ras_event.h  | 87 
 3 files changed, 102 insertions(+)

diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 251d7e0..bcb8160 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -518,9 +518,19 @@ static void ghes_do_proc(struct ghes *ghes,
else if (!uuid_le_cmp(sec_type, CPER_SEC_PROC_ARM) &&
 trace_arm_event_enabled()) {
struct cper_sec_proc_arm *arm_err;
+   struct cper_arm_err_info *err_info;
+   int i;

arm_err = acpi_hest_generic_data_payload(gdata);
trace_arm_event(arm_err);
+
+   if (trace_arm_proc_err_enabled()) {
+   err_info = (struct cper_arm_err_info *)(arm_err 
+ 1);
+   for (i = 0; i < arm_err->err_info_num; i++) {
+   trace_arm_proc_err(err_info);
+   err_info += 1;
+   }
+   }
} else if (trace_unknown_sec_event_enabled()) {
void *unknown_err = 
acpi_hest_generic_data_payload(gdata);
trace_unknown_sec_event(&sec_type,
diff --git a/include/linux/cper.h b/include/linux/cper.h
index 85450f3..0cae900 100644
--- a/include/linux/cper.h
+++ b/include/linux/cper.h
@@ -270,6 +270,11 @@ enum {
 #define CPER_ARM_INFO_VALID_VIRT_ADDR  0x0008
 #define CPER_ARM_INFO_VALID_PHYSICAL_ADDR  0x0010

+#define CPER_ARM_INFO_TYPE_CACHE   0
+#define CPER_ARM_INFO_TYPE_TLB 1
+#define CPER_ARM_INFO_TYPE_BUS 2
+#define CPER_ARM_INFO_TYPE_UARCH   3
+
 #define CPER_ARM_INFO_FLAGS_FIRST  0x0001
 #define CPER_ARM_INFO_FLAGS_LAST   0x0002
 #define CPER_ARM_INFO_FLAGS_PROPAGATED 0x0004
diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h
index b36db48..0f9f46e 100644
--- a/include/ras/ras_event.h
+++ b/include/ras/ras_event.h
@@ -195,6 +195,93 @@
  __entry->running_state, __entry->psci_state)
 );

+#define ARM_PROC_ERR_TYPE  \
+   EM ( CPER_ARM_INFO_TYPE_CACHE, "cache error" )  \
+   EM ( CPER_ARM_INFO_TYPE_TLB,  "TLB error" ) \
+   EM ( CPER_ARM_INFO_TYPE_BUS, "bus error" )  \
+   EMe ( CPER_ARM_INFO_TYPE_UARCH, "micro-architectural error" )
+
+#define ARM_PROC_ERR_FLAGS \
+   EM ( CPER_ARM_INFO_FLAGS_FIRST, "First error captured" )\
+   EM ( CPER_ARM_INFO_FLAGS_LAST,  "Last error captured" ) \
+   EM ( CPER_ARM_INFO_FLAGS_PROPAGATED, "Propagated" ) \
+   EMe ( CPER_ARM_INFO_FLAGS_OVERFLOW, "Overflow" )
+
+/*
+ * First define the enums in MM_ACTION_RESULT to be exported to userspace
+ * via TRACE_DEFINE_ENUM().
+ */
+#undef EM
+#undef EMe
+#define EM(a, b) TRACE_DEFINE_ENUM(a);
+#define EMe(a, b)  TRACE_DEFINE_ENUM(a);
+
+ARM_PROC_ERR_TYPE
+ARM_PROC_ERR_FLAGS
+
+/*
+ * Now redefine the EM() and EMe() macros to map the enums to the strings
+ * that will be printed in the output.
+ */
+#undef EM
+#undef EMe
+#define EM(a, b)   { a, b },
+#define EMe(a, b)  { a, b }
+
+TRACE_EVENT(arm_proc_err,
+
+   TP_PROTO(const struct cper_arm_err_info *err),
+
+   TP_ARGS(err),
+
+   TP_STRUCT__entry(
+   __field(u8, type)
+   __field(u16, multiple_error)
+   __field(u8, flags)
+   __field(u64, error_info)
+   __field(u64, virt_fault_addr)
+   __field(u64, physical_fault_addr)
+   ),
+
+   TP_fast_assign(
+   __entry->type = err->type;
+
+   if (err->validation_bits & CPER_ARM_INFO_VALID_MULTI_ERR)
+   __entry->multiple_error = err->multiple_error;
+   else
+   __entry->multiple_error = ~0;
+   
+   if (err->validation_bits &

Re: [PATCH V12 09/10] trace, ras: add ARM processor error trace event

2017-03-13 Thread Xie XiuQi
Hi Baicar Tyler,

On 2017/3/13 10:31, Xie XiuQi wrote:
> Hi Baicar Tyler,
> 
> On 2017/3/11 2:23, Baicar, Tyler wrote:
>> Hello Xie XiuQi,
>>
>>
>> On 3/9/2017 2:41 AM, Xie XiuQi wrote:
>>> On 2017/3/7 4:45, Tyler Baicar wrote:
>>>> Currently there are trace events for the various RAS
>>>> errors with the exception of ARM processor type errors.
>>>> Add a new trace event for such errors so that the user
>>>> will know when they occur. These trace events are
>>>> consistent with the ARM processor error section type
>>>> defined in UEFI 2.6 spec section N.2.4.4.
>>>>
>>>> Signed-off-by: Tyler Baicar 
>>>> Acked-by: Steven Rostedt 
>>>> ---
>>>>   drivers/acpi/apei/ghes.c|  8 +++-
>>>>   drivers/firmware/efi/cper.c |  1 +
>>>>   drivers/ras/ras.c   |  1 +
>>>>   include/ras/ras_event.h | 34 ++
>>>>   4 files changed, 43 insertions(+), 1 deletion(-)
>>
>>>> diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h
>>>> index 5861b6f..b36db48 100644
>>>> --- a/include/ras/ras_event.h
>>>> +++ b/include/ras/ras_event.h
>>>> @@ -162,6 +162,40 @@
>>>>   );
>>>> /*
>>>> + * ARM Processor Events Report
>>>> + *
>>>> + * This event is generated when hardware detects an ARM processor error
>>>> + * has occurred. UEFI 2.6 spec section N.2.4.4.
>>>> + */
>>>> +TRACE_EVENT(arm_event,
>>>> +
>>>> +TP_PROTO(const struct cper_sec_proc_arm *proc),
>>>> +
>>>> +TP_ARGS(proc),
>>>> +
>>>> +TP_STRUCT__entry(
>>>> +__field(u64, mpidr)
>>>> +__field(u64, midr)
>>>> +__field(u32, running_state)
>>>> +__field(u32, psci_state)
>>>> +__field(u8, affinity)
>>>> +),
>>>> +
>>>> +TP_fast_assign(
>>>> +__entry->affinity = proc->affinity_level;
>>>> +__entry->mpidr = proc->mpidr;
>>>> +__entry->midr = proc->midr;
>>>> +__entry->running_state = proc->running_state;
>>>> +__entry->psci_state = proc->psci_state;
>>>> +),
>>>> +
>>>> +TP_printk("affinity level: %d; MPIDR: %016llx; MIDR: %016llx; "
>>>> +  "running state: %d; PSCI state: %d",
>>>> +  __entry->affinity, __entry->mpidr, __entry->midr,
>>>> +  __entry->running_state, __entry->psci_state)
>>>> +);
>>>> +
>>> I think these fields are not enough, we need also export arm processor error
>>> information (UEFI 2.6 spec section N.2.4.4.1), or at least the error type,
>>> address, etc. So that the userspace (such as rasdaemon tool) could know what
>>> error occurred.
>>
>> This is something I am planning on adding in later. It is not clear to me 
>> how to
>> actually do this at this point. If you look at the spec, there is not a 
>> single
>> error information structure. There is at least one, but possibly a lot. 
>> There is
>> also an unknown amount of context information structures. In "Table 260. ARM 
>> Processor
>> Error Section" there are ERR_INFO_NUM and CONTEXT_INFO_NUM which give the 
>> number of these
>> structures. I think there will need to be separate trace events added in for 
>> each of
>> these structures because I don't think there is a way to have variable 
>> amounts of
>> structures inside of a trace event.

I have a patch below to add a trace event to expose arm processor error 
information
to user space. Would you take it to your series or later series if possible.
Any comments is welcome.

This patch is just compile OK. I have no arm box for testing just now.
Any one who can help to test it is very grateful.

Thanks.

>From e591570eecc6cd70e18d8f8ae75534b55a22f7ba Mon Sep 17 00:00:00 2001
From: Xie XiuQi 
Date: Mon, 13 Mar 2017 15:46:06 +0800
Subject: [PATCH] trace: ras: add ARM processor error information trace event

Add a new trace event for ARM processor error information, so that
the user will know what error occurred. With this information the
user may take appropriate action.

These trace events are consistent with the ARM processor error
information table which defined in UEFI 2.6 spec section N.2.4.4.1.

Signed-off-by: Xie XiuQi 
---
 drivers/acpi

Re: [PATCH V12 09/10] trace, ras: add ARM processor error trace event

2017-03-12 Thread Xie XiuQi
Hi Baicar Tyler,

On 2017/3/11 2:23, Baicar, Tyler wrote:
> Hello Xie XiuQi,
> 
> 
> On 3/9/2017 2:41 AM, Xie XiuQi wrote:
>> On 2017/3/7 4:45, Tyler Baicar wrote:
>>> Currently there are trace events for the various RAS
>>> errors with the exception of ARM processor type errors.
>>> Add a new trace event for such errors so that the user
>>> will know when they occur. These trace events are
>>> consistent with the ARM processor error section type
>>> defined in UEFI 2.6 spec section N.2.4.4.
>>>
>>> Signed-off-by: Tyler Baicar 
>>> Acked-by: Steven Rostedt 
>>> ---
>>>   drivers/acpi/apei/ghes.c|  8 +++-
>>>   drivers/firmware/efi/cper.c |  1 +
>>>   drivers/ras/ras.c   |  1 +
>>>   include/ras/ras_event.h | 34 ++
>>>   4 files changed, 43 insertions(+), 1 deletion(-)
> 
>>> diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h
>>> index 5861b6f..b36db48 100644
>>> --- a/include/ras/ras_event.h
>>> +++ b/include/ras/ras_event.h
>>> @@ -162,6 +162,40 @@
>>>   );
>>> /*
>>> + * ARM Processor Events Report
>>> + *
>>> + * This event is generated when hardware detects an ARM processor error
>>> + * has occurred. UEFI 2.6 spec section N.2.4.4.
>>> + */
>>> +TRACE_EVENT(arm_event,
>>> +
>>> +TP_PROTO(const struct cper_sec_proc_arm *proc),
>>> +
>>> +TP_ARGS(proc),
>>> +
>>> +TP_STRUCT__entry(
>>> +__field(u64, mpidr)
>>> +__field(u64, midr)
>>> +__field(u32, running_state)
>>> +__field(u32, psci_state)
>>> +__field(u8, affinity)
>>> +),
>>> +
>>> +TP_fast_assign(
>>> +__entry->affinity = proc->affinity_level;
>>> +__entry->mpidr = proc->mpidr;
>>> +__entry->midr = proc->midr;
>>> +__entry->running_state = proc->running_state;
>>> +__entry->psci_state = proc->psci_state;
>>> +),
>>> +
>>> +TP_printk("affinity level: %d; MPIDR: %016llx; MIDR: %016llx; "
>>> +  "running state: %d; PSCI state: %d",
>>> +  __entry->affinity, __entry->mpidr, __entry->midr,
>>> +  __entry->running_state, __entry->psci_state)
>>> +);
>>> +
>> I think these fields are not enough, we need also export arm processor error
>> information (UEFI 2.6 spec section N.2.4.4.1), or at least the error type,
>> address, etc. So that the userspace (such as rasdaemon tool) could know what
>> error occurred.
>
> This is something I am planning on adding in later. It is not clear to me how 
> to
> actually do this at this point. If you look at the spec, there is not a single
> error information structure. There is at least one, but possibly a lot. There 
> is
> also an unknown amount of context information structures. In "Table 260. ARM 
> Processor
> Error Section" there are ERR_INFO_NUM and CONTEXT_INFO_NUM which give the 
> number of these
> structures. I think there will need to be separate trace events added in for 
> each of
> these structures because I don't think there is a way to have variable 
> amounts of
> structures inside of a trace event.

Yes, I agree.

Additional, cper_sec_proc_arm has validation bit, which indicates whether or 
not each of
the fields is valid in this section. How could we show it in this trace event? 
If the filed
is invalid, we would get a wrong value here.

--
Thanks,
Xie XiuQi

> 
> The ARM processor error section also has a vendor specific error info buffer 
> which will need to be exposed to userspace. This may be something that can 
> reuse the unknown section type trace event or have it's own trace event for.
> 
> Thanks,
> Tyler
> 

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH V12 09/10] trace, ras: add ARM processor error trace event

2017-03-09 Thread Xie XiuQi
Hi Tyler Baicar,

On 2017/3/7 4:45, Tyler Baicar wrote:
> Currently there are trace events for the various RAS
> errors with the exception of ARM processor type errors.
> Add a new trace event for such errors so that the user
> will know when they occur. These trace events are
> consistent with the ARM processor error section type
> defined in UEFI 2.6 spec section N.2.4.4.
> 
> Signed-off-by: Tyler Baicar 
> Acked-by: Steven Rostedt 
> ---
>  drivers/acpi/apei/ghes.c|  8 +++-
>  drivers/firmware/efi/cper.c |  1 +
>  drivers/ras/ras.c   |  1 +
>  include/ras/ras_event.h | 34 ++
>  4 files changed, 43 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
> index 842c0cc..81d7b79 100644
> --- a/drivers/acpi/apei/ghes.c
> +++ b/drivers/acpi/apei/ghes.c
> @@ -514,7 +514,13 @@ static void ghes_do_proc(struct ghes *ghes,
>   }
>  #endif
>  #ifdef CONFIG_RAS
> - else if (trace_unknown_sec_event_enabled()) {
> + else if (!uuid_le_cmp(sec_type, CPER_SEC_PROC_ARM) &&
> +  trace_arm_event_enabled()) {
> + struct cper_sec_proc_arm *arm_err;
> +
> + arm_err = acpi_hest_generic_data_payload(gdata);
> + trace_arm_event(arm_err);
> + } else if (trace_unknown_sec_event_enabled()) {
>   void *unknown_err = 
> acpi_hest_generic_data_payload(gdata);
>   trace_unknown_sec_event(&sec_type,
>   fru_id, fru_text, sec_sev,
> diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
> index 545a6c2..e9fb56a 100644
> --- a/drivers/firmware/efi/cper.c
> +++ b/drivers/firmware/efi/cper.c
> @@ -35,6 +35,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  #define INDENT_SP" "
>  
> diff --git a/drivers/ras/ras.c b/drivers/ras/ras.c
> index fb2500b..8ba5a94 100644
> --- a/drivers/ras/ras.c
> +++ b/drivers/ras/ras.c
> @@ -28,3 +28,4 @@ static int __init ras_init(void)
>  #endif
>  EXPORT_TRACEPOINT_SYMBOL_GPL(mc_event);
>  EXPORT_TRACEPOINT_SYMBOL_GPL(unknown_sec_event);
> +EXPORT_TRACEPOINT_SYMBOL_GPL(arm_event);
> diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h
> index 5861b6f..b36db48 100644
> --- a/include/ras/ras_event.h
> +++ b/include/ras/ras_event.h
> @@ -162,6 +162,40 @@
>  );
>  
>  /*
> + * ARM Processor Events Report
> + *
> + * This event is generated when hardware detects an ARM processor error
> + * has occurred. UEFI 2.6 spec section N.2.4.4.
> + */
> +TRACE_EVENT(arm_event,
> +
> + TP_PROTO(const struct cper_sec_proc_arm *proc),
> +
> + TP_ARGS(proc),
> +
> + TP_STRUCT__entry(
> + __field(u64, mpidr)
> + __field(u64, midr)
> + __field(u32, running_state)
> + __field(u32, psci_state)
> + __field(u8, affinity)
> + ),
> +
> + TP_fast_assign(
> + __entry->affinity = proc->affinity_level;
> + __entry->mpidr = proc->mpidr;
> + __entry->midr = proc->midr;
> + __entry->running_state = proc->running_state;
> + __entry->psci_state = proc->psci_state;
> + ),
> +
> + TP_printk("affinity level: %d; MPIDR: %016llx; MIDR: %016llx; "
> +   "running state: %d; PSCI state: %d",
> +   __entry->affinity, __entry->mpidr, __entry->midr,
> +   __entry->running_state, __entry->psci_state)
> +);
> +

I think these fields are not enough, we need also export arm processor error
information (UEFI 2.6 spec section N.2.4.4.1), or at least the error type,
address, etc. So that the userspace (such as rasdaemon tool) could know what
error occurred.

Thanks,
Xie XiuQi

> +/*
>   * Unknown Section Report
>   *
>   * This event is generated when hardware detected a hardware
> 

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH V11 05/10] acpi: apei: handle SEA notification type for ARMv8

2017-02-28 Thread Xie XiuQi
Hi Tyler,

On 2017/2/22 5:21, Tyler Baicar wrote:
> ARM APEI extension proposal added SEA (Synchronous External Abort)
> notification type for ARMv8.
> Add a new GHES error source handling function for SEA. If an error
> source's notification type is SEA, then this function can be registered
> into the SEA exception handler. That way GHES will parse and report
> SEA exceptions when they occur.

I have a question about ghes_proc. In ghes_proc, we just parse and report
the error information, but no one use it for error recovery now.

Take the SEA case for example, we get the physical address from parsing
the GHES table. But the memory management system or other drivers/modules
know what the really meaning of the error address/page. There is no way to
notify them to do the recovery now.

So, could we add a notify at appropriate position. All drivers or modules
which are interested in this error could receive and take the corresponding
action.

---
Thanks,
Xie XiuQi


> An SEA can interrupt code that had interrupts masked and is treated as
> an NMI. To aid this the page of address space for mapping APEI buffers
> while in_nmi() is always reserved, and ghes_ioremap_pfn_nmi() is
> changed to use the helper methods to find the prot_t to map with in
> the same way as ghes_ioremap_pfn_irq().
> 
> Signed-off-by: Tyler Baicar 
> CC: Jonathan (Zhixiong) Zhang 
> ---
>  arch/arm64/Kconfig|  1 +
>  arch/arm64/mm/fault.c | 13 
>  drivers/acpi/apei/Kconfig | 15 +
>  drivers/acpi/apei/ghes.c  | 77 
> +++
>  include/acpi/ghes.h   |  7 +
>  5 files changed, 107 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 1117421..fca4dc1 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -88,6 +88,7 @@ config ARM64
>   select HAVE_IRQ_TIME_ACCOUNTING
>   select HAVE_MEMBLOCK
>   select HAVE_MEMBLOCK_NODE_MAP if NUMA
> + select HAVE_NMI if ACPI_APEI_SEA
>   select HAVE_PATA_PLATFORM
>   select HAVE_PERF_EVENTS
>   select HAVE_PERF_REGS
> diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
> index d178dc0..b2d57fc 100644
> --- a/arch/arm64/mm/fault.c
> +++ b/arch/arm64/mm/fault.c
> @@ -41,6 +41,8 @@
>  #include 
>  #include 
>  
> +#include 
> +
>  static const char *fault_name(unsigned int esr);
>  
>  #ifdef CONFIG_KPROBES
> @@ -498,6 +500,17 @@ static int do_sea(unsigned long addr, unsigned int esr, 
> struct pt_regs *regs)
>   pr_err("Synchronous External Abort: %s (0x%08x) at 0x%016lx\n",
>fault_name(esr), esr, addr);
>  
> + /*
> +  * Synchronous aborts may interrupt code which had interrupts masked.
> +  * Before calling out into the wider kernel tell the interested
> +  * subsystems.
> +  */
> + if (IS_ENABLED(ACPI_APEI_SEA)) {
> + nmi_enter();
> + ghes_notify_sea();
> + nmi_exit();
> + }
> +
>   info.si_signo = SIGBUS;
>   info.si_errno = 0;
>   info.si_code  = 0;
> diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig
> index b0140c8..c545dd1 100644
> --- a/drivers/acpi/apei/Kconfig
> +++ b/drivers/acpi/apei/Kconfig
> @@ -39,6 +39,21 @@ config ACPI_APEI_PCIEAER
> PCIe AER errors may be reported via APEI firmware first mode.
> Turn on this option to enable the corresponding support.
>  
> +config ACPI_APEI_SEA
> + bool "APEI Synchronous External Abort logging/recovering support"
> + depends on ARM64 && ACPI_APEI && ACPI_APEI_GHES
> + default y
> + help
> +   This option should be enabled if the system supports
> +   firmware first handling of SEA (Synchronous External Abort).
> +   SEA happens with certain faults of data abort or instruction
> +   abort synchronous exceptions on ARMv8 systems. If a system
> +   supports firmware first handling of SEA, the platform analyzes
> +   and handles hardware error notifications from SEA, and it may then
> +   form a HW error record for the OS to parse and handle. This
> +   option allows the OS to look for such hardware error record, and
> +   take appropriate action.
> +
>  config ACPI_APEI_MEMORY_FAILURE
>   bool "APEI memory error recovering support"
>   depends on ACPI_APEI && MEMORY_FAILURE
> diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
> index b25e7cf..b0596ba 100644
> --- a/drivers/acpi/apei/ghes.c
> +++ b/drivers/acpi/apei/ghes.c
> @@ -114,11 +114,7 @@
>   * Two virtual pages are used, one for IRQ/PROCESS context, the other for
>   * NMI con