This seems like the easier approach from my RFC yesterday. Instead
of trying to make ich9 interrupt mapping look like piix, just add a
new slot-to-irq function so we can not only get bus 0 devices, but
root ports fixed as well. The change from piix mapping is subtle,
but required for device assignment. Additionally, fix the PIRQn
initialization value, enabling the interrupts for boot ROMs. Thanks,
Alex Williamson (2):
q35: Enable all PIRQn IRQs at startup
q35: Add new PCI slot to irq routing function
src/pciinit.c | 41 ++++++++++++++++++++++++++++++++++++-----
1 file changed, 36 insertions(+), 5 deletions(-)
I was trying to revive the patch to add Qemu INTx routing support for
Q35 and stumbled on some rather broken interrupt routing problems.
Sadly a seabios release claiming Q35 support snuck out already, but
I'd like to at least discuss these before Qemu 1.4 even though they
may not get fixed for that release either.
ICH9 adds 4 more PCI interrupt routing registers, so in addition to
the previous PIRQ[A:D], we now also have PIRQ[E:H]. AIUI, each pin
can operate in either PIC or APIC mode based on whether the IRQEN bit
of each register is clear or set respectively. In PIC mode bits 3:0
of the PIRQn register identifiy the ISA compatible interrupt to
trigger. In APIC mode each PIRQn is statically mapped to an APIC
pin, where PIRQA->16, PIRQB->17, ..., PIRQH->23.
The first problem we encounter is that the system boots into PIC mode
but we're programming the PIRQn registers into APIC mode. After
fixing that, we quickly notice that seabios has a single function for
programming PCI interrupt line registers based on the PIIX mapping
of PIRQn registers. A comment in the Qemu source indicates the
slot:pin to PIRQn mapping is arbitrary so long as Qemu and ACPI
match, disregarding that boot ROMs may also use interrupts and have
no ACPI support. Solutions to this are either to create an ICH9
specific mapping function or to adjust slot:pin mappings to match
PIIX. I've done the latter here, but it's incomplete as slots 25-31
have directly programmable mappings.
I'm looking for comments on how to proceed. Do we want to try to
meld ICH9 to be more PIIX compatible or do we want to do our own
thing. I suspect there are still a number of holes in ICH9 irq
programming no matter which path we take and these in particular
are likely to be challenging for migration compatibility. Thanks,
Alex Williamson (2):
q35: Fix PIC-mode interrupt setup
q35: Fix ACPI _PRT routing to match PIIX
src/pciinit.c | 6 +--
src/q35-acpi-dsdt.dsl | 100 +++++++++++++++++++++++++------------------------
2 files changed, 52 insertions(+), 54 deletions(-)
Op dinsdag 15-01-2013 om 08:16 uur [tijdzone +0100], schreef Christian
> This RFC version works better... with the old one every 3rd boot some
> ehci bulk transfers timed out. Verified
> with my ellisys usb explorer. I will spend 1-3 hours today to get some
> sort of OS booting via USB.
> > BTW, the current usb-ehci code does work on "bare metal" on several
> > different boards. What board(s) did this help on?
> This patch helps on a lx800 platform with a cs5536. As this patch is
> RFC I am quite happy if some USB
> expert can share his/her thoughts.
> Christian Gmeiner, MSc
Nice to see that you are making progress.
I would like to test your patch but unfortunately i don`t have a geode
board at the moment.
I hope to get some back in a few weeks.
I am curious if you see the same problems as i had with Seabios USB-ohci
My USB keyboard and mouse did not work.
The 1.7.2 version of SeaBIOS has now been released. For more
information on the release, please see:
New in this release:
* Support for ICH9 host chipset ("q35") on emulators
* Support for booting from LSI MegaRAID SAS controllers
* Support for using the ACPI PM timer on emulators
* Improved Geode VGA BIOS support.
* Several bug fixes
For information on obtaining SeaBIOS, please see:
GCC, for reasons unknown, will refuse to compile code such as
extern int bar;
uint16_t foo = &bar;
The assembler would happily emit a R_386_16 relocation for this if asked
nicely, and all would be well. But instead, GCC complains about the
initialiser not being constant.
So we tend to fill in 16-bit offsets at run-time, which is only
moderately inefficient. But for the CSM table used by EFI, it doesn't
work. We need the offset to be present in the *image*, before a line of
our own code has been run. Likewise the checksum.
This special-cases the table and entry point in checkrom.py rather than
attempting to do something generic. I did have a functional generic
implementation which could be invoked from csm.c along the lines of
... and which would emit the required offsetof(typeof(\1), \2) into
a special data section which was elided from the final build but parsed
by 'objdump -s' and the location of the table to be checksummed was
inferred from the name of the *variable* that got put into that special
section... seriously, it's better just to special-case it.
It was baroque enough just for the checksums, and filling in the entry
point which required access to *two* symbols was probably going to involve
emitting a *string* into that special build-data section. It had to die.
So yes, we have hard-coded symbol names, and even magic numbers in the
python script for table offsets etc., but that's because this is an ABI.
It doesn't change, and neither do any of the other tables that we might
now consider filling at build time just to avoid having to spend time
on doing so at runtime.
Signed-off-by: David Woodhouse <David.Woodhouse(a)intel.com>
tools/checkrom.py | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/tools/checkrom.py b/tools/checkrom.py
index 69d65e8..00a652a 100755
@@ -8,6 +8,17 @@
+def subst(data, offset, new):
+ return data[:offset] + new + data[offset + len(new):]
+def checksum(data, start, size, csum):
+ sumbyte = 0
+ while size:
+ sumbyte = sumbyte + ord(data[start + size - 1])
+ size = size - 1
+ sumbyte = (0x100 - sumbyte) & 0xff
+ return subst(data, start+csum, chr(sumbyte))
# Get args
objinfo, rawfile, outfile = sys.argv[1:]
@@ -45,6 +56,22 @@ def main():
+ # Fix up CSM Compatibility16 table
+ if 'csm_compat_table' in symbols and 'entry_csm16' in symbols:
+ # Field offsets within EFI_COMPATIBILITY16_TABLE
+ ENTRY_FIELD_OFS = 14 # Compatibility16CallOffset (UINT16)
+ SIZE_FIELD_OFS = 5 # TableLength (UINT8)
+ CSUM_FIELD_OFS = 4 # TableChecksum (UINT8)
+ tableofs = symbols['csm_compat_table'].offset - symbols['code32flat_start'].offset
+ entry_addr = symbols['entry_csm16'].offset - layoutrom.BUILD_BIOS_ADDR
+ byte1 = chr(entry_addr & 0xff)
+ byte2 = chr(entry_addr >> 8)
+ rawdata = subst(rawdata, tableofs+ENTRY_FIELD_OFS, byte1+byte2)
+ tablesize = ord(rawdata[tableofs+SIZE_FIELD_OFS])
+ rawdata = checksum(rawdata, tableofs, tablesize, CSUM_FIELD_OFS)
# Print statistics
runtimesize = datasize
if '_reloc_abs_start' in symbols: