lib: set up specific purpose memory as LB_MEM_SOFT_RESERVED

CXL (Compute Express Link) [1] is a cache-coherent interconnect
standard for processors, memory expansion and accelerators.

CXL memory is provided through CXL device which is connected
through CXL/PCIe link, while regular system memory is provided
through DIMMs plugged into DIMM slots which are connected to
memory controllers of processor.

With CXL memory, the server's memory capacity is increased.
CXL memory is in its own NUMA domain, with longer latency
and added bandwidth, comparing to regular system memory.

Host firmware may present CXL memory as specific purpose memory.
Linux kernel dax driver provides direct access to such differentiated
memory. In particular, hmem dax driver provides direct access to
specific purpose memory.

Specific purpose memory needs to be represented in e820 table as
soft reserved, as described in [2].

Add IORESOURCE_SOFT_RESERVE resource property to indicate (memory)
resource that needs to be soft reserved.

Add soft_reserved_ram_resource macro to allow soc/mb code to add
memory resource as soft reserved.

[1] https://www.computeexpresslink.org/

[2] https://web.archive.org/web/20230130233752/https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v5.10.32&id=262b45ae3ab4bf8e2caf1fcfd0d8307897519630

Signed-off-by: Jonathan Zhang <jonzhang@fb.com>
Change-Id: Ie70795bcb8c97e9dd5fb772adc060e1606f9bab0
Reviewed-on: https://review.coreboot.org/c/coreboot/+/52585
Reviewed-by: Marc Jones <marc@marcjonesconsulting.com>
Reviewed-by: David Hendricks <david.hendricks@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Tim Wawrzynczak <inforichland@gmail.com>
Reviewed-by: Lean Sheng Tan <sheng.tan@9elements.com>
diff --git a/src/commonlib/include/commonlib/coreboot_tables.h b/src/commonlib/include/commonlib/coreboot_tables.h
index 86bf543..e299e54 100644
--- a/src/commonlib/include/commonlib/coreboot_tables.h
+++ b/src/commonlib/include/commonlib/coreboot_tables.h
@@ -140,6 +140,7 @@
 #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 */
+#define LB_MEM_SOFT_RESERVED	0xefffffff /* Specific purpose memory */
 };
 
 struct lb_memory {
diff --git a/src/include/bootmem.h b/src/include/bootmem.h
index 6ccdd88..0478a12 100644
--- a/src/include/bootmem.h
+++ b/src/include/bootmem.h
@@ -22,6 +22,7 @@
 	BM_MEM_FIRST = 0x10000,	/* First entry in this list */
 	BM_MEM_RAM,		/* Memory anyone can use */
 	BM_MEM_RESERVED,	/* Don't use this memory region */
+	BM_MEM_SOFT_RESERVED,	/* Specific purpose memory */
 	BM_MEM_ACPI,		/* ACPI Tables */
 	BM_MEM_NVS,		/* ACPI NVS Memory */
 	BM_MEM_UNUSABLE,	/* Unusable address space */
diff --git a/src/include/device/device.h b/src/include/device/device.h
index b4b2d20..8a663f0 100644
--- a/src/include/device/device.h
+++ b/src/include/device/device.h
@@ -428,6 +428,9 @@
 	fixed_mem_resource_kb(dev, idx, basek, sizek, IORESOURCE_CACHEABLE \
 		| IORESOURCE_RESERVE)
 
+#define soft_reserved_ram_resource(dev, idx, basek, sizek) \
+	fixed_mem_resource(dev, idx, basek, sizek, IORESOURCE_SOFT_RESERVE)
+
 #define bad_ram_resource_kb(dev, idx, basek, sizek) \
 	reserved_ram_resource_kb((dev), (idx), (basek), (sizek))
 
diff --git a/src/include/device/resource.h b/src/include/device/resource.h
index 9624135..3afdf6a 100644
--- a/src/include/device/resource.h
+++ b/src/include/device/resource.h
@@ -28,6 +28,8 @@
 #define IORESOURCE_BRIDGE	0x00080000
 /* This is a request to allocate resource about 4G boundary. */
 #define IORESOURCE_ABOVE_4G	0x00100000
+/* The resource needs to be soft reserved in the coreboot table */
+#define IORESOURCE_SOFT_RESERVE	0x00200000
 /* The resource needs to be reserved in the coreboot table */
 #define IORESOURCE_RESERVE	0x10000000
 /* The IO resource assignment has been stored in the device */
diff --git a/src/lib/bootmem.c b/src/lib/bootmem.c
index ea971b6..578ddac 100644
--- a/src/lib/bootmem.c
+++ b/src/lib/bootmem.c
@@ -50,6 +50,8 @@
 		return LB_MEM_RESERVED;
 	case BM_MEM_TABLE:
 		return LB_MEM_TABLE;
+	case BM_MEM_SOFT_RESERVED:
+		return LB_MEM_SOFT_RESERVED;
 	default:
 		printk(BIOS_ERR, "Unsupported tag %u\n", tag);
 		return LB_MEM_RESERVED;
@@ -60,6 +62,7 @@
 {
 	const unsigned long cacheable = IORESOURCE_CACHEABLE;
 	const unsigned long reserved = IORESOURCE_RESERVE;
+	const unsigned long soft_reserved = IORESOURCE_SOFT_RESERVE;
 	struct memranges *bm = &bootmem;
 
 	initialized = 1;
@@ -71,6 +74,7 @@
 	 */
 	memranges_init(bm, cacheable, cacheable, BM_MEM_RAM);
 	memranges_add_resources(bm, reserved, reserved, BM_MEM_RESERVED);
+	memranges_add_resources(bm, soft_reserved, soft_reserved, BM_MEM_SOFT_RESERVED);
 	memranges_clone(&bootmem_os, bm);
 
 	/* Add memory used by CBMEM. */
@@ -136,6 +140,7 @@
 	{ BM_MEM_BL31, "BL31" },
 	{ BM_MEM_OPENSBI, "OPENSBI" },
 	{ BM_MEM_TABLE, "CONFIGURATION TABLES" },
+	{ BM_MEM_SOFT_RESERVED, "SOFT RESERVED" },
 	{ BM_MEM_RAMSTAGE, "RAMSTAGE" },
 	{ BM_MEM_PAYLOAD, "PAYLOAD" },
 };