From patchwork Mon Jan 27 05:05:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 240170 List-Id: U-Boot discussion From: sjg at chromium.org (Simon Glass) Date: Sun, 26 Jan 2020 22:05:25 -0700 Subject: [PATCH 018/108] acpi: Add support for DMAR In-Reply-To: <20200127050655.170614-1-sjg@chromium.org> References: <20200127050655.170614-1-sjg@chromium.org> Message-ID: <20200126220508.18.Iffd9fd365ee53abc99a8f1e85c40d30c9368c19d@changeid> The DMA Remapping Reporting (DMAR) table contains information about DMA remapping. Add a version simple version of this table with only the minimum fields filled out. i.e. no entries. Signed-off-by: Simon Glass --- include/acpi_table.h | 57 +++++++++++++++++++++++++++++++++++++++++++ lib/acpi/acpi_table.c | 26 ++++++++++++++++++++ test/dm/acpi.c | 14 +++++++++++ 3 files changed, 97 insertions(+) diff --git a/include/acpi_table.h b/include/acpi_table.h index 91496ac047..d5a9e1c96f 100644 --- a/include/acpi_table.h +++ b/include/acpi_table.h @@ -21,6 +21,9 @@ #define ACPI_RSDP_REV_ACPI_1_0 0 #define ACPI_RSDP_REV_ACPI_2_0 2 +/* TODO(sjg at chromium.org): Figure out how to get compiler revision */ +#define ASL_REVISION 0 + #if !defined(__ACPI__) /* @@ -352,6 +355,51 @@ struct acpi_csrt_shared_info { u32 max_block_size; }; +enum dmar_type { + DMAR_DRHD = 0, + DMAR_RMRR = 1, + DMAR_ATSR = 2, + DMAR_RHSA = 3, + DMAR_ANDD = 4 +}; + +enum { + DRHD_INCLUDE_PCI_ALL = 1 +}; + +enum dmar_flags { + DMAR_INTR_REMAP = 1 << 0, + DMAR_X2APIC_OPT_OUT = 1 << 1, + DMA_CTRL_PLATFORM_OPT_IN_FLAG = 1 << 2, +}; + +struct __packed dmar_entry { + u16 type; + u16 length; + u8 flags; + u8 reserved; + u16 segment; + u64 bar; +}; + +struct __packed dmar_rmrr_entry { + u16 type; + u16 length; + u16 reserved; + u16 segment; + u64 bar; + u64 limit; +}; + +/* DMAR (DMA Remapping Reporting Structure) */ +struct acpi_dmar { + struct acpi_table_header header; + u8 host_address_width; + u8 flags; + u8 reserved[10]; + struct dmar_entry structure[0]; +} __packed; + /* DBG2 definitions are partially used for SPCR interface_type */ /* Types for port_type field */ @@ -444,6 +492,15 @@ enum acpi_tables { */ int acpi_get_table_revision(enum acpi_tables table); +/** + * acpi_create_dmar() - Create a DMA Remapping Reporting (DMAR) table + * + * @dmar: Place to put the table + * @flags: DMAR flags to use + * @return 0 if OK, -ve on error + */ +int acpi_create_dmar(struct acpi_dmar *dmar, enum dmar_flags flags); + #endif /* !__ACPI__*/ #include diff --git a/lib/acpi/acpi_table.c b/lib/acpi/acpi_table.c index 971191f428..85147ac61a 100644 --- a/lib/acpi/acpi_table.c +++ b/lib/acpi/acpi_table.c @@ -6,7 +6,33 @@ */ #include +#include #include +#include + +int acpi_create_dmar(struct acpi_dmar *dmar, enum dmar_flags flags) +{ + struct acpi_table_header *header = &dmar->header; + struct cpu_info info; + struct udevice *cpu; + int ret; + + ret = uclass_first_device(UCLASS_CPU, &cpu); + if (ret) + return log_msg_ret("cpu", ret); + ret = cpu_get_info(cpu, &info); + memset((void *)dmar, 0, sizeof(struct acpi_dmar)); + + /* Fill out header fields. */ + acpi_fill_header(&dmar->header, "DMAR"); + header->length = sizeof(struct acpi_dmar); + header->revision = acpi_get_table_revision(ACPITAB_DMAR); + + dmar->host_address_width = info.address_width - 1; + dmar->flags = flags; + + return 0; +} int acpi_get_table_revision(enum acpi_tables table) { diff --git a/test/dm/acpi.c b/test/dm/acpi.c index e65295b7ca..2737896643 100644 --- a/test/dm/acpi.c +++ b/test/dm/acpi.c @@ -67,3 +67,17 @@ static int dm_test_acpi_get_table_revision(struct unit_test_state *uts) } DM_TEST(dm_test_acpi_get_table_revision, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +/* Test acpi_create_dmar() */ +static int dm_test_acpi_create_dmar(struct unit_test_state *uts) +{ + struct acpi_dmar dmar; + + ut_assertok(acpi_create_dmar(&dmar, DMAR_INTR_REMAP)); + ut_asserteq(DMAR_INTR_REMAP, dmar.flags); + ut_asserteq(DMAR_INTR_REMAP, dmar.flags); + ut_asserteq(32 - 1, dmar.host_address_width); + + return 0; +} +DM_TEST(dm_test_acpi_create_dmar, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);