--- tools/firmware/hvmloader/acpi/dsdt.asl 2011-08-13 18:43:39.000000000 +0200 +++ tools/firmware/hvmloader/acpi/dsdt.asl 2011-08-13 18:58:25.000000000 +0200 @@ -173,15 +173,43 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, 0x00000000, 0x00020000) + /* reserve MMIO BARs of gfx for 1:1 mapping */ DWordMemory( ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite, 0x00000000, - 0xF0000000, - 0xF4FFFFFF, + 0xFA000000, + 0xFAFFFFFF, 0x00000000, - 0x05000000, - ,, _Y01) + 0x01000000) + + DWordMemory( + ResourceProducer, PosDecode, MinFixed, MaxFixed, + NonCacheable, ReadWrite, + 0x00000000, + 0xC0000000, + 0xCFFFFFFF, + 0x00000000, + 0x10000000) + + DWordMemory( + ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, + 0xD0000000, + 0xD1FFFFFF, + 0x00000000, + 0x02000000) + + DWordMemory( + ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, + 0xFB000000, + 0xFB07FFFF, + 0x00000000, + 0x00080000, + ,, _Y01) }) CreateDWordField(PRT0, \_SB.PCI0._CRS._Y01._MIN, MMIN) --- tools/firmware/hvmloader/hvmloader.c 2011-08-13 18:43:39.000000000 +0200 +++ tools/firmware/hvmloader/hvmloader.c 2011-08-13 19:16:21.000000000 +0200 @@ -31,6 +31,7 @@ #include #define ROM_INCLUDE_VGABIOS +#define ROM_INCLUDE_PTVGABIOS #define ROM_INCLUDE_ETHERBOOT #include "roms.inc" @@ -113,6 +114,9 @@ asm ( unsigned long scratch_start = SCRATCH_PHYSICAL_ADDRESS; +/* virtual BDF of pass-throughed gfx */ +uint8_t gfx_bdf; + static void init_hypercalls(void) { uint32_t eax, ebx, ecx, edx; @@ -310,6 +314,20 @@ static int pci_load_option_roms(unsigned return rom_phys_addr - rom_base_addr; } +static void init_vm86_tss(void) +{ + void *tss; + struct xen_hvm_param p; + + tss = mem_alloc(128, 128); + memset(tss, 0, 128); + p.domid = DOMID_SELF; + p.index = HVM_PARAM_VM86_TSS; + p.value = virt_to_phys(tss); + hypercall_hvm_op(HVMOP_set_param, &p); + printf("vm86 TSS at %08lx\n", virt_to_phys(tss)); +} + /* Replace possibly erroneous memory-size CMOS fields with correct values. */ static void cmos_write_memory_size(void) { @@ -336,25 +354,6 @@ static void cmos_write_memory_size(void) cmos_outb(0x35, (uint8_t)( alt_mem >> 8)); } -/* - * Set up an empty TSS area for virtual 8086 mode to use. - * The only important thing is that it musn't have any bits set - * in the interrupt redirection bitmap, so all zeros will do. - */ -static void init_vm86_tss(void) -{ - void *tss; - struct xen_hvm_param p; - - tss = mem_alloc(128, 128); - memset(tss, 0, 128); - p.domid = DOMID_SELF; - p.index = HVM_PARAM_VM86_TSS; - p.value = virt_to_phys(tss); - hypercall_hvm_op(HVMOP_set_param, &p); - printf("vm86 TSS at %08lx\n", virt_to_phys(tss)); -} - static void apic_setup(void) { /* Set the IOAPIC ID to the static value used in the MP/ACPI tables. */ @@ -487,8 +486,10 @@ int main(void) break; case VGA_pt: printf("Loading VGABIOS of passthroughed gfx ...\n"); - vgabios_sz = round_option_rom( - (*(uint8_t *)(VGABIOS_PHYSICAL_ADDRESS+2)) * 512); + memcpy((void *)VGABIOS_PHYSICAL_ADDRESS, + vgabios_pt, sizeof(vgabios_pt)); + *(uint8_t *)(VGABIOS_PHYSICAL_ADDRESS + sizeof(vgabios_pt)) = gfx_bdf; + vgabios_sz = round_option_rom(sizeof(vgabios_pt) + 1); break; default: printf("No emulated VGA adaptor ...\n"); @@ -525,7 +526,7 @@ int main(void) hypercall_hvm_op(HVMOP_set_param, &p); } - init_vm86_tss(); + init_vm86_tss(); cmos_write_memory_size(); --- tools/firmware/hvmloader/Makefile 2011-08-13 18:43:39.000000000 +0200 +++ tools/firmware/hvmloader/Makefile 2011-08-13 18:58:36.000000000 +0200 @@ -56,6 +56,7 @@ CIRRUSVGA_ROM := ../vgabios/VGABIOS-lgpl else CIRRUSVGA_ROM := ../vgabios/VGABIOS-lgpl-latest.cirrus.bin endif +PTVGA_ROM := ../vgabios/vgabios-pt.bin .PHONY: all all: subdirs-all @@ -94,6 +95,11 @@ ifneq ($(CIRRUSVGA_ROM),) sh ./mkhex vgabios_cirrusvga $(CIRRUSVGA_ROM) >> $@.new echo "#endif" >> $@.new endif +ifneq ($(PTVGA_ROM),) + echo "#ifdef ROM_INCLUDE_PTVGABIOS" >> $@.new + sh ./mkhex vgabios_pt $(PTVGA_ROM) >> $@.new + echo "#endif" >> $@.new +endif echo "#ifdef ROM_INCLUDE_ETHERBOOT" >> $@.new cat ../etherboot/eb-roms.h >> $@.new --- tools/ioemu-remote/hw/pass-through.c 2011-08-13 23:15:13.000000000 +0200 +++ tools/ioemu-remote/hw/pass-through.c 2011-08-13 18:58:41.000000000 +0200 @@ -3243,6 +3243,8 @@ static int pt_cmd_reg_read(struct pt_dev } /* read BAR */ +static int gfx_first_read_BAR[7] = {1, 1, 1, 1, 1, 1, 1}; + static int pt_bar_reg_read(struct pt_dev *ptdev, struct pt_reg_tbl *cfg_entry, uint32_t *value, uint32_t valid_mask) @@ -3265,6 +3267,17 @@ static int pt_bar_reg_read(struct pt_dev /* use fixed-up value from kernel sysfs */ *value = ptdev->pci_dev->base_addr[index]; + if ( ptdev->pci_dev->device_class == 0x300 ) + { + if ( gfx_first_read_BAR[index] == 1 ) + { + gfx_first_read_BAR[index] = 0; + PT_LOG("first read BARs of gfx\n"); + return 0; + } + } + + /* set emulate mask depend on BAR flag */ switch (ptdev->bases[index].bar_flag) { --- tools/firmware/hvmloader/pci.c 2011-08-13 18:43:39.000000000 +0200 +++ tools/firmware/hvmloader/pci.c 2011-08-13 18:58:53.000000000 +0200 @@ -33,6 +33,10 @@ unsigned long pci_mem_end = PCI_MEM_END; enum virtual_vga virtual_vga = VGA_none; +/* virtual BDF of pass-throughed gfx declared in hvmloader.c*/ +extern uint8_t gfx_bdf; + + void pci_setup(void) { uint32_t base, devfn, bar_reg, bar_data, bar_sz, cmd, mmio_total = 0; @@ -93,9 +97,44 @@ void pci_setup(void) } else if ( virtual_vga == VGA_none ) { - vga_devfn = devfn; - virtual_vga = VGA_pt; + virtual_vga = VGA_pt; + gfx_bdf = devfn; + + /* Make vBAR=pBAR */ + printf("Make vBAR = pBAR of assigned gfx\n"); + for ( bar = 0; bar < 7; bar++ ) + { + bar_reg = PCI_BASE_ADDRESS_0 + 4*bar; + if ( bar == 6 ) + bar_reg = PCI_ROM_ADDRESS; + /* When first time read, it will return physical address */ + bar_data = pci_readl(devfn, bar_reg); + pci_writel(devfn, bar_reg, bar_data); + + /* Now enable the memory or I/O mapping. */ + cmd = pci_readw(devfn, PCI_COMMAND); + if ( (bar_reg == PCI_ROM_ADDRESS) || + ((bar_data & PCI_BASE_ADDRESS_SPACE) == + PCI_BASE_ADDRESS_SPACE_MEMORY) ) + cmd |= PCI_COMMAND_MEMORY; + else + cmd |= PCI_COMMAND_IO; + cmd |= PCI_COMMAND_MASTER; + pci_writew(devfn, PCI_COMMAND, cmd); + } + + /* Map the interrupt. */ + pin = pci_readb(devfn, PCI_INTERRUPT_PIN); + if ( pin != 0 ) + { + /* This is the barber's pole mapping used by Xen. */ + link = ((pin - 1) + (devfn >> 3)) & 3; + isa_irq = pci_readb(PCI_ISA_DEVFN, 0x60 + link); + pci_writeb(devfn, PCI_INTERRUPT_LINE, isa_irq); + } + continue; } + break; case 0x0680: /* PIIX4 ACPI PM. Special device with special PCI config space. */