Check this example:

ce0e2a0140 drivers/intel/fsp2_0: use FSP to allocate APEI BERT memory region

 

From: Rocky Phagura via coreboot <coreboot@coreboot.org>
Reply-To: Rocky Phagura <rphagura@fb.com>
Date: Sunday, January 3, 2021 at 10:45 PM
To: "coreboot@coreboot.org" <coreboot@coreboot.org>
Subject: [coreboot] Re: Reserve Device DRAM

 

Hello,

Can anyone provide guidance on the previous email? It seems in bootmem.c, the memory is marked type 16, LB_MEM_TABLE.  Is there a way to explicitly add an entry (cbmem_add) for reserved memory that is not type 16? Thank you,

 

 

#define LB_MEM_RAM               1           /* Memory anyone can use */

#define LB_MEM_RESERVED                    2           /* Don't use this memory region */

#define LB_MEM_ACPI                3           /* ACPI Tables */

#define LB_MEM_NVS                 4           /* ACPI NVS Memory */

#define LB_MEM_UNUSABLE                   5           /* Unusable address space */

#define LB_MEM_VENDOR_RSVD           6           /* Vendor Reserved */

#define LB_MEM_TABLE                           16    /* Ram configuration tables are kept in */

 

 

 

From: Bryan Angelo <bangelo@gmail.com>
Sent: Wednesday, September 16, 2020 4:16 PM
To: coreboot@coreboot.org
Subject: [coreboot] Reserve Device DRAM

 

I would appreciate any guidance on the proper way to reserve (arbitrary) DRAM for a MMIO device in coreboot such that the Linux driver for that device is also able to map the reserved DRAM.

 

Based on code inspection, my attempt is to add a cbmem entry via cbmem_alloc and mark that memory as reserved via reserved_ram_resource in the read_resources operation for the device driver.

 

static void foo_read_resources(struct device *dev)

{

        void *buf;

        const unsigned long size = 0x8000;

 

        if (cbmem_entry_find(CBMEM_ID_FOO))

                return;

 

        buf = cbmem_add(CBMEM_ID_FOO, size);

        if (!buf)

                return;

                                                                                                                   

        reserved_ram_resource(dev, 0, ((unsigned long)buf) >> 10, size >> 10);

}

 

I can see that the resource is allocated during resource reading.

 

MMIO: fd110500 resource base 8de82000 size 8000 align 0 gran 0 limit 0 flags f0004200 index 0

 

I then pass this resource to the linux driver via an ACPI device entry.

 

acpigen_write_name("_CRS");

acpigen_write_resourcetemplate_header();

const struct cbmem_entry *ce = cbmem_entry_find(CBMEM_ID_FOO);

if (ce)

        acpigen_write_mem32fixed(1, (uint32_t)cbmem_entry_start(ce), (uint32_t)cbmem_entry_size(ce));

 

However, the memory is presented to Linux as "type 16" instead of "reserved" in the physical RAM map.

 

[    0.000000] BIOS-provided physical RAM map:

[    0.000000] BIOS-e820: [mem 0x0000000000000000-0x0000000000000fff] type 16

[    0.000000] BIOS-e820: [mem 0x0000000000001000-0x000000000009ffff] usable

[    0.000000] BIOS-e820: [mem 0x00000000000a0000-0x00000000000fffff] reserved

[    0.000000] BIOS-e820: [mem 0x0000000000100000-0x000000008de34fff] usable

[    0.000000] BIOS-e820: [mem 0x000000008de35000-0x000000008fffffff] type 16

[    0.000000] BIOS-e820: [mem 0x0000000090000000-0x00000000cfffffff] reserved

[    0.000000] BIOS-e820: [mem 0x00000000f8000000-0x00000000fbffffff] reserved

[    0.000000] BIOS-e820: [mem 0x0000000100000000-0x000000022f33ffff] usable

[    0.000000] BIOS-e820: [mem 0x000000022f340000-0x000000022fffffff] reserved

 

The e820 type 16 is unknown to the linux kernel, causing it to mark the region as busy.  This subsequently causes devm_ioremap_resource to fail when called on the DRAM address from the ACPI device entry.

 

Looking through the code, it seems that coreboot marks the entire cbmem as type 16 in bootmem despite my (improper, it would seem) attempt to mark the ram as reserved.  What would be the proper way to reserve (arbitrary) DRAM for a MMIO device such that the memory is marked as reserved in the BIOS physical RAM map?

 

Thanks.