[v2,3/8] nvdimm acpi: introduce _FIT
diff mbox

Message ID 1470984850-66891-4-git-send-email-guangrong.xiao@linux.intel.com
State New
Headers show

Commit Message

Xiao Guangrong Aug. 12, 2016, 6:54 a.m. UTC
_FIT is required for hotplug support, guest will inquire the updated
device info from it if a hotplug event is received

As FIT buffer is not completely mapped into guest address space, so a
new function, Read FIT whose function index is 0xFFFFFFFF, is reserved
by QEMU to read the piece of FIT buffer. The buffer is concatenated
before _FIT return

Refer to docs/specs/acpi-nvdimm.txt for detailed design

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/acpi/nvdimm.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)

Comments

Igor Mammedov Sept. 30, 2016, 1:14 p.m. UTC | #1
On Fri, 12 Aug 2016 14:54:05 +0800
Xiao Guangrong <guangrong.xiao@linux.intel.com> wrote:

> _FIT is required for hotplug support, guest will inquire the updated
> device info from it if a hotplug event is received
> 
> As FIT buffer is not completely mapped into guest address space, so a
> new function, Read FIT whose function index is 0xFFFFFFFF, is reserved
> by QEMU to read the piece of FIT buffer. The buffer is concatenated
> before _FIT return
Only issuer of UUID 2F10E7A4-9E91-11E4-89D3-123B93F75CBA can reserve
0xFFFFFFFF for some purposes.
So spec should be amended first or custom generated UUID should be used.

> 
> Refer to docs/specs/acpi-nvdimm.txt for detailed design
and amend docs to reflect that.

> 
> Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
> ---
>  hw/acpi/nvdimm.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 82 insertions(+)
> 
> diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
> index 0e2b9f0..4bbd1e7 100644
> --- a/hw/acpi/nvdimm.c
> +++ b/hw/acpi/nvdimm.c
> @@ -886,6 +886,87 @@ static void nvdimm_build_device_dsm(Aml *dev, uint32_t handle)
>      aml_append(dev, method);
>  }
>  
> +static void nvdimm_build_fit(Aml *dev)
> +{
> +    Aml *method, *pkg, *buf, *buf_size, *offset, *call_result;
> +    Aml *whilectx, *ifcond, *ifctx, *fit;
> +
> +    buf = aml_local(0);
> +    buf_size = aml_local(1);
> +    fit = aml_local(2);
> +
> +    /* build helper function, RFIT. */
> +    method = aml_method("RFIT", 1, AML_NOTSERIALIZED);
since you create named fields (global variable) in method scope,
you should make method serialized. Same goes for _FIT method.


> +    aml_append(method, aml_create_dword_field(aml_buffer(4, NULL),
> +                                              aml_int(0), "OFST"));
> +
> +    /* prepare input package. */
> +    pkg = aml_package(1);
> +    aml_append(method, aml_store(aml_arg(0), aml_name("OFST")));
> +    aml_append(pkg, aml_name("OFST"));
> +
> +    /* call Read_FIT function. */
> +    call_result = aml_call5(NVDIMM_COMMON_DSM,
> +                            aml_touuid("2F10E7A4-9E91-11E4-89D3-123B93F75CBA"
> +                            /* UUID for NVDIMM Root Device */),
> +                            aml_int(1) /* Revision 1 */,
> +                            aml_int(0xFFFFFFFF) /* Read FIT. */,
> +                            pkg, aml_int(0) /* for root device. */);
> +    aml_append(method, aml_store(call_result, buf));
> +
> +    /* handle _DSM result. */
> +    aml_append(method, aml_create_dword_field(buf,
> +               aml_int(0) /* offset at byte 0 */, "STAU"));
> +
> +     /* if something is wrong during _DSM. */
> +    ifcond = aml_equal(aml_int(0 /* Success */), aml_name("STAU"));
> +    ifctx = aml_if(aml_lnot(ifcond));
> +    aml_append(ifctx, aml_return(aml_buffer(0, NULL)));
> +    aml_append(method, ifctx);
> +    aml_append(method, aml_store(aml_sizeof(buf), buf_size));
> +    aml_append(method, aml_subtract(buf_size,
> +                                    aml_int(4) /* the size of "STAU" */,
> +                                    buf_size));

Since you handle error case the same as EOF case you could replace
it with EOF case here and on qemu side of interface as well. That should
simplify code a bit as you won't need to strip out func_ret_status.

> +
> +    /* if we read the end of fit. */
> +    ifctx = aml_if(aml_equal(buf_size, aml_int(0)));
> +    aml_append(ifctx, aml_return(aml_buffer(0, NULL)));
> +    aml_append(method, ifctx);
> +
> +    aml_append(method, aml_store(aml_shiftleft(buf_size, aml_int(3)),
> +                                 buf_size));
> +    aml_append(method, aml_create_field(buf,
> +                            aml_int(4 * BITS_PER_BYTE), /* offset at byte 4.*/
> +                            buf_size, "BUFF"));
> +    aml_append(method, aml_return(aml_name("BUFF")));
> +    aml_append(dev, method);
> +
> +    /* build _FIT. */
> +    method = aml_method("_FIT", 0, AML_NOTSERIALIZED);
> +    offset = aml_local(3);
> +
> +    aml_append(method, aml_store(aml_buffer(0, NULL), fit));
> +    aml_append(method, aml_store(aml_int(0), offset));
> +
> +    whilectx = aml_while(aml_int(1));
> +    aml_append(whilectx, aml_store(aml_call1("RFIT", offset), buf));
> +    aml_append(whilectx, aml_store(aml_sizeof(buf), buf_size));
> +
> +    /* finish fit read if no data is read out. */
> +    ifctx = aml_if(aml_equal(buf_size, aml_int(0)));
> +    aml_append(ifctx, aml_return(fit));
> +    aml_append(whilectx, ifctx);
> +
> +    /* update the offset. */
> +    aml_append(whilectx, aml_add(offset, buf_size, offset));
> +    /* append the data we read out to the fit buffer. */
> +    aml_append(whilectx, aml_concatenate(fit, buf, fit));
> +    aml_append(method, whilectx);
> +
> +    aml_append(dev, method);
> +}
> +
>  static void nvdimm_build_nvdimm_devices(Aml *root_dev, uint32_t ram_slots)
>  {
>      uint32_t slot;
> @@ -1001,6 +1082,7 @@ static void nvdimm_build_ssdt(GArray *table_offsets, GArray *table_data,
>  
>      /* 0 is reserved for root device. */
>      nvdimm_build_device_dsm(dev, 0);
> +    nvdimm_build_fit(dev);
>  
>      nvdimm_build_nvdimm_devices(dev, ram_slots);
>  

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Xiao Guangrong Oct. 8, 2016, 7:17 a.m. UTC | #2
On 09/30/2016 09:14 PM, Igor Mammedov wrote:
> On Fri, 12 Aug 2016 14:54:05 +0800
> Xiao Guangrong <guangrong.xiao@linux.intel.com> wrote:
>
>> _FIT is required for hotplug support, guest will inquire the updated
>> device info from it if a hotplug event is received
>>
>> As FIT buffer is not completely mapped into guest address space, so a
>> new function, Read FIT whose function index is 0xFFFFFFFF, is reserved
>> by QEMU to read the piece of FIT buffer. The buffer is concatenated
>> before _FIT return
> Only issuer of UUID 2F10E7A4-9E91-11E4-89D3-123B93F75CBA can reserve
> 0xFFFFFFFF for some purposes.
> So spec should be amended first or custom generated UUID should be used.

Okay.

I will change the changelog to reflect this fact and move the spec update
to this patch.

>
>>
>> Refer to docs/specs/acpi-nvdimm.txt for detailed design
> and amend docs to reflect that.

Already done in the spec, i will merge the spec changes into
this patch as you suggested later.

>
>>
>> Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
>> ---
>>  hw/acpi/nvdimm.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 82 insertions(+)
>>
>> diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
>> index 0e2b9f0..4bbd1e7 100644
>> --- a/hw/acpi/nvdimm.c
>> +++ b/hw/acpi/nvdimm.c
>> @@ -886,6 +886,87 @@ static void nvdimm_build_device_dsm(Aml *dev, uint32_t handle)
>>      aml_append(dev, method);
>>  }
>>
>> +static void nvdimm_build_fit(Aml *dev)
>> +{
>> +    Aml *method, *pkg, *buf, *buf_size, *offset, *call_result;
>> +    Aml *whilectx, *ifcond, *ifctx, *fit;
>> +
>> +    buf = aml_local(0);
>> +    buf_size = aml_local(1);
>> +    fit = aml_local(2);
>> +
>> +    /* build helper function, RFIT. */
>> +    method = aml_method("RFIT", 1, AML_NOTSERIALIZED);
> since you create named fields (global variable) in method scope,
> you should make method serialized. Same goes for _FIT method.

Indeed, will fix.

>
>
>> +    aml_append(method, aml_create_dword_field(aml_buffer(4, NULL),
>> +                                              aml_int(0), "OFST"));
>> +
>> +    /* prepare input package. */
>> +    pkg = aml_package(1);
>> +    aml_append(method, aml_store(aml_arg(0), aml_name("OFST")));
>> +    aml_append(pkg, aml_name("OFST"));
>> +
>> +    /* call Read_FIT function. */
>> +    call_result = aml_call5(NVDIMM_COMMON_DSM,
>> +                            aml_touuid("2F10E7A4-9E91-11E4-89D3-123B93F75CBA"
>> +                            /* UUID for NVDIMM Root Device */),
>> +                            aml_int(1) /* Revision 1 */,
>> +                            aml_int(0xFFFFFFFF) /* Read FIT. */,
>> +                            pkg, aml_int(0) /* for root device. */);
>> +    aml_append(method, aml_store(call_result, buf));
>> +
>> +    /* handle _DSM result. */
>> +    aml_append(method, aml_create_dword_field(buf,
>> +               aml_int(0) /* offset at byte 0 */, "STAU"));
>> +
>> +     /* if something is wrong during _DSM. */
>> +    ifcond = aml_equal(aml_int(0 /* Success */), aml_name("STAU"));
>> +    ifctx = aml_if(aml_lnot(ifcond));
>> +    aml_append(ifctx, aml_return(aml_buffer(0, NULL)));
>> +    aml_append(method, ifctx);
>> +    aml_append(method, aml_store(aml_sizeof(buf), buf_size));
>> +    aml_append(method, aml_subtract(buf_size,
>> +                                    aml_int(4) /* the size of "STAU" */,
>> +                                    buf_size));
>
> Since you handle error case the same as EOF case you could replace
> it with EOF case here and on qemu side of interface as well. That should
> simplify code a bit as you won't need to strip out func_ret_status.
>

You mean returning NULL buffer if errors happen? However, the buffer is
generated by NVDIMM_COMMON_DSM function which is also used by _DSM based
on NVDIMM DSN specification, i.e, the 'func_ret_status' is needed anyway
no matter is successful or failed.

Or i missed your idea?




--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Igor Mammedov Oct. 10, 2016, 12:51 p.m. UTC | #3
On Sat, 8 Oct 2016 15:17:14 +0800
Xiao Guangrong <guangrong.xiao@linux.intel.com> wrote:

> On 09/30/2016 09:14 PM, Igor Mammedov wrote:
> > On Fri, 12 Aug 2016 14:54:05 +0800
> > Xiao Guangrong <guangrong.xiao@linux.intel.com> wrote:
> >  
> >> _FIT is required for hotplug support, guest will inquire the updated
> >> device info from it if a hotplug event is received
> >>
> >> As FIT buffer is not completely mapped into guest address space, so a
> >> new function, Read FIT whose function index is 0xFFFFFFFF, is reserved
> >> by QEMU to read the piece of FIT buffer. The buffer is concatenated
> >> before _FIT return  
> > Only issuer of UUID 2F10E7A4-9E91-11E4-89D3-123B93F75CBA can reserve
> > 0xFFFFFFFF for some purposes.
> > So spec should be amended first or custom generated UUID should be used.  
> 
> Okay.
> 
> I will change the changelog to reflect this fact and move the spec update
> to this patch.
under spec, I've meant ACPI spec where this UUID is declared

> 
> >  
> >>
> >> Refer to docs/specs/acpi-nvdimm.txt for detailed design  
> > and amend docs to reflect that.  
> 
> Already done in the spec, i will merge the spec changes into
> this patch as you suggested later.
> 
> >  
> >>
> >> Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
> >> ---
> >>  hw/acpi/nvdimm.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >>  1 file changed, 82 insertions(+)
> >>
> >> diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
> >> index 0e2b9f0..4bbd1e7 100644
> >> --- a/hw/acpi/nvdimm.c
> >> +++ b/hw/acpi/nvdimm.c
> >> @@ -886,6 +886,87 @@ static void nvdimm_build_device_dsm(Aml *dev, uint32_t handle)
> >>      aml_append(dev, method);
> >>  }
> >>
> >> +static void nvdimm_build_fit(Aml *dev)
> >> +{
> >> +    Aml *method, *pkg, *buf, *buf_size, *offset, *call_result;
> >> +    Aml *whilectx, *ifcond, *ifctx, *fit;
> >> +
> >> +    buf = aml_local(0);
> >> +    buf_size = aml_local(1);
> >> +    fit = aml_local(2);
> >> +
> >> +    /* build helper function, RFIT. */
> >> +    method = aml_method("RFIT", 1, AML_NOTSERIALIZED);  
> > since you create named fields (global variable) in method scope,
> > you should make method serialized. Same goes for _FIT method.  
> 
> Indeed, will fix.
> 
> >
> >  
> >> +    aml_append(method, aml_create_dword_field(aml_buffer(4, NULL),
> >> +                                              aml_int(0), "OFST"));
> >> +
> >> +    /* prepare input package. */
> >> +    pkg = aml_package(1);
> >> +    aml_append(method, aml_store(aml_arg(0), aml_name("OFST")));
> >> +    aml_append(pkg, aml_name("OFST"));
> >> +
> >> +    /* call Read_FIT function. */
> >> +    call_result = aml_call5(NVDIMM_COMMON_DSM,
> >> +                            aml_touuid("2F10E7A4-9E91-11E4-89D3-123B93F75CBA"
> >> +                            /* UUID for NVDIMM Root Device */),
> >> +                            aml_int(1) /* Revision 1 */,
> >> +                            aml_int(0xFFFFFFFF) /* Read FIT. */,
> >> +                            pkg, aml_int(0) /* for root device. */);
> >> +    aml_append(method, aml_store(call_result, buf));
> >> +
> >> +    /* handle _DSM result. */
> >> +    aml_append(method, aml_create_dword_field(buf,
> >> +               aml_int(0) /* offset at byte 0 */, "STAU"));
> >> +
> >> +     /* if something is wrong during _DSM. */
> >> +    ifcond = aml_equal(aml_int(0 /* Success */), aml_name("STAU"));
> >> +    ifctx = aml_if(aml_lnot(ifcond));
> >> +    aml_append(ifctx, aml_return(aml_buffer(0, NULL)));
> >> +    aml_append(method, ifctx);
> >> +    aml_append(method, aml_store(aml_sizeof(buf), buf_size));
> >> +    aml_append(method, aml_subtract(buf_size,
> >> +                                    aml_int(4) /* the size of "STAU" */,
> >> +                                    buf_size));  
> >
> > Since you handle error case the same as EOF case you could replace
> > it with EOF case here and on qemu side of interface as well. That should
> > simplify code a bit as you won't need to strip out func_ret_status.
> >  
> 
> You mean returning NULL buffer if errors happen? However, the buffer is
> generated by NVDIMM_COMMON_DSM function which is also used by _DSM based
> on NVDIMM DSN specification, i.e, the 'func_ret_status' is needed anyway
> no matter is successful or failed.
> 
> Or i missed your idea?
ok, leave it as is.

> 
> 
> 
> 

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Xiao Guangrong Oct. 10, 2016, 1:09 p.m. UTC | #4
On 10/10/2016 08:51 PM, Igor Mammedov wrote:
> On Sat, 8 Oct 2016 15:17:14 +0800
> Xiao Guangrong <guangrong.xiao@linux.intel.com> wrote:
>
>> On 09/30/2016 09:14 PM, Igor Mammedov wrote:
>>> On Fri, 12 Aug 2016 14:54:05 +0800
>>> Xiao Guangrong <guangrong.xiao@linux.intel.com> wrote:
>>>
>>>> _FIT is required for hotplug support, guest will inquire the updated
>>>> device info from it if a hotplug event is received
>>>>
>>>> As FIT buffer is not completely mapped into guest address space, so a
>>>> new function, Read FIT whose function index is 0xFFFFFFFF, is reserved
>>>> by QEMU to read the piece of FIT buffer. The buffer is concatenated
>>>> before _FIT return
>>> Only issuer of UUID 2F10E7A4-9E91-11E4-89D3-123B93F75CBA can reserve
>>> 0xFFFFFFFF for some purposes.
>>> So spec should be amended first or custom generated UUID should be used.
>>
>> Okay.
>>
>> I will change the changelog to reflect this fact and move the spec update
>> to this patch.
> under spec, I've meant ACPI spec where this UUID is declared

Er. ACPI spec just said that "0xFFFF is reserved", not sure it will be used
in the future.

I'd prefer to custom-generated UUID, however, currently the UUID is checked
in OSPM, i.e, QEMU is not able to distinguish other UUIDs, so how about
drop the UUID check in ACPI and pass the UUID info to QEMU?
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Igor Mammedov Oct. 11, 2016, 11:49 a.m. UTC | #5
On Mon, 10 Oct 2016 21:09:30 +0800
Xiao Guangrong <guangrong.xiao@linux.intel.com> wrote:

> On 10/10/2016 08:51 PM, Igor Mammedov wrote:
> > On Sat, 8 Oct 2016 15:17:14 +0800
> > Xiao Guangrong <guangrong.xiao@linux.intel.com> wrote:
> >  
> >> On 09/30/2016 09:14 PM, Igor Mammedov wrote:  
> >>> On Fri, 12 Aug 2016 14:54:05 +0800
> >>> Xiao Guangrong <guangrong.xiao@linux.intel.com> wrote:
> >>>  
> >>>> _FIT is required for hotplug support, guest will inquire the updated
> >>>> device info from it if a hotplug event is received
> >>>>
> >>>> As FIT buffer is not completely mapped into guest address space, so a
> >>>> new function, Read FIT whose function index is 0xFFFFFFFF, is reserved
> >>>> by QEMU to read the piece of FIT buffer. The buffer is concatenated
> >>>> before _FIT return  
> >>> Only issuer of UUID 2F10E7A4-9E91-11E4-89D3-123B93F75CBA can reserve
> >>> 0xFFFFFFFF for some purposes.
> >>> So spec should be amended first or custom generated UUID should be used.  
> >>
> >> Okay.
> >>
> >> I will change the changelog to reflect this fact and move the spec update
> >> to this patch.  
> > under spec, I've meant ACPI spec where this UUID is declared  
> 
> Er. ACPI spec just said that "0xFFFF is reserved", not sure it will be used
> in the future.
> 
> I'd prefer to custom-generated UUID, however, currently the UUID is checked
> in OSPM, i.e, QEMU is not able to distinguish other UUIDs,
I'd go with custom-generated UUID

> so how about
> drop the UUID check in ACPI and pass the UUID info to QEMU?
It's a bit late to do so as it would be qemu-guest ABI change and
one would need to maintain old and new protocol.
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Xiao Guangrong Oct. 12, 2016, 8:20 a.m. UTC | #6
On 10/11/2016 07:49 PM, Igor Mammedov wrote:
> On Mon, 10 Oct 2016 21:09:30 +0800
> Xiao Guangrong <guangrong.xiao@linux.intel.com> wrote:
>
>> On 10/10/2016 08:51 PM, Igor Mammedov wrote:
>>> On Sat, 8 Oct 2016 15:17:14 +0800
>>> Xiao Guangrong <guangrong.xiao@linux.intel.com> wrote:
>>>
>>>> On 09/30/2016 09:14 PM, Igor Mammedov wrote:
>>>>> On Fri, 12 Aug 2016 14:54:05 +0800
>>>>> Xiao Guangrong <guangrong.xiao@linux.intel.com> wrote:
>>>>>
>>>>>> _FIT is required for hotplug support, guest will inquire the updated
>>>>>> device info from it if a hotplug event is received
>>>>>>
>>>>>> As FIT buffer is not completely mapped into guest address space, so a
>>>>>> new function, Read FIT whose function index is 0xFFFFFFFF, is reserved
>>>>>> by QEMU to read the piece of FIT buffer. The buffer is concatenated
>>>>>> before _FIT return
>>>>> Only issuer of UUID 2F10E7A4-9E91-11E4-89D3-123B93F75CBA can reserve
>>>>> 0xFFFFFFFF for some purposes.
>>>>> So spec should be amended first or custom generated UUID should be used.
>>>>
>>>> Okay.
>>>>
>>>> I will change the changelog to reflect this fact and move the spec update
>>>> to this patch.
>>> under spec, I've meant ACPI spec where this UUID is declared
>>
>> Er. ACPI spec just said that "0xFFFF is reserved", not sure it will be used
>> in the future.
>>
>> I'd prefer to custom-generated UUID, however, currently the UUID is checked
>> in OSPM, i.e, QEMU is not able to distinguish other UUIDs,
> I'd go with custom-generated UUID
>
>> so how about
>> drop the UUID check in ACPI and pass the UUID info to QEMU?
> It's a bit late to do so as it would be qemu-guest ABI change and
> one would need to maintain old and new protocol.
>

Okay.

How about extract 16 bits from 'handle' filed in NvdimmDsmIn buffer and use
it to indicate different UUIDs, i,e:
struct NvdimmDsmIn {
     uint16_t handle;
     uint16_t uuid_type;
     uint32_t revision;
     uint32_t function;
     /* the remaining size in the page is used by arg3. */
     union {
         uint8_t arg3[4084];
     };
} QEMU_PACKED;
typedef struct NvdimmDsmIn NvdimmDsmIn;

For this case, we set uuid_type = 1 to indicate the UUID is the one used
for RFIT.

u16 for 'handle' is large enough as QEMU supports 255 memory devices.



--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Igor Mammedov Oct. 13, 2016, 1:33 p.m. UTC | #7
On Wed, 12 Oct 2016 16:20:07 +0800
Xiao Guangrong <guangrong.xiao@linux.intel.com> wrote:

> On 10/11/2016 07:49 PM, Igor Mammedov wrote:
> > On Mon, 10 Oct 2016 21:09:30 +0800
> > Xiao Guangrong <guangrong.xiao@linux.intel.com> wrote:
> >  
> >> On 10/10/2016 08:51 PM, Igor Mammedov wrote:  
> >>> On Sat, 8 Oct 2016 15:17:14 +0800
> >>> Xiao Guangrong <guangrong.xiao@linux.intel.com> wrote:
> >>>  
> >>>> On 09/30/2016 09:14 PM, Igor Mammedov wrote:  
> >>>>> On Fri, 12 Aug 2016 14:54:05 +0800
> >>>>> Xiao Guangrong <guangrong.xiao@linux.intel.com> wrote:
> >>>>>  
> >>>>>> _FIT is required for hotplug support, guest will inquire the updated
> >>>>>> device info from it if a hotplug event is received
> >>>>>>
> >>>>>> As FIT buffer is not completely mapped into guest address space, so a
> >>>>>> new function, Read FIT whose function index is 0xFFFFFFFF, is reserved
> >>>>>> by QEMU to read the piece of FIT buffer. The buffer is concatenated
> >>>>>> before _FIT return  
> >>>>> Only issuer of UUID 2F10E7A4-9E91-11E4-89D3-123B93F75CBA can reserve
> >>>>> 0xFFFFFFFF for some purposes.
> >>>>> So spec should be amended first or custom generated UUID should be used.  
> >>>>
> >>>> Okay.
> >>>>
> >>>> I will change the changelog to reflect this fact and move the spec update
> >>>> to this patch.  
> >>> under spec, I've meant ACPI spec where this UUID is declared  
> >>
> >> Er. ACPI spec just said that "0xFFFF is reserved", not sure it will be used
> >> in the future.
> >>
> >> I'd prefer to custom-generated UUID, however, currently the UUID is checked
> >> in OSPM, i.e, QEMU is not able to distinguish other UUIDs,  
> > I'd go with custom-generated UUID
> >  
> >> so how about
> >> drop the UUID check in ACPI and pass the UUID info to QEMU?  
> > It's a bit late to do so as it would be qemu-guest ABI change and
> > one would need to maintain old and new protocol.
> >  
> 
> Okay.
> 
> How about extract 16 bits from 'handle' filed in NvdimmDsmIn buffer and use
> it to indicate different UUIDs, i,e:
> struct NvdimmDsmIn {
>      uint16_t handle;
>      uint16_t uuid_type;
>      uint32_t revision;
>      uint32_t function;
>      /* the remaining size in the page is used by arg3. */
>      union {
>          uint8_t arg3[4084];
>      };
> } QEMU_PACKED;
> typedef struct NvdimmDsmIn NvdimmDsmIn;
> 
> For this case, we set uuid_type = 1 to indicate the UUID is the one used
> for RFIT.
> 
> u16 for 'handle' is large enough as QEMU supports 255 memory devices.
I wouldn't do above as it needlessly complicates qemu<->OSPM
protocol.
Since handle is completely internal QEMU thing we can just reserve 0xFFFFFFFF value
in docs/specs/acpi_nvdimm.txt  for RFIT and keep UUID checks only on ASL side.

and on QEMU side add check to guaranty that auto generated handle for DIMMs
would never go into reserved range.
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Xiao Guangrong Oct. 14, 2016, 7:43 a.m. UTC | #8
On 10/13/2016 09:33 PM, Igor Mammedov wrote:
> On Wed, 12 Oct 2016 16:20:07 +0800
> Xiao Guangrong <guangrong.xiao@linux.intel.com> wrote:
>
>> On 10/11/2016 07:49 PM, Igor Mammedov wrote:
>>> On Mon, 10 Oct 2016 21:09:30 +0800
>>> Xiao Guangrong <guangrong.xiao@linux.intel.com> wrote:
>>>
>>>> On 10/10/2016 08:51 PM, Igor Mammedov wrote:
>>>>> On Sat, 8 Oct 2016 15:17:14 +0800
>>>>> Xiao Guangrong <guangrong.xiao@linux.intel.com> wrote:
>>>>>
>>>>>> On 09/30/2016 09:14 PM, Igor Mammedov wrote:
>>>>>>> On Fri, 12 Aug 2016 14:54:05 +0800
>>>>>>> Xiao Guangrong <guangrong.xiao@linux.intel.com> wrote:
>>>>>>>
>>>>>>>> _FIT is required for hotplug support, guest will inquire the updated
>>>>>>>> device info from it if a hotplug event is received
>>>>>>>>
>>>>>>>> As FIT buffer is not completely mapped into guest address space, so a
>>>>>>>> new function, Read FIT whose function index is 0xFFFFFFFF, is reserved
>>>>>>>> by QEMU to read the piece of FIT buffer. The buffer is concatenated
>>>>>>>> before _FIT return
>>>>>>> Only issuer of UUID 2F10E7A4-9E91-11E4-89D3-123B93F75CBA can reserve
>>>>>>> 0xFFFFFFFF for some purposes.
>>>>>>> So spec should be amended first or custom generated UUID should be used.
>>>>>>
>>>>>> Okay.
>>>>>>
>>>>>> I will change the changelog to reflect this fact and move the spec update
>>>>>> to this patch.
>>>>> under spec, I've meant ACPI spec where this UUID is declared
>>>>
>>>> Er. ACPI spec just said that "0xFFFF is reserved", not sure it will be used
>>>> in the future.
>>>>
>>>> I'd prefer to custom-generated UUID, however, currently the UUID is checked
>>>> in OSPM, i.e, QEMU is not able to distinguish other UUIDs,
>>> I'd go with custom-generated UUID
>>>
>>>> so how about
>>>> drop the UUID check in ACPI and pass the UUID info to QEMU?
>>> It's a bit late to do so as it would be qemu-guest ABI change and
>>> one would need to maintain old and new protocol.
>>>
>>
>> Okay.
>>
>> How about extract 16 bits from 'handle' filed in NvdimmDsmIn buffer and use
>> it to indicate different UUIDs, i,e:
>> struct NvdimmDsmIn {
>>      uint16_t handle;
>>      uint16_t uuid_type;
>>      uint32_t revision;
>>      uint32_t function;
>>      /* the remaining size in the page is used by arg3. */
>>      union {
>>          uint8_t arg3[4084];
>>      };
>> } QEMU_PACKED;
>> typedef struct NvdimmDsmIn NvdimmDsmIn;
>>
>> For this case, we set uuid_type = 1 to indicate the UUID is the one used
>> for RFIT.
>>
>> u16 for 'handle' is large enough as QEMU supports 255 memory devices.
> I wouldn't do above as it needlessly complicates qemu<->OSPM
> protocol.
> Since handle is completely internal QEMU thing we can just reserve 0xFFFFFFFF value
> in docs/specs/acpi_nvdimm.txt  for RFIT and keep UUID checks only on ASL side.
>
> and on QEMU side add check to guaranty that auto generated handle for DIMMs
> would never go into reserved range.
>

Okay, I agree. As we may need to support multiple UUIDs in the future. I'd
like to document the rule for handle reservation:
   The handle is completely QEMU internal thing, the value in range [0, 0xFFFF]
   indicates nvdimm device (O means nvdimm root device named NVDR), the values
   out of this region are reserved by other purpose.

   Current reserved handles:
   0x10000 is reserved for RFIT.
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Igor Mammedov Oct. 14, 2016, 11:59 a.m. UTC | #9
On Fri, 14 Oct 2016 15:43:50 +0800
Xiao Guangrong <guangrong.xiao@linux.intel.com> wrote:

> On 10/13/2016 09:33 PM, Igor Mammedov wrote:
> > On Wed, 12 Oct 2016 16:20:07 +0800
> > Xiao Guangrong <guangrong.xiao@linux.intel.com> wrote:
> >  
> >> On 10/11/2016 07:49 PM, Igor Mammedov wrote:  
> >>> On Mon, 10 Oct 2016 21:09:30 +0800
> >>> Xiao Guangrong <guangrong.xiao@linux.intel.com> wrote:
> >>>  
> >>>> On 10/10/2016 08:51 PM, Igor Mammedov wrote:  
> >>>>> On Sat, 8 Oct 2016 15:17:14 +0800
> >>>>> Xiao Guangrong <guangrong.xiao@linux.intel.com> wrote:
> >>>>>  
> >>>>>> On 09/30/2016 09:14 PM, Igor Mammedov wrote:  
> >>>>>>> On Fri, 12 Aug 2016 14:54:05 +0800
> >>>>>>> Xiao Guangrong <guangrong.xiao@linux.intel.com> wrote:
> >>>>>>>  
> >>>>>>>> _FIT is required for hotplug support, guest will inquire the updated
> >>>>>>>> device info from it if a hotplug event is received
> >>>>>>>>
> >>>>>>>> As FIT buffer is not completely mapped into guest address space, so a
> >>>>>>>> new function, Read FIT whose function index is 0xFFFFFFFF, is reserved
> >>>>>>>> by QEMU to read the piece of FIT buffer. The buffer is concatenated
> >>>>>>>> before _FIT return  
> >>>>>>> Only issuer of UUID 2F10E7A4-9E91-11E4-89D3-123B93F75CBA can reserve
> >>>>>>> 0xFFFFFFFF for some purposes.
> >>>>>>> So spec should be amended first or custom generated UUID should be used.  
> >>>>>>
> >>>>>> Okay.
> >>>>>>
> >>>>>> I will change the changelog to reflect this fact and move the spec update
> >>>>>> to this patch.  
> >>>>> under spec, I've meant ACPI spec where this UUID is declared  
> >>>>
> >>>> Er. ACPI spec just said that "0xFFFF is reserved", not sure it will be used
> >>>> in the future.
> >>>>
> >>>> I'd prefer to custom-generated UUID, however, currently the UUID is checked
> >>>> in OSPM, i.e, QEMU is not able to distinguish other UUIDs,  
> >>> I'd go with custom-generated UUID
> >>>  
> >>>> so how about
> >>>> drop the UUID check in ACPI and pass the UUID info to QEMU?  
> >>> It's a bit late to do so as it would be qemu-guest ABI change and
> >>> one would need to maintain old and new protocol.
> >>>  
> >>
> >> Okay.
> >>
> >> How about extract 16 bits from 'handle' filed in NvdimmDsmIn buffer and use
> >> it to indicate different UUIDs, i,e:
> >> struct NvdimmDsmIn {
> >>      uint16_t handle;
> >>      uint16_t uuid_type;
> >>      uint32_t revision;
> >>      uint32_t function;
> >>      /* the remaining size in the page is used by arg3. */
> >>      union {
> >>          uint8_t arg3[4084];
> >>      };
> >> } QEMU_PACKED;
> >> typedef struct NvdimmDsmIn NvdimmDsmIn;
> >>
> >> For this case, we set uuid_type = 1 to indicate the UUID is the one used
> >> for RFIT.
> >>
> >> u16 for 'handle' is large enough as QEMU supports 255 memory devices.  
> > I wouldn't do above as it needlessly complicates qemu<->OSPM
> > protocol.
> > Since handle is completely internal QEMU thing we can just reserve 0xFFFFFFFF value
> > in docs/specs/acpi_nvdimm.txt  for RFIT and keep UUID checks only on ASL side.
> >
> > and on QEMU side add check to guaranty that auto generated handle for DIMMs
> > would never go into reserved range.
> >  
> 
> Okay, I agree. As we may need to support multiple UUIDs in the future. I'd
> like to document the rule for handle reservation:
>    The handle is completely QEMU internal thing, the value in range [0, 0xFFFF]
>    indicates nvdimm device (O means nvdimm root device named NVDR), the values
>    out of this region are reserved by other purpose.
> 
>    Current reserved handles:
>    0x10000 is reserved for RFIT.
sounds fine to me
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch
diff mbox

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index 0e2b9f0..4bbd1e7 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -886,6 +886,87 @@  static void nvdimm_build_device_dsm(Aml *dev, uint32_t handle)
     aml_append(dev, method);
 }
 
+static void nvdimm_build_fit(Aml *dev)
+{
+    Aml *method, *pkg, *buf, *buf_size, *offset, *call_result;
+    Aml *whilectx, *ifcond, *ifctx, *fit;
+
+    buf = aml_local(0);
+    buf_size = aml_local(1);
+    fit = aml_local(2);
+
+    /* build helper function, RFIT. */
+    method = aml_method("RFIT", 1, AML_NOTSERIALIZED);
+    aml_append(method, aml_create_dword_field(aml_buffer(4, NULL),
+                                              aml_int(0), "OFST"));
+
+    /* prepare input package. */
+    pkg = aml_package(1);
+    aml_append(method, aml_store(aml_arg(0), aml_name("OFST")));
+    aml_append(pkg, aml_name("OFST"));
+
+    /* call Read_FIT function. */
+    call_result = aml_call5(NVDIMM_COMMON_DSM,
+                            aml_touuid("2F10E7A4-9E91-11E4-89D3-123B93F75CBA"
+                            /* UUID for NVDIMM Root Device */),
+                            aml_int(1) /* Revision 1 */,
+                            aml_int(0xFFFFFFFF) /* Read FIT. */,
+                            pkg, aml_int(0) /* for root device. */);
+    aml_append(method, aml_store(call_result, buf));
+
+    /* handle _DSM result. */
+    aml_append(method, aml_create_dword_field(buf,
+               aml_int(0) /* offset at byte 0 */, "STAU"));
+
+     /* if something is wrong during _DSM. */
+    ifcond = aml_equal(aml_int(0 /* Success */), aml_name("STAU"));
+    ifctx = aml_if(aml_lnot(ifcond));
+    aml_append(ifctx, aml_return(aml_buffer(0, NULL)));
+    aml_append(method, ifctx);
+
+    aml_append(method, aml_store(aml_sizeof(buf), buf_size));
+    aml_append(method, aml_subtract(buf_size,
+                                    aml_int(4) /* the size of "STAU" */,
+                                    buf_size));
+
+    /* if we read the end of fit. */
+    ifctx = aml_if(aml_equal(buf_size, aml_int(0)));
+    aml_append(ifctx, aml_return(aml_buffer(0, NULL)));
+    aml_append(method, ifctx);
+
+    aml_append(method, aml_store(aml_shiftleft(buf_size, aml_int(3)),
+                                 buf_size));
+    aml_append(method, aml_create_field(buf,
+                            aml_int(4 * BITS_PER_BYTE), /* offset at byte 4.*/
+                            buf_size, "BUFF"));
+    aml_append(method, aml_return(aml_name("BUFF")));
+    aml_append(dev, method);
+
+    /* build _FIT. */
+    method = aml_method("_FIT", 0, AML_NOTSERIALIZED);
+    offset = aml_local(3);
+
+    aml_append(method, aml_store(aml_buffer(0, NULL), fit));
+    aml_append(method, aml_store(aml_int(0), offset));
+
+    whilectx = aml_while(aml_int(1));
+    aml_append(whilectx, aml_store(aml_call1("RFIT", offset), buf));
+    aml_append(whilectx, aml_store(aml_sizeof(buf), buf_size));
+
+    /* finish fit read if no data is read out. */
+    ifctx = aml_if(aml_equal(buf_size, aml_int(0)));
+    aml_append(ifctx, aml_return(fit));
+    aml_append(whilectx, ifctx);
+
+    /* update the offset. */
+    aml_append(whilectx, aml_add(offset, buf_size, offset));
+    /* append the data we read out to the fit buffer. */
+    aml_append(whilectx, aml_concatenate(fit, buf, fit));
+    aml_append(method, whilectx);
+
+    aml_append(dev, method);
+}
+
 static void nvdimm_build_nvdimm_devices(Aml *root_dev, uint32_t ram_slots)
 {
     uint32_t slot;
@@ -1001,6 +1082,7 @@  static void nvdimm_build_ssdt(GArray *table_offsets, GArray *table_data,
 
     /* 0 is reserved for root device. */
     nvdimm_build_device_dsm(dev, 0);
+    nvdimm_build_fit(dev);
 
     nvdimm_build_nvdimm_devices(dev, ram_slots);