[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |