qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* Re: [Qemu-devel] [PATCH v11 5/6] target-arm: kvm64: handle SIGBUS signal for synchronous External Abort
@ 2017-09-08 16:17 gengdongjiu
  2017-09-08 16:21 ` Peter Maydell
  0 siblings, 1 reply; 5+ messages in thread
From: gengdongjiu @ 2017-09-08 16:17 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Michael S. Tsirkin, Igor Mammedov, Zhaoshenglong, Paolo Bonzini,
	QEMU Developers, qemu-arm, kvm-devel, edk2-devel@lists.01.org,
	Christoffer Dall, Marc Zyngier, Will Deacon, James Morse,
	Tyler Baicar, Ard Biesheuvel, Ingo Molnar, bp@suse.de, Shiju Jose,
	zjzhang@codeaurora.org, arm-mail-list,
	kvmarm@lists.cs.columbia.edu, lkml - Kernel Mailing List,
	linux-acpi@vger.kernel.org, devel@acpica.org, John Garry,
	Jonathan Cameron, Shameerali Kolothum Thodi, huangdaode,
	Wangzhou (B), Huangshaoyu, Wuquanming, Linuxarm,
	Zhengqiang (turing)

Hi peter,
  Sorry for the late response.

> 
> On 18 August 2017 at 15:23, Dongjiu Geng <gengdongjiu@huawei.com> wrote:
> > Add SIGBUS signal handler. In this handler, it checks the exception
> > type, translates the host VA which is delivered by host or KVM to
> > guest PA, then fills this PA to CPER, finally injects a Error to guest
> > OS through KVM.
> >
> > Add synchronous external abort injection logic, setup spsr_elx,
> > esr_elx, PSTATE, far_elx, elr_elx etc, when switch to guest OS, it
> > will jump to the synchronous external abort vector table entry.
> >
> > Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
> > Signed-off-by: Quanming Wu <wuquanming@huawei.com>
> > ---
> >  include/sysemu/kvm.h          |   2 +-
> >  linux-headers/asm-arm64/kvm.h |   5 ++
> >  target/arm/internals.h        |  13 ++++
> >  target/arm/kvm.c              |  34 ++++++++++
> >  target/arm/kvm64.c            | 150 ++++++++++++++++++++++++++++++++++++++++++
> >  target/arm/kvm_arm.h          |   1 +
> >  6 files changed, 204 insertions(+), 1 deletion(-)
> 
> Have you tested whether this patchset builds OK on aarch32 ?


Sorry, I have not tested the build on aarch32, because we only support RAS extension on aarch64 in software.
I will fix the build issue on aarch32.

> 
> > diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index
> > 3a458f5..90c1605 100644
> > --- a/include/sysemu/kvm.h
> > +++ b/include/sysemu/kvm.h
> > @@ -361,7 +361,7 @@ bool kvm_vcpu_id_is_valid(int vcpu_id);
> >  /* Returns VCPU ID to be used on KVM_CREATE_VCPU ioctl() */  unsigned
> > long kvm_arch_vcpu_id(CPUState *cpu);
> >
> > -#ifdef TARGET_I386
> > +#if defined(TARGET_I386) || defined(TARGET_AARCH64)
> >  #define KVM_HAVE_MCE_INJECTION 1
> >  void kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr);
> > #endif diff --git a/linux-headers/asm-arm64/kvm.h
> > b/linux-headers/asm-arm64/kvm.h index d254700..5909c30 100644
> > --- a/linux-headers/asm-arm64/kvm.h
> > +++ b/linux-headers/asm-arm64/kvm.h
> > @@ -181,6 +181,11 @@ struct kvm_arch_memory_slot {  #define
> > KVM_REG_ARM64_SYSREG_OP2_MASK  0x0000000000000007  #define
> > KVM_REG_ARM64_SYSREG_OP2_SHIFT 0
> >
> > +/* AArch64 fault registers */
> > +#define KVM_REG_ARM64_FAULT             (0x0014 << KVM_REG_ARM_COPROC_SHIFT)
> > +#define KVM_REG_ARM64_FAULT_ESR_EC      (0)
> > +#define KVM_REG_ARM64_FAULT_FAR         (1)
> > +
> >  #define ARM64_SYS_REG_SHIFT_MASK(x,n) \
> >         (((x) << KVM_REG_ARM64_SYSREG_ ## n ## _SHIFT) & \
> >         KVM_REG_ARM64_SYSREG_ ## n ## _MASK)
> 
> Again, linux-headers changes need to go in their own header sync patch.


Ok.

> 
> > diff --git a/target/arm/internals.h b/target/arm/internals.h index
> > 1f6efef..fc0ad6d 100644
> > --- a/target/arm/internals.h
> > +++ b/target/arm/internals.h
> > @@ -235,6 +235,19 @@ enum arm_exception_class {  #define
> > ARM_EL_ISV_SHIFT 24  #define ARM_EL_IL (1 << ARM_EL_IL_SHIFT)  #define
> > ARM_EL_ISV (1 << ARM_EL_ISV_SHIFT)
> > +#define ARM_EL_EC_MASK  ((0x3F) << ARM_EL_EC_SHIFT) #define
> > +ARM_EL_FSC_TYPE (0x3C)
> > +
> > +#define FSC_SEA         (0x10)
> > +#define FSC_SEA_TTW0    (0x14)
> > +#define FSC_SEA_TTW1    (0x15)
> > +#define FSC_SEA_TTW2    (0x16)
> > +#define FSC_SEA_TTW3    (0x17)
> > +#define FSC_SECC        (0x18)
> > +#define FSC_SECC_TTW0   (0x1c)
> > +#define FSC_SECC_TTW1   (0x1d)
> > +#define FSC_SECC_TTW2   (0x1e)
> > +#define FSC_SECC_TTW3   (0x1f)
> >
> >  /* Utility functions for constructing various kinds of syndrome value.
> >   * Note that in general we follow the AArch64 syndrome values; in a
> > diff --git a/target/arm/kvm.c b/target/arm/kvm.c index
> > 7c17f0d..2e1716a 100644
> > --- a/target/arm/kvm.c
> > +++ b/target/arm/kvm.c
> > @@ -129,6 +129,39 @@ void kvm_arm_destroy_scratch_host_vcpu(int *fdarray)
> >      }
> >  }
> >
> > +typedef struct HWPoisonPage {
> > +    ram_addr_t ram_addr;
> > +    QLIST_ENTRY(HWPoisonPage) list;
> > +} HWPoisonPage;
> > +
> > +static QLIST_HEAD(, HWPoisonPage) hwpoison_page_list =
> > +    QLIST_HEAD_INITIALIZER(hwpoison_page_list);
> > +
> > +static void kvm_unpoison_all(void *param) {
> > +    HWPoisonPage *page, *next_page;
> > +
> > +    QLIST_FOREACH_SAFE(page, &hwpoison_page_list, list, next_page) {
> > +        QLIST_REMOVE(page, list);
> > +        qemu_ram_remap(page->ram_addr, TARGET_PAGE_SIZE);
> > +        g_free(page);
> > +    }
> > +}
> > +
> > +void kvm_hwpoison_page_add(ram_addr_t ram_addr) {
> > +    HWPoisonPage *page;
> > +
> > +    QLIST_FOREACH(page, &hwpoison_page_list, list) {
> > +        if (page->ram_addr == ram_addr) {
> > +            return;
> > +        }
> > +    }
> > +    page = g_new(HWPoisonPage, 1);
> > +    page->ram_addr = ram_addr;
> > +    QLIST_INSERT_HEAD(&hwpoison_page_list, page, list); }
> 
> This code has all just been copied-and-pasted from target/i386/kvm.c.
> Please instead abstract it out properly into a cpu-independent source file.


Yes, it copied from x86.
Do you mean abstracting this code to a common folder so that i386 and arm platform share it?


> 
> >  static void kvm_arm_host_cpu_class_init(ObjectClass *oc, void *data)
> > {
> >      ARMHostCPUClass *ahcc = ARM_HOST_CPU_CLASS(oc); @@ -182,6 +215,7
> > @@ int kvm_arch_init(MachineState *ms, KVMState *s)
> >
> >      cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
> >

[...]

> > +static int kvm_arm_cpreg_value(ARMCPU *cpu, ptrdiff_t fieldoffset) {
> > +    int i;
> > +
> > +    for (i = 0; i < cpu->cpreg_array_len; i++) {
> > +        uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]);
> > +        const ARMCPRegInfo *ri;
> > +        ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
> > +        if (!ri) {
> > +            continue;
> > +        }
> > +
> > +        if (ri->type & ARM_CP_NO_RAW) {
> > +            continue;
> > +        }
> > +
> > +        if (ri->fieldoffset == fieldoffset) {
> > +            cpu->cpreg_values[i] = read_raw_cp_reg(&cpu->env, ri);
> > +            return 0;
> > +        }
> > +    }
> > +    return -EINVAL;
> 
> What is this ??? You should never need to look up things in the cpreg arrays by fieldoffset.


I used it to set the esr_el1's and far_el1's value, for example:

  /* set ESR_EL1 */
  ret = kvm_arm_cpreg_value(cpu, offsetof(CPUARMState, cp15.esr_el[1]));

  /* set FAR_EL1 */
  ret = kvm_arm_cpreg_value(cpu, offsetof(CPUARMState, cp15.far_el[1]));

other people suggests me injecting the synchronous exception abort in the user space, so I need to set the esr_el1 and far_el1's value
So use the added API kvm_arm_cpreg_value() to set their value. If not used it, do you better method to set their value?


> 
> The code for handling debug exits (software step, watchpoint, etc) is probably a good place to look for how to deal with register state.
> 
> > +}
> > +
> > +/* Inject synchronous external abort */ static int
> > +kvm_inject_arm_sea(CPUState *c) {
> > +    ARMCPU *cpu = ARM_CPU(c);
> > +    CPUARMState *env = &cpu->env;
> > +    unsigned long cpsr = pstate_read(env);
> > +    uint32_t esr = 0;
> > +    int ret;
> > +
> > +    c->exception_index = EXCP_DATA_ABORT;
> > +    /* Inject the exception to El1 */
> > +    env->exception.target_el = 1;
> > +    CPUClass *cc = CPU_GET_CLASS(c);
> > +
> > +    esr |= (EC_DATAABORT << ARM_EL_EC_SHIFT);
> 
> We have functions in internals.h for constructing ESR values, please use them.

Ok, thanks for the reminder, I will check it in internals.h

> 
> > +    /* This exception syndrome includes {I,D}FSC in the bits [5:0]
> > +     */
> > +    esr |= (env->exception.syndrome & 0x3f);
> > +
> > +    /* This exception is EL0 or EL1 fault. */
> > +    if ((cpsr & 0xf) == PSTATE_MODE_EL0t) {
> > +        esr |= (EC_INSNABORT << ARM_EL_EC_SHIFT);
> > +    } else {
> > +        esr |= (EC_INSNABORT_SAME_EL << ARM_EL_EC_SHIFT);
> > +    }
> > +
> > +    /* In the aarch64, there is only 32-bit instruction*/
> > +    esr |= ARM_EL_IL;
> > +    env->exception.syndrome = esr;
> > +    cc->do_interrupt(c);
> > +
> > +    /* set ESR_EL1 */
> > +    ret = kvm_arm_cpreg_value(cpu, offsetof(CPUARMState,
> > + cp15.esr_el[1]));
> > +
> > +    if (ret) {
> > +        fprintf(stderr, "<%s> failed to set esr_el1\n", __func__);
> > +        abort();
> > +    }
> > +
> > +    /* set FAR_EL1 */
> > +    ret = kvm_arm_cpreg_value(cpu, offsetof(CPUARMState, cp15.far_el[1]));
> > +    if (ret) {
> > +        fprintf(stderr, "<%s> failed to set far_el1\n", __func__);
> > +        abort();
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> >  #define AARCH64_CORE_REG(x)   (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
> >                   KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
> >
> > @@ -599,6 +674,9 @@ int kvm_arm_cpreg_level(uint64_t regidx)
> >  #define AARCH64_SIMD_CTRL_REG(x)   (KVM_REG_ARM64 | KVM_REG_SIZE_U32 | \
> >                   KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
> >
> > +#define AARCH64_FAULT_REG(x)   (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
> > +                 KVM_REG_ARM64_FAULT | (x))
> > +
> >  int kvm_arch_put_registers(CPUState *cs, int level)  {
> >      struct kvm_one_reg reg;
> > @@ -873,6 +951,22 @@ int kvm_arch_get_registers(CPUState *cs)
> >      }
> >      vfp_set_fpcr(env, fpr);
> >
> > +    if (is_a64(env)) {
> > +        reg.id = AARCH64_FAULT_REG(KVM_REG_ARM64_FAULT_ESR_EC);
> > +        reg.addr = (uintptr_t)(&env->exception.syndrome);
> > +        ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
> > +        if (ret) {
> > +            return ret;
> > +        }
> > +
> > +        reg.id = AARCH64_FAULT_REG(KVM_REG_ARM64_FAULT_FAR);
> > +        reg.addr = (uintptr_t)(&env->exception.vaddress);
> > +        ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
> 
> This looks dubious. exception.syndrome and exception.vaddress are just internal information QEMU uses, not guest visible things.
> And only synchronizing them if the CPU happens to be in AArch64 at the point when this function is called is also odd.
 

Now I needs to get the exception.syndrome(esr_el2) to judge whether the exception is a synchronization about or asynchronous abort,
and get the exception.vaddress(esr_el2) value to inject the fault address for the synchronization exception about.
But currently the two EL2 values are not exposed to userspace. So I need to call IOCTL to get their values.
Meanwhile, we only support RAS in AArch64, not in AArch32, so it only gets the two values in Aarch64.  

> 
> > +        if (ret) {
> > +            return ret;
> > +        }
> > +    }
> > +
> >      if (!write_kvmstate_to_list(cpu)) {
> >          return EINVAL;
> >      }
> > @@ -887,6 +981,62 @@ int kvm_arch_get_registers(CPUState *cs)
> >      return ret;
> >  }
> >
> > +static bool is_abort_sea(unsigned long syndrome) {
> > +    unsigned long fault_status;
> 
> Don't use "unsigned long" when you really mean uint32_t.

Ok, thanks, I will change it.

> 
> > +    uint8_t ec = ((syndrome & ARM_EL_EC_MASK) >> ARM_EL_EC_SHIFT);
> > +    if ((ec != EC_INSNABORT) && (ec != EC_DATAABORT)) {
> > +        return false;
> > +    }
> > +
> > +    fault_status = syndrome & ARM_EL_FSC_TYPE;
> > +    switch (fault_status) {
> > +    case FSC_SEA:
> > +    case FSC_SEA_TTW0:
> > +    case FSC_SEA_TTW1:
> > +    case FSC_SEA_TTW2:
> > +    case FSC_SEA_TTW3:
> > +    case FSC_SECC:
> > +    case FSC_SECC_TTW0:
> > +    case FSC_SECC_TTW1:
> > +    case FSC_SECC_TTW2:
> > +    case FSC_SECC_TTW3:
> > +        return true;
> > +    default:
> > +        return false;
> > +    }
> > +}
> > +
> > +void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr) {
> > +    ram_addr_t ram_addr;
> > +    hwaddr paddr;
> > +
> > +    ARMCPU *cpu = ARM_CPU(c);
> > +    CPUARMState *env = &cpu->env;
> > +    assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO);
> > +    if (addr) {
> > +        ram_addr = qemu_ram_addr_from_host(addr);
> > +        if (ram_addr != RAM_ADDR_INVALID &&
> > +            kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
> > +            kvm_cpu_synchronize_state(c);
> > +            kvm_hwpoison_page_add(ram_addr);
> > +            if (is_abort_sea(env->exception.syndrome)) {
> > +                ghes_update_guest(ACPI_HEST_NOTIFY_SEA, paddr);
> > +                kvm_inject_arm_sea(c);
> > +            }
> 
> This looks a bit odd. There are cases where we hwpoison the page but don't tell the guest about it? When would we get this kind of sigbus
> when the exception syndrome wasn't the right kind ?

I explained it in detail.

1. Firstly, when guest happen abort, it will firstly trap to host EL3 firmware, then jump to hypervisor exception entry, then exits from guest.
When exits from guest, KVM will record the exception syndrome to the VCPU structure.
2. KVM calls host ACPI driver, host APEI driver gets the error address from APEI table and calls host memory_failure(), memory_failure() sets this page 
to poison page, then send the sigbus.
3. Qemu gets this sigbus, call kvm_cpu_synchronize_state() which will get the right exception syndrome from kvm, this step will make sure the exception syndrome
Is the right kind.
4. Qemu calls ghes_update_guest() to record this CPER to APEI table for guest, and notify guest there is an error through kvm_inject_arm_sea().
5. when guest received error notification, it will parse guest APEI table in which have the CPER record.

> 
> Are we guaranteed not to get this kind of signal if we told the kernel not to expose RAS to the guest ?

Now we are still discussing whether needs to check the RAS extension when user space received the sigbus.

> 
> > +            return;
> > +        }
> > +        fprintf(stderr, "Hardware memory error for memory used by "
> > +                "QEMU itself instead of guest system!\n");
> > +    }
> > +
> > +    if (code == BUS_MCEERR_AR) {
> > +        fprintf(stderr, "Hardware memory error!\n");
> > +        exit(1);
> > +    }
> > +}
> > +
> >  /* C6.6.29 BRK instruction */
> >  static const uint32_t brk_insn = 0xd4200000;
> >
> > diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h index
> > 633d088..7cdde97 100644
> > --- a/target/arm/kvm_arm.h
> > +++ b/target/arm/kvm_arm.h
> > @@ -288,4 +288,5 @@ static inline const char *its_class_name(void)
> >      }
> >  }
> >
> > +void kvm_hwpoison_page_add(ram_addr_t ram_addr);
> 
> Any new globally-visible function prototype in a header should have a doc-comment formatted documentation comment, please.


Ok, thanks for this reminder. Do you mean I need to add comments for this globally-visible function, such as below:

/*
 * xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
 */
void kvm_hwpoison_page_add(ram_addr_t ram_addr);

> 
> >  #endif
> > --
> > 1.8.3.1
> 
> thanks
> -- PMM

^ permalink raw reply	[flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH v11 0/6] Add RAS virtualization support for armv8 SEA and SEI
@ 2017-08-18 14:23 Dongjiu Geng
  2017-08-18 14:23 ` [Qemu-devel] [PATCH v11 5/6] target-arm: kvm64: handle SIGBUS signal for synchronous External Abort Dongjiu Geng
  0 siblings, 1 reply; 5+ messages in thread
From: Dongjiu Geng @ 2017-08-18 14:23 UTC (permalink / raw)
  To: mst, imammedo, zhaoshenglong, peter.maydell, pbonzini, qemu-devel,
	qemu-arm, kvm, edk2-devel, christoffer.dall, marc.zyngier,
	will.deacon, james.morse, tbaicar, ard.biesheuvel, mingo, bp,
	shiju.jose, zjzhang, linux-arm-kernel, kvmarm, linux-kernel,
	linux-acpi, devel, john.garry, jonathan.cameron,
	shameerali.kolothum.thodi, huangdaode, wangzhou1
  Cc: huangshaoyu, wuquanming, linuxarm, gengdongjiu, zhengqiang10

In the armv8 platform, the mainly processor hardware error notification
type are synchronous external abort(SEA) and SError Interrupt (SEI), For
the ARMv8 SEA/SEI, KVM or host kernel will deliver SIGBUS or use other
interface to notify user space. After user space gets the notification,
it will record the CPER to simulate GHES for guest OS and inject the a
exception(SEA/SEI) to KVM. 

This series patch has two parts, one part handles synchronous external
abort(SEA) exception and SError Interrupt (SEI) exception; another part
is generating APEI table when guest OS boot up, and dynamically record
CPER for the guest OS about the generic hardware errors. Currently the
userspace only handles the memory section hardware errors. Before Qemu
record the CPER, it needs to check the ACK value written by the guest
OS to avoid read-write race condition. In the simulated APEI/GHESV2/CPER
table, the max number of error soure is 11, which is classified by
notification type, now only enable the SEA/SEI notification type error
source to avoid OS boot warning.


About the whole solution we ever discuessed it in here before:
https://patchwork.kernel.org/patch/9633105/

Below is the APEI/GHESV2/CPER table layout, the max number of error soure is 11:

       etc/acpi/tables                               etc/hardware_errors
    ====================                    ==========================================
+ +--------------------------+            +------------------+
| | HEST                     |            |    address       |              +--------------+
| +--------------------------+            |    registers     |              | Error Status |
| | GHES0                    |            | +----------------+              | Data Block 0 |
| +--------------------------+ +--------->| |status_address0 |------------->| +------------+
| | .................        | |          | +----------------+              | |  CPER      |
| | error_status_address-----+-+ +------->| |status_address1 |----------+   | |  CPER      |
| | .................        |   |        | +----------------+          |   | |  ....      |
| | read_ack_register--------+-+ |        |  .............   |          |   | |  CPER      |
| | read_ack_preserve        | | |        +------------------+          |   | +------------+
| | read_ack_write           | | | +----->| |status_address10|--------+ |   | Error Status |
+ +--------------------------+ | | |      | +----------------+        | |   | Data Block 1 |
| | GHES1                    | +-+-+----->| | ack_value0     |        | +-->| +------------+
+ +--------------------------+   | |      | +----------------+        |     | |  CPER      |
| | .................        |   | | +--->| | ack_value1     |        |     | |  CPER      |
| | error_status_address-----+---+ | |    | +----------------+        |     | |  ....      |
| | .................        |     | |    | |  ............. |        |     | |  CPER      |
| | read_ack_register--------+-----+-+    | +----------------+        |     +-+------------+
| | read_ack_preserve        |     |   +->| | ack_value10    |        |     | |..........  |
| | read_ack_write           |     |   |  | +----------------+        |     | +------------+
+ +--------------------------|     |   |                              |     | Error Status |
| | ...............          |     |   |                              |     | Data Block 10|
+ +--------------------------+     |   |                              +---->| +------------+
| | GHES10                   |     |   |                                    | |  CPER      |
+ +--------------------------+     |   |                                    | |  CPER      |
| | .................        |     |   |                                    | |  ....      |
| | error_status_address-----+-----+   |                                    | |  CPER      |
| | .................        |         |                                    +-+------------+
| | read_ack_register--------+---------+
| | read_ack_preserve        |
| | read_ack_write           |
+ +--------------------------+


----------------------------------------------------------------------------------------------
How to test guest OS do SEA/SEI recovery:

1. In the guest OS, trigger a SEA or SEI.
2. Then you will see below error log that printed by the memory failure
3. Memory failure will do the recovery for the error.

Such as the below shown kernel log:
[   21.101216] Synchronous External Abort: synchronous external abort (0x96000010) at 0xffffff8008064018
[   21.104969] {1}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 8
[   21.106918] {1}[Hardware Error]: event severity: recoverable
[   21.109027] {1}[Hardware Error]:  Error 0, type: recoverable
[   21.110362] {1}[Hardware Error]:   section_type: memory error
[   21.111705] {1}[Hardware Error]:   physical_address: 0x000000007a200000
[   21.113255] {1}[Hardware Error]:   error_type: 3, multi-bit ECC
[   21.118528] Internal error: : 96000010 [#1] SMP
[   21.119587] Modules linked in:
[   21.120307] CPU: 0 PID: 509 Comm: devmem Not tainted 4.12.0-rc4ajb-00990-g954379b-dirty #67
[   21.122307] Hardware name: QEMU KVM Virtual Machine, BIOS 0.0.0 02/06/2015
[   21.123915] task: ffffffc03da32900 task.stack: ffffffc03dbbc000
[   21.125302] PC is at __do_user_fault+0x58/0x110
[   21.126370] LR is at __do_user_fault+0x54/0x110
[   21.127433] pc : [<ffffff8008097528>] lr : [<ffffff8008097524>] pstate: 80000145
[   21.129164] sp : ffffffc03dbbfd20
[   21.129940] x29: ffffffc03dbbfd20 x28: ffffffc03da32900
[   21.131204] x27: 0000000000000000 x26: 0000007f7edc5001
[   21.132439] x25: ffffff8008648438 x24: ffffffc03dbbfec0
[   21.133689] x23: 0000000000030001 x22: 0000007f7edc5001
[   21.134934] x21: 0000000000000007 x20: 0000000092000021
[   21.136195] x19: ffffffc03da32900 x18: 0000007fdd4c18f0
[   21.137439] x17: 0000007f7ecb9ebc x16: 0000000000412058

------------------------------------------------------------------------------------------------
how to test guest OS APTI/GHES:
1. In the guest OS, use this command to dump the APEI table: 
    "iasl -p ./HEST -d /sys/firmware/acpi/tables/HEST"
2. And find the address for the generic error status block
   according to the notification type
3. then find the CPER record through the generic error status block.

For example(notification type is SEA):

(1) root@genericarmv8:~# iasl -p ./HEST -d /sys/firmware/acpi/tables/HEST
(2) root@genericarmv8:~# cat HEST.dsl
    /*
     * Intel ACPI Component Architecture
     * AML/ASL+ Disassembler version 20170728 (64-bit version)
     * Copyright (c) 2000 - 2017 Intel Corporation
     *
     * Disassembly of /sys/firmware/acpi/tables/HEST, Mon Sep  5 07:59:17 2016
     *
     * ACPI Data Table [HEST]
     *
     * Format: [HexOffset DecimalOffset ByteLength]  FieldName : FieldValue
     */

    ..................................................................................
    [308h 0776   2]                Subtable Type : 000A [Generic Hardware Error Source V2]
    [30Ah 0778   2]                    Source Id : 0008
    [30Ch 0780   2]            Related Source Id : FFFF
    [30Eh 0782   1]                     Reserved : 00
    [30Fh 0783   1]                      Enabled : 01
    [310h 0784   4]       Records To Preallocate : 00000001
    [314h 0788   4]      Max Sections Per Record : 00000001
    [318h 0792   4]          Max Raw Data Length : 00001000

    [31Ch 0796  12]         Error Status Address : [Generic Address Structure]
    [31Ch 0796   1]                     Space ID : 00 [SystemMemory]
    [31Dh 0797   1]                    Bit Width : 40
    [31Eh 0798   1]                   Bit Offset : 00
    [31Fh 0799   1]         Encoded Access Width : 04 [QWord Access:64]
    [320h 0800   8]                      Address : 00000000785D0040

    [328h 0808  28]                       Notify : [Hardware Error Notification Structure]
    [328h 0808   1]                  Notify Type : 08 [SEA]
    [329h 0809   1]                Notify Length : 1C
    [32Ah 0810   2]   Configuration Write Enable : 0000
    [32Ch 0812   4]                 PollInterval : 00000000
    [330h 0816   4]                       Vector : 00000000
    [334h 0820   4]      Polling Threshold Value : 00000000
    [338h 0824   4]     Polling Threshold Window : 00000000
    [33Ch 0828   4]        Error Threshold Value : 00000000
    [340h 0832   4]       Error Threshold Window : 00000000

    [344h 0836   4]    Error Status Block Length : 00001000
    [348h 0840  12]            Read Ack Register : [Generic Address Structure]
    [348h 0840   1]                     Space ID : 00 [SystemMemory]
    [349h 0841   1]                    Bit Width : 40
    [34Ah 0842   1]                   Bit Offset : 00
    [34Bh 0843   1]         Encoded Access Width : 04 [QWord Access:64]
    [34Ch 0844   8]                      Address : 00000000785D0098

    [354h 0852   8]            Read Ack Preserve : 00000000FFFFFFFE
    [35Ch 0860   8]               Read Ack Write : 0000000000000001

    [364h 0868   2]                Subtable Type : 000A [Generic Hardware Error Source V2]
    [366h 0870   2]                    Source Id : 0009
    [368h 0872   2]            Related Source Id : FFFF
    [36Ah 0874   1]                     Reserved : 00
    [36Bh 0875   1]                      Enabled : 01
    [36Ch 0876   4]       Records To Preallocate : 00000001
    [370h 0880   4]      Max Sections Per Record : 00000001
    [374h 0884   4]          Max Raw Data Length : 00001000

    [378h 0888  12]         Error Status Address : [Generic Address Structure]
    [378h 0888   1]                     Space ID : 00 [SystemMemory]
    [379h 0889   1]                    Bit Width : 40
    [37Ah 0890   1]                   Bit Offset : 00
    [37Bh 0891   1]         Encoded Access Width : 04 [QWord Access:64]
    [37Ch 0892   8]                      Address : 00000000785D0048

    [384h 0900  28]                       Notify : [Hardware Error Notification Structure]
    [384h 0900   1]                  Notify Type : 09 [SEI]
    [385h 0901   1]                Notify Length : 1C
    [386h 0902   2]   Configuration Write Enable : 0000
    [388h 0904   4]                 PollInterval : 00000000
    [38Ch 0908   4]                       Vector : 00000000
    [390h 0912   4]      Polling Threshold Value : 00000000
    [394h 0916   4]     Polling Threshold Window : 00000000
    [398h 0920   4]        Error Threshold Value : 00000000
    [39Ch 0924   4]       Error Threshold Window : 00000000

    [3A0h 0928   4]    Error Status Block Length : 00001000
    [3A4h 0932  12]            Read Ack Register : [Generic Address Structure]
    [3A4h 0932   1]                     Space ID : 00 [SystemMemory]
    [3A5h 0933   1]                    Bit Width : 40
    [3A6h 0934   1]                   Bit Offset : 00
    [3A7h 0935   1]         Encoded Access Width : 04 [QWord Access:64]
    [3A8h 0936   8]                      Address : 00000000785D00A0

    [3B0h 0944   8]            Read Ack Preserve : 00000000FFFFFFFE
    [3B8h 0952   8]               Read Ack Write : 0000000000000001
    .....................................................................................
(3) according to above table, the address that contains the physical address of a block
    of memory that holds the error status data for SEA notification error source is 0x00000000785D0040
(4) the address for SEA notification error source is 0x785d8108
    (qemu) xp /1 0x00000000785D0040
    00000000785d0040: 0x785d80b0

(5) check the content of generic error status block and generic error data entry
    (qemu) xp /100x 0x785d80b0
    00000000785d80b0: 0x00000001 0x00000000 0x00000000 0x00000098
    00000000785d80c0: 0x00000000 0xa5bc1114 0x4ede6f64 0x833e63b8
    00000000785d80d0: 0xb1837ced 0x00000000 0x00000300 0x00000050
    00000000785d80e0: 0x00000000 0x00000000 0x00000000 0x00000000
    00000000785d80f0: 0x00000000 0x00000000 0x00000000 0x00000000
    00000000785d8100: 0x00000000 0x00000000 0x00000000 0x00004002
    00000000785d8110: 0x00000000 0x00000000 0x00000000 0x00001111
    00000000785d8120: 0x00000000 0x00000000 0x00000000 0x00000000
    00000000785d8130: 0x00000000 0x00000000 0x00000000 0x00000000
    00000000785d8140: 0x00000000 0x00000000 0x00000000 0x00000000
    00000000785d8150: 0x00000000 0x00000003 0x00000000 0x00000000
    00000000785d8160: 0x00000000 0x00000000 0x00000000 0x00000000
    00000000785d8170: 0x00000000 0x00000000 0x00000000 0x00000000
    00000000785d8180: 0x00000000 0x00000000 0x00000000 0x00000000
    00000000785d8190: 0x00000000 0x00000000 0x00000000 0x00000000
    00000000785d81a0: 0x00000000 0x00000000 0x00000000 0x00000000
    00000000785d81b0: 0x00000000 0x00000000 0x00000000 0x00000000
    00000000785d81c0: 0x00000000 0x00000000 0x00000000 0x00000000
    00000000785d81d0: 0x00000000 0x00000000 0x00000000 0x00000000
    00000000785d81e0: 0x00000000 0x00000000 0x00000000 0x00000000
    00000000785d81f0: 0x00000000 0x00000000 0x00000000 0x00000000
    00000000785d8200: 0x00000000 0x00000000 0x00000000 0x00000000
    00000000785d8210: 0x00000000 0x00000000 0x00000000 0x00000000
    00000000785d8220: 0x00000000 0x00000000 0x00000000 0x00000000
    00000000785d8230: 0x00000000 0x00000000 0x00000000 0x00000000
(6) check the OSPM's ACK value(for example SEA)
    /* Before OSPM acknowledges the error, check the ACK value */
    (qemu) xp /1 0x00000000785D0098
    00000000785d00f0: 0x00000000

    /* After OSPM acknowledges the error, check the ACK value */
    (qemu) xp /1 0x00000000785D0098
    00000000785d00f0: 0x00000001

Dongjiu Geng (6):
  ACPI: add APEI/HEST/CPER structures and macros
  ACPI: Add APEI GHES Table Generation support
  ACPI: build and enable APEI GHES in the Makefile and configuration
  target-arm: kvm64: detect guest RAS EXTENSION feature
  target-arm: kvm64: handle SIGBUS signal for synchronous External Abort
  target-arm: kvm64: Handle SError interrupt from the guest OS

 default-configs/arm-softmmu.mak |   1 +
 hw/acpi/Makefile.objs           |   1 +
 hw/acpi/aml-build.c             |   2 +
 hw/acpi/hest_ghes.c             | 345 ++++++++++++++++++++++++++++++++++++++++
 hw/arm/virt-acpi-build.c        |   6 +
 include/hw/acpi/acpi-defs.h     | 193 ++++++++++++++++++++++
 include/hw/acpi/aml-build.h     |   1 +
 include/hw/acpi/hest_ghes.h     |  47 ++++++
 include/sysemu/kvm.h            |   2 +-
 linux-headers/asm-arm64/kvm.h   |   5 +
 linux-headers/linux/kvm.h       |   2 +
 target/arm/cpu.h                |   3 +
 target/arm/internals.h          |  14 ++
 target/arm/kvm.c                |  34 ++++
 target/arm/kvm64.c              | 186 ++++++++++++++++++++++
 target/arm/kvm_arm.h            |   1 +
 16 files changed, 842 insertions(+), 1 deletion(-)
 create mode 100644 hw/acpi/hest_ghes.c
 create mode 100644 include/hw/acpi/hest_ghes.h

-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2017-09-08 16:41 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-09-08 16:17 [Qemu-devel] [PATCH v11 5/6] target-arm: kvm64: handle SIGBUS signal for synchronous External Abort gengdongjiu
2017-09-08 16:21 ` Peter Maydell
2017-09-08 16:40   ` [Qemu-devel] 答复: " gengdongjiu
  -- strict thread matches above, loose matches on Subject: below --
2017-08-18 14:23 [Qemu-devel] [PATCH v11 0/6] Add RAS virtualization support for armv8 SEA and SEI Dongjiu Geng
2017-08-18 14:23 ` [Qemu-devel] [PATCH v11 5/6] target-arm: kvm64: handle SIGBUS signal for synchronous External Abort Dongjiu Geng
2017-09-05 17:46   ` Peter Maydell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).