All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
To: Sunil V L <sunilvl@ventanamicro.com>,
	qemu-riscv@nongnu.org, qemu-devel@nongnu.org
Cc: Alistair Francis <alistair.francis@wdc.com>,
	Palmer Dabbelt <palmer@dabbelt.com>,
	Weiwei Li <liwei1518@gmail.com>,
	Liu Zhiwei <zhiwei_liu@linux.alibaba.com>,
	Andrew Jones <ajones@ventanamicro.com>,
	Anup Patel <apatel@ventanamicro.com>,
	Atish Patra <atishp@rivosinc.com>
Subject: Re: [PATCH 2/2] hw/riscv/virt-acpi-build: Add support for RIMT
Date: Wed, 19 Mar 2025 09:40:26 -0300	[thread overview]
Message-ID: <06ed94a2-8b7e-4022-8ba9-36b62e8f59e2@ventanamicro.com> (raw)
In-Reply-To: <20250314051527.1892488-3-sunilvl@ventanamicro.com>



On 3/14/25 2:15 AM, Sunil V L wrote:
> RISC-V IO Mapping Table (RIMT) is a new static ACPI table used to
> communicate IOMMU information to the OS. Add support for creating this
> table when the IOMMU is present. The specification is frozen and
> available at [1].
> 
> [1] - https://github.com/riscv-non-isa/riscv-acpi-rimt/releases/download/v0.99/rimt-spec.pdf
> 
> Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
> ---
>   hw/riscv/virt-acpi-build.c | 215 +++++++++++++++++++++++++++++++++++++
>   1 file changed, 215 insertions(+)
> 
> diff --git a/hw/riscv/virt-acpi-build.c b/hw/riscv/virt-acpi-build.c
> index 1ad6800508..2b4f5b2cea 100644
> --- a/hw/riscv/virt-acpi-build.c
> +++ b/hw/riscv/virt-acpi-build.c
> @@ -198,6 +198,32 @@ acpi_dsdt_add_uart(Aml *scope, const MemMapEntry *uart_memmap,
>       aml_append(scope, dev);
>   }
>   
> +/*
> + * Add DSDT entry for the IOMMU platform device.
> + * ACPI ID for IOMMU is defined in the section 6.2 of RISC-V BRS spec.
> + * https://github.com/riscv-non-isa/riscv-brs/releases/download/v0.8/riscv-brs-spec.pdf
> + */
> +static void acpi_dsdt_add_iommu_sys(Aml *scope, const MemMapEntry *iommu_memmap,
> +                                    uint32_t iommu_irq)
> +{
> +    uint32_t i;
> +
> +    Aml *dev = aml_device("IMU0");
> +    aml_append(dev, aml_name_decl("_HID", aml_string("RSCV0004")));
> +    aml_append(dev, aml_name_decl("_UID", aml_int(0)));
> +
> +    Aml *crs = aml_resource_template();
> +    aml_append(crs, aml_memory32_fixed(iommu_memmap->base,
> +                                       iommu_memmap->size, AML_READ_WRITE));
> +    for (i = iommu_irq; i < iommu_irq + 4; i++) {
> +        aml_append(crs, aml_interrupt(AML_CONSUMER, AML_EDGE, AML_ACTIVE_LOW,
> +                                      AML_EXCLUSIVE, &i, 1));
> +    }
> +
> +    aml_append(dev, aml_name_decl("_CRS", crs));
> +    aml_append(scope, dev);
> +}
> +
>   /*
>    * Serial Port Console Redirection Table (SPCR)
>    * Rev: 1.10
> @@ -450,6 +476,9 @@ static void build_dsdt(GArray *table_data,
>       }
>   
>       acpi_dsdt_add_uart(scope, &memmap[VIRT_UART0], UART0_IRQ);
> +    if (virt_is_iommu_sys_enabled(s)) {
> +        acpi_dsdt_add_iommu_sys(scope, &memmap[VIRT_IOMMU_SYS], IOMMU_SYS_IRQ);
> +    }
>   
>       if (socket_count == 1) {
>           virtio_acpi_dsdt_add(scope, memmap[VIRT_VIRTIO].base,
> @@ -602,6 +631,187 @@ static void build_madt(GArray *table_data,
>       acpi_table_end(linker, &table);
>   }
>   
> +#define ID_MAPPING_ENTRY_SIZE        20
> +#define IOMMU_ENTRY_SIZE             40
> +#define RISCV_INTERRUPT_WIRE_OFFSSET 40
> +#define ROOT_COMPLEX_ENTRY_SIZE      20
> +#define RIMT_NODE_OFFSET             48
> +
> +/*
> + * ID Mapping Structure
> + */
> +static void build_rimt_id_mapping(GArray *table_data, uint32_t source_id_base,
> +                                  uint32_t num_ids, uint32_t dest_id_base)
> +{
> +    /* Source ID Base */
> +    build_append_int_noprefix(table_data, source_id_base, 4);
> +    /* Number of IDs */
> +    build_append_int_noprefix(table_data, num_ids, 4);
> +    /* Destination Device ID Base */
> +    build_append_int_noprefix(table_data, source_id_base, 4);
> +    /* Destination IOMMU Offset */
> +    build_append_int_noprefix(table_data, dest_id_base, 4);
> +    /* Flags */
> +    build_append_int_noprefix(table_data, 0, 4);
> +}
> +
> +struct AcpiRimtIdMapping {
> +    uint32_t source_id_base;
> +    uint32_t num_ids;
> +};
> +typedef struct AcpiRimtIdMapping AcpiRimtIdMapping;
> +
> +/* Build the rimt ID mapping to IOMMU for a given PCI host bridge */
> +static int rimt_host_bridges(Object *obj, void *opaque)
> +{
> +    GArray *idmap_blob = opaque;
> +
> +    if (object_dynamic_cast(obj, TYPE_PCI_HOST_BRIDGE)) {
> +        PCIBus *bus = PCI_HOST_BRIDGE(obj)->bus;
> +
> +        if (bus && !pci_bus_bypass_iommu(bus)) {
> +            int min_bus, max_bus;
> +
> +            pci_bus_range(bus, &min_bus, &max_bus);
> +
> +            AcpiRimtIdMapping idmap = {
> +                .source_id_base = min_bus << 8,
> +                .num_ids = (max_bus - min_bus + 1) << 8,
> +            };
> +            g_array_append_val(idmap_blob, idmap);
> +        }
> +    }
> +
> +    return 0;
> +}
> +
> +static int rimt_idmap_compare(gconstpointer a, gconstpointer b)
> +{
> +    AcpiRimtIdMapping *idmap_a = (AcpiRimtIdMapping *)a;
> +    AcpiRimtIdMapping *idmap_b = (AcpiRimtIdMapping *)b;
> +
> +    return idmap_a->source_id_base - idmap_b->source_id_base;
> +}
> +
> +/*
> + * RISC-V IO Mapping Table (RIMT)
> + * https://github.com/riscv-non-isa/riscv-acpi-rimt/releases/download/v0.99/rimt-spec.pdf
> + */
> +static void build_rimt(GArray *table_data, BIOSLinker *linker,
> +                       RISCVVirtState *s)
> +{
> +    int i, nb_nodes, rc_mapping_count;
> +    size_t node_size, iommu_offset = 0;
> +    uint32_t id = 0;
> +    GArray *iommu_idmaps = g_array_new(false, true, sizeof(AcpiRimtIdMapping));

I suggest using


g_autoptr(GArray) *iommu_idmaps = g_array_new(false, true, sizeof(AcpiRimtIdMapping));


And then you can get rid of the g_array_free() in the end.


With this change:

Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>

> +
> +    AcpiTable table = { .sig = "RIMT", .rev = 1, .oem_id = s->oem_id,
> +                        .oem_table_id = s->oem_table_id };
> +
> +    acpi_table_begin(&table, table_data);
> +
> +    object_child_foreach_recursive(object_get_root(),
> +                                   rimt_host_bridges, iommu_idmaps);
> +
> +    /* Sort the ID mapping  by Source ID Base*/
> +    g_array_sort(iommu_idmaps, rimt_idmap_compare);
> +
> +    nb_nodes = 2; /* RC, IOMMU */
> +    rc_mapping_count = iommu_idmaps->len;
> +    /* Number of RIMT Nodes */
> +    build_append_int_noprefix(table_data, nb_nodes, 4);
> +
> +    /* Offset to Array of RIMT Nodes */
> +    build_append_int_noprefix(table_data, RIMT_NODE_OFFSET, 4);
> +    build_append_int_noprefix(table_data, 0, 4); /* Reserved */
> +
> +    iommu_offset = table_data->len - table.table_offset;
> +    /*  IOMMU Device Structure */
> +    build_append_int_noprefix(table_data, 0, 1);         /* Type - IOMMU*/
> +    build_append_int_noprefix(table_data, 1, 1);         /* Revision */
> +    node_size =  IOMMU_ENTRY_SIZE;
> +    build_append_int_noprefix(table_data, node_size, 2); /* Length */
> +    build_append_int_noprefix(table_data, 0, 2);         /* Reserved */
> +    build_append_int_noprefix(table_data, id++, 2);      /* ID */
> +    if (virt_is_iommu_sys_enabled(s)) {
> +        /* Hardware ID */
> +        build_append_int_noprefix(table_data, 'R', 1);
> +        build_append_int_noprefix(table_data, 'S', 1);
> +        build_append_int_noprefix(table_data, 'C', 1);
> +        build_append_int_noprefix(table_data, 'V', 1);
> +        build_append_int_noprefix(table_data, '0', 1);
> +        build_append_int_noprefix(table_data, '0', 1);
> +        build_append_int_noprefix(table_data, '0', 1);
> +        build_append_int_noprefix(table_data, '4', 1);
> +        /* Base Address */
> +        build_append_int_noprefix(table_data,
> +                                  s->memmap[VIRT_IOMMU_SYS].base, 8);
> +        build_append_int_noprefix(table_data, 0, 4);   /* Flags */
> +    } else {
> +        /* Hardware ID */
> +        build_append_int_noprefix(table_data, '0', 1);
> +        build_append_int_noprefix(table_data, '0', 1);
> +        build_append_int_noprefix(table_data, '1', 1);
> +        build_append_int_noprefix(table_data, '0', 1);
> +        build_append_int_noprefix(table_data, '0', 1);
> +        build_append_int_noprefix(table_data, '0', 1);
> +        build_append_int_noprefix(table_data, '1', 1);
> +        build_append_int_noprefix(table_data, '4', 1);
> +
> +        build_append_int_noprefix(table_data, 0, 8);   /* Base Address */
> +        build_append_int_noprefix(table_data, 1, 4);   /* Flags */
> +    }
> +
> +    build_append_int_noprefix(table_data, 0, 4);       /* Proximity Domain */
> +    build_append_int_noprefix(table_data, 0, 2);       /* PCI Segment number */
> +    /* PCIe B/D/F */
> +    if (virt_is_iommu_sys_enabled(s)) {
> +        build_append_int_noprefix(table_data, 0, 2);
> +    } else {
> +        build_append_int_noprefix(table_data, s->pci_iommu_bdf, 2);
> +    }
> +    /* Number of interrupt wires */
> +    build_append_int_noprefix(table_data, 0, 2);
> +    /* Interrupt wire array offset */
> +    build_append_int_noprefix(table_data, RISCV_INTERRUPT_WIRE_OFFSSET, 2);
> +
> +    /*  PCIe Root Complex Node */
> +    build_append_int_noprefix(table_data, 1, 1);           /* Type */
> +    build_append_int_noprefix(table_data, 1, 1);           /* Revision */
> +    node_size =  ROOT_COMPLEX_ENTRY_SIZE +
> +                 ID_MAPPING_ENTRY_SIZE * rc_mapping_count;
> +    build_append_int_noprefix(table_data, node_size, 2);   /* Length */
> +    build_append_int_noprefix(table_data, 0, 2);           /* Reserved */
> +    build_append_int_noprefix(table_data, id++, 2);        /* ID */
> +    build_append_int_noprefix(table_data, 0, 4);           /* Flags */
> +    build_append_int_noprefix(table_data, 0, 2);           /* Reserved */
> +    /* PCI Segment number */
> +    build_append_int_noprefix(table_data, 0, 2);
> +    /* ID mapping array offset */
> +    build_append_int_noprefix(table_data, ROOT_COMPLEX_ENTRY_SIZE, 2);
> +    /* Number of ID mappings */
> +    build_append_int_noprefix(table_data, rc_mapping_count, 2);
> +
> +    /* Output Reference */
> +    AcpiRimtIdMapping *range;
> +
> +    /* ID mapping array */
> +    for (i = 0; i < iommu_idmaps->len; i++) {
> +        range = &g_array_index(iommu_idmaps, AcpiRimtIdMapping, i);
> +        if (virt_is_iommu_sys_enabled(s)) {
> +            range->source_id_base = 0;
> +        } else {
> +            range->source_id_base = s->pci_iommu_bdf + 1;
> +        }
> +        range->num_ids = 0xffff - s->pci_iommu_bdf;
> +        build_rimt_id_mapping(table_data, range->source_id_base,
> +                              range->num_ids, iommu_offset);
> +    }
> +
> +    acpi_table_end(linker, &table);
> +    g_array_free(iommu_idmaps, true);
> +}
> +
>   /*
>    * ACPI spec, Revision 6.5+
>    * 5.2.16 System Resource Affinity Table (SRAT)
> @@ -679,6 +889,11 @@ static void virt_acpi_build(RISCVVirtState *s, AcpiBuildTables *tables)
>       acpi_add_table(table_offsets, tables_blob);
>       build_rhct(tables_blob, tables->linker, s);
>   
> +    if (virt_is_iommu_sys_enabled(s) || s->pci_iommu_bdf) {
> +        acpi_add_table(table_offsets, tables_blob);
> +        build_rimt(tables_blob, tables->linker, s);
> +    }
> +
>       acpi_add_table(table_offsets, tables_blob);
>       spcr_setup(tables_blob, tables->linker, s);
>   



      reply	other threads:[~2025-03-19 12:41 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-03-14  5:15 [PATCH 0/2] RISC-V: ACPI: Add support for RIMT Sunil V L
2025-03-14  5:15 ` [PATCH 1/2] hw/riscv/virt: Add the BDF of IOMMU to RISCVVirtState structure Sunil V L
2025-03-19 12:40   ` Daniel Henrique Barboza
2025-03-14  5:15 ` [PATCH 2/2] hw/riscv/virt-acpi-build: Add support for RIMT Sunil V L
2025-03-19 12:40   ` Daniel Henrique Barboza [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=06ed94a2-8b7e-4022-8ba9-36b62e8f59e2@ventanamicro.com \
    --to=dbarboza@ventanamicro.com \
    --cc=ajones@ventanamicro.com \
    --cc=alistair.francis@wdc.com \
    --cc=apatel@ventanamicro.com \
    --cc=atishp@rivosinc.com \
    --cc=liwei1518@gmail.com \
    --cc=palmer@dabbelt.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-riscv@nongnu.org \
    --cc=sunilvl@ventanamicro.com \
    --cc=zhiwei_liu@linux.alibaba.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.