RE: [PATCH 0/5] ARM virt: Add NVDIMM support

Shameerali Kolothum Thodi posted 5 patches 4 years, 5 months ago
Only 0 patches received!
RE: [PATCH 0/5] ARM virt: Add NVDIMM support
Posted by Shameerali Kolothum Thodi 4 years, 5 months ago
Hi Igor,

> -----Original Message-----
> From: Igor Mammedov [mailto:imammedo@redhat.com]
> Sent: 25 November 2019 15:46
> To: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
> Cc: Auger Eric <eric.auger@redhat.com>; qemu-devel@nongnu.org;
> qemu-arm@nongnu.org; peter.maydell@linaro.org;
> shannon.zhaosl@gmail.com; xuwei (O) <xuwei5@huawei.com>;
> lersek@redhat.com; Linuxarm <linuxarm@huawei.com>
> Subject: Re: [PATCH 0/5] ARM virt: Add NVDIMM support
> 
> On Mon, 25 Nov 2019 13:20:02 +0000
> Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com> wrote:
> 
> > Hi Eric/Igor,
> >
> > > -----Original Message-----
> > > From: Shameerali Kolothum Thodi
> > > Sent: 22 October 2019 15:05
> > > To: 'Auger Eric' <eric.auger@redhat.com>; qemu-devel@nongnu.org;
> > > qemu-arm@nongnu.org; imammedo@redhat.com
> > > Cc: peter.maydell@linaro.org; shannon.zhaosl@gmail.com; xuwei (O)
> > > <xuwei5@huawei.com>; lersek@redhat.com; Linuxarm
> > > <linuxarm@huawei.com>
> > > Subject: RE: [PATCH 0/5] ARM virt: Add NVDIMM support
> 
> not related to problem discussed in this patch but you probably
> need to update docs/specs/acpi_nvdimm.txt to account for your changes

Ok.

> > >
> >
> > [..]
> >
> > > > one question: I noticed that when a NVDIMM slot is hotplugged one get
> > > > the following trace on guest:
> > > >
> > > > nfit ACPI0012:00: found a zero length table '0' parsing nfit
> > > > pmem0: detected capacity change from 0 to 1073741824
> > > >
> > > > Have you experienced the 0 length trace?
> > >
> > > I double checked and yes that trace is there. And I did a quick check with
> > > x86 and it is not there.
> > >
> > > The reason looks like, ARM64 kernel receives an additional 8 bytes size
> when
> > > the kernel evaluates the "_FIT" object.
> > >
> > > For the same test scenario, Qemu reports a FIT buffer size of 0xb8 and
> > >
> > > X86 Guest kernel,
> > > [    1.601077] acpi_nfit_init: data 0xffff8a273dc12b18 sz 0xb8
> > >
> > > ARM64 Guest,
> > > [    0.933133] acpi_nfit_init: data 0xffff00003cbe6018 sz 0xc0
> > >
> > > I am not sure how that size gets changed for ARM which results in
> > > the above mentioned 0 length trace. I need to debug this further.
> > >
> > > Please let me know if you have any pointers...
> >
> > I spend some time debugging this further and it looks like the AML code
> > behaves differently on x86 and ARM64.
> FIT table is built dynamically and you are the first to debug
> such issue.
> (apart from the author the NVDIMM code.
:)
>  btw: why NVDIMM author is not on CC list???)

Right. Missed that. CCd.
 
> 
> > Booted guest with nvdimm mem, and used SSDT override with dbg prints
> > added,
> >
> > -object memory-backend-ram,id=mem1,size=1G \
> > -device nvdimm,id=dimm1,memdev=mem1 \
> >
> > On X86,
> > -----------
> >
> > [Qemu]NVDIMM:nvdimm_dsm_func_read_fit: Read FIT: offset 0 FIT size 0xb8
> Dirty Yes.
> > [Qemu]NVDIMM:nvdimm_dsm_func_read_fit: read_fit_out buf size 0xc0
> func_ret_status 0
> >
> > [AML]"NVDIMM-NCAL: Rcvd RLEN 000000C0"
> > [AML]"NVDIMM-NCAL: Creating OBUF with 000005E0 bits"
> > [AML]"NVDIMM-NCAL: Created  BUF(Local7) size 000000BC"
> > [AML]"NVDIMM-RFIT Rcvd buf size 000000BC"
> > [AML]"NVDIMM-RFIT Created NVDR.RFIT.BUFF size 000000B8"
> > [AML]"NVDIMM-FIT: Rcvd buf size 000000B8"
> >
> > [Qemu]NVDIMM:nvdimm_dsm_func_read_fit: Read FIT: offset 0xb8 FIT size
> 0xb8 Dirty No.
> > [Qemu]NVDIMM:nvdimm_dsm_func_read_fit: read_fit_out buf size 0x8
> func_ret_status 0
> >
> > [AML]"NVDIMM-NCAL: Rcvd RLEN 00000008"
> > [AML]"NVDIMM-NCAL: Creating OBUF with 00000020 bits"
> > [AML]"NVDIMM-NCAL: Created  BUF(Local7) size 00000004"
> > [AML]"NVDIMM-RFIT Rcvd buf size 00000004"
> > [AML]"NVDIMM-FIT: Rcvd buf size 00000000"
> > [AML]"NVDIMM-FIT: _FIT returned size 000000B8"
> >
> > [ KERNEL] acpi_nfit_init: NVDIMM: data 0xffff9855bb9a7518 sz 0xb8  -->
> Guest receives correct size(0xb8) here
> >
> > On ARM64,
> > ---------------
> >
> > [Qemu]NVDIMM:nvdimm_dsm_func_read_fit: Read FIT: offset 0 FIT size 0xb8
> Dirty Yes.
> > [Qemu]VDIMM:nvdimm_dsm_func_read_fit: read_fit_out buf size 0xc0
> func_ret_status 0
> >
> > [AML]"NVDIMM-NCAL: Rcvd RLEN 00000000000000C0"
> > [AML]"NVDIMM-NCAL: Creating OBUF with 00000000000005E0 bits"
> > [AML]"NVDIMM-NCAL: Created  BUF(Local7) size 00000000000000BC"
> > [AML]"NVDIMM-RFIT Rcvd buf size 00000000000000BC"
> > [AML]"NVDIMM-RFIT Created NVDR.RFIT.BUFF size 00000000000000B8"
> > [AML]"NVDIMM-FIT: Rcvd buf size 00000000000000B8"
> >
> > [Qemu]NVDIMM:nvdimm_dsm_func_read_fit: Read FIT: offset 0xb8 FIT size
> 0xb8 Dirty No.
> > [Qemu]NVDIMM:nvdimm_dsm_func_read_fit: read_fit_out buf size 0x8
> func_ret_status 0
> >
> > [AML]"NVDIMM-NCAL: Rcvd RLEN 0000000000000008"
> > [AML]"NVDIMM-NCAL: Creating OBUF with 0000000000000020 bits"  --> All
> looks same as x86 up to here.
> > [AML]"NVDIMM-NCAL: Created  BUF(Local7) size 0000000000000008"  --->
> The size goes wrong. 8 bytes instead of 4!.
> 
> > [AML]"NVDIMM-RFIT Rcvd buf size 0000000000000008"
> > [AML]"NVDIMM-RFIT Created NVDR.RFIT.BUFF size 0000000000000004"
> > [AML]"NVDIMM-FIT: Rcvd buf size 0000000000000008"  --> Again size goes
> wrong. 8 bytes instead of 4!.
> 
>                 Local1 = SizeOf (Local0)
>                 printf("NVDIMM-RFIT Rcvd buf size %o", Local1)
> 
>                 Local1 -= 0x04
>        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ here you get -4 so sizes you
> see are consistent

Hmm...IIUC, Method(RFIT, ) creates a buffer of size 0x4 as per 
this,

"NVDIMM-RFIT Created NVDR.RFIT.BUFF size 0000000000000004"

And this is the buffer received by Method(_FIT, ), 

                    Local0 = RFIT (Local3)
                    Local1 = SizeOf (Local0)
                    printf("NVDIMM-FIT: Rcvd buf size %o", Local1)

But "NVDIMM-FIT: Rcvd buf size 0000000000000008".

As you can see above, in the first iteration the buffer size received by _FIT is
actually what RFIT created(0xB8).

> 
>                 If ((Local1 == Zero))
>                 {
>                     Return (Buffer (Zero){})
>                 }
> 
>                 CreateField (Local0, 0x20, (Local1 << 0x03), BUFF)
>                 printf("NVDIMM-RFIT Created NVDR.RFIT.BUFF size %o",
> Local1)
> 
> 
> > [Qemu]NVDIMM:nvdimm_dsm_func_read_fit: Read FIT: offset 0xc0 FIT size
> 0xb8 Dirty No.  -->Another read is attempted
> > [Qemu]NVDIMM:nvdimm_dsm_func_read_fit: read_fit_out buf size 0x8
> func_ret_status 3  --> Error status returned
> 
> status 3 means that QEMU didn't like content of NRAM, and there is only
> 1 place like this in nvdimm_dsm_func_read_fit()
>     if (read_fit->offset > fit->len) {
>         func_ret_status = NVDIMM_DSM_RET_STATUS_INVALID;
>         goto exit;
>     }
> 
> so I'd start looking from here and check that QEMU gets expected data
> in nvdimm_dsm_write(). In other words I'd try to trace/compare
> content of DSM buffer (from qemu side).

I had printed the DSM buffer previously and it looked same, I will double check
that.
 
> 
> > [AML]"NVDIMM-NCAL: Rcvd RLEN 0000000000000008"
> > [AML]"NVDIMM-NCAL: Creating OBUF with 0000000000000020 bits"
> > [AML]"NVDIMM-NCAL: Created  BUF(Local7) size 0000000000000008"
> > [AML]"NVDIMM-FIT: Rcvd buf size 0000000000000000"
> RFIT returns 0-sized buffer in case of error

Yes.
                If ((Zero != STAU))
                {
                    Return (Buffer (Zero){})
                }
 
> > [AML]"NVDIMM-FIT: _FIT returned size 00000000000000C0"   --> Wrong
> size returned.
> after that it goes
> 
>                     Local0 = Buffer (Zero){}
>                     Local0 = RFIT (Local3)
>                     Local1 = SizeOf (Local0)
>                     printf("NVDIMM-FIT: Rcvd buf size %o", Local1)
>                     If ((RSTA == 0x0100))
>                     {
>                         Local2 = Buffer (Zero){}
>                         Local3 = Zero
>                     }
>                     Else
>                     {
>                         If ((Local1 == Zero))
>   --> here, probably on the second iteration of the loop taking Zero
>       size as EOF sign but without checking for any error (RSTA !=0)
>       and returning partial buffer only

I guess you meant the third iteration. Yes, it doesn't check for RSTA != 0
case. And in the second iteration, since status == 0 and buffer len received is
8 bytes, 
                        Concatenate (Local2, Local0, Local2)

The final buffer returned to Guest becomes 0xC0 (0xb8 + 0x8).
 
>                         {
>                            printf("NVDIMM-FIT: _FIT returned size %o",
> SizeOf(Local2))
>                            Return (Local2)
>                         }
> 
> relevant code in QEMU that builds this AML is in nvdimm_build_fit()
> 
> > [ KERNEL] acpi_nfit_init: NVDIMM: data 0xffff0000fc57ce18 sz 0xc0
> -->Kernel gets 0xc0 instead of 0xb8
> >
> >
> > It looks like the aml, "CreateField (ODAT, Zero, Local1, OBUF)" goes wrong for
> > ARM64 when the buffer is all zeroes. My knowledge on aml is very limited and
> not
> > sure this is a 32/64bit issue or not. I am attaching the SSDT files with the
> above
> > dbg prints added. Could you please take a look and let me know what actually
> is
> > going on here...
> 
> diff -u SSDT-dbg-x86.dsl SSDT-dbg-arm64.dsl
> --- SSDT-dbg-x86.dsl	2019-11-25 14:50:22.024983026 +0100
> +++ SSDT-dbg-arm64.dsl	2019-11-25 14:50:06.740690645 +0100
> @@[...]
> @@ -28,7 +28,7 @@
>              Method (NCAL, 5, Serialized)
>              {
>                  Local6 = MEMA /* \MEMA */
> -                OperationRegion (NPIO, SystemIO, 0x0A18, 0x04)
> +                OperationRegion (NPIO, SystemMemory, 0x09090000,
> 0x04)
> that's fine and matches your code
> 
>                  OperationRegion (NRAM, SystemMemory, Local6, 0x1000)
>                  Field (NPIO, DWordAcc, NoLock, Preserve)
>                  {
> @@ -210,6 +210,6 @@
>          }
>      }
> 
> -    Name (MEMA, 0xBFBFD000)
> +    Name (MEMA, 0xFFFF0000)
> 
> However value here is suspicious. If I recall right it should
> point to DMS buffer allocated by firmware somewhere in the guest RAM.

But then it will be horribly wrong and will result in inconsistent behavior
as well, right?

Thanks,
Shameer
 
> 
>  }
> 
> > Much appreciated,
> > Shameer.
> >
> >


Re: [PATCH 0/5] ARM virt: Add NVDIMM support
Posted by Igor Mammedov 4 years, 5 months ago
On Mon, 25 Nov 2019 16:25:54 +0000
Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com> wrote:

> Hi Igor,
> 
> > -----Original Message-----
> > From: Igor Mammedov [mailto:imammedo@redhat.com]
> > Sent: 25 November 2019 15:46
> > To: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
> > Cc: Auger Eric <eric.auger@redhat.com>; qemu-devel@nongnu.org;
> > qemu-arm@nongnu.org; peter.maydell@linaro.org;
> > shannon.zhaosl@gmail.com; xuwei (O) <xuwei5@huawei.com>;
> > lersek@redhat.com; Linuxarm <linuxarm@huawei.com>
> > Subject: Re: [PATCH 0/5] ARM virt: Add NVDIMM support
> > 
> > On Mon, 25 Nov 2019 13:20:02 +0000
> > Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com> wrote:
> >   
> > > Hi Eric/Igor,
> > >  
> > > > -----Original Message-----
> > > > From: Shameerali Kolothum Thodi
> > > > Sent: 22 October 2019 15:05
> > > > To: 'Auger Eric' <eric.auger@redhat.com>; qemu-devel@nongnu.org;
> > > > qemu-arm@nongnu.org; imammedo@redhat.com
> > > > Cc: peter.maydell@linaro.org; shannon.zhaosl@gmail.com; xuwei (O)
> > > > <xuwei5@huawei.com>; lersek@redhat.com; Linuxarm
> > > > <linuxarm@huawei.com>
> > > > Subject: RE: [PATCH 0/5] ARM virt: Add NVDIMM support  
> > 
> > not related to problem discussed in this patch but you probably
> > need to update docs/specs/acpi_nvdimm.txt to account for your changes  
> 
> Ok.
> 
> > > >  
> > >
> > > [..]
> > >  
> > > > > one question: I noticed that when a NVDIMM slot is hotplugged one get
> > > > > the following trace on guest:
> > > > >
> > > > > nfit ACPI0012:00: found a zero length table '0' parsing nfit
> > > > > pmem0: detected capacity change from 0 to 1073741824
> > > > >
> > > > > Have you experienced the 0 length trace?  
> > > >
> > > > I double checked and yes that trace is there. And I did a quick check with
> > > > x86 and it is not there.
> > > >
> > > > The reason looks like, ARM64 kernel receives an additional 8 bytes size  
> > when  
> > > > the kernel evaluates the "_FIT" object.
> > > >
> > > > For the same test scenario, Qemu reports a FIT buffer size of 0xb8 and
> > > >
> > > > X86 Guest kernel,
> > > > [    1.601077] acpi_nfit_init: data 0xffff8a273dc12b18 sz 0xb8
> > > >
> > > > ARM64 Guest,
> > > > [    0.933133] acpi_nfit_init: data 0xffff00003cbe6018 sz 0xc0
> > > >
> > > > I am not sure how that size gets changed for ARM which results in
> > > > the above mentioned 0 length trace. I need to debug this further.
> > > >
> > > > Please let me know if you have any pointers...  
> > >
> > > I spend some time debugging this further and it looks like the AML code
> > > behaves differently on x86 and ARM64.  
> > FIT table is built dynamically and you are the first to debug
> > such issue.
> > (apart from the author the NVDIMM code.  
> :)
> >  btw: why NVDIMM author is not on CC list???)  
> 
> Right. Missed that. CCd.
>  
> >   
> > > Booted guest with nvdimm mem, and used SSDT override with dbg prints
> > > added,
> > >
> > > -object memory-backend-ram,id=mem1,size=1G \
> > > -device nvdimm,id=dimm1,memdev=mem1 \
> > >
> > > On X86,
> > > -----------
> > >
> > > [Qemu]NVDIMM:nvdimm_dsm_func_read_fit: Read FIT: offset 0 FIT size 0xb8  
> > Dirty Yes.  
> > > [Qemu]NVDIMM:nvdimm_dsm_func_read_fit: read_fit_out buf size 0xc0  
> > func_ret_status 0  
> > >
> > > [AML]"NVDIMM-NCAL: Rcvd RLEN 000000C0"
> > > [AML]"NVDIMM-NCAL: Creating OBUF with 000005E0 bits"
> > > [AML]"NVDIMM-NCAL: Created  BUF(Local7) size 000000BC"
> > > [AML]"NVDIMM-RFIT Rcvd buf size 000000BC"
> > > [AML]"NVDIMM-RFIT Created NVDR.RFIT.BUFF size 000000B8"
> > > [AML]"NVDIMM-FIT: Rcvd buf size 000000B8"
> > >
> > > [Qemu]NVDIMM:nvdimm_dsm_func_read_fit: Read FIT: offset 0xb8 FIT size  
> > 0xb8 Dirty No.  
> > > [Qemu]NVDIMM:nvdimm_dsm_func_read_fit: read_fit_out buf size 0x8  
> > func_ret_status 0  
> > >
> > > [AML]"NVDIMM-NCAL: Rcvd RLEN 00000008"
> > > [AML]"NVDIMM-NCAL: Creating OBUF with 00000020 bits"
> > > [AML]"NVDIMM-NCAL: Created  BUF(Local7) size 00000004"
> > > [AML]"NVDIMM-RFIT Rcvd buf size 00000004"
> > > [AML]"NVDIMM-FIT: Rcvd buf size 00000000"
> > > [AML]"NVDIMM-FIT: _FIT returned size 000000B8"
> > >
> > > [ KERNEL] acpi_nfit_init: NVDIMM: data 0xffff9855bb9a7518 sz 0xb8  -->  
> > Guest receives correct size(0xb8) here  
> > >
> > > On ARM64,
> > > ---------------
> > >
> > > [Qemu]NVDIMM:nvdimm_dsm_func_read_fit: Read FIT: offset 0 FIT size 0xb8  
> > Dirty Yes.  
> > > [Qemu]VDIMM:nvdimm_dsm_func_read_fit: read_fit_out buf size 0xc0  
> > func_ret_status 0  
> > >
> > > [AML]"NVDIMM-NCAL: Rcvd RLEN 00000000000000C0"
> > > [AML]"NVDIMM-NCAL: Creating OBUF with 00000000000005E0 bits"
> > > [AML]"NVDIMM-NCAL: Created  BUF(Local7) size 00000000000000BC"
> > > [AML]"NVDIMM-RFIT Rcvd buf size 00000000000000BC"
> > > [AML]"NVDIMM-RFIT Created NVDR.RFIT.BUFF size 00000000000000B8"
> > > [AML]"NVDIMM-FIT: Rcvd buf size 00000000000000B8"
> > >
> > > [Qemu]NVDIMM:nvdimm_dsm_func_read_fit: Read FIT: offset 0xb8 FIT size  
> > 0xb8 Dirty No.  
> > > [Qemu]NVDIMM:nvdimm_dsm_func_read_fit: read_fit_out buf size 0x8  
> > func_ret_status 0  
> > >
> > > [AML]"NVDIMM-NCAL: Rcvd RLEN 0000000000000008"
> > > [AML]"NVDIMM-NCAL: Creating OBUF with 0000000000000020 bits"  --> All  
> > looks same as x86 up to here.  
> > > [AML]"NVDIMM-NCAL: Created  BUF(Local7) size 0000000000000008"  --->  
> > The size goes wrong. 8 bytes instead of 4!.
> >   
> > > [AML]"NVDIMM-RFIT Rcvd buf size 0000000000000008"
> > > [AML]"NVDIMM-RFIT Created NVDR.RFIT.BUFF size 0000000000000004"
> > > [AML]"NVDIMM-FIT: Rcvd buf size 0000000000000008"  --> Again size goes  
> > wrong. 8 bytes instead of 4!.
> > 
> >                 Local1 = SizeOf (Local0)
> >                 printf("NVDIMM-RFIT Rcvd buf size %o", Local1)
> > 
> >                 Local1 -= 0x04
> >        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ here you get -4 so sizes you
> > see are consistent  
> 
> Hmm...IIUC, Method(RFIT, ) creates a buffer of size 0x4 as per 
> this,
> 
> "NVDIMM-RFIT Created NVDR.RFIT.BUFF size 0000000000000004"
> 
> And this is the buffer received by Method(_FIT, ), 
> 
>                     Local0 = RFIT (Local3)
>                     Local1 = SizeOf (Local0)
>                     printf("NVDIMM-FIT: Rcvd buf size %o", Local1)
> 
> But "NVDIMM-FIT: Rcvd buf size 0000000000000008".
> 
> As you can see above, in the first iteration the buffer size received by _FIT is
> actually what RFIT created(0xB8).
> 
> > 
> >                 If ((Local1 == Zero))
> >                 {
> >                     Return (Buffer (Zero){})
> >                 }
> > 
> >                 CreateField (Local0, 0x20, (Local1 << 0x03), BUFF)
> >                 printf("NVDIMM-RFIT Created NVDR.RFIT.BUFF size %o",
> > Local1)
> > 
> >   
> > > [Qemu]NVDIMM:nvdimm_dsm_func_read_fit: Read FIT: offset 0xc0 FIT size  
> > 0xb8 Dirty No.  -->Another read is attempted  
> > > [Qemu]NVDIMM:nvdimm_dsm_func_read_fit: read_fit_out buf size 0x8  
> > func_ret_status 3  --> Error status returned
> > 
> > status 3 means that QEMU didn't like content of NRAM, and there is only
> > 1 place like this in nvdimm_dsm_func_read_fit()
> >     if (read_fit->offset > fit->len) {
> >         func_ret_status = NVDIMM_DSM_RET_STATUS_INVALID;
> >         goto exit;
> >     }
> > 
> > so I'd start looking from here and check that QEMU gets expected data
> > in nvdimm_dsm_write(). In other words I'd try to trace/compare
> > content of DSM buffer (from qemu side).  
> 
> I had printed the DSM buffer previously and it looked same, I will double check
> that.
>  
> >   
> > > [AML]"NVDIMM-NCAL: Rcvd RLEN 0000000000000008"
> > > [AML]"NVDIMM-NCAL: Creating OBUF with 0000000000000020 bits"
> > > [AML]"NVDIMM-NCAL: Created  BUF(Local7) size 0000000000000008"
> > > [AML]"NVDIMM-FIT: Rcvd buf size 0000000000000000"  
> > RFIT returns 0-sized buffer in case of error  
> 
> Yes.
>                 If ((Zero != STAU))
>                 {
>                     Return (Buffer (Zero){})
>                 }
>  
> > > [AML]"NVDIMM-FIT: _FIT returned size 00000000000000C0"   --> Wrong  
> > size returned.
> > after that it goes
> > 
> >                     Local0 = Buffer (Zero){}
> >                     Local0 = RFIT (Local3)
> >                     Local1 = SizeOf (Local0)
> >                     printf("NVDIMM-FIT: Rcvd buf size %o", Local1)
> >                     If ((RSTA == 0x0100))
> >                     {
> >                         Local2 = Buffer (Zero){}
> >                         Local3 = Zero
> >                     }
> >                     Else
> >                     {
> >                         If ((Local1 == Zero))  
> >   --> here, probably on the second iteration of the loop taking Zero  
> >       size as EOF sign but without checking for any error (RSTA !=0)
> >       and returning partial buffer only  
> 
> I guess you meant the third iteration. Yes, it doesn't check for RSTA != 0
> case. And in the second iteration, since status == 0 and buffer len received is
> 8 bytes, 
>                         Concatenate (Local2, Local0, Local2)
> 
> The final buffer returned to Guest becomes 0xC0 (0xb8 + 0x8).
>  
> >                         {
> >                            printf("NVDIMM-FIT: _FIT returned size %o",
> > SizeOf(Local2))
> >                            Return (Local2)
> >                         }
> > 
> > relevant code in QEMU that builds this AML is in nvdimm_build_fit()
> >   
> > > [ KERNEL] acpi_nfit_init: NVDIMM: data 0xffff0000fc57ce18 sz 0xc0
> > -->Kernel gets 0xc0 instead of 0xb8
> > >
> > >
> > > It looks like the aml, "CreateField (ODAT, Zero, Local1, OBUF)" goes wrong for
> > > ARM64 when the buffer is all zeroes. My knowledge on aml is very limited and  
> > not  
> > > sure this is a 32/64bit issue or not. I am attaching the SSDT files with the  
> > above  
> > > dbg prints added. Could you please take a look and let me know what actually  
> > is  
> > > going on here...  
> > 
> > diff -u SSDT-dbg-x86.dsl SSDT-dbg-arm64.dsl
> > --- SSDT-dbg-x86.dsl	2019-11-25 14:50:22.024983026 +0100
> > +++ SSDT-dbg-arm64.dsl	2019-11-25 14:50:06.740690645 +0100
> > @@[...]
> > @@ -28,7 +28,7 @@
> >              Method (NCAL, 5, Serialized)
> >              {
> >                  Local6 = MEMA /* \MEMA */
> > -                OperationRegion (NPIO, SystemIO, 0x0A18, 0x04)
> > +                OperationRegion (NPIO, SystemMemory, 0x09090000,
> > 0x04)
> > that's fine and matches your code
> > 
> >                  OperationRegion (NRAM, SystemMemory, Local6, 0x1000)
> >                  Field (NPIO, DWordAcc, NoLock, Preserve)
> >                  {
> > @@ -210,6 +210,6 @@
> >          }
> >      }
> > 
> > -    Name (MEMA, 0xBFBFD000)
> > +    Name (MEMA, 0xFFFF0000)
> > 
> > However value here is suspicious. If I recall right it should
> > point to DMS buffer allocated by firmware somewhere in the guest RAM.  
> 
> But then it will be horribly wrong and will result in inconsistent behavior
> as well, right?

I'd thinks so. I'm not sure what happens but RAM starts at 0x100000000
which is above the address you have in MEMA so you shouldn't have
sensible data there and access probably should raise some sort of error.

CCing Drew

> 
> Thanks,
> Shameer
>  
> > 
> >  }
> >   
> > > Much appreciated,
> > > Shameer.
> > >
> > >  
> 


Re: [PATCH 0/5] ARM virt: Add NVDIMM support
Posted by Andrew Jones 4 years, 5 months ago
On Tue, Nov 26, 2019 at 09:56:55AM +0100, Igor Mammedov wrote:
> On Mon, 25 Nov 2019 16:25:54 +0000
> Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com> wrote:
> > > -    Name (MEMA, 0xBFBFD000)
> > > +    Name (MEMA, 0xFFFF0000)
> > > 
> > > However value here is suspicious. If I recall right it should
> > > point to DMS buffer allocated by firmware somewhere in the guest RAM.  
> > 
> > But then it will be horribly wrong and will result in inconsistent behavior
> > as well, right?
> 
> I'd thinks so. I'm not sure what happens but RAM starts at 0x100000000
> which is above the address you have in MEMA so you shouldn't have
> sensible data there and access probably should raise some sort of error.
> 
> CCing Drew

RAM starts at 0x40000000 (the 1G boundary). So 0xffff0000 is OK, assuming
you want this just below the 3G boundary. With TCG, a data abort exception
will be injected for any access to an unmapped region. With KVM, unless
paging is enabled in the guest, then reads of unmapped regions will return
zero and writes will be ignored.

Thanks,
drew


RE: [PATCH 0/5] ARM virt: Add NVDIMM support
Posted by Shameerali Kolothum Thodi 4 years, 5 months ago

> -----Original Message-----
> From: Qemu-devel
> [mailto:qemu-devel-bounces+shameerali.kolothum.thodi=huawei.com@nongn
> u.org] On Behalf Of Igor Mammedov
> Sent: 26 November 2019 08:57
> To: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
> Cc: peter.maydell@linaro.org; drjones@redhat.com;
> xiaoguangrong.eric@gmail.com; shannon.zhaosl@gmail.com;
> qemu-devel@nongnu.org; Linuxarm <linuxarm@huawei.com>; Auger Eric
> <eric.auger@redhat.com>; qemu-arm@nongnu.org; xuwei (O)
> <xuwei5@huawei.com>; lersek@redhat.com
> Subject: Re: [PATCH 0/5] ARM virt: Add NVDIMM support

[..]

> > > 0xb8 Dirty No.  -->Another read is attempted
> > > > [Qemu]NVDIMM:nvdimm_dsm_func_read_fit: read_fit_out buf size 0x8
> > > func_ret_status 3  --> Error status returned
> > >
> > > status 3 means that QEMU didn't like content of NRAM, and there is only
> > > 1 place like this in nvdimm_dsm_func_read_fit()
> > >     if (read_fit->offset > fit->len) {
> > >         func_ret_status = NVDIMM_DSM_RET_STATUS_INVALID;
> > >         goto exit;
> > >     }
> > >
> > > so I'd start looking from here and check that QEMU gets expected data
> > > in nvdimm_dsm_write(). In other words I'd try to trace/compare
> > > content of DSM buffer (from qemu side).
> >
> > I had printed the DSM buffer previously and it looked same, I will double check
> > that.

Tried printing the buffer in both Qemu/AML code.

On Amr64,
-------------
(1st iteration with offset 0)
[QEMU]NVDIMM:nvdimm_dsm_func_read_fit: Read FIT: offset 0 FIT size 0xb8 Dirty Yes.
[QEMU]NVDIMM:nvdimm_dsm_func_read_fit: read_fit_out buff: 
[QEMU]NVDIMM BUF[0x0] = 0xC0
[QEMU]NVDIMM BUF[0x1] = 0x0
[QEMU]NVDIMM BUF[0x2] = 0x0
[QEMU]NVDIMM BUF[0x3] = 0x0
[QEMU]NVDIMM BUF[0x4] = 0x0
[QEMU]NVDIMM BUF[0x5] = 0x0
[QEMU]NVDIMM BUF[0x6] = 0x0
[QEMU]NVDIMM BUF[0x7] = 0x0
[QEMU]NVDIMM BUF[0x8] = 0x0
[QEMU]NVDIMM BUF[0x9] = 0x0
[QEMU]NVDIMM BUF[0xA] = 0x38
[QEMU]NVDIMM BUF[0xB] = 0x0
[QEMU]NVDIMM BUF[0xC] = 0x2
[QEMU]NVDIMM BUF[0xD] = 0x0
[QEMU]NVDIMM BUF[0xE] = 0x3
[QEMU]NVDIMM BUF[0xF] = 0x0
.........
[QEMU]NVDIMM BUF[0xBC] = 0x0
[QEMU]NVDIMM BUF[0xBD] = 0x0
[QEMU]NVDIMM BUF[0xBE] = 0x0
[QEMU]NVDIMM BUF[0xBF] = 0x0
[QEMU]NVDIMM:nvdimm_dsm_func_read_fit: read_fit_out buf size 0xc0 func_ret_status 0 

"AML:NVDIMM-NCAL: Rcvd RLEN 00000000000000C0"
"AML:NVDIMM-NCAL TBUF[0000000000000000] = 0x00000000000000C0"
"AML:NVDIMM-NCAL TBUF[0000000000000001] = 0x0000000000000000"
"AML:NVDIMM-NCAL TBUF[0000000000000002] = 0x0000000000000000"
"AML:NVDIMM-NCAL TBUF[0000000000000003] = 0x0000000000000000"
"AML:NVDIMM-NCAL TBUF[0000000000000004] = 0x0000000000000000"
"AML:NVDIMM-NCAL TBUF[0000000000000005] = 0x0000000000000000"
"AML:NVDIMM-NCAL TBUF[0000000000000006] = 0x0000000000000000"
"AML:NVDIMM-NCAL TBUF[0000000000000007] = 0x0000000000000000"
"AML:NVDIMM-NCAL TBUF[0000000000000008] = 0x0000000000000000"
"AML:NVDIMM-NCAL TBUF[0000000000000009] = 0x0000000000000000"
"AML:NVDIMM-NCAL TBUF[000000000000000A] = 0x0000000000000038"
"AML:NVDIMM-NCAL TBUF[000000000000000B] = 0x0000000000000000"
"AML:NVDIMM-NCAL TBUF[000000000000000C] = 0x0000000000000002"
"AML:NVDIMM-NCAL TBUF[000000000000000D] = 0x0000000000000000"
"AML:NVDIMM-NCAL TBUF[000000000000000E] = 0x0000000000000003"
"AML:NVDIMM-NCAL TBUF[000000000000000F] = 0x0000000000000000"
...........
"AML:NVDIMM-NCAL TBUF[00000000000000BC] = 0x0000000000000000"
"AML:NVDIMM-NCAL TBUF[00000000000000BD] = 0x0000000000000000"
"AML:NVDIMM-NCAL TBUF[00000000000000BE] = 0x0000000000000000"
"AML:NVDIMM-NCAL TBUF[00000000000000BF] = 0x0000000000000000"
"AML:NVDIMM-NCAL: Creating OBUF with bytes 00000000000000BC"
"AML:NVDIMM-NCAL: Created  BUF(Local7) size 00000000000000BC"
"AML:NVDIMM-RFIT Rcvd buf size 00000000000000BC"
"AML:NVDIMM-RFIT Created NVDR.RFIT.BUFF size 00000000000000B8"
"AML:NVDIMM-FIT: Rcvd buf size 00000000000000B8"     -->All looks fine in first iteration.

(2nd iteration with offset 0xb8)
[QEMU]NVDIMM:nvdimm_dsm_func_read_fit: Read FIT: offset 0xb8 FIT size 0xb8 Dirty No.
[QEMU]NVDIMM:nvdimm_dsm_func_read_fit: read_fit_out buff: 
[QEMU]NVDIMM BUF[0x0] = 0x8
[QEMU]NVDIMM BUF[0x1] = 0x0
[QEMU]NVDIMM BUF[0x2] = 0x0
[QEMU]NVDIMM BUF[0x3] = 0x0
[QEMU]NVDIMM BUF[0x4] = 0x0
[QEMU]NVDIMM BUF[0x5] = 0x0
[QEMU]NVDIMM BUF[0x6] = 0x0
[QEMU]NVDIMM BUF[0x7] = 0x0
[QEMU]NVDIMM:nvdimm_dsm_func_read_fit: read_fit_out buf size 0x8 func_ret_status 0 

"AML:NVDIMM-NCAL: Rcvd RLEN 0000000000000008"
"AML:NVDIMM-NCAL TBUF[0000000000000000] = 0x0000000000000008"
"AML:NVDIMM-NCAL TBUF[0000000000000001] = 0x0000000000000000"
"AML:NVDIMM-NCAL TBUF[0000000000000002] = 0x0000000000000000"
"AML:NVDIMM-NCAL TBUF[0000000000000003] = 0x0000000000000000"
"AML:NVDIMM-NCAL TBUF[0000000000000004] = 0x0000000000000000"
"AML:NVDIMM-NCAL TBUF[0000000000000005] = 0x0000000000000000"
"AML:NVDIMM-NCAL TBUF[0000000000000006] = 0x0000000000000000"
"AML:NVDIMM-NCAL TBUF[0000000000000007] = 0x0000000000000000"
"AML:NVDIMM-NCAL: Creating OBUF with bytes 0000000000000004"   -->Requested size is 4
"AML:NVDIMM-NCAL: Created  BUF(Local7) size 0000000000000008" --> Created size is 8 !.
"AML:NVDIMM-RFIT Rcvd buf size 0000000000000008"
"AML:NVDIMM-RFIT Created NVDR.RFIT.BUFF size 0000000000000004" 
"AML:NVDIMM-FIT: Rcvd buf size 0000000000000008"  -->Again wrong here.

(3rd iteration with offset 0xc0 -->0xb8 + 0x8)
[QEMU]NVDIMM:nvdimm_dsm_func_read_fit: Read FIT: offset 0xc0 FIT size 0xb8 Dirty No.
[QEMU]NVDIMM:nvdimm_dsm_func_read_fit: read_fit_out buff: 
[QEMU]NVDIMM BUF[0x0] = 0x8
[QEMU]NVDIMM BUF[0x1] = 0x0
[QEMU]NVDIMM BUF[0x2] = 0x0
[QEMU]NVDIMM BUF[0x3] = 0x0
[QEMU]NVDIMM BUF[0x4] = 0x3
[QEMU]NVDIMM BUF[0x5] = 0x0
[QEMU]NVDIMM BUF[0x6] = 0x0
[QEMU]NVDIMM BUF[0x7] = 0x0
[QEMU]NVDIMM:nvdimm_dsm_func_read_fit: read_fit_out buf size 0x8 func_ret_status 3 

"AML:NVDIMM-NCAL: Rcvd RLEN 0000000000000008"
"AML:NVDIMM-NCAL TBUF[0000000000000000] = 0x0000000000000008"
"AML:NVDIMM-NCAL TBUF[0000000000000001] = 0x0000000000000000"
"AML:NVDIMM-NCAL TBUF[0000000000000002] = 0x0000000000000000"
"AML:NVDIMM-NCAL TBUF[0000000000000003] = 0x0000000000000000"
"AML:NVDIMM-NCAL TBUF[0000000000000004] = 0x0000000000000003"
"AML:NVDIMM-NCAL TBUF[0000000000000005] = 0x0000000000000000"
"AML:NVDIMM-NCAL TBUF[0000000000000006] = 0x0000000000000000"
"AML:NVDIMM-NCAL TBUF[0000000000000007] = 0x0000000000000000"
"AML:NVDIMM-NCAL: Created  BUF(Local7) size 0000000000000008"
"AML:NVDIMM-RFIT: Zero Buff return, status 0000000000000003"   -->Error status, return 
"AML:NVDIMM-FIT: Rcvd buf size 0000000000000000"
"AML:NVDIMM-FIT: _FIT returned size 00000000000000C0"
[KERNEL] acpi_nfit_init: NVDIMM: data 0xffff0000fc57de18 sz 0xc0


On x86
(1st iteration with offset 0)
-Same as ARM64

(2nd iteration with offset 0xb8)
[QEMU]NVDIMM:nvdimm_dsm_func_read_fit: Read FIT: offset 0xb8 FIT size 0xb8 Dirty No.
[QEMU]NVDIMM:nvdimm_dsm_func_read_fit: read_fit_out buff: 
[QEMU]NVDIMM BUF[0x0] = 0x8
[QEMU]NVDIMM BUF[0x1] = 0x0
[QEMU]NVDIMM BUF[0x2] = 0x0
[QEMU]NVDIMM BUF[0x3] = 0x0
[QEMU]NVDIMM BUF[0x4] = 0x0
[QEMU]NVDIMM BUF[0x5] = 0x0
[QEMU]NVDIMM BUF[0x6] = 0x0
[QEMU]NVDIMM BUF[0x7] = 0x0
[QEMU]NVDIMM:nvdimm_dsm_func_read_fit: read_fit_out buf size 0x8 func_ret_status 0 
"AML:NVDIMM-NCAL: Rcvd RLEN 00000008"
"AML:NVDIMM-NCAL TBUF[00000000] = 0x00000008"
"AML:NVDIMM-NCAL TBUF[00000001] = 0x00000000"
"AML:NVDIMM-NCAL TBUF[00000002] = 0x00000000"
"AML:NVDIMM-NCAL TBUF[00000003] = 0x00000000"
"AML:NVDIMM-NCAL TBUF[00000004] = 0x00000000"
"AML:NVDIMM-NCAL TBUF[00000005] = 0x00000000"
"AML:NVDIMM-NCAL TBUF[00000006] = 0x00000000"
"AML:NVDIMM-NCAL TBUF[00000007] = 0x00000000"
"AML:NVDIMM-NCAL: Creating OBUF with bytes 00000004"
"AML:NVDIMM-NCAL: Created  BUF(Local7) size 00000004" -->Correct size
"AML:NVDIMM-RFIT Rcvd buf size 00000004"
"AML:NVDIMM-FIT: Rcvd buf size 00000000"   --> Hence there is no data payload. 
"AML:NVDIMM-FIT: _FIT returned size 000000B8"  --> No 3rd iteration. Return correct size. 
[KERNEL] acpi_nfit_init: NVDIMM: data 0xffff8c6abd5b5518 sz 0xb8

Attached the SSDT.dsl used for debugging. I am still not clear why on ARM64, 
2nd iteration case, the created buffer size in NCAL and RFIT methods have
additional 4 bytes!.

    CreateField (ODAT, Zero, Local1, OBUF)
    Concatenate (Buffer (Zero){}, OBUF, Local7)

Please let me know if you have any clue.

Thanks,
Shameer

.
/*
 * Intel ACPI Component Architecture
 * AML/ASL+ Disassembler version 20180105 (64-bit version)
 * Copyright (c) 2000 - 2018 Intel Corporation
 * 
 * Disassembling to symbolic ASL+ operators
 *
 * Disassembly of SSDT, Mon Nov 18 16:09:53 2019
 *
 * Original Table Header:
 *     Signature        "SSDT"
 *     Length           0x000002EF (751)
 *     Revision         0x01
 *     Checksum         0xA4
 *     OEM ID           "BOCHS "
 *     OEM Table ID     "NVDIMM"
 *     OEM Revision     0x00000001 (1)
 *     Compiler ID      "BXPC"
 *     Compiler Version 0x00000001 (1)
 */
DefinitionBlock ("", "SSDT", 1, "BOCHS ", "NVDIMM", 0x00000002)
{
    Scope (\_SB)
    {
        Device (NVDR)
        {
            Name (_HID, "ACPI0012" /* NVDIMM Root Device */)  // _HID: Hardware ID
            Method (NCAL, 5, Serialized)
            {
                Local6 = MEMA /* \MEMA */
                OperationRegion (NPIO, SystemMemory, 0x09090000, 0x04)
                OperationRegion (NRAM, SystemMemory, Local6, 0x1000)
                Field (NPIO, DWordAcc, NoLock, Preserve)
                {
                    NTFI,   32
                }

                Field (NRAM, DWordAcc, NoLock, Preserve)
                {
                    HDLE,   32, 
                    REVS,   32, 
                    FUNC,   32, 
                    FARG,   32672
                }

                Field (NRAM, DWordAcc, NoLock, Preserve)
                {
                    RLEN,   32, 
                    ODAT,   32736
                }

                Field (NRAM, DWordAcc, NoLock, Preserve)
                {
                    TBUF,   32768
                }

                If ((Arg4 == Zero))
                {
                    Local0 = ToUUID ("2f10e7a4-9e91-11e4-89d3-123b93f75cba")
                }
                ElseIf ((Arg4 == 0x00010000))
                {
                    Local0 = ToUUID ("648b9cf2-cda1-4312-8ad9-49c4af32bd62")
                }
                Else
                {
                    Local0 = ToUUID ("4309ac30-0d11-11e4-9191-0800200c9a66")
                }

                If (((Local6 == Zero) | (Arg0 != Local0)))
                {
                    If ((Arg2 == Zero))
                    {
                        Return (Buffer (One)
                        {
                             0x00                                             // .
                        })
                    }

                    Return (Buffer (One)
                    {
                         0x01                                             // .
                    })
                }

                HDLE = Arg4
                REVS = Arg1
                FUNC = Arg2
                If (((ObjectType (Arg3) == 0x04) & (SizeOf (Arg3) == One)))
                {
                    Local2 = Arg3 [Zero]
                    Local3 = DerefOf (Local2)
                    FARG = Local3
                }

                NTFI = Local6
                printf("AML:NVDIMM-NCAL: Rcvd RLEN %o", RLEN)
                Local2 = Zero
                While (RLEN > Local2)
                {
                    printf("AML:NVDIMM-NCAL TBUF[%o] = 0x%o", Local2, Derefof(TBUF[local2]))
                    Local2 += 1	
				}

                Local1 = (RLEN - 0x04)
                printf("AML:NVDIMM-NCAL: Creating OBUF with bytes %o", Local1)
                Local1 = (Local1 << 0x03)
                CreateField (ODAT, Zero, Local1, OBUF)
                Concatenate (Buffer (Zero){}, OBUF, Local7)
                printf("AML:NVDIMM-NCAL: Created  BUF(Local7) size %o", SizeOf(Local7))
                Return (Local7)
            }

            Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
            {
                Return (NCAL (Arg0, Arg1, Arg2, Arg3, Zero))
            }

            Name (RSTA, Zero)
            Method (RFIT, 1, Serialized)
            {
                Name (OFST, Zero)
                OFST = Arg0
                Local0 = Buffer (Zero){}
                Local0 = NCAL (ToUUID ("648b9cf2-cda1-4312-8ad9-49c4af32bd62"), One, One, Package (0x01)
                        {
                            OFST
                        }, 0x00010000)
                CreateDWordField (Local0, Zero, STAU)
                RSTA = STAU /* \_SB_.NVDR.RFIT.STAU */
                If ((Zero != STAU))
                {
                    printf("AML:NVDIMM-RFIT: Zero Buff return, status %o", RSTA)
                    Return (Buffer (Zero){})
                }

                Local1 = SizeOf (Local0)
                printf("AML:NVDIMM-RFIT Rcvd buf size %o", Local1)
                Local1 -= 0x04
                If ((Local1 == Zero))
                {
                    Return (Buffer (Zero){})
                }

                CreateField (Local0, 0x20, (Local1 << 0x03), BUFF)
                printf("AML:NVDIMM-RFIT Created NVDR.RFIT.BUFF size %o", Local1)
                Return (BUFF) /* \_SB_.NVDR.RFIT.BUFF */
            }

            Method (_FIT, 0, Serialized)  // _FIT: Firmware Interface Table
            {
                Local2 = Buffer (Zero){}
                Local3 = Zero
                While (One)
                {
                    Local0 = Buffer (Zero){}
                    Local0 = RFIT (Local3)
                    Local1 = SizeOf (Local0)
                    printf("AML:NVDIMM-FIT: Rcvd buf size %o", Local1)
                    If ((RSTA == 0x0100))
                    {
                        Local2 = Buffer (Zero){}
                        Local3 = Zero
                    }
                    Else
                    {
                        If ((Local1 == Zero))
                        {
                           printf("AML:NVDIMM-FIT: _FIT returned size %o", SizeOf(Local2))
                           Return (Local2)
                        }
                      
                        Local3 += Local1
                        Concatenate (Local2, Local0, Local2)
                    }
                }
            }

            Device (NV00)
            {
                Name (_ADR, One)  // _ADR: Address
                Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
                {
                    Return (NCAL (Arg0, Arg1, Arg2, Arg3, One))
                }
            }

            Device (NV01)
            {
                Name (_ADR, 0x02)  // _ADR: Address
                Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
                {
                    Return (NCAL (Arg0, Arg1, Arg2, Arg3, 0x02))
                }
            }

            Device (NV02)
            {
                Name (_ADR, 0x03)  // _ADR: Address
                Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
                {
                    Return (NCAL (Arg0, Arg1, Arg2, Arg3, 0x03))
                }
            }

            Device (NV03)
            {
                Name (_ADR, 0x04)  // _ADR: Address
                Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
                {
                    Return (NCAL (Arg0, Arg1, Arg2, Arg3, 0x04))
                }
            }

            Device (NV04)
            {
                Name (_ADR, 0x05)  // _ADR: Address
                Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
                {
                    Return (NCAL (Arg0, Arg1, Arg2, Arg3, 0x05))
                }
            }
        }
    }

    Name (MEMA, 0xFFFF0000)
}

/*
 * Intel ACPI Component Architecture
 * AML/ASL+ Disassembler version 20180105 (64-bit version)
 * Copyright (c) 2000 - 2018 Intel Corporation
 * 
 * Disassembling to symbolic ASL+ operators
 *
 * Disassembly of SSDT, Mon Nov 18 15:53:14 2019
 *
 * Original Table Header:
 *     Signature        "SSDT"
 *     Length           0x000002ED (749)
 *     Revision         0x01
 *     Checksum         0x3D
 *     OEM ID           "BOCHS "
 *     OEM Table ID     "NVDIMM"
 *     OEM Revision     0x00000001 (1)
 *     Compiler ID      "BXPC"
 *     Compiler Version 0x00000001 (1)
 */
DefinitionBlock ("", "SSDT", 1, "BOCHS ", "NVDIMM", 0x00000002)
{
    Scope (\_SB)
    {
        Device (NVDR)
        {
            Name (_HID, "ACPI0012" /* NVDIMM Root Device */)  // _HID: Hardware ID
            Method (NCAL, 5, Serialized)
            {
                Local6 = MEMA /* \MEMA */
                OperationRegion (NPIO, SystemIO, 0x0A18, 0x04)
                OperationRegion (NRAM, SystemMemory, Local6, 0x1000)
                Field (NPIO, DWordAcc, NoLock, Preserve)
                {
                    NTFI,   32
                }

                Field (NRAM, DWordAcc, NoLock, Preserve)
                {
                    HDLE,   32, 
                    REVS,   32, 
                    FUNC,   32, 
                    FARG,   32672
                }

                Field (NRAM, DWordAcc, NoLock, Preserve)
                {
                    RLEN,   32, 
                    ODAT,   32736
                }

                Field (NRAM, DWordAcc, NoLock, Preserve)
                {
                    TBUF,   32768
                }

                If ((Arg4 == Zero))
                {
                    Local0 = ToUUID ("2f10e7a4-9e91-11e4-89d3-123b93f75cba")
                }
                ElseIf ((Arg4 == 0x00010000))
                {
                    Local0 = ToUUID ("648b9cf2-cda1-4312-8ad9-49c4af32bd62")
                }
                Else
                {
                    Local0 = ToUUID ("4309ac30-0d11-11e4-9191-0800200c9a66")
                }

                If (((Local6 == Zero) | (Arg0 != Local0)))
                {
                    If ((Arg2 == Zero))
                    {
                        Return (Buffer (One)
                        {
                             0x00                                             // .
                        })
                    }

                    Return (Buffer (One)
                    {
                         0x01                                             // .
                    })
                }

                HDLE = Arg4
                REVS = Arg1
                FUNC = Arg2
                If (((ObjectType (Arg3) == 0x04) & (SizeOf (Arg3) == One)))
                {
                    Local2 = Arg3 [Zero]
                    Local3 = DerefOf (Local2)
                    FARG = Local3
                }

                NTFI = Local6
                printf("AML:NVDIMM-NCAL: Rcvd RLEN %o", RLEN)
                Local2 = Zero
                While (RLEN > Local2)
                {
                    printf("AML:NVDIMM-NCAL TBUF[%o] = 0x%o", Local2, Derefof(TBUF[local2]))
                    Local2 += 1	
				}

                Local1 = (RLEN - 0x04)
                printf("AML:NVDIMM-NCAL: Creating OBUF with bytes %o", Local1)
                Local1 = (Local1 << 0x03)
                CreateField (ODAT, Zero, Local1, OBUF)
                Concatenate (Buffer (Zero){}, OBUF, Local7)
                printf("AML:NVDIMM-NCAL: Created  BUF(Local7) size %o", SizeOf(Local7))
                Return (Local7)
            }

            Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
            {
                Return (NCAL (Arg0, Arg1, Arg2, Arg3, Zero))
            }

            Name (RSTA, Zero)
            Method (RFIT, 1, Serialized)
            {
                Name (OFST, Zero)
                OFST = Arg0
                Local0 = Buffer (Zero){}
                Local0 = NCAL (ToUUID ("648b9cf2-cda1-4312-8ad9-49c4af32bd62"), One, One, Package (0x01)
                        {
                            OFST
                        }, 0x00010000)
                CreateDWordField (Local0, Zero, STAU)
                RSTA = STAU /* \_SB_.NVDR.RFIT.STAU */
                If ((Zero != STAU))
                {
                    printf("AML:NVDIMM-RFIT: Zero Buff return, status %o", RSTA)
                    Return (Buffer (Zero){})
                }

                Local1 = SizeOf (Local0)
                printf("AML:NVDIMM-RFIT Rcvd buf size %o", Local1)
                Local1 -= 0x04
                If ((Local1 == Zero))
                {
                    Return (Buffer (Zero){})
                }

                CreateField (Local0, 0x20, (Local1 << 0x03), BUFF)
                printf("AML:NVDIMM-RFIT Created NVDR.RFIT.BUFF size %o", Local1)
                Return (BUFF) /* \_SB_.NVDR.RFIT.BUFF */
            }

            Method (_FIT, 0, Serialized)  // _FIT: Firmware Interface Table
            {
                Local2 = Buffer (Zero){}
                Local3 = Zero
                While (One)
                {
                    Local0 = Buffer (Zero){}
                    Local0 = RFIT (Local3)
                    Local1 = SizeOf (Local0)
                    printf("AML:NVDIMM-FIT: Rcvd buf size %o", Local1)
                    If ((RSTA == 0x0100))
                    {
                        Local2 = Buffer (Zero){}
                        Local3 = Zero
                    }
                    Else
                    {
                        If ((Local1 == Zero))
                        {
                           printf("AML:NVDIMM-FIT: _FIT returned size %o", SizeOf(Local2))
                           Return (Local2)
                        }
                      
                        Local3 += Local1
                        Concatenate (Local2, Local0, Local2)
                    }
                }
            }

            Device (NV00)
            {
                Name (_ADR, One)  // _ADR: Address
                Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
                {
                    Return (NCAL (Arg0, Arg1, Arg2, Arg3, One))
                }
            }

            Device (NV01)
            {
                Name (_ADR, 0x02)  // _ADR: Address
                Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
                {
                    Return (NCAL (Arg0, Arg1, Arg2, Arg3, 0x02))
                }
            }

            Device (NV02)
            {
                Name (_ADR, 0x03)  // _ADR: Address
                Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
                {
                    Return (NCAL (Arg0, Arg1, Arg2, Arg3, 0x03))
                }
            }

            Device (NV03)
            {
                Name (_ADR, 0x04)  // _ADR: Address
                Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
                {
                    Return (NCAL (Arg0, Arg1, Arg2, Arg3, 0x04))
                }
            }

            Device (NV04)
            {
                Name (_ADR, 0x05)  // _ADR: Address
                Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
                {
                    Return (NCAL (Arg0, Arg1, Arg2, Arg3, 0x05))
                }
            }
        }
    }

    Name (MEMA, 0xBFBFD000)
}