[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [v8][PATCH 06/16] hvmloader/pci: disable all pci devices conflicting with rdm



On Thu, Jul 16, 2015 at 7:52 AM, Tiejun Chen <tiejun.chen@xxxxxxxxx> wrote:
> When allocating mmio address for PCI bars, mmio may overlap with
> reserved regions. Currently we just want to disable these associate
> devices simply to avoid conflicts but we will reshape current mmio
> allocation mechanism to fix this completely.

On the whole I still think it would be good to try to relocate BARs if
possible; I would be OK with this if there isn't a better option.

A couple of comments on the patch, however:

>
> CC: Keir Fraser <keir@xxxxxxx>
> CC: Jan Beulich <jbeulich@xxxxxxxx>
> CC: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
> CC: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
> CC: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
> CC: Ian Campbell <ian.campbell@xxxxxxxxxx>
> CC: Wei Liu <wei.liu2@xxxxxxxxxx>
> Signed-off-by: Tiejun Chen <tiejun.chen@xxxxxxxxx>
> ---
> v8:
>
> * Based on current discussion its hard to reshape the original mmio
>   allocation mechanism but we haven't a good and simple way to in short term.
>   So instead, we don't bring more complicated to intervene that process but
>   still check any conflicts to disable all associated devices.
>
> v6 ~ v7:
>
> * Nothing is changed.
>
> v5:
>
> * Rename that field, is_64bar, inside struct bars with flag, and
>   then extend to also indicate if this bar is already allocated.
>
> v4:
>
> * We have to re-design this as follows:
>
>   #1. Goal
>
>   MMIO region should exclude all reserved device memory
>
>   #2. Requirements
>
>   #2.1 Still need to make sure MMIO region is fit all pci devices as before
>
>   #2.2 Accommodate the not aligned reserved memory regions
>
>   If I'm missing something let me know.
>
>   #3. How to
>
>   #3.1 Address #2.1
>
>   We need to either of populating more RAM, or of expanding more highmem. But
>   we should know just 64bit-bar can work with highmem, and as you mentioned we
>   also should avoid expanding highmem as possible. So my implementation is to
>   allocate 32bit-bar and 64bit-bar orderly.
>
>   1>. The first allocation round just to 32bit-bar
>
>   If we can finish allocating all 32bit-bar, we just go to allocate 64bit-bar
>   with all remaining resources including low pci memory.
>
>   If not, we need to calculate how much RAM should be populated to allocate 
> the
>   remaining 32bit-bars, then populate sufficient RAM as exp_mem_resource to go
>   to the second allocation round 2>.
>
>   2>. The second allocation round to the remaining 32bit-bar
>
>   We should can finish allocating all 32bit-bar in theory, then go to the 
> third
>   allocation round 3>.
>
>   3>. The third allocation round to 64bit-bar
>
>   We'll try to first allocate from the remaining low memory resource. If that
>   isn't enough, we try to expand highmem to allocate for 64bit-bar. This 
> process
>   should be same as the original.
>
>   #3.2 Address #2.2
>
>   I'm trying to accommodate the not aligned reserved memory regions:
>
>   We should skip all reserved device memory, but we also need to check if 
> other
>   smaller bars can be allocated if a mmio hole exists between resource->base 
> and
>   reserved device memory. If a hole exists between base and reserved device
>   memory, lets go out simply to try allocate for next bar since all bars are 
> in
>   descending order of size. If not, we need to move resource->base to 
> reserved_end
>   just to reallocate this bar.
>
>  tools/firmware/hvmloader/pci.c | 87 
> ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 87 insertions(+)
>
> diff --git a/tools/firmware/hvmloader/pci.c b/tools/firmware/hvmloader/pci.c
> index 5ff87a7..9e017d5 100644
> --- a/tools/firmware/hvmloader/pci.c
> +++ b/tools/firmware/hvmloader/pci.c
> @@ -38,6 +38,90 @@ uint64_t pci_hi_mem_start = 0, pci_hi_mem_end = 0;
>  enum virtual_vga virtual_vga = VGA_none;
>  unsigned long igd_opregion_pgbase = 0;
>
> +/*
> + * We should check if all valid bars conflict with RDM.
> + *
> + * Here we just need to check mmio bars in the case of non-highmem
> + * since the hypervisor can make sure RDM doesn't involve highmem.
> + */
> +static void disable_conflicting_devices(void)
> +{
> +    uint8_t is_64bar;
> +    uint32_t devfn, bar_reg, cmd, bar_data;
> +    uint16_t vendor_id, device_id;
> +    unsigned int bar, i;
> +    uint64_t bar_sz;
> +    bool is_conflict = false;
> +
> +    for ( devfn = 0; devfn < 256; devfn++ )
> +    {
> +        vendor_id = pci_readw(devfn, PCI_VENDOR_ID);
> +        device_id = pci_readw(devfn, PCI_DEVICE_ID);
> +        if ( (vendor_id == 0xffff) && (device_id == 0xffff) )
> +            continue;
> +
> +        /* Check all bars */
> +        for ( bar = 0; bar < 7; bar++ )
> +        {
> +            bar_reg = PCI_BASE_ADDRESS_0 + 4*bar;
> +            if ( bar == 6 )
> +                bar_reg = PCI_ROM_ADDRESS;
> +
> +            bar_data = pci_readl(devfn, bar_reg);
> +            bar_data &= PCI_BASE_ADDRESS_MEM_MASK;
> +            if ( !bar_data )
> +                continue;
> +
> +            if ( bar_reg != PCI_ROM_ADDRESS )
> +                is_64bar = !!((bar_data & (PCI_BASE_ADDRESS_SPACE |
> +                             PCI_BASE_ADDRESS_MEM_TYPE_MASK)) ==
> +                             (PCI_BASE_ADDRESS_SPACE_MEMORY |
> +                             PCI_BASE_ADDRESS_MEM_TYPE_64));
> +
> +            /* Until here we never conflict high memory. */
> +            if ( is_64bar && pci_readl(devfn, bar_reg + 4) )
> +                continue;
> +
> +            /* Just check mmio bars. */
> +            if ( ((bar_data & PCI_BASE_ADDRESS_SPACE) ==
> +                  PCI_BASE_ADDRESS_SPACE_IO) )
> +                continue;
> +
> +            bar_sz = pci_readl(devfn, bar_reg);
> +            bar_sz &= PCI_BASE_ADDRESS_MEM_MASK;
> +
> +            for ( i = 0; i < memory_map.nr_map ; i++ )
> +            {
> +                if ( memory_map.map[i].type != E820_RAM )

Here we're assuming that any region not marked as RAM is an RMRR.  Is that true?

In any case, it would be just as strange to have a device BAR overlap
with guest RAM as with an RMRR, wouldn't it?

> +                {
> +                    uint64_t reserved_start, reserved_size;
> +                    reserved_start = memory_map.map[i].addr;
> +                    reserved_size = memory_map.map[i].size;
> +                    if ( check_overlap(bar_data , bar_sz,
> +                                   reserved_start, reserved_size) )
> +                    {
> +                        is_conflict = true;
> +                        /* Now disable the memory or I/O mapping. */
> +                        printf("pci dev %02x:%x bar %02x : 0x%08x : 
> conflicts "
> +                               "reserved resource so disable this 
> device.!\n",
> +                               devfn>>3, devfn&7, bar_reg, bar_data);
> +                        cmd = pci_readw(devfn, PCI_COMMAND);
> +                        pci_writew(devfn, PCI_COMMAND, ~cmd);
> +                        break;
> +                    }
> +                }
> +
> +                /* Jump next device. */
> +                if ( is_conflict )
> +                {
> +                    is_conflict = false;
> +                    break;
> +                }

This conditional is still inside the memory_map loop; you want it one
loop futher out, in the bar loop, don't you?

Also, if you declare is_conflict inside the devfn loop, rather than in
the main function, then you don't need this "is_conflict=false" here.

It might also be more sensible to use a goto instead; but this is one
where Jan will have a better idea what standard practice will be.

 -George

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.