pci: add foreachcap() helper
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 2/4 pci: add foreachcap() helper
This iterates over capabilities exposed by PCI devices. It's needed by IOMMU initialization code to discover the Secure Device capability.
--- src/pci.h | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)
src/pci.h +5 -0
@@ -2,6 +2,7 @@#define __PCI_H#include "types.h" // u32 +#include "pci_regs.h" // PCI_CAPABILITY_LIST et al. static inline u8 pci_bdf_to_bus (u16 bdf) {return bdf >>8 ;
@@ -52,6 +53,10 @@ int pci_next(int bdf, int *pmax);for (MAX =0x0100 ,BDF =pci_next (0 , &MAX ) \ ;BDF >=0 \ ; BDF=pci_next(BDF+1, &MAX)) +#define foreachcap (BDF ,PTR ,CAP ) \ + for (PTR = PCI_CAPABILITY_LIST, CAP = pci_config_readb(BDF, PTR); \ + CAP; \ + PTR = CAP + PCI_CAP_LIST_NEXT, CAP = pci_config_readb(BDF, PTR))#define foreachpci_in_bus (BDF ,MAX ,BUS ) \ for (MAX = pci_bus_devfn_to_bdf(BUS, 0) + 0x0100, \
Signature · 1 line
1.7.1
Given the usage of 3/4, u32 pci_find_capability(bdf, cap) would be more direct. Maybe this is a matter of taste, though.
Quoted 40 lines · Eduard - Gabriel Munteanu
This iterates over capabilities exposed by PCI devices. It's needed by IOMMU initialization code to discover the Secure Device capability.
Signed-off-by Eduard - Gabriel Munteanu <[email protected]>--- src/pci.h | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)src/pci.h +5
-0@@ -2,6 +2,7 @@#define __PCI_H#include "types.h" // u32 +#include "pci_regs.h" // PCI_CAPABILITY_LIST et al. static inline u8 pci_bdf_to_bus (u16 bdf) {return bdf >>8 ;@@ -52,6 +53,10 @@ int pci_next(int bdf, int *pmax);for (MAX =0x0100 ,BDF =pci_next (0 , &MAX ) \ ;BDF >=0 \ ; BDF=pci_next(BDF+1, &MAX)) +#define foreachcap (BDF ,PTR ,CAP ) \ + for (PTR = PCI_CAPABILITY_LIST, CAP = pci_config_readb(BDF, PTR); \ + CAP; \ + PTR = CAP + PCI_CAP_LIST_NEXT, CAP = pci_config_readb(BDF, PTR))#define foreachpci_in_bus (BDF ,MAX ,BUS ) \ for (MAX = pci_bus_devfn_to_bdf(BUS, 0) + 0x0100, \Signature · 7 lines
1.7.1 _______________________________________________ SeaBIOS mailing list [email protected] http://www.seabios.org/mailman/listinfo/seabios
Signature · 1 line
yamahata
PATCH 3/4 iommu: introduce AMD IOMMU support, initialize it
In reply to a message not in the archiveThe AMD IOMMU must be discovered and initialized by the BIOS if present.
--- Makefile | 2 +- src/iommu.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/iommu.h | 12 ++++++++++ src/pci_ids.h | 1 + src/pci_regs.h | 1 + src/pciinit.c | 15 +++++++++++++ 6 files changed, 93 insertions(+), 1 deletions(-) create mode 100644 src/iommu.c create mode 100644 src/iommu.h
Makefile +1 -1
@@ -15,7 +15,7 @@ SRCBOTH=misc.c pmm.c stacks.c output.c util.c block.c floppy.c ata.c mouse.c \ kbd.c pci.c serial.c clock.c pic.c cdrom.c ps2port.c smp.c resume.c \ pnpbios.c pirtable.c vgahooks.c ramdisk.c pcibios.c blockcmd.c \ usb.c usb-uhci.c usb-ohci.c usb-ehci.c usb-hid.c usb-msc.c \ - virtio-ring.c virtio-pci.c virtio-blk.c + virtio-ring.c virtio-pci.c virtio-blk.c iommu.c SRC16=$(SRCBOTH) system.c disk.c apm.c font.c SRC32FLAT=$(SRCBOTH) post.c shadow.c memmap.c coreboot.c boot.c \ acpi.c smm.c mptable.c smbios.c pciinit.c optionroms.c mtrr.c \
src/iommu.c new file +63 -0
63 lines not on this page · raw message
src/iommu.h new file +12 -0
@@ -0,0 +1,12 @@ +#ifndef __IOMMU_H +#define __IOMMU_H + +#include "types.h" + +void iommu_init (int bdf,u32 base); +int iommu_get_bdf (void ); +u8 iommu_get_cap_offset (void ); +u32 iommu_get_misc (void ); +u32 iommu_get_base (void ); + +#endif // __IOMMU_H
src/pci_ids.h +1 -0
@@ -72,6 +72,7 @@#define PCI_CLASS_SYSTEM_RTC 0x0803#define PCI_CLASS_SYSTEM_PCI_HOTPLUG 0x0804#define PCI_CLASS_SYSTEM_SDHCI 0x0805 +#define PCI_CLASS_SYSTEM_IOMMU 0x0806#define PCI_CLASS_SYSTEM_OTHER 0x0880#define PCI_BASE_CLASS_INPUT 0x09
src/pci_regs.h +1 -0
@@ -208,6 +208,7 @@#define PCI_CAP_ID_SHPC 0x0C/* PCI Standard Hot-Plug Controller */ #define PCI_CAP_ID_SSVID 0x0D/* Bridge subsystem vendor/device ID */ #define PCI_CAP_ID_AGP3 0x0E/* AGP Target PCI-PCI bridge */ +#define PCI_CAP_ID_SEC 0x0F/* Secure Device (AMD IOMMU) */ #define PCI_CAP_ID_EXP 0x10/* PCI Express */ #define PCI_CAP_ID_MSIX 0x11/* MSI-X */ #define PCI_CAP_LIST_NEXT 1/* Next capability in the list */
src/pciinit.c +15 -0
@@ -11,6 +11,7 @@#include "pci_ids.h" // PCI_VENDOR_ID_INTEL #include "pci_regs.h" // PCI_COMMAND #include "dev-i440fx.h" +#include "iommu.h" #define PCI_ROM_SLOT 6#define PCI_NUM_REGIONS 7
@@ -262,6 +263,16 @@ static void apple_macio_init(u16 bdf, void *arg)pci_set_io_region_addr (bdf,0 ,0x80800000 ); } +static void pci_bios_init_iommu (u16 bdf,void *arg) +{ +u32 base; + + base =ALIGN (pci_bios_mem_addr,0x4000 ); + pci_bios_mem_addr +=0x4000 ; + +iommu_init (bdf, base); +} +static const struct pci_device_id pci_class_tbl[] = {/* STORAGE IDE */ PCI_DEVICE_CLASS(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1,
@@ -285,6 +296,10 @@ static const struct pci_device_id pci_class_tbl[] = {PCI_DEVICE_CLASS (PCI_ANY_ID ,PCI_ANY_ID ,PCI_CLASS_BRIDGE_PCI , pci_bios_init_device_bridge), +/* AMD IOMMU */ +PCI_DEVICE_CLASS (PCI_ANY_ID ,PCI_ANY_ID ,PCI_CLASS_SYSTEM_IOMMU , + pci_bios_init_iommu), +/* default */ PCI_DEVICE(PCI_ANY_ID, PCI_ANY_ID, pci_bios_allocate_regions),
Signature · 1 line
1.7.1
Re: [SeaBIOS] [PATCH 3/4] iommu: introduce AMD IOMMU support, initialize it
I think those global variables are unnecessary.
Please see the comment on 4/4.
thanks,
Quoted 187 lines · Eduard - Gabriel Munteanu
The AMD IOMMU must be discovered and initialized by the BIOS if present.
Signed-off-by Eduard - Gabriel Munteanu <[email protected]>--- Makefile | 2 +- src/iommu.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/iommu.h | 12 ++++++++++ src/pci_ids.h | 1 + src/pci_regs.h | 1 + src/pciinit.c | 15 +++++++++++++ 6 files changed, 93 insertions(+), 1 deletions(-) create mode 100644 src/iommu.c create mode 100644 src/iommu.hMakefile +1
-1@@ -15,7 +15,7 @@ SRCBOTH=misc.c pmm.c stacks.c output.c util.c block.c floppy.c ata.c mouse.c \ kbd.c pci.c serial.c clock.c pic.c cdrom.c ps2port.c smp.c resume.c \ pnpbios.c pirtable.c vgahooks.c ramdisk.c pcibios.c blockcmd.c \ usb.c usb-uhci.c usb-ohci.c usb-ehci.c usb-hid.c usb-msc.c \ - virtio-ring.c virtio-pci.c virtio-blk.c + virtio-ring.c virtio-pci.c virtio-blk.c iommu.c SRC16=$(SRCBOTH) system.c disk.c apm.c font.c SRC32FLAT=$(SRCBOTH) post.c shadow.c memmap.c coreboot.c boot.c \ acpi.c smm.c mptable.c smbios.c pciinit.c optionroms.c mtrr.c \src/iommu.c new file +63
-0@@ -0,0 +1,63 @@ +// AMD IOMMU initialization code. +// +// Copyright (C) 2010 Eduard - Gabriel Munteanu <[email protected]> +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "iommu.h" +#include "pci.h" +#include "types.h" + +#define IOMMU_CAP_BAR_LOW 0x04 +#define IOMMU_CAP_BAR_HIGH 0x08 +#define IOMMU_CAP_RANGE 0x0C +#define IOMMU_CAP_MISC 0x10 + +static int iommu_bdf =-1 ; +static u8 iommu_cap_offset; +static u32 iommu_base; + +void iommu_init (int bdf,u32 base) +{ +u8 ptr, cap, type; + +/* Only one IOMMU is supported. */ +if (iommu_bdf >=0 ) +return ; + + foreachcap(bdf, ptr, cap) { + type =pci_config_readb (bdf, cap); +if (type ==PCI_CAP_ID_SEC ) +break ; + } +if (!cap) +return ; + +pci_config_writel (bdf, cap +IOMMU_CAP_RANGE ,0 ); +pci_config_writel (bdf, cap +IOMMU_CAP_BAR_HIGH ,0 ); +pci_config_writel (bdf, cap +IOMMU_CAP_BAR_LOW , base |1 ); + + iommu_bdf = bdf; + iommu_cap_offset = cap; + iommu_base = base; +} + +int iommu_get_bdf (void ) +{ +return iommu_bdf; +} + +u8 iommu_get_cap_offset (void ) +{ +return iommu_cap_offset; +} + +u32 iommu_get_misc (void ) +{ +return pci_config_readw (iommu_bdf, iommu_cap_offset +IOMMU_CAP_MISC +2 ); +} + +u32 iommu_get_base (void ) +{ +return iommu_base; +}src/iommu.h new file +12
-0@@ -0,0 +1,12 @@ +#ifndef __IOMMU_H +#define __IOMMU_H + +#include "types.h" + +void iommu_init (int bdf,u32 base); +int iommu_get_bdf (void ); +u8 iommu_get_cap_offset (void ); +u32 iommu_get_misc (void ); +u32 iommu_get_base (void ); + +#endif // __IOMMU_H src/pci_ids.h +1
-0@@ -72,6 +72,7 @@#define PCI_CLASS_SYSTEM_RTC 0x0803#define PCI_CLASS_SYSTEM_PCI_HOTPLUG 0x0804#define PCI_CLASS_SYSTEM_SDHCI 0x0805 +#define PCI_CLASS_SYSTEM_IOMMU 0x0806#define PCI_CLASS_SYSTEM_OTHER 0x0880#define PCI_BASE_CLASS_INPUT 0x09src/pci_regs.h +1
-0@@ -208,6 +208,7 @@#define PCI_CAP_ID_SHPC 0x0C/* PCI Standard Hot-Plug Controller */ #define PCI_CAP_ID_SSVID 0x0D/* Bridge subsystem vendor/device ID */ #define PCI_CAP_ID_AGP3 0x0E/* AGP Target PCI-PCI bridge */ +#define PCI_CAP_ID_SEC 0x0F/* Secure Device (AMD IOMMU) */ #define PCI_CAP_ID_EXP 0x10/* PCI Express */ #define PCI_CAP_ID_MSIX 0x11/* MSI-X */ #define PCI_CAP_LIST_NEXT 1/* Next capability in the list */ src/pciinit.c +15
-0@@ -11,6 +11,7 @@#include "pci_ids.h" // PCI_VENDOR_ID_INTEL #include "pci_regs.h" // PCI_COMMAND #include "dev-i440fx.h" +#include "iommu.h" #define PCI_ROM_SLOT 6#define PCI_NUM_REGIONS 7@@ -262,6 +263,16 @@ static void apple_macio_init(u16 bdf, void *arg)pci_set_io_region_addr (bdf,0 ,0x80800000 ); } +static void pci_bios_init_iommu (u16 bdf,void *arg) +{ +u32 base; + + base =ALIGN (pci_bios_mem_addr,0x4000 ); + pci_bios_mem_addr +=0x4000 ; + +iommu_init (bdf, base); +} +static const struct pci_device_id pci_class_tbl[] = {/* STORAGE IDE */ PCI_DEVICE_CLASS(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1,@@ -285,6 +296,10 @@ static const struct pci_device_id pci_class_tbl[] = {PCI_DEVICE_CLASS (PCI_ANY_ID ,PCI_ANY_ID ,PCI_CLASS_BRIDGE_PCI , pci_bios_init_device_bridge), +/* AMD IOMMU */ +PCI_DEVICE_CLASS (PCI_ANY_ID ,PCI_ANY_ID ,PCI_CLASS_SYSTEM_IOMMU , + pci_bios_init_iommu), +/* default */ PCI_DEVICE(PCI_ANY_ID, PCI_ANY_ID, pci_bios_allocate_regions),Signature · 7 lines
1.7.1 _______________________________________________ SeaBIOS mailing list [email protected] http://www.seabios.org/mailman/listinfo/seabios
Signature · 1 line
yamahata
PATCH 4/4 iommu: provide ACPI tables
In reply to a message not in the archiveThe OS needs an ACPI IVRS table to discover and use the IOMMU.
--- src/acpi.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 79 insertions(+), 0 deletions(-)
src/acpi.c +79 -0
@@ -6,6 +6,7 @@// This file may be distributed under the terms of the GNU LGPLv3 license. #include "acpi.h" // struct rsdp_descriptor +#include "iommu.h" #include "util.h" // memcpy #include "pci.h" // pci_find_device #include "biosvar.h" // GET_EBDA
@@ -196,6 +197,36 @@ struct srat_memory_affinityu32 reserved3[2 ]; }PACKED ; +/* +* IVRS (I/O Virtualization Reporting Structure) table. +* +* Describes the AMD IOMMU, as per: +* "AMD I/O Virtualization Technology (IOMMU) Specification", rev 1.26 +*/ + +struct ivrs_ivhd +{ +u8 type; +u8 flags; +u16 length; +u16 devid; +u16 capab_off; +u32 iommu_base_low; +u32 iommu_base_high; +u16 pci_seg_group; +u16 iommu_info; +u32 reserved; +u8 entry[0 ]; +}PACKED ; + +struct ivrs_table +{ +ACPI_TABLE_HEADER_DEF /* ACPI common table header. */ + u32 iv_info; +u32 reserved[2 ]; +struct ivrs_ivhd ivhd; +}PACKED ; +#include "acpi-dsdt.hex" static void
@@ -586,6 +617,53 @@ static const struct pci_device_id acpi_find_tbl[] = { PCI_DEVICE_END, }; +#define IVRS_SIGNATURE 0x53525649 // IVRS +#define IVRS_MAX_DEVS 32 +static void * +build_ivrs (void ) +{ +int iommu_bdf, bdf, max, i; +struct ivrs_table *ivrs; +struct ivrs_ivhd *ivhd; + + iommu_bdf =pci_find_class (PCI_CLASS_SYSTEM_IOMMU ); +if (iommu_bdf <0 ) +return NULL ; + + ivrs =malloc_high (sizeof (struct ivrs_table ) +4 *IVRS_MAX_DEVS ); + ivrs->iv_info =iommu_get_misc () & ~0x000F ; + + ivhd = &ivrs->ivhd; + ivhd->type =0x10 ; + ivhd->flags =0 ; + ivhd->length =sizeof (struct ivrs_ivhd ); + ivhd->devid =iommu_get_bdf (); + ivhd->capab_off =iommu_get_cap_offset (); + ivhd->iommu_base_low =iommu_get_base (); + ivhd->iommu_base_high =0 ; + ivhd->pci_seg_group =0 ; + ivhd->iommu_info =0 ; + ivhd->reserved =0 ; + + i =0 ; + foreachpci(bdf, max) { +if (bdf == ivhd->devid) +continue ; + ivhd->entry[4 * i +0 ] =2 ; + ivhd->entry[4 * i +1 ] = bdf &0xFF ; + ivhd->entry[4 * i +2 ] = (bdf >>8 ) &0xFF ; + ivhd->entry[4 * i +3 ] = ~(1 <<3 ); + ivhd->length +=4 ; +if (++i >=IVRS_MAX_DEVS ) +break ; + } + +build_header ((void *) ivrs,IVRS_SIGNATURE , +sizeof (struct ivrs_table ) +4 * i,1 ); + +return ivrs; +} +struct rsdp_descriptor *RsdpAddr;#define MAX_ACPI_TABLES 20
@@ -625,6 +703,7 @@ acpi_bios_init(void)ACPI_INIT_TABLE (build_madt ());ACPI_INIT_TABLE (build_hpet ());ACPI_INIT_TABLE (build_srat ()); +ACPI_INIT_TABLE (build_ivrs ());u16 i, external_tables =qemu_cfg_acpi_additional_tables ();
Signature · 1 line
1.7.1
Re: [SeaBIOS] [PATCH 4/4] iommu: provide ACPI tables
How about the following approach?
Although I'm not sure how much multiple iommus is wanted, it wouldn't pose single iommu limit and global variables in 3/4 would be unnecessary.
In stead of ACPI_INIT_TABLE(build_ivrs()),
something like
foreachpci() {
if (class == PCI_CLASS_SYSTEM_IOMMU) {
ACPI_INIT_TABLE(build_ivrs(bdf))
}
}and in build_ivrs()
iommu_get_bdf() -> unnecessary. iommu_get_cap_offset() -> pci_find_capability(PCI_CAP_ID_SEC) iommu_get_misc() -> cap + IOMMU_CAP_MISC + 2 iommu_get_base() -> read from cap + IOMMU_CAP_BAR_LOW/HIGH
thanks,
Quoted 127 lines · Eduard - Gabriel Munteanu
The OS needs an ACPI IVRS table to discover and use the IOMMU.
Signed-off-by Eduard - Gabriel Munteanu <[email protected]>--- src/acpi.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 79 insertions(+), 0 deletions(-)src/acpi.c +79
-0@@ -6,6 +6,7 @@// This file may be distributed under the terms of the GNU LGPLv3 license. #include "acpi.h" // struct rsdp_descriptor +#include "iommu.h" #include "util.h" // memcpy #include "pci.h" // pci_find_device #include "biosvar.h" // GET_EBDA @@ -196,6 +197,36 @@ struct srat_memory_affinityu32 reserved3[2 ]; }PACKED ; +/* +* IVRS (I/O Virtualization Reporting Structure) table. +* +* Describes the AMD IOMMU, as per: +* "AMD I/O Virtualization Technology (IOMMU) Specification", rev 1.26 +*/ + +struct ivrs_ivhd +{ +u8 type; +u8 flags; +u16 length; +u16 devid; +u16 capab_off; +u32 iommu_base_low; +u32 iommu_base_high; +u16 pci_seg_group; +u16 iommu_info; +u32 reserved; +u8 entry[0 ]; +}PACKED ; + +struct ivrs_table +{ +ACPI_TABLE_HEADER_DEF /* ACPI common table header. */ + u32 iv_info; +u32 reserved[2 ]; +struct ivrs_ivhd ivhd; +}PACKED ; +#include "acpi-dsdt.hex" static void@@ -586,6 +617,53 @@ static const struct pci_device_id acpi_find_tbl[] = { PCI_DEVICE_END, }; +#define IVRS_SIGNATURE 0x53525649 // IVRS +#define IVRS_MAX_DEVS 32 +static void * +build_ivrs (void ) +{ +int iommu_bdf, bdf, max, i; +struct ivrs_table *ivrs; +struct ivrs_ivhd *ivhd; + + iommu_bdf =pci_find_class (PCI_CLASS_SYSTEM_IOMMU ); +if (iommu_bdf <0 ) +return NULL ; + + ivrs =malloc_high (sizeof (struct ivrs_table ) +4 *IVRS_MAX_DEVS ); + ivrs->iv_info =iommu_get_misc () & ~0x000F ; + + ivhd = &ivrs->ivhd; + ivhd->type =0x10 ; + ivhd->flags =0 ; + ivhd->length =sizeof (struct ivrs_ivhd ); + ivhd->devid =iommu_get_bdf (); + ivhd->capab_off =iommu_get_cap_offset (); + ivhd->iommu_base_low =iommu_get_base (); + ivhd->iommu_base_high =0 ; + ivhd->pci_seg_group =0 ; + ivhd->iommu_info =0 ; + ivhd->reserved =0 ; + + i =0 ; + foreachpci(bdf, max) { +if (bdf == ivhd->devid) +continue ; + ivhd->entry[4 * i +0 ] =2 ; + ivhd->entry[4 * i +1 ] = bdf &0xFF ; + ivhd->entry[4 * i +2 ] = (bdf >>8 ) &0xFF ; + ivhd->entry[4 * i +3 ] = ~(1 <<3 ); + ivhd->length +=4 ; +if (++i >=IVRS_MAX_DEVS ) +break ; + } + +build_header ((void *) ivrs,IVRS_SIGNATURE , +sizeof (struct ivrs_table ) +4 * i,1 ); + +return ivrs; +} +struct rsdp_descriptor *RsdpAddr;#define MAX_ACPI_TABLES 20@@ -625,6 +703,7 @@ acpi_bios_init(void)ACPI_INIT_TABLE (build_madt ());ACPI_INIT_TABLE (build_hpet ());ACPI_INIT_TABLE (build_srat ()); +ACPI_INIT_TABLE (build_ivrs ());u16 i, external_tables =qemu_cfg_acpi_additional_tables ();Signature · 7 lines
1.7.1 _______________________________________________ SeaBIOS mailing list [email protected] http://www.seabios.org/mailman/listinfo/seabios
Signature · 1 line
yamahata
Re: [PATCH 1/4] pci: expand tabs to spaces in pci_ids.h and pci_regs.h
In reply to a message not in the archiveQuoted 4 lines · Eduard - Gabriel Munteanu
The conversion was done using the GNU 'expand' tool (default settings) to make it obey the SeaBIOS coding style.
Signed-off-by Eduard - Gabriel Munteanu <[email protected]>
Thanks Eduard.
Patch 1 - I don't think we should reindent pci_ids.h - it's a copy from Linux - reindenting will make diff'ing it harder.
Patch 2 & 3 - Can you get an acked'ed by from qemu/kvm developers?
Patch 4 - I think this will have to wait until there is a plan for handling acpi tables. I'd like to tackle this post seabios v0.6.1.
-Kevin