qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH 11/12] Migrate 64bit entries to 64bit pci region


From: Alexey Korolev
Subject: Re: [Qemu-devel] [PATCH 11/12] Migrate 64bit entries to 64bit pci regions
Date: Wed, 25 Apr 2012 18:25:07 +1200
User-agent: Mozilla/5.0 (X11; Linux i686; rv:11.0) Gecko/20120329 Thunderbird/11.0.1

On 25/04/12 13:48, Kevin O'Connor wrote:
> On Tue, Apr 24, 2012 at 06:25:39PM +1200, Alexey Korolev wrote:
>> Migrate 64bit entries to 64bit pci regions if they do
>> not fit in 32bit range.
> [...]
>> +static void pci_region_migrate_64bit_entries(struct pci_region *from,
>> +                                             struct pci_region *to)
>> +{
>> +    struct pci_region_entry **pprev = &from->list;
>> +    struct pci_region_entry **last = &to->list;
>> +    while(*pprev) {
>> +        if ((*pprev)->is64) {
>> +            struct pci_region_entry *entry;
>> +            entry = *pprev;
>> +            /* Delete the entry and move next */
>> +            *pprev = (*pprev)->next;
>> +            /* Add entry at tail to keep a sorted order */
>> +            entry->next = NULL;
>> +            if (*last) {
>> +               (*last)->next = entry;
>> +                last  = &(*last)->next;
>> +            }
>> +            else
>> +               (*last) = entry;
>> +        }
>> +        else
>> +            pprev = &(*pprev)->next;
>> +    }
>> +}
> It should be possible to simplify this - something like (untested):
>
> static void pci_region_migrate_64bit_entries(struct pci_region *from,
>                                              struct pci_region *to)
> {
>     struct pci_region_entry **pprev = &from->list, **last = &to->list;
>     for (; *pprev; pprev = &(*pprev)->next) {
>         struct pci_region_entry *entry = *pprev;
>         if (!entry->is64)
>             continue;
>         // Move from source list to dest list.
>         *pprev = entry->next;
>         entry->next = NULL;
>         *last = entry;
>         last = &entry->next;
>     }
> }
Sorry it's not working.
I agree it's possible to simplify code a bit.


static void pci_region_migrate_64bit_entries(struct pci_region *from,
                                             struct pci_region *to)
{
    struct pci_region_entry **pprev = &from->list;
    struct pci_region_entry **last = &to->list;
    while(*pprev) {
        if ((*pprev)->is64) {
            struct pci_region_entry *entry;
            entry = *pprev;
            /* Delete the entry and move next */
            *pprev = (*pprev)->next;
            /* Add entry at tail to keep the order */
            entry->next = NULL;
            *last = entry;
            last = &entry->next;
        }
        else
            pprev = &(*pprev)->next;
    }
}

That should work.
> [...]
>>  static void pci_bios_map_devices(struct pci_bus *busses)
>>  {
>> +    if (pci_bios_init_root_regions(busses)) {
>> +        struct pci_region r64_mem, r64_pref;
>> +        r64_mem.list = NULL;
>> +        r64_pref.list = NULL;
>> +        pci_region_migrate_64bit_entries(&busses[0].r[PCI_REGION_TYPE_MEM],
>> +                                         &r64_mem);
>> +        
>> pci_region_migrate_64bit_entries(&busses[0].r[PCI_REGION_TYPE_PREFMEM],
>> +                                         &r64_pref);
>> +
>> +        if (pci_bios_init_root_regions(busses))
>> +            panic("PCI: out of address space\n");
>> +
>> +        r64_mem.base = BUILD_PCIMEM64_START;
>> +        r64_pref.base = ALIGN(r64_mem.base + pci_region_sum(&r64_mem),
>> +                              pci_region_align(&r64_pref));
> There should be a check to see if the regions fit.  Maybe pass
> start/end into pci_bios_init_root_regions() and call it again for the
>> 4g region?
Agree, I just ignored the check as 64bit range size is 2^39.
I will think how to make it better.
>> +        pci_region_map_entries(busses, &r64_mem);
>> +        pci_region_map_entries(busses, &r64_pref);
>> +    }
>>      // Map regions on each device.
> This doesn't look right to me.  This will map the devices on bus 0 to
> the proper >4g address, but devices on any subsequent bus will use
> busses[0].r[].base which will be reset to the <4gig address.  Perhaps
> pull base out of pci_region and make pci_region_map_entries()
> recursive?
No recursion is need here!
We map all entries which are 64bit on root bus.
If entry is a bridge region - a corresponding bus address will be updated.
Region won't be reseted to <4gig address as address is derived from parent 
region only.

Thanks,
Alexey




reply via email to

[Prev in Thread] Current Thread [Next in Thread]