diff mbox

[V2,9/25] tools/libxl: build DMAR table for a guest with one virtual VTD

Message ID 1502310866-10450-10-git-send-email-tianyu.lan@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

lan,Tianyu Aug. 9, 2017, 8:34 p.m. UTC
From: Chao Gao <chao.gao@intel.com>

A new logic is added to build ACPI DMAR table in tool stack for a guest
with one virtual VTD and pass through it to guest via existing mechanism. If
there already are ACPI tables needed to pass through, we joint the tables.

Signed-off-by: Chao Gao <chao.gao@intel.com>
Signed-off-by: Lan Tianyu <tianyu.lan@intel.com>
---
 tools/libxl/libxl_arch.h     |  5 +++++
 tools/libxl/libxl_dom.c      | 36 +++++++++++++++++++++++++++++++++
 tools/libxl/libxl_x86_acpi.c | 48 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 89 insertions(+)

Comments

Wei Liu Aug. 17, 2017, 11:32 a.m. UTC | #1
On Wed, Aug 09, 2017 at 04:34:10PM -0400, Lan Tianyu wrote:
> diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
> index f54fd49..94c9196 100644
> --- a/tools/libxl/libxl_dom.c
> +++ b/tools/libxl/libxl_dom.c
> @@ -1060,6 +1060,42 @@ static int libxl__domain_firmware(libxl__gc *gc,
>          }
>      }
>  
> +    /*
> +     * If a guest has one virtual VTD, build DMAR table for it and joint this
> +     * table with existing content in acpi_modules in order to employ HVM
> +     * firmware pass-through mechanism to pass-through DMAR table.
> +     */
> +    if (info->viommu.type == LIBXL_VIOMMU_TYPE_INTEL_VTD) {
> +        datalen = 0;
> +        e = libxl__dom_build_dmar(gc, info, dom, &data, &datalen);
> +        if (e) {
> +            LOGEV(ERROR, e, "failed to build DMAR table");
> +            rc = ERROR_FAIL;
> +            goto out;
> +        }
> +        if (datalen) {
> +            libxl__ptr_add(gc, data);
> +            if (!dom->acpi_modules[0].data) {
> +                dom->acpi_modules[0].data = data;
> +                dom->acpi_modules[0].length = (uint32_t)datalen;
> +            } else {
> +                /* joint tables */
> +                void *newdata;
> +                newdata = malloc(datalen + dom->acpi_modules[0].length);

All memory allocations in libxl should use libxl__*lloc wrappers.

> +                if (!newdata) {
> +                    LOGE(ERROR, "failed to joint DMAR table to acpi modules");
> +                    rc = ERROR_FAIL;
> +                    goto out;
> +                }
> +                memcpy(newdata, dom->acpi_modules[0].data,
> +                       dom->acpi_modules[0].length);
> +                memcpy(newdata + dom->acpi_modules[0].length, data, datalen);
> +                dom->acpi_modules[0].data = newdata;
> +                dom->acpi_modules[0].length += (uint32_t)datalen;
> +            }
> +        }
> +    }

This still looks wrong to me. How do you know acpi_modules[0] is DMAR
table?

You should have a look at libxl_x86_acpi.c and work out a proper
solution.
Wei Liu Aug. 17, 2017, 12:28 p.m. UTC | #2
On Thu, Aug 17, 2017 at 12:32:17PM +0100, Wei Liu wrote:
> On Wed, Aug 09, 2017 at 04:34:10PM -0400, Lan Tianyu wrote:
> > diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
> > index f54fd49..94c9196 100644
> > --- a/tools/libxl/libxl_dom.c
> > +++ b/tools/libxl/libxl_dom.c
> > @@ -1060,6 +1060,42 @@ static int libxl__domain_firmware(libxl__gc *gc,
> >          }
> >      }
> >  
> > +    /*
> > +     * If a guest has one virtual VTD, build DMAR table for it and joint this
> > +     * table with existing content in acpi_modules in order to employ HVM
> > +     * firmware pass-through mechanism to pass-through DMAR table.
> > +     */
> > +    if (info->viommu.type == LIBXL_VIOMMU_TYPE_INTEL_VTD) {
> > +        datalen = 0;
> > +        e = libxl__dom_build_dmar(gc, info, dom, &data, &datalen);
> > +        if (e) {
> > +            LOGEV(ERROR, e, "failed to build DMAR table");
> > +            rc = ERROR_FAIL;
> > +            goto out;
> > +        }
> > +        if (datalen) {
> > +            libxl__ptr_add(gc, data);
> > +            if (!dom->acpi_modules[0].data) {
> > +                dom->acpi_modules[0].data = data;
> > +                dom->acpi_modules[0].length = (uint32_t)datalen;
> > +            } else {
> > +                /* joint tables */
> > +                void *newdata;
> > +                newdata = malloc(datalen + dom->acpi_modules[0].length);
> 
> All memory allocations in libxl should use libxl__*lloc wrappers.
> 
> > +                if (!newdata) {
> > +                    LOGE(ERROR, "failed to joint DMAR table to acpi modules");
> > +                    rc = ERROR_FAIL;
> > +                    goto out;
> > +                }
> > +                memcpy(newdata, dom->acpi_modules[0].data,
> > +                       dom->acpi_modules[0].length);
> > +                memcpy(newdata + dom->acpi_modules[0].length, data, datalen);
> > +                dom->acpi_modules[0].data = newdata;
> > +                dom->acpi_modules[0].length += (uint32_t)datalen;

Also, this leaks the old pointer, right?

> > +            }
> > +        }
> > +    }
> 
> This still looks wrong to me. How do you know acpi_modules[0] is DMAR
> table?
> 

Oh, I sorta see why you do this, but I still think this is wrong. The
DMAR should either be a new module or be joined to the existing one (and
with all conflicts resolved).
Chao Gao Aug. 18, 2017, 5:45 a.m. UTC | #3
On Thu, Aug 17, 2017 at 01:28:21PM +0100, Wei Liu wrote:
>On Thu, Aug 17, 2017 at 12:32:17PM +0100, Wei Liu wrote:
>> On Wed, Aug 09, 2017 at 04:34:10PM -0400, Lan Tianyu wrote:
>> > diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
>> > index f54fd49..94c9196 100644
>> > --- a/tools/libxl/libxl_dom.c
>> > +++ b/tools/libxl/libxl_dom.c
>> > @@ -1060,6 +1060,42 @@ static int libxl__domain_firmware(libxl__gc *gc,
>> >          }
>> >      }
>> >  
>> > +    /*
>> > +     * If a guest has one virtual VTD, build DMAR table for it and joint this
>> > +     * table with existing content in acpi_modules in order to employ HVM
>> > +     * firmware pass-through mechanism to pass-through DMAR table.
>> > +     */
>> > +    if (info->viommu.type == LIBXL_VIOMMU_TYPE_INTEL_VTD) {
>> > +        datalen = 0;
>> > +        e = libxl__dom_build_dmar(gc, info, dom, &data, &datalen);
>> > +        if (e) {
>> > +            LOGEV(ERROR, e, "failed to build DMAR table");
>> > +            rc = ERROR_FAIL;
>> > +            goto out;
>> > +        }
>> > +        if (datalen) {
>> > +            libxl__ptr_add(gc, data);
>> > +            if (!dom->acpi_modules[0].data) {
>> > +                dom->acpi_modules[0].data = data;
>> > +                dom->acpi_modules[0].length = (uint32_t)datalen;
>> > +            } else {
>> > +                /* joint tables */
>> > +                void *newdata;
>> > +                newdata = malloc(datalen + dom->acpi_modules[0].length);
>> 
>> All memory allocations in libxl should use libxl__*lloc wrappers.
>> 
>> > +                if (!newdata) {
>> > +                    LOGE(ERROR, "failed to joint DMAR table to acpi modules");
>> > +                    rc = ERROR_FAIL;
>> > +                    goto out;
>> > +                }
>> > +                memcpy(newdata, dom->acpi_modules[0].data,
>> > +                       dom->acpi_modules[0].length);
>> > +                memcpy(newdata + dom->acpi_modules[0].length, data, datalen);
>> > +                dom->acpi_modules[0].data = newdata;
>> > +                dom->acpi_modules[0].length += (uint32_t)datalen;
>
>Also, this leaks the old pointer, right?

Yes. Will fix this.

>
>> > +            }
>> > +        }
>> > +    }
>> 
>> This still looks wrong to me. How do you know acpi_modules[0] is DMAR
>> table?
>> 
>
>Oh, I sorta see why you do this, but I still think this is wrong. The
>DMAR should either be a new module or be joined to the existing one (and
>with all conflicts resolved).

Hi, Wei
Thanks for your comments.

iirc, HVM only supports one module; DMAR cannot be a new module. Joining to
the existing one is the approach we are taking. 

Which kind of conflicts you think should be resolved? If you mean I
forget to free the old buf, I will fix this. If you mean the potential
overlap between the binary passed by admin and DMAR table built here, I
don't have much idea on this. Even without the DMAR table, the binary
may contains MADT or other tables and tool stacks don't intrepret the
binary and check whether there are conflicts, right?

Thanks
Chao
Wei Liu Aug. 18, 2017, 1:45 p.m. UTC | #4
On Fri, Aug 18, 2017 at 01:45:50PM +0800, Chao Gao wrote:
> >
> >> > +            }
> >> > +        }
> >> > +    }
> >> 
> >> This still looks wrong to me. How do you know acpi_modules[0] is DMAR
> >> table?
> >> 
> >
> >Oh, I sorta see why you do this, but I still think this is wrong. The
> >DMAR should either be a new module or be joined to the existing one (and
> >with all conflicts resolved).
> 
> Hi, Wei
> Thanks for your comments.
> 
> iirc, HVM only supports one module;

This is indeed how it is stated in various comments. I'm not sure why
there is such restriction. Maybe x86 maintainers can shed more light on
this?

> DMAR cannot be a new module. Joining to
> the existing one is the approach we are taking. 
> 
> Which kind of conflicts you think should be resolved? If you mean I
> forget to free the old buf, I will fix this. If you mean the potential
> overlap between the binary passed by admin and DMAR table built here, I
> don't have much idea on this. Even without the DMAR table, the binary
> may contains MADT or other tables and tool stacks don't intrepret the
> binary and check whether there are conflicts, right?

That's true. Ignore the comment about fixing up conflicts then.
Jan Beulich Aug. 18, 2017, 1:56 p.m. UTC | #5
>>> On 18.08.17 at 15:45, <wei.liu2@citrix.com> wrote:
> On Fri, Aug 18, 2017 at 01:45:50PM +0800, Chao Gao wrote:
>> >
>> >> > +            }
>> >> > +        }
>> >> > +    }
>> >> 
>> >> This still looks wrong to me. How do you know acpi_modules[0] is DMAR
>> >> table?
>> >> 
>> >
>> >Oh, I sorta see why you do this, but I still think this is wrong. The
>> >DMAR should either be a new module or be joined to the existing one (and
>> >with all conflicts resolved).
>> 
>> Hi, Wei
>> Thanks for your comments.
>> 
>> iirc, HVM only supports one module;
> 
> This is indeed how it is stated in various comments. I'm not sure why
> there is such restriction. Maybe x86 maintainers can shed more light on
> this?

Not me, sorry. Maybe ask whoever has written that code?

Jan
Wei Liu Aug. 22, 2017, 1:44 p.m. UTC | #6
On Fri, Aug 18, 2017 at 07:56:36AM -0600, Jan Beulich wrote:
> >>> On 18.08.17 at 15:45, <wei.liu2@citrix.com> wrote:
> > On Fri, Aug 18, 2017 at 01:45:50PM +0800, Chao Gao wrote:
> >> >
> >> >> > +            }
> >> >> > +        }
> >> >> > +    }
> >> >> 
> >> >> This still looks wrong to me. How do you know acpi_modules[0] is DMAR
> >> >> table?
> >> >> 
> >> >
> >> >Oh, I sorta see why you do this, but I still think this is wrong. The
> >> >DMAR should either be a new module or be joined to the existing one (and
> >> >with all conflicts resolved).
> >> 
> >> Hi, Wei
> >> Thanks for your comments.
> >> 
> >> iirc, HVM only supports one module;
> > 
> > This is indeed how it is stated in various comments. I'm not sure why
> > there is such restriction. Maybe x86 maintainers can shed more light on
> > this?
> 
> Not me, sorry. Maybe ask whoever has written that code?
> 

OK. I have misunderstood the restriction was from hvmloader.
Wei Liu Aug. 22, 2017, 1:48 p.m. UTC | #7
On Fri, Aug 18, 2017 at 01:45:50PM +0800, Chao Gao wrote:
> On Thu, Aug 17, 2017 at 01:28:21PM +0100, Wei Liu wrote:
> >On Thu, Aug 17, 2017 at 12:32:17PM +0100, Wei Liu wrote:
> >> On Wed, Aug 09, 2017 at 04:34:10PM -0400, Lan Tianyu wrote:
> >> > diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
> >> > index f54fd49..94c9196 100644
> >> > --- a/tools/libxl/libxl_dom.c
> >> > +++ b/tools/libxl/libxl_dom.c
> >> > @@ -1060,6 +1060,42 @@ static int libxl__domain_firmware(libxl__gc *gc,
> >> >          }
> >> >      }
> >> >  
> >> > +    /*
> >> > +     * If a guest has one virtual VTD, build DMAR table for it and joint this
> >> > +     * table with existing content in acpi_modules in order to employ HVM
> >> > +     * firmware pass-through mechanism to pass-through DMAR table.
> >> > +     */
> >> > +    if (info->viommu.type == LIBXL_VIOMMU_TYPE_INTEL_VTD) {
> >> > +        datalen = 0;
> >> > +        e = libxl__dom_build_dmar(gc, info, dom, &data, &datalen);
> >> > +        if (e) {
> >> > +            LOGEV(ERROR, e, "failed to build DMAR table");
> >> > +            rc = ERROR_FAIL;
> >> > +            goto out;
> >> > +        }
> >> > +        if (datalen) {
> >> > +            libxl__ptr_add(gc, data);
> >> > +            if (!dom->acpi_modules[0].data) {
> >> > +                dom->acpi_modules[0].data = data;
> >> > +                dom->acpi_modules[0].length = (uint32_t)datalen;
> >> > +            } else {
> >> > +                /* joint tables */
> >> > +                void *newdata;
> >> > +                newdata = malloc(datalen + dom->acpi_modules[0].length);
> >> 
> >> All memory allocations in libxl should use libxl__*lloc wrappers.
> >> 
> >> > +                if (!newdata) {
> >> > +                    LOGE(ERROR, "failed to joint DMAR table to acpi modules");
> >> > +                    rc = ERROR_FAIL;
> >> > +                    goto out;
> >> > +                }
> >> > +                memcpy(newdata, dom->acpi_modules[0].data,
> >> > +                       dom->acpi_modules[0].length);
> >> > +                memcpy(newdata + dom->acpi_modules[0].length, data, datalen);
> >> > +                dom->acpi_modules[0].data = newdata;
> >> > +                dom->acpi_modules[0].length += (uint32_t)datalen;
> >
> >Also, this leaks the old pointer, right?
> 
> Yes. Will fix this.
> 
> >
> >> > +            }
> >> > +        }
> >> > +    }
> >> 
> >> This still looks wrong to me. How do you know acpi_modules[0] is DMAR
> >> table?
> >> 
> >
> >Oh, I sorta see why you do this, but I still think this is wrong. The
> >DMAR should either be a new module or be joined to the existing one (and
> >with all conflicts resolved).
> 
> Hi, Wei
> Thanks for your comments.
> 
> iirc, HVM only supports one module; DMAR cannot be a new module. Joining to
> the existing one is the approach we are taking. 
> 
> Which kind of conflicts you think should be resolved? If you mean I
> forget to free the old buf, I will fix this. If you mean the potential
> overlap between the binary passed by admin and DMAR table built here, I
> don't have much idea on this. Even without the DMAR table, the binary
> may contains MADT or other tables and tool stacks don't intrepret the
> binary and check whether there are conflicts, right?
> 

Thinking a bit more about this, when I first said "conflicts" I didn't
mean to parse the content. I was referring to the code in
libxl_x86_apci.c which also seems to manipulate acpi_modules.

I would like the code to generate dmar take into consideration
libxl__dom_load_acpi.
lan,Tianyu Aug. 23, 2017, 5:35 a.m. UTC | #8
On 2017年08月22日 21:48, Wei Liu wrote:
>> > Hi, Wei
>> > Thanks for your comments.
>> > 
>> > iirc, HVM only supports one module; DMAR cannot be a new module. Joining to
>> > the existing one is the approach we are taking. 
>> > 
>> > Which kind of conflicts you think should be resolved? If you mean I
>> > forget to free the old buf, I will fix this. If you mean the potential
>> > overlap between the binary passed by admin and DMAR table built here, I
>> > don't have much idea on this. Even without the DMAR table, the binary
>> > may contains MADT or other tables and tool stacks don't intrepret the
>> > binary and check whether there are conflicts, right?
>> > 
> Thinking a bit more about this, when I first said "conflicts" I didn't
> mean to parse the content. I was referring to the code in
> libxl_x86_apci.c which also seems to manipulate acpi_modules.

Code in libxl_x86_acpi.c works for Hvmlite/PVHv2. The code we added is
for hvm guest.

> 
> I would like the code to generate dmar take into consideration
> libxl__dom_load_acpi.
> 

If add dmar table for hvmlite, we should combine dmar table with other
ACPI table and populate into acpi_modules[2]. This is how hvmlite add
other ACPI tables in libxl__dom_load_acpi().
Wei Liu Aug. 23, 2017, 8:34 a.m. UTC | #9
On Wed, Aug 23, 2017 at 01:35:17PM +0800, Lan Tianyu wrote:
> On 2017年08月22日 21:48, Wei Liu wrote:
> >> > Hi, Wei
> >> > Thanks for your comments.
> >> > 
> >> > iirc, HVM only supports one module; DMAR cannot be a new module. Joining to
> >> > the existing one is the approach we are taking. 
> >> > 
> >> > Which kind of conflicts you think should be resolved? If you mean I
> >> > forget to free the old buf, I will fix this. If you mean the potential
> >> > overlap between the binary passed by admin and DMAR table built here, I
> >> > don't have much idea on this. Even without the DMAR table, the binary
> >> > may contains MADT or other tables and tool stacks don't intrepret the
> >> > binary and check whether there are conflicts, right?
> >> > 
> > Thinking a bit more about this, when I first said "conflicts" I didn't
> > mean to parse the content. I was referring to the code in
> > libxl_x86_apci.c which also seems to manipulate acpi_modules.
> 
> Code in libxl_x86_acpi.c works for Hvmlite/PVHv2. The code we added is
> for hvm guest.
> 

That's correct for the code as-is but what is preventing the code there
from working with HVM? Assuming correct checks and branches are added
to appropriate places?

I'm against having multiple locations doing things that could
potentially clash with each other. In the foreseeable future PVH is
going to get need similar functionality.

My expectation is that if the existing code needs to be taken into
consideration and the contributors need to figure out if and how it can
be modified to suite their needs. If everyone is doing their own thing
in their own little function Xen will eventually become unmaintainable.

> > 
> > I would like the code to generate dmar take into consideration
> > libxl__dom_load_acpi.
> > 
> 
> If add dmar table for hvmlite, we should combine dmar table with other
> ACPI table and populate into acpi_modules[2]. This is how hvmlite add
> other ACPI tables in libxl__dom_load_acpi().
> 

Sure, that sounds plausible.

What I would like to see is to have one entry point to manipulate APCI
tables.

Given the patch volume we're seeing now, we expect contributors to drive
the discussion forward. If you're not sure, feel free to ask more questions.

> 
> -- 
> Best regards
> Tianyu Lan
lan,Tianyu Aug. 24, 2017, 3:24 a.m. UTC | #10
On 2017年08月23日 16:34, Wei Liu wrote:
> On Wed, Aug 23, 2017 at 01:35:17PM +0800, Lan Tianyu wrote:
>> On 2017年08月22日 21:48, Wei Liu wrote:
>>>>> Hi, Wei
>>>>> Thanks for your comments.
>>>>>
>>>>> iirc, HVM only supports one module; DMAR cannot be a new module. Joining to
>>>>> the existing one is the approach we are taking. 
>>>>>
>>>>> Which kind of conflicts you think should be resolved? If you mean I
>>>>> forget to free the old buf, I will fix this. If you mean the potential
>>>>> overlap between the binary passed by admin and DMAR table built here, I
>>>>> don't have much idea on this. Even without the DMAR table, the binary
>>>>> may contains MADT or other tables and tool stacks don't intrepret the
>>>>> binary and check whether there are conflicts, right?
>>>>>
>>> Thinking a bit more about this, when I first said "conflicts" I didn't
>>> mean to parse the content. I was referring to the code in
>>> libxl_x86_apci.c which also seems to manipulate acpi_modules.
>>
>> Code in libxl_x86_acpi.c works for Hvmlite/PVHv2. The code we added is
>> for hvm guest.
>>
> 
> That's correct for the code as-is but what is preventing the code there
> from working with HVM? Assuming correct checks and branches are added
> to appropriate places?
> 
> I'm against having multiple locations doing things that could
> potentially clash with each other. In the foreseeable future PVH is
> going to get need similar functionality.
> 
> My expectation is that if the existing code needs to be taken into
> consideration and the contributors need to figure out if and how it can
> be modified to suite their needs. If everyone is doing their own thing
> in their own little function Xen will eventually become unmaintainable.
> 
>>>
>>> I would like the code to generate dmar take into consideration
>>> libxl__dom_load_acpi.
>>>
>>
>> If add dmar table for hvmlite, we should combine dmar table with other
>> ACPI table and populate into acpi_modules[2]. This is how hvmlite add
>> other ACPI tables in libxl__dom_load_acpi().
>>
> 
> Sure, that sounds plausible.
> 
> What I would like to see is to have one entry point to manipulate APCI
> tables.
> 
> Given the patch volume we're seeing now, we expect contributors to drive
> the discussion forward. If you're not sure, feel free to ask more questions.

I am not sure whether I understood correctly.

PVHv2 builds all ACPI table in tool stack and uses acpi_module[0, 1, 2]
to pass related table content.

HVM builds ACPI tables in hvmloader and just use acpi_module[0] to pass
additional ACPI firmware or table.

These two modes have different way to use acpi_modules[]. So I think we
can't combine them, right?

For build dmar table, we have introduced construct_dmar() in under
libacpi to build dmar table and PVHv2 also can use it in
libxl__dom_load_acpi().
Wei Liu Aug. 24, 2017, 11:08 a.m. UTC | #11
On Thu, Aug 24, 2017 at 11:24:12AM +0800, Lan Tianyu wrote:
> On 2017年08月23日 16:34, Wei Liu wrote:
> >>>
> >>> I would like the code to generate dmar take into consideration
> >>> libxl__dom_load_acpi.
> >>>
> >>
> >> If add dmar table for hvmlite, we should combine dmar table with other
> >> ACPI table and populate into acpi_modules[2]. This is how hvmlite add
> >> other ACPI tables in libxl__dom_load_acpi().
> >>
> > 
> > Sure, that sounds plausible.
> > 
> > What I would like to see is to have one entry point to manipulate APCI
> > tables.
> > 
> > Given the patch volume we're seeing now, we expect contributors to drive
> > the discussion forward. If you're not sure, feel free to ask more questions.
> 
> I am not sure whether I understood correctly.
> 
> PVHv2 builds all ACPI table in tool stack and uses acpi_module[0, 1, 2]
> to pass related table content.
> 
> HVM builds ACPI tables in hvmloader and just use acpi_module[0] to pass
> additional ACPI firmware or table.
> 
> These two modes have different way to use acpi_modules[]. So I think we
> can't combine them, right?
> 

There might be some misunderstanding.  We probably don't want to
manipulate the content of the tables in libxl.

> For build dmar table, we have introduced construct_dmar() in under
> libacpi to build dmar table and PVHv2 also can use it in
> libxl__dom_load_acpi().
> 

My major complain is now there are two functions and in two different
locations, in two different phases of domain construction that would
manipulate ACPI tables. I would like to have only one.

The function you're currently modifying libxl__domain_firmware is not
the right place. It's primary function is to load files from disks.

You should be able to call the function you introduced in
libxl__dom_load_acpi, provided appropriate checks are added.
lan,Tianyu Aug. 25, 2017, 3:19 a.m. UTC | #12
On 2017年08月24日 19:08, Wei Liu wrote:
>>>> If add dmar table for hvmlite, we should combine dmar table with other
>>>> > >> ACPI table and populate into acpi_modules[2]. This is how hvmlite add
>>>> > >> other ACPI tables in libxl__dom_load_acpi().
>>>> > >>
>>> > > 
>>> > > Sure, that sounds plausible.
>>> > > 
>>> > > What I would like to see is to have one entry point to manipulate APCI
>>> > > tables.
>>> > > 
>>> > > Given the patch volume we're seeing now, we expect contributors to drive
>>> > > the discussion forward. If you're not sure, feel free to ask more questions.
>> > 
>> > I am not sure whether I understood correctly.
>> > 
>> > PVHv2 builds all ACPI table in tool stack and uses acpi_module[0, 1, 2]
>> > to pass related table content.
>> > 
>> > HVM builds ACPI tables in hvmloader and just use acpi_module[0] to pass
>> > additional ACPI firmware or table.
>> > 
>> > These two modes have different way to use acpi_modules[]. So I think we
>> > can't combine them, right?
>> > 
> There might be some misunderstanding.  We probably don't want to
> manipulate the content of the tables in libxl.
> 
>> > For build dmar table, we have introduced construct_dmar() in under
>> > libacpi to build dmar table and PVHv2 also can use it in
>> > libxl__dom_load_acpi().
>> > 
> My major complain is now there are two functions and in two different
> locations, in two different phases of domain construction that would
> manipulate ACPI tables. I would like to have only one.
> 
> The function you're currently modifying libxl__domain_firmware is not
> the right place. It's primary function is to load files from disks.
> 
> You should be able to call the function you introduced in
> libxl__dom_load_acpi, provided appropriate checks are added.

But libxl__dom_load_acpi() isn't called on hvm guest code path. It just
works for PVHv2/HVMlite and have some conflict with hvm guest
configuration(i.e, acpi_module).


int libxl__arch_domain_finalise_hw_description(libxl__gc *gc,
                                               libxl_domain_build_info
*info,
                                               struct xc_dom_image *dom)
{
    int rc = 0;

    if ((info->type == LIBXL_DOMAIN_TYPE_HVM) &&
        (info->device_model_version == LIBXL_DEVICE_MODEL_VERSION_NONE)) {
        rc = libxl__dom_load_acpi(gc, info, dom);
        if (rc != 0)
            LOGE(ERROR, "libxl_dom_load_acpi failed");
    }

    return rc;
}
lan,Tianyu Aug. 25, 2017, 7:33 a.m. UTC | #13
On 2017年08月25日 11:19, Lan Tianyu wrote:
> On 2017年08月24日 19:08, Wei Liu wrote:
>>>>> If add dmar table for hvmlite, we should combine dmar table with other
>>>>>>>> ACPI table and populate into acpi_modules[2]. This is how hvmlite add
>>>>>>>> other ACPI tables in libxl__dom_load_acpi().
>>>>>>>>
>>>>>>
>>>>>> Sure, that sounds plausible.
>>>>>>
>>>>>> What I would like to see is to have one entry point to manipulate APCI
>>>>>> tables.
>>>>>>
>>>>>> Given the patch volume we're seeing now, we expect contributors to drive
>>>>>> the discussion forward. If you're not sure, feel free to ask more questions.
>>>>
>>>> I am not sure whether I understood correctly.
>>>>
>>>> PVHv2 builds all ACPI table in tool stack and uses acpi_module[0, 1, 2]
>>>> to pass related table content.
>>>>
>>>> HVM builds ACPI tables in hvmloader and just use acpi_module[0] to pass
>>>> additional ACPI firmware or table.
>>>>
>>>> These two modes have different way to use acpi_modules[]. So I think we
>>>> can't combine them, right?
>>>>
>> There might be some misunderstanding.  We probably don't want to
>> manipulate the content of the tables in libxl.
>>
>>>> For build dmar table, we have introduced construct_dmar() in under
>>>> libacpi to build dmar table and PVHv2 also can use it in
>>>> libxl__dom_load_acpi().
>>>>
>> My major complain is now there are two functions and in two different
>> locations, in two different phases of domain construction that would
>> manipulate ACPI tables. I would like to have only one.
>>
>> The function you're currently modifying libxl__domain_firmware is not
>> the right place. It's primary function is to load files from disks.
>>
>> You should be able to call the function you introduced in
>> libxl__dom_load_acpi, provided appropriate checks are added.
> 
> But libxl__dom_load_acpi() isn't called on hvm guest code path. It just
> works for PVHv2/HVMlite and have some conflict with hvm guest
> configuration(i.e, acpi_module).
> 
> 
> int libxl__arch_domain_finalise_hw_description(libxl__gc *gc,
>                                                libxl_domain_build_info
> *info,
>                                                struct xc_dom_image *dom)
> {
>     int rc = 0;
> 
>     if ((info->type == LIBXL_DOMAIN_TYPE_HVM) &&
>         (info->device_model_version == LIBXL_DEVICE_MODEL_VERSION_NONE)) {
>         rc = libxl__dom_load_acpi(gc, info, dom);
>         if (rc != 0)
>             LOGE(ERROR, "libxl_dom_load_acpi failed");
>     }
> 
>     return rc;
> }

We may remove the check and move introduced code in
libxl__dom_load_acpi(). Run new code just for hvm guest. Does this make
sense?
Wei Liu Aug. 25, 2017, 9:11 a.m. UTC | #14
On Fri, Aug 25, 2017 at 03:33:47PM +0800, Lan Tianyu wrote:
> > 
> > int libxl__arch_domain_finalise_hw_description(libxl__gc *gc,
> >                                                libxl_domain_build_info
> > *info,
> >                                                struct xc_dom_image *dom)
> > {
> >     int rc = 0;
> > 
> >     if ((info->type == LIBXL_DOMAIN_TYPE_HVM) &&
> >         (info->device_model_version == LIBXL_DEVICE_MODEL_VERSION_NONE)) {
> >         rc = libxl__dom_load_acpi(gc, info, dom);
> >         if (rc != 0)
> >             LOGE(ERROR, "libxl_dom_load_acpi failed");
> >     }
> > 
> >     return rc;
> > }
> 
> We may remove the check and move introduced code in
> libxl__dom_load_acpi(). Run new code just for hvm guest. Does this make
> sense?
> 

More or less. Push the check down to libxl__dom_load_acpi

> -- 
> Best regards
> Tianyu Lan
diff mbox

Patch

diff --git a/tools/libxl/libxl_arch.h b/tools/libxl/libxl_arch.h
index 5e1fc60..d8ddd60 100644
--- a/tools/libxl/libxl_arch.h
+++ b/tools/libxl/libxl_arch.h
@@ -78,6 +78,11 @@  int libxl__arch_extra_memory(libxl__gc *gc,
 int libxl__dom_load_acpi(libxl__gc *gc,
                          const libxl_domain_build_info *b_info,
                          struct xc_dom_image *dom);
+
+int libxl__dom_build_dmar(libxl__gc *gc,
+                          const libxl_domain_build_info *b_info,
+                          struct xc_dom_image *dom,
+                          void **data, int *len);
 #endif
 
 #endif
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index f54fd49..94c9196 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -1060,6 +1060,42 @@  static int libxl__domain_firmware(libxl__gc *gc,
         }
     }
 
+    /*
+     * If a guest has one virtual VTD, build DMAR table for it and joint this
+     * table with existing content in acpi_modules in order to employ HVM
+     * firmware pass-through mechanism to pass-through DMAR table.
+     */
+    if (info->viommu.type == LIBXL_VIOMMU_TYPE_INTEL_VTD) {
+        datalen = 0;
+        e = libxl__dom_build_dmar(gc, info, dom, &data, &datalen);
+        if (e) {
+            LOGEV(ERROR, e, "failed to build DMAR table");
+            rc = ERROR_FAIL;
+            goto out;
+        }
+        if (datalen) {
+            libxl__ptr_add(gc, data);
+            if (!dom->acpi_modules[0].data) {
+                dom->acpi_modules[0].data = data;
+                dom->acpi_modules[0].length = (uint32_t)datalen;
+            } else {
+                /* joint tables */
+                void *newdata;
+                newdata = malloc(datalen + dom->acpi_modules[0].length);
+                if (!newdata) {
+                    LOGE(ERROR, "failed to joint DMAR table to acpi modules");
+                    rc = ERROR_FAIL;
+                    goto out;
+                }
+                memcpy(newdata, dom->acpi_modules[0].data,
+                       dom->acpi_modules[0].length);
+                memcpy(newdata + dom->acpi_modules[0].length, data, datalen);
+                dom->acpi_modules[0].data = newdata;
+                dom->acpi_modules[0].length += (uint32_t)datalen;
+            }
+        }
+    }
+
     return 0;
 out:
     assert(rc != 0);
diff --git a/tools/libxl/libxl_x86_acpi.c b/tools/libxl/libxl_x86_acpi.c
index c0a6e32..1fa97ff 100644
--- a/tools/libxl/libxl_x86_acpi.c
+++ b/tools/libxl/libxl_x86_acpi.c
@@ -16,6 +16,7 @@ 
 #include "libxl_arch.h"
 #include <xen/hvm/hvm_info_table.h>
 #include <xen/hvm/e820.h>
+#include "libacpi/acpi2_0.h"
 #include "libacpi/libacpi.h"
 
 #include <xc_dom.h>
@@ -236,6 +237,53 @@  out:
     return rc;
 }
 
+static void *acpi_memalign(struct acpi_ctxt *ctxt, uint32_t size,
+                           uint32_t align)
+{
+    int ret;
+    void *ptr;
+
+    ret = posix_memalign(&ptr, align, size);
+    if (ret != 0 || !ptr)
+        return NULL;
+
+    return ptr;
+}
+
+int libxl__dom_build_dmar(libxl__gc *gc,
+                          const libxl_domain_build_info *b_info,
+                          struct xc_dom_image *dom,
+                          void **data, int *len)
+{
+    struct acpi_config config = { 0 };
+    struct acpi_ctxt ctxt;
+    void *table;
+
+    if ((b_info->type != LIBXL_DOMAIN_TYPE_HVM) ||
+        (b_info->device_model_version == LIBXL_DEVICE_MODEL_VERSION_NONE) ||
+        (b_info->viommu.type != LIBXL_VIOMMU_TYPE_INTEL_VTD))
+        return 0;
+
+    ctxt.mem_ops.alloc = acpi_memalign;
+    ctxt.mem_ops.v2p = virt_to_phys;
+    ctxt.mem_ops.free = acpi_mem_free;
+
+    if (libxl_defbool_val(b_info->viommu.intremap))
+        config.iommu_intremap_supported = true;
+    if (libxl_defbool_val(b_info->viommu.u.intel_vtd.x2apic))
+        config.iommu_x2apic_supported = true;
+    config.iommu_base_addr = b_info->viommu.base_addr;
+
+    config.ioapic_id = 1; /* the IOAPIC_ID used by HVM */
+
+    table = construct_dmar(&ctxt, &config);
+    if ( !table )
+        return ERROR_NOMEM;
+    *data = table;
+    *len = ((struct acpi_header *)table)->length;
+    return 0;
+}
+
 /*
  * Local variables:
  * mode: C