Skip to content

Commit bc62f5b

Browse files
djbwdavejiang
authored andcommitted
dax/hmem, e820, resource: Defer Soft Reserved insertion until hmem is ready
Insert Soft Reserved memory into a dedicated soft_reserve_resource tree instead of the iomem_resource tree at boot. Delay publishing these ranges into the iomem hierarchy until ownership is resolved and the HMEM path is ready to consume them. Publishing Soft Reserved ranges into iomem too early conflicts with CXL hotplug and prevents region assembly when those ranges overlap CXL windows. Follow up patches will reinsert Soft Reserved ranges into iomem after CXL window publication is complete and HMEM is ready to claim the memory. This provides a cleaner handoff between EFI-defined memory ranges and CXL resource management without trimming or deleting resources later. In the meantime "Soft Reserved" resources will no longer appear in /proc/iomem, only their results. I.e. with "memmap=4G%4G+0xefffffff" Before: 100000000-1ffffffff : Soft Reserved 100000000-1ffffffff : dax1.0 100000000-1ffffffff : System RAM (kmem) After: 100000000-1ffffffff : dax1.0 100000000-1ffffffff : System RAM (kmem) The expectation is that this does not lead to a user visible regression because the dax1.0 device is created in both instances. Co-developed-by: Smita Koralahalli <Smita.KoralahalliChannabasappa@amd.com> [Smita: incorporate feedback from x86 maintainer review] Signed-off-by: Smita Koralahalli <Smita.KoralahalliChannabasappa@amd.com> Link: https://patch.msgid.link/20251120031925.87762-2-Smita.KoralahalliChannabasappa@amd.com [djbw: cleanups and clarifications] Link: https://lore.kernel.org/69443f707b025_1cee10022@dwillia2-mobl4.notmuch Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
1 parent 29317f8 commit bc62f5b

5 files changed

Lines changed: 80 additions & 19 deletions

File tree

arch/x86/kernel/e820.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,11 +1151,18 @@ void __init e820__reserve_resources_late(void)
11511151
int i;
11521152
struct resource *res;
11531153

1154-
res = e820_res;
1155-
for (i = 0; i < e820_table->nr_entries; i++) {
1156-
if (!res->parent && res->end)
1154+
for (i = 0, res = e820_res; i < e820_table->nr_entries; i++, res++) {
1155+
/* skip added or uninitialized resources */
1156+
if (res->parent || !res->end)
1157+
continue;
1158+
1159+
/* set aside soft-reserved resources for driver consideration */
1160+
if (res->desc == IORES_DESC_SOFT_RESERVED) {
1161+
insert_resource_expand_to_fit(&soft_reserve_resource, res);
1162+
} else {
1163+
/* publish the rest immediately */
11571164
insert_resource_expand_to_fit(&iomem_resource, res);
1158-
res++;
1165+
}
11591166
}
11601167

11611168
/*

drivers/dax/hmem/device.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,7 @@ static __init int hmem_register_one(struct resource *res, void *data)
8383

8484
static __init int hmem_init(void)
8585
{
86-
walk_iomem_res_desc(IORES_DESC_SOFT_RESERVED,
87-
IORESOURCE_MEM, 0, -1, NULL, hmem_register_one);
86+
walk_soft_reserve_res(0, -1, NULL, hmem_register_one);
8887
return 0;
8988
}
9089

drivers/dax/hmem/hmem.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,12 @@ static int hmem_register_device(struct device *host, int target_nid,
7373
return 0;
7474
}
7575

76-
rc = region_intersects(res->start, resource_size(res), IORESOURCE_MEM,
77-
IORES_DESC_SOFT_RESERVED);
76+
rc = region_intersects_soft_reserve(res->start, resource_size(res));
7877
if (rc != REGION_INTERSECTS)
7978
return 0;
8079

80+
/* TODO: Add Soft-Reserved memory back to iomem */
81+
8182
id = memregion_alloc(GFP_KERNEL);
8283
if (id < 0) {
8384
dev_err(host, "memregion allocation failure for %pr\n", res);

include/linux/ioport.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ struct resource_constraint {
232232
/* PC/ISA/whatever - the normal PC address spaces: IO and memory */
233233
extern struct resource ioport_resource;
234234
extern struct resource iomem_resource;
235+
extern struct resource soft_reserve_resource;
235236

236237
extern struct resource *request_resource_conflict(struct resource *root, struct resource *new);
237238
extern int request_resource(struct resource *root, struct resource *new);
@@ -418,6 +419,10 @@ walk_system_ram_res_rev(u64 start, u64 end, void *arg,
418419
extern int
419420
walk_iomem_res_desc(unsigned long desc, unsigned long flags, u64 start, u64 end,
420421
void *arg, int (*func)(struct resource *, void *));
422+
extern int walk_soft_reserve_res(u64 start, u64 end, void *arg,
423+
int (*func)(struct resource *, void *));
424+
extern int
425+
region_intersects_soft_reserve(resource_size_t start, size_t size);
421426

422427
struct resource *devm_request_free_mem_region(struct device *dev,
423428
struct resource *base, unsigned long size);

kernel/resource.c

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ struct resource iomem_resource = {
4848
};
4949
EXPORT_SYMBOL(iomem_resource);
5050

51+
struct resource soft_reserve_resource = {
52+
.name = "Soft Reserved",
53+
.start = 0,
54+
.end = -1,
55+
.desc = IORES_DESC_SOFT_RESERVED,
56+
.flags = IORESOURCE_MEM,
57+
};
58+
5159
static DEFINE_RWLOCK(resource_lock);
5260

5361
/*
@@ -321,13 +329,14 @@ static bool is_type_match(struct resource *p, unsigned long flags, unsigned long
321329
}
322330

323331
/**
324-
* find_next_iomem_res - Finds the lowest iomem resource that covers part of
325-
* [@start..@end].
332+
* find_next_res - Finds the lowest resource that covers part of
333+
* [@start..@end].
326334
*
327335
* If a resource is found, returns 0 and @*res is overwritten with the part
328336
* of the resource that's within [@start..@end]; if none is found, returns
329337
* -ENODEV. Returns -EINVAL for invalid parameters.
330338
*
339+
* @parent: resource tree root to search
331340
* @start: start address of the resource searched for
332341
* @end: end address of same resource
333342
* @flags: flags which the resource must have
@@ -337,9 +346,9 @@ static bool is_type_match(struct resource *p, unsigned long flags, unsigned long
337346
* The caller must specify @start, @end, @flags, and @desc
338347
* (which may be IORES_DESC_NONE).
339348
*/
340-
static int find_next_iomem_res(resource_size_t start, resource_size_t end,
341-
unsigned long flags, unsigned long desc,
342-
struct resource *res)
349+
static int find_next_res(struct resource *parent, resource_size_t start,
350+
resource_size_t end, unsigned long flags,
351+
unsigned long desc, struct resource *res)
343352
{
344353
/* Skip children until we find a top level range that matches */
345354
bool skip_children = true;
@@ -353,7 +362,7 @@ static int find_next_iomem_res(resource_size_t start, resource_size_t end,
353362

354363
read_lock(&resource_lock);
355364

356-
for_each_resource(&iomem_resource, p, skip_children) {
365+
for_each_resource(parent, p, skip_children) {
357366
/* If we passed the resource we are looking for, stop */
358367
if (p->start > end) {
359368
p = NULL;
@@ -390,16 +399,23 @@ static int find_next_iomem_res(resource_size_t start, resource_size_t end,
390399
return p ? 0 : -ENODEV;
391400
}
392401

393-
static int __walk_iomem_res_desc(resource_size_t start, resource_size_t end,
394-
unsigned long flags, unsigned long desc,
395-
void *arg,
396-
int (*func)(struct resource *, void *))
402+
static int find_next_iomem_res(resource_size_t start, resource_size_t end,
403+
unsigned long flags, unsigned long desc,
404+
struct resource *res)
405+
{
406+
return find_next_res(&iomem_resource, start, end, flags, desc, res);
407+
}
408+
409+
static int walk_res_desc(struct resource *parent, resource_size_t start,
410+
resource_size_t end, unsigned long flags,
411+
unsigned long desc, void *arg,
412+
int (*func)(struct resource *, void *))
397413
{
398414
struct resource res;
399415
int ret = -EINVAL;
400416

401417
while (start < end &&
402-
!find_next_iomem_res(start, end, flags, desc, &res)) {
418+
!find_next_res(parent, start, end, flags, desc, &res)) {
403419
ret = (*func)(&res, arg);
404420
if (ret)
405421
break;
@@ -410,6 +426,15 @@ static int __walk_iomem_res_desc(resource_size_t start, resource_size_t end,
410426
return ret;
411427
}
412428

429+
static int __walk_iomem_res_desc(resource_size_t start, resource_size_t end,
430+
unsigned long flags, unsigned long desc,
431+
void *arg,
432+
int (*func)(struct resource *, void *))
433+
{
434+
return walk_res_desc(&iomem_resource, start, end, flags, desc, arg, func);
435+
}
436+
437+
413438
/**
414439
* walk_iomem_res_desc - Walks through iomem resources and calls func()
415440
* with matching resource ranges.
@@ -434,6 +459,18 @@ int walk_iomem_res_desc(unsigned long desc, unsigned long flags, u64 start,
434459
}
435460
EXPORT_SYMBOL_GPL(walk_iomem_res_desc);
436461

462+
/*
463+
* In support of device drivers claiming Soft Reserved resources, walk the Soft
464+
* Reserved resource deferral tree.
465+
*/
466+
int walk_soft_reserve_res(u64 start, u64 end, void *arg,
467+
int (*func)(struct resource *, void *))
468+
{
469+
return walk_res_desc(&soft_reserve_resource, start, end, IORESOURCE_MEM,
470+
IORES_DESC_SOFT_RESERVED, arg, func);
471+
}
472+
EXPORT_SYMBOL_GPL(walk_soft_reserve_res);
473+
437474
/*
438475
* This function calls the @func callback against all memory ranges of type
439476
* System RAM which are marked as IORESOURCE_SYSTEM_RAM and IORESOUCE_BUSY.
@@ -656,6 +693,18 @@ int region_intersects(resource_size_t start, size_t size, unsigned long flags,
656693
}
657694
EXPORT_SYMBOL_GPL(region_intersects);
658695

696+
/*
697+
* Check if the provided range is registered in the Soft Reserved resource
698+
* deferral tree for driver consideration.
699+
*/
700+
int region_intersects_soft_reserve(resource_size_t start, size_t size)
701+
{
702+
guard(read_lock)(&resource_lock);
703+
return __region_intersects(&soft_reserve_resource, start, size,
704+
IORESOURCE_MEM, IORES_DESC_SOFT_RESERVED);
705+
}
706+
EXPORT_SYMBOL_GPL(region_intersects_soft_reserve);
707+
659708
void __weak arch_remove_reservations(struct resource *avail)
660709
{
661710
}

0 commit comments

Comments
 (0)