Skip to content

Commit 00ab027

Browse files
mickflemmpalmer-dabbelt
authored andcommitted
RISC-V: Add kernel image sections to the resource tree
This patch (previously part of my kexec/kdump series) populates /proc/iomem with the various sections of the kernel image. We need this for kexec-tools to be able to prepare the crashkernel image for kdump to work. Since resource tree initialization is not related to memory initialization I added the code to kernel/setup.c and removed the original code (derived from the arm64 tree) from mm/init.c. Signed-off-by: Nick Kossifidis <[email protected]> Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 3650b22 commit 00ab027

File tree

2 files changed

+160
-27
lines changed

2 files changed

+160
-27
lines changed

arch/riscv/kernel/setup.c

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
* Chen Liqin <[email protected]>
55
* Lennox Wu <[email protected]>
66
* Copyright (C) 2012 Regents of the University of California
7+
* Copyright (C) 2020 FORTH-ICS/CARV
8+
* Nick Kossifidis <[email protected]>
79
*/
810

911
#include <linux/init.h>
@@ -51,6 +53,163 @@ atomic_t hart_lottery __section(".sdata");
5153
unsigned long boot_cpu_hartid;
5254
static DEFINE_PER_CPU(struct cpu, cpu_devices);
5355

56+
/*
57+
* Place kernel memory regions on the resource tree so that
58+
* kexec-tools can retrieve them from /proc/iomem. While there
59+
* also add "System RAM" regions for compatibility with other
60+
* archs, and the rest of the known regions for completeness.
61+
*/
62+
static struct resource code_res = { .name = "Kernel code", };
63+
static struct resource data_res = { .name = "Kernel data", };
64+
static struct resource rodata_res = { .name = "Kernel rodata", };
65+
static struct resource bss_res = { .name = "Kernel bss", };
66+
67+
static int __init add_resource(struct resource *parent,
68+
struct resource *res)
69+
{
70+
int ret = 0;
71+
72+
ret = insert_resource(parent, res);
73+
if (ret < 0) {
74+
pr_err("Failed to add a %s resource at %llx\n",
75+
res->name, (unsigned long long) res->start);
76+
return ret;
77+
}
78+
79+
return 1;
80+
}
81+
82+
static int __init add_kernel_resources(struct resource *res)
83+
{
84+
int ret = 0;
85+
86+
/*
87+
* The memory region of the kernel image is continuous and
88+
* was reserved on setup_bootmem, find it here and register
89+
* it as a resource, then register the various segments of
90+
* the image as child nodes
91+
*/
92+
if (!(res->start <= code_res.start && res->end >= data_res.end))
93+
return 0;
94+
95+
res->name = "Kernel image";
96+
res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
97+
98+
/*
99+
* We removed a part of this region on setup_bootmem so
100+
* we need to expand the resource for the bss to fit in.
101+
*/
102+
res->end = bss_res.end;
103+
104+
ret = add_resource(&iomem_resource, res);
105+
if (ret < 0)
106+
return ret;
107+
108+
ret = add_resource(res, &code_res);
109+
if (ret < 0)
110+
return ret;
111+
112+
ret = add_resource(res, &rodata_res);
113+
if (ret < 0)
114+
return ret;
115+
116+
ret = add_resource(res, &data_res);
117+
if (ret < 0)
118+
return ret;
119+
120+
ret = add_resource(res, &bss_res);
121+
122+
return ret;
123+
}
124+
125+
static void __init init_resources(void)
126+
{
127+
struct memblock_region *region = NULL;
128+
struct resource *res = NULL;
129+
int ret = 0;
130+
131+
code_res.start = __pa_symbol(_text);
132+
code_res.end = __pa_symbol(_etext) - 1;
133+
code_res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
134+
135+
rodata_res.start = __pa_symbol(__start_rodata);
136+
rodata_res.end = __pa_symbol(__end_rodata) - 1;
137+
rodata_res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
138+
139+
data_res.start = __pa_symbol(_data);
140+
data_res.end = __pa_symbol(_edata) - 1;
141+
data_res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
142+
143+
bss_res.start = __pa_symbol(__bss_start);
144+
bss_res.end = __pa_symbol(__bss_stop) - 1;
145+
bss_res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
146+
147+
/*
148+
* Start by adding the reserved regions, if they overlap
149+
* with /memory regions, insert_resource later on will take
150+
* care of it.
151+
*/
152+
for_each_reserved_mem_region(region) {
153+
res = memblock_alloc(sizeof(struct resource), SMP_CACHE_BYTES);
154+
if (!res)
155+
panic("%s: Failed to allocate %zu bytes\n", __func__,
156+
sizeof(struct resource));
157+
158+
res->name = "Reserved";
159+
res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
160+
res->start = __pfn_to_phys(memblock_region_reserved_base_pfn(region));
161+
res->end = __pfn_to_phys(memblock_region_reserved_end_pfn(region)) - 1;
162+
163+
ret = add_kernel_resources(res);
164+
if (ret < 0)
165+
goto error;
166+
else if (ret)
167+
continue;
168+
169+
/*
170+
* Ignore any other reserved regions within
171+
* system memory.
172+
*/
173+
if (memblock_is_memory(res->start))
174+
continue;
175+
176+
ret = add_resource(&iomem_resource, res);
177+
if (ret < 0)
178+
goto error;
179+
}
180+
181+
/* Add /memory regions to the resource tree */
182+
for_each_mem_region(region) {
183+
res = memblock_alloc(sizeof(struct resource), SMP_CACHE_BYTES);
184+
if (!res)
185+
panic("%s: Failed to allocate %zu bytes\n", __func__,
186+
sizeof(struct resource));
187+
188+
if (unlikely(memblock_is_nomap(region))) {
189+
res->name = "Reserved";
190+
res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
191+
} else {
192+
res->name = "System RAM";
193+
res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
194+
}
195+
196+
res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region));
197+
res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1;
198+
199+
ret = add_resource(&iomem_resource, res);
200+
if (ret < 0)
201+
goto error;
202+
}
203+
204+
return;
205+
206+
error:
207+
memblock_free((phys_addr_t) res, sizeof(struct resource));
208+
/* Better an empty resource tree than an inconsistent one */
209+
release_child_resources(&iomem_resource);
210+
}
211+
212+
54213
static void __init parse_dtb(void)
55214
{
56215
/* Early scan of device tree from init memory */
@@ -80,6 +239,7 @@ void __init setup_arch(char **cmdline_p)
80239
efi_init();
81240
setup_bootmem();
82241
paging_init();
242+
init_resources();
83243
#if IS_ENABLED(CONFIG_BUILTIN_DTB)
84244
unflatten_and_copy_device_tree();
85245
#else

arch/riscv/mm/init.c

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -625,39 +625,12 @@ void mark_rodata_ro(void)
625625
}
626626
#endif
627627

628-
static void __init resource_init(void)
629-
{
630-
struct memblock_region *region;
631-
632-
for_each_mem_region(region) {
633-
struct resource *res;
634-
635-
res = memblock_alloc(sizeof(struct resource), SMP_CACHE_BYTES);
636-
if (!res)
637-
panic("%s: Failed to allocate %zu bytes\n", __func__,
638-
sizeof(struct resource));
639-
640-
if (memblock_is_nomap(region)) {
641-
res->name = "reserved";
642-
res->flags = IORESOURCE_MEM;
643-
} else {
644-
res->name = "System RAM";
645-
res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
646-
}
647-
res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region));
648-
res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1;
649-
650-
request_resource(&iomem_resource, res);
651-
}
652-
}
653-
654628
void __init paging_init(void)
655629
{
656630
setup_vm_final();
657631
sparse_init();
658632
setup_zero_page();
659633
zone_sizes_init();
660-
resource_init();
661634
}
662635

663636
#ifdef CONFIG_SPARSEMEM_VMEMMAP

0 commit comments

Comments
 (0)