|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [RFC PATCH 06/12] hvmloader: add basic Q35 support
On Mon, 19 Mar 2018 15:30:14 +0000
Roger Pau Monné <roger.pau@xxxxxxxxxx> wrote:
>On Tue, Mar 13, 2018 at 04:33:51AM +1000, Alexey Gerasimenko wrote:
>> This patch does following:
>>
>> 1. Move PCI-device specific initialization out of pci_setup function
>> to the newly created class_specific_pci_device_setup function to
>> simplify code.
>>
>> 2. PCI-device specific initialization extended with LPC controller
>> initialization
>>
>> 3. Initialize PIRQA...{PIRQD, PIRQH} routing accordingly to the
>> emulated south bridge (either located on PCI_ISA_DEVFN or
>> PCI_ICH9_LPC_DEVFN).
>>
>> Signed-off-by: Alexey Gerasimenko <x1917x@xxxxxxxxx>
>> ---
>> tools/firmware/hvmloader/config.h | 1 +
>> tools/firmware/hvmloader/pci.c | 162
>> ++++++++++++++++++++++++-------------- 2 files changed, 104
>> insertions(+), 59 deletions(-)
>>
>> diff --git a/tools/firmware/hvmloader/config.h
>> b/tools/firmware/hvmloader/config.h index 6e00413f2e..6fde6b7b60
>> 100644 --- a/tools/firmware/hvmloader/config.h
>> +++ b/tools/firmware/hvmloader/config.h
>> @@ -52,6 +52,7 @@ extern uint8_t ioapic_version;
>>
>> #define PCI_ISA_DEVFN 0x08 /* dev 1, fn 0 */
>> #define PCI_ISA_IRQ_MASK 0x0c20U /* ISA IRQs 5,10,11 are PCI
>> connected */ +#define PCI_ICH9_LPC_DEVFN 0xf8 /* dev 31, fn 0 */
>>
>> /* MMIO hole: Hardcoded defaults, which can be dynamically
>> expanded. */ #define PCI_MEM_END 0xfc000000
>> diff --git a/tools/firmware/hvmloader/pci.c
>> b/tools/firmware/hvmloader/pci.c index 0b708bf578..033bd20992 100644
>> --- a/tools/firmware/hvmloader/pci.c
>> +++ b/tools/firmware/hvmloader/pci.c
>> @@ -35,6 +35,7 @@ unsigned long pci_mem_end = PCI_MEM_END;
>> uint64_t pci_hi_mem_start = 0, pci_hi_mem_end = 0;
>>
>> enum virtual_vga virtual_vga = VGA_none;
>> +uint32_t vga_devfn = 256;
>
>uint8_t should be enough to store a devfn. Also this should be static
>maybe?
Yep, forgot 'static'. Changing uint32_t to uint8_t here will require
to change the
' if ( vga_devfn != 256 )' condition as well -- it's a bit out of the
patch scope, probably a separate tiny patch would be better.
>> unsigned long igd_opregion_pgbase = 0;
>>
>> /* Check if the specified range conflicts with any reserved device
>> memory. */ @@ -76,14 +77,93 @@ static int find_next_rmrr(uint32_t
>> base) return next_rmrr;
>> }
>>
>> +#define SCI_EN_IOPORT (ACPI_PM1A_EVT_BLK_ADDRESS_V1 + 0x30)
>> +#define GBL_SMI_EN (1 << 0)
>> +#define APMC_EN (1 << 5)
>
>Alignment.
Will correct.
>> +
>> +static void class_specific_pci_device_setup(uint16_t vendor_id,
>> + uint16_t device_id,
>> + uint8_t bus, uint8_t
>> devfn) +{
>> + uint16_t class;
>> +
>> + class = pci_readw(devfn, PCI_CLASS_DEVICE);
>> +
>> + switch ( class )
>
>switch ( pci_readw(devfn, PCI_CLASS_DEVICE) ) ?
>
>I don't see class being used elsewhere.
>Also why is vendor_id/device_id provided by the caller but not class?
>It seems kind of pointless.
'class' is not used by pci_setup(), thus moved to
class_specific_pci_device_setup().
pci_readw(devfn, PCI_CLASS_DEVICE) inside the switch condition to drop
the variable -- sure, agree.
Passing vendor_id/device_id pair via function args allows to avoid
reading the vendor_id/device_id from PCI conf twice -- a bit less
garbage in the polluted PCI setup debuglog. It's not a big problem
really, so this can be changed to passing only BDF to
class_specific_pci_device_setup().
>Why not fetch vendor/device from the function itself and move the
>(vendor_id == 0xffff) && (device_id == 0xffff) check inside the
>function?
Hmm, this is a part of the PCI bus enumeration, not PCI device setup.
>Also in this case I think it would be better to have a non-functional
>patch that introduces class_specific_pci_device_setup and a second
>patch that adds support for ICH9.
>
>Having code movement and new code in the same patch makes it harder to
>very what you are actually moving vs introducing.
Agree, will split this actions to separate patches for the next version.
>> + {
>> + case 0x0300:
>
>All this values need to be defines documented somewhere.
Agree... although it was not me who introduced all these hardcoded PCI
class values. :) I'll change these numbers into newly added pci_regs.h
#defines in the non-functional patch.
>> + /* If emulated VGA is found, preserve it as primary VGA. */
>> + if ( (vendor_id == 0x1234) && (device_id == 0x1111) )
>> + {
>> + vga_devfn = devfn;
>> + virtual_vga = VGA_std;
>> + }
>> + else if ( (vendor_id == 0x1013) && (device_id == 0xb8) )
>> + {
>> + vga_devfn = devfn;
>> + virtual_vga = VGA_cirrus;
>> + }
>> + else if ( virtual_vga == VGA_none )
>> + {
>> + vga_devfn = devfn;
>> + virtual_vga = VGA_pt;
>> + if ( vendor_id == 0x8086 )
>> + {
>> + igd_opregion_pgbase =
>> mem_hole_alloc(IGD_OPREGION_PAGES);
>> + /*
>> + * Write the the OpRegion offset to give the
>> opregion
>> + * address to the device model. The device model
>> will trap
>> + * and map the OpRegion at the give address.
>> + */
>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>> + igd_opregion_pgbase << PAGE_SHIFT);
>> + }
>> + }
>> + break;
>> +
>> + case 0x0680:
>> + /* PIIX4 ACPI PM. Special device with special PCI config
>> space. */
>> + ASSERT((vendor_id == 0x8086) && (device_id == 0x7113));
>> + pci_writew(devfn, 0x20, 0x0000); /* No smb bus IO enable */
>> + pci_writew(devfn, 0xd2, 0x0000); /* No smb bus IO enable */
>> + pci_writew(devfn, 0x22, 0x0000);
>> + pci_writew(devfn, 0x3c, 0x0009); /* Hardcoded IRQ9 */
>> + pci_writew(devfn, 0x3d, 0x0001);
>> + pci_writel(devfn, 0x40, ACPI_PM1A_EVT_BLK_ADDRESS_V1 | 1);
>> + pci_writeb(devfn, 0x80, 0x01); /* enable PM io space */
>> + break;
>> +
>> + case 0x0601:
>> + /* LPC bridge */
>> + if (vendor_id == 0x8086 && device_id == 0x2918)
>> + {
>> + pci_writeb(devfn, 0x3c, 0x09); /* Hardcoded IRQ9 */
>> + pci_writeb(devfn, 0x3d, 0x01);
>> + pci_writel(devfn, 0x40, ACPI_PM1A_EVT_BLK_ADDRESS_V1 |
>> 1);
>> + pci_writeb(devfn, 0x44, 0x80); /* enable PM io space */
>> + outl(SCI_EN_IOPORT, inl(SCI_EN_IOPORT) | GBL_SMI_EN |
>> APMC_EN);
>> + }
>> + break;
>> +
>> + case 0x0101:
>> + if ( vendor_id == 0x8086 )
>> + {
>> + /* Intel ICHs since PIIX3: enable IDE legacy mode. */
>> + pci_writew(devfn, 0x40, 0x8000); /* enable IDE0 */
>> + pci_writew(devfn, 0x42, 0x8000); /* enable IDE1 */
>> + }
>> + break;
>> + }
>> +}
>> +
>> void pci_setup(void)
>> {
>> uint8_t is_64bar, using_64bar, bar64_relocate = 0;
>> uint32_t devfn, bar_reg, cmd, bar_data, bar_data_upper;
>> uint64_t base, bar_sz, bar_sz_upper, mmio_total = 0;
>> - uint32_t vga_devfn = 256;
>> - uint16_t class, vendor_id, device_id;
>> + uint16_t vendor_id, device_id;
>> unsigned int bar, pin, link, isa_irq;
>> + int is_running_on_q35 = 0;
>
>bool is_running_on_q35 = (get_pc_machine_type() == MACHINE_TYPE_Q35);
OK
>>
>> /* Resources assignable to PCI devices via BARs. */
>> struct resource {
>> @@ -130,13 +210,28 @@ void pci_setup(void)
>> if ( s )
>> mmio_hole_size = strtoll(s, NULL, 0);
>>
>> + /* check if we are on Q35 and set the flag if it is the case */
>> + is_running_on_q35 = get_pc_machine_type() == MACHINE_TYPE_Q35;
>> +
>> /* Program PCI-ISA bridge with appropriate link routes. */
>> isa_irq = 0;
>> for ( link = 0; link < 4; link++ )
>> {
>> do { isa_irq = (isa_irq + 1) & 15;
>> } while ( !(PCI_ISA_IRQ_MASK & (1U << isa_irq)) );
>> - pci_writeb(PCI_ISA_DEVFN, 0x60 + link, isa_irq);
>> +
>> + if (is_running_on_q35)
>
>Coding style.
OK
>> + {
>> + pci_writeb(PCI_ICH9_LPC_DEVFN, 0x60 + link, isa_irq);
>> +
>> + /* PIRQE..PIRQH are unused */
>> + pci_writeb(PCI_ICH9_LPC_DEVFN, 0x68 + link, 0x80);
>
>According to the spec 0x80 is the default value for this registers, do
>you really need to write it?
>
>Is maybe QEMU not correctly setting the default value?
Won't agree here. We're initializing PIRQ[n] routing in this
fragment, it's better not to rely on any values but simply initialize
all PIRQ[n]_ROUT registers, this makes it explicit.
Even if it is unnecessary due to defaults it's more obvious to set
these registers to our own values than to force a reader to either look
up their emulation in QEMU code or read the ICH9 pdf to confirm
assumptions.
>> + }
>> + else
>> + {
>> + pci_writeb(PCI_ISA_DEVFN, 0x60 + link, isa_irq);
>
>Is all this magic described somewhere that you can reference?
It's setting up PCI interrupt routing for PIC mode. All this
PIRQ[n]_ROUT stuff basically needed for legacy compatibility only,
normally we deal with APIC mode (+MSIs).
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |