qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] Re: Unusual physical address when using 64-bit BAR


From: Avi Kivity
Subject: [Qemu-devel] Re: Unusual physical address when using 64-bit BAR
Date: Tue, 29 Jun 2010 09:50:45 +0300
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.10) Gecko/20100621 Fedora/3.0.5-1.fc13 Thunderbird/3.0.5

On 06/28/2010 11:38 PM, Cam Macdonell wrote:


Is this really the address the guest programmed, or is qemu
misinterpreting
it?

Well, what's the answer?
You're going to have to give me a hint on how to determine that.

lspci in the guest shows the following

Memory at c20000000000 (64-bit, non-prefetchable) [size=1024M]

does that demonstrate a guest generated address?

That's the result of a round trip: the guest programmed the address and then read it back. It could have been screwed up in the first place, or perhaps qemu screwed it up.

Add a printf() to the config space handlers in qemu (likely in your own code) on writes and reads, and show the relevant writes (and reads) for this BAR.

That's the theory of deductive debugging; however browsing the code shows the guest is at fault:

        for (i = 0; i < PCI_NUM_REGIONS; i++) {
            int ofs;
            if (i == PCI_ROM_SLOT)
                ofs = PCI_ROM_ADDRESS;
            else
                ofs = PCI_BASE_ADDRESS_0 + i * 4;

            u32 old = pci_config_readl(bdf, ofs);
            u32 mask;
            if (i == PCI_ROM_SLOT) {
                mask = PCI_ROM_ADDRESS_MASK;
                pci_config_writel(bdf, ofs, mask);
            } else {
                if (old & PCI_BASE_ADDRESS_SPACE_IO)
                    mask = PCI_BASE_ADDRESS_IO_MASK;
                else
                    mask = PCI_BASE_ADDRESS_MEM_MASK;
                pci_config_writel(bdf, ofs, ~0);
            }
            u32 val = pci_config_readl(bdf, ofs);
            pci_config_writel(bdf, ofs, old);

            if (val != 0) {
                u32 size = (~(val & mask)) + 1;
                if (val & PCI_BASE_ADDRESS_SPACE_IO)
                    paddr = &pci_bios_io_addr;
                else
                    paddr = &pci_bios_mem_addr;
                *paddr = ALIGN(*paddr, size);
                pci_set_io_region_addr(bdf, i, *paddr);
                *paddr += size;
            }
        }
        break;
    }

Seabios completely ignore the 64-bitness of the BAR. Looks like it also thinks the second half of the BAR is an I/O region instead of memory (hence the c200, that's part of the pci portio region.

Do post those reads and writes, I think there's more than one thing wrong here.


--
I have a truly marvellous patch that fixes the bug which this
signature is too narrow to contain.




reply via email to

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