On 1/21/2025 11:52 PM, Fan Ni wrote: > On Thu, Jan 16, 2025 at 11:42:05AM -0600, Nathan Fontenot wrote: >> Introduce the ability to manage SOFT RESERVED kernel resources prior to >> these resources being placed in the iomem resource tree. This provides >> the ability for drivers to update SOFT RESERVED resources that intersect >> with their memory resources. >> >> During boot, any resources marked as IORES_DESC_SOFT_RESERVED are placed >> on the soft reserve resource tree. Once boot completes all resources >> are placed on the iomem resource tree. This behavior is gated by a new >> kernel option CONFIG_SOFT_RESERVED_MANAGED. >> >> As part of this update two new interfaces are added for management of >> the SOFT RESERVED resources. The release_srmem_region_adjustable() >> routine allows for removing pieces of SOFT RESERVED resources. The >> the merge_srmem_resources() allows drivers to merge any remaining SOFT >> RESERVED resources into the iomem resource tree once updatea are complete. >> >> Signed-off-by: Nathan Fontenot <nathan.fontenot@xxxxxxx> >> --- >> include/linux/ioport.h | 9 +++++ >> kernel/resource.c | 79 +++++++++++++++++++++++++++++++++++++++--- >> lib/Kconfig | 4 +++ >> 3 files changed, 87 insertions(+), 5 deletions(-) >> >> diff --git a/include/linux/ioport.h b/include/linux/ioport.h >> index 6e9fb667a1c5..2c95cf0be45e 100644 >> --- a/include/linux/ioport.h >> +++ b/include/linux/ioport.h >> @@ -249,6 +249,15 @@ struct resource *lookup_resource(struct resource *root, resource_size_t start); >> int adjust_resource(struct resource *res, resource_size_t start, >> resource_size_t size); >> resource_size_t resource_alignment(struct resource *res); >> + >> +#ifdef CONFIG_SOFT_RESERVED_MANAGED >> +void merge_srmem_resources(void); >> +extern void release_srmem_region_adjustable(resource_size_t start, >> + resource_size_t size); >> +#else >> +static inline void merge_srmem_resources(void) { } >> +#endif >> + >> static inline resource_size_t resource_size(const struct resource *res) >> { >> return res->end - res->start + 1; >> diff --git a/kernel/resource.c b/kernel/resource.c >> index a83040fde236..9db420078a3f 100644 >> --- a/kernel/resource.c >> +++ b/kernel/resource.c >> @@ -48,6 +48,14 @@ struct resource iomem_resource = { >> }; >> EXPORT_SYMBOL(iomem_resource); >> >> +static struct resource srmem_resource = { >> + .name = "Soft Reserved mem", >> + .start = 0, >> + .end = -1, >> + .flags = IORESOURCE_MEM, >> + .desc = IORES_DESC_SOFT_RESERVED, >> +}; >> + >> static DEFINE_RWLOCK(resource_lock); >> >> static struct resource *next_resource(struct resource *p, bool skip_children) >> @@ -818,6 +826,19 @@ static struct resource * __insert_resource(struct resource *parent, struct resou >> { >> struct resource *first, *next; >> >> + if (IS_ENABLED(CONFIG_SOFT_RESERVED_MANAGED)) { >> + /* >> + * During boot SOFT RESERVED resources are placed on the srmem >> + * resource tree. These resources may be updated later in boot, >> + * for example see the CXL driver, prior to being merged into >> + * the iomem resource tree. >> + */ >> + if (system_state < SYSTEM_RUNNING && >> + parent == &iomem_resource && >> + new->desc == IORES_DESC_SOFT_RESERVED) >> + parent = &srmem_resource; >> + } >> + >> for (;; parent = first) { >> first = __request_resource(parent, new); >> if (!first) >> @@ -1336,11 +1357,12 @@ void __release_region(struct resource *parent, resource_size_t start, >> } >> EXPORT_SYMBOL(__release_region); >> >> -#ifdef CONFIG_MEMORY_HOTREMOVE > > If CONFIG_MEMORY_HOTREMOVE not defined, it seems we do not have a > user for release_region_adjustable as > release_mem_region_adjustable() will not exist. The release_region_adjustable() routine is used by by release_mem_region_adjustable() and release_srmem_region_adjustable(). We could put the following around release_region_adjustable() to prevent it being present when not used. #if defined(CONFIG_MEMORY_HOTREMOVE) || defined(CONFIG_SOFT_RESERVED_MANAGED) -Nathan > > Fan >> /** >> - * release_mem_region_adjustable - release a previously reserved memory region >> + * release_region_adjustable - release a previously reserved memory region >> + * @parent: resource tree to release resource from >> * @start: resource start address >> * @size: resource region size >> + * @busy_check: check for IORESOURCE_BUSY >> * >> * This interface is intended for memory hot-delete. The requested region >> * is released from a currently busy memory resource. The requested region >> @@ -1356,9 +1378,11 @@ EXPORT_SYMBOL(__release_region); >> * assumes that all children remain in the lower address entry for >> * simplicity. Enhance this logic when necessary. >> */ >> -void release_mem_region_adjustable(resource_size_t start, resource_size_t size) >> +static void release_region_adjustable(struct resource *parent, >> + resource_size_t start, >> + resource_size_t size, >> + bool busy_check) >> { >> - struct resource *parent = &iomem_resource; >> struct resource *new_res = NULL; >> bool alloc_nofail = false; >> struct resource **p; >> @@ -1395,7 +1419,7 @@ void release_mem_region_adjustable(resource_size_t start, resource_size_t size) >> if (!(res->flags & IORESOURCE_MEM)) >> break; >> >> - if (!(res->flags & IORESOURCE_BUSY)) { >> + if (busy_check && !(res->flags & IORESOURCE_BUSY)) { >> p = &res->child; >> continue; >> } >> @@ -1445,6 +1469,51 @@ void release_mem_region_adjustable(resource_size_t start, resource_size_t size) >> write_unlock(&resource_lock); >> free_resource(new_res); >> } >> + >> +#ifdef CONFIG_SOFT_RESERVED_MANAGED >> +/** >> + * merge_srmem_resources - merge srmem resources into the iomem resource tree >> + * >> + * This is intended to allow kernel drivers that manage the SOFT RESERVED >> + * resources to merge any remaining resources into the iomem resource tree >> + * once any updates have been made. >> + */ >> +void merge_srmem_resources(void) >> +{ >> + struct resource *res, *next; >> + int rc; >> + >> + for (res = srmem_resource.child; res; res = next) { >> + next = next_resource(res, true); >> + >> + write_lock(&resource_lock); >> + >> + if (WARN_ON(__release_resource(res, true))) { >> + write_unlock(&resource_lock); >> + continue; >> + } >> + >> + if (WARN_ON(__insert_resource(&iomem_resource, res))) >> + __insert_resource(&srmem_resource, res); >> + >> + write_unlock(&resource_lock); >> + } >> +} >> +EXPORT_SYMBOL_GPL(merge_srmem_resources); >> + >> +void release_srmem_region_adjustable(resource_size_t start, >> + resource_size_t size) >> +{ >> + release_region_adjustable(&srmem_resource, start, size, false); >> +} >> +EXPORT_SYMBOL(release_srmem_region_adjustable); >> +#endif >> + >> +#ifdef CONFIG_MEMORY_HOTREMOVE >> +void release_mem_region_adjustable(resource_size_t start, resource_size_t size) >> +{ >> + release_region_adjustable(&iomem_resource, start, size, true); >> +} >> #endif /* CONFIG_MEMORY_HOTREMOVE */ >> >> #ifdef CONFIG_MEMORY_HOTPLUG >> diff --git a/lib/Kconfig b/lib/Kconfig >> index b38849af6f13..4f4011334051 100644 >> --- a/lib/Kconfig >> +++ b/lib/Kconfig >> @@ -777,3 +777,7 @@ config POLYNOMIAL >> >> config FIRMWARE_TABLE >> bool >> + >> +config SOFT_RESERVED_MANAGED >> + bool >> + default n >> -- >> 2.43.0 >>