Skip to content
/ linux Public

Commit 2b7a25d

Browse files
committed
Merge tag 'mm-nonmm-stable-2026-02-18-19-56' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
Pull more non-MM updates from Andrew Morton: - "two fixes in kho_populate()" fixes a couple of not-major issues in the kexec handover code (Ran Xiaokai) - misc singletons * tag 'mm-nonmm-stable-2026-02-18-19-56' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm: lib/group_cpus: handle const qualifier from clusters allocation type kho: remove unnecessary WARN_ON(err) in kho_populate() kho: fix missing early_memunmap() call in kho_populate() scripts/gdb: implement x86_page_ops in mm.py objpool: fix the overestimation of object pooling metadata size selftests/memfd: use IPC semaphore instead of SIGSTOP/SIGCONT delayacct: fix build regression on accounting tool
2 parents eeccf28 + 90627a1 commit 2b7a25d

File tree

7 files changed

+301
-31
lines changed

7 files changed

+301
-31
lines changed

kernel/liveupdate/kexec_handover.c

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1463,36 +1463,37 @@ void __init kho_populate(phys_addr_t fdt_phys, u64 fdt_len,
14631463
struct kho_scratch *scratch = NULL;
14641464
phys_addr_t mem_map_phys;
14651465
void *fdt = NULL;
1466+
bool populated = false;
14661467
int err;
14671468

14681469
/* Validate the input FDT */
14691470
fdt = early_memremap(fdt_phys, fdt_len);
14701471
if (!fdt) {
14711472
pr_warn("setup: failed to memremap FDT (0x%llx)\n", fdt_phys);
1472-
goto err_report;
1473+
goto report;
14731474
}
14741475
err = fdt_check_header(fdt);
14751476
if (err) {
14761477
pr_warn("setup: handover FDT (0x%llx) is invalid: %d\n",
14771478
fdt_phys, err);
1478-
goto err_unmap_fdt;
1479+
goto unmap_fdt;
14791480
}
14801481
err = fdt_node_check_compatible(fdt, 0, KHO_FDT_COMPATIBLE);
14811482
if (err) {
14821483
pr_warn("setup: handover FDT (0x%llx) is incompatible with '%s': %d\n",
14831484
fdt_phys, KHO_FDT_COMPATIBLE, err);
1484-
goto err_unmap_fdt;
1485+
goto unmap_fdt;
14851486
}
14861487

14871488
mem_map_phys = kho_get_mem_map_phys(fdt);
14881489
if (!mem_map_phys)
1489-
goto err_unmap_fdt;
1490+
goto unmap_fdt;
14901491

14911492
scratch = early_memremap(scratch_phys, scratch_len);
14921493
if (!scratch) {
14931494
pr_warn("setup: failed to memremap scratch (phys=0x%llx, len=%lld)\n",
14941495
scratch_phys, scratch_len);
1495-
goto err_unmap_fdt;
1496+
goto unmap_fdt;
14961497
}
14971498

14981499
/*
@@ -1506,10 +1507,10 @@ void __init kho_populate(phys_addr_t fdt_phys, u64 fdt_len,
15061507

15071508
memblock_add(area->addr, size);
15081509
err = memblock_mark_kho_scratch(area->addr, size);
1509-
if (WARN_ON(err)) {
1510+
if (err) {
15101511
pr_warn("failed to mark the scratch region 0x%pa+0x%pa: %pe",
15111512
&area->addr, &size, ERR_PTR(err));
1512-
goto err_unmap_scratch;
1513+
goto unmap_scratch;
15131514
}
15141515
pr_debug("Marked 0x%pa+0x%pa as scratch", &area->addr, &size);
15151516
}
@@ -1529,16 +1530,17 @@ void __init kho_populate(phys_addr_t fdt_phys, u64 fdt_len,
15291530
kho_in.scratch_phys = scratch_phys;
15301531
kho_in.mem_map_phys = mem_map_phys;
15311532
kho_scratch_cnt = scratch_cnt;
1532-
pr_info("found kexec handover data.\n");
15331533

1534-
return;
1534+
populated = true;
1535+
pr_info("found kexec handover data.\n");
15351536

1536-
err_unmap_scratch:
1537+
unmap_scratch:
15371538
early_memunmap(scratch, scratch_len);
1538-
err_unmap_fdt:
1539+
unmap_fdt:
15391540
early_memunmap(fdt, fdt_len);
1540-
err_report:
1541-
pr_warn("disabling KHO revival\n");
1541+
report:
1542+
if (!populated)
1543+
pr_warn("disabling KHO revival\n");
15421544
}
15431545

15441546
/* Helper functions for kexec_file_load */

lib/group_cpus.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ static int alloc_cluster_groups(unsigned int ncpus,
320320
goto no_cluster;
321321

322322
/* Allocate memory based on cluster number. */
323-
clusters = kcalloc(ncluster, sizeof(struct cpumask *), GFP_KERNEL);
323+
clusters = kcalloc(ncluster, sizeof(*clusters), GFP_KERNEL);
324324
if (!clusters)
325325
goto no_cluster;
326326
cluster_groups = kcalloc(ncluster, sizeof(struct node_groups), GFP_KERNEL);

lib/objpool.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ int objpool_init(struct objpool_head *pool, int nr_objs, int object_size,
142142
pool->gfp = gfp & ~__GFP_ZERO;
143143
pool->context = context;
144144
pool->release = release;
145-
slot_size = nr_cpu_ids * sizeof(struct objpool_slot);
145+
slot_size = nr_cpu_ids * sizeof(struct objpool_slot *);
146146
pool->cpu_slots = kzalloc(slot_size, pool->gfp);
147147
if (!pool->cpu_slots)
148148
return -ENOMEM;

scripts/gdb/linux/constants.py.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,8 @@ LX_CONFIG(CONFIG_ARM64_64K_PAGES)
150150
if IS_BUILTIN(CONFIG_ARM64):
151151
LX_VALUE(CONFIG_ARM64_PA_BITS)
152152
LX_VALUE(CONFIG_ARM64_VA_BITS)
153-
LX_VALUE(CONFIG_PAGE_SHIFT)
154153
LX_VALUE(CONFIG_ARCH_FORCE_MAX_ORDER)
154+
LX_VALUE(CONFIG_PAGE_SHIFT)
155155
LX_CONFIG(CONFIG_SPARSEMEM)
156156
LX_CONFIG(CONFIG_SPARSEMEM_EXTREME)
157157
LX_CONFIG(CONFIG_SPARSEMEM_VMEMMAP)

scripts/gdb/linux/mm.py

Lines changed: 172 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,179 @@ def __init__(self):
2626
raise gdb.GdbError('Only support CONFIG_SPARSEMEM_VMEMMAP now')
2727
if constants.LX_CONFIG_ARM64 and utils.is_target_arch('aarch64'):
2828
self.ops = aarch64_page_ops()
29+
elif utils.is_target_arch('x86_64') or utils.is_target_arch('x86-64'):
30+
self.ops = x86_page_ops()
2931
else:
30-
raise gdb.GdbError('Only support aarch64 now')
32+
raise gdb.GdbError('Only support aarch64 and x86_64 now')
33+
34+
class x86_page_ops():
35+
def __init__(self):
36+
self.struct_page_size = utils.get_page_type().sizeof
37+
self.PAGE_SHIFT = constants.LX_CONFIG_PAGE_SHIFT
38+
self.PAGE_SIZE = 1 << self.PAGE_SHIFT
39+
self.PAGE_MASK = (~(self.PAGE_SIZE - 1)) & ((1 << 64) - 1)
40+
41+
self.PAGE_OFFSET = int(gdb.parse_and_eval("page_offset_base"))
42+
self.VMEMMAP_START = int(gdb.parse_and_eval("vmemmap_base"))
43+
self.PHYS_BASE = int(gdb.parse_and_eval("phys_base"))
44+
self.START_KERNEL_map = 0xffffffff80000000
45+
46+
self.KERNEL_START = gdb.parse_and_eval("_text")
47+
self.KERNEL_END = gdb.parse_and_eval("_end")
48+
49+
self.VMALLOC_START = int(gdb.parse_and_eval("vmalloc_base"))
50+
if self.VMALLOC_START == 0xffffc90000000000:
51+
self.VMALLOC_END = self.VMALLOC_START + (32 * 1024 * 1024 * 1024 * 1024) - 1
52+
elif self.VMALLOC_START == 0xffa0000000000000:
53+
self.VMALLOC_END = self.VMALLOC_START + (12800 * 1024 * 1024 * 1024 * 1024) - 1
54+
else:
55+
self.VMALLOC_END = self.VMALLOC_START + (12800 * 1024 * 1024 * 1024 * 1024) - 1
56+
57+
self.MAX_PHYSMEM_BITS = 46
58+
self.SECTION_SIZE_BITS = 27
59+
self.MAX_ORDER = 10
60+
61+
self.SECTIONS_SHIFT = self.MAX_PHYSMEM_BITS - self.SECTION_SIZE_BITS
62+
self.NR_MEM_SECTIONS = 1 << self.SECTIONS_SHIFT
63+
self.PFN_SECTION_SHIFT = self.SECTION_SIZE_BITS - self.PAGE_SHIFT
64+
self.PAGES_PER_SECTION = 1 << self.PFN_SECTION_SHIFT
65+
self.PAGE_SECTION_MASK = (~(self.PAGES_PER_SECTION - 1)) & ((1 << 64) - 1)
66+
67+
if constants.LX_CONFIG_SPARSEMEM_EXTREME:
68+
self.SECTIONS_PER_ROOT = self.PAGE_SIZE // gdb.lookup_type("struct mem_section").sizeof
69+
else:
70+
self.SECTIONS_PER_ROOT = 1
71+
72+
self.NR_SECTION_ROOTS = DIV_ROUND_UP(self.NR_MEM_SECTIONS, self.SECTIONS_PER_ROOT)
73+
self.SECTION_ROOT_MASK = self.SECTIONS_PER_ROOT - 1
74+
75+
try:
76+
self.SECTION_HAS_MEM_MAP = 1 << int(gdb.parse_and_eval('SECTION_HAS_MEM_MAP_BIT'))
77+
self.SECTION_IS_EARLY = 1 << int(gdb.parse_and_eval('SECTION_IS_EARLY_BIT'))
78+
except:
79+
self.SECTION_HAS_MEM_MAP = 1 << 0
80+
self.SECTION_IS_EARLY = 1 << 3
81+
82+
self.SUBSECTION_SHIFT = 21
83+
self.PAGES_PER_SUBSECTION = 1 << (self.SUBSECTION_SHIFT - self.PAGE_SHIFT)
84+
85+
if constants.LX_CONFIG_NUMA and constants.LX_CONFIG_NODES_SHIFT:
86+
self.NODE_SHIFT = constants.LX_CONFIG_NODES_SHIFT
87+
else:
88+
self.NODE_SHIFT = 0
89+
90+
self.MAX_NUMNODES = 1 << self.NODE_SHIFT
91+
92+
self.vmemmap = gdb.Value(self.VMEMMAP_START).cast(utils.get_page_type().pointer())
93+
94+
def kasan_reset_tag(self, addr):
95+
return addr
96+
97+
def SECTION_NR_TO_ROOT(self, sec):
98+
return sec // self.SECTIONS_PER_ROOT
99+
100+
def __nr_to_section(self, nr):
101+
root = self.SECTION_NR_TO_ROOT(nr)
102+
mem_section = gdb.parse_and_eval("mem_section")
103+
return mem_section[root][nr & self.SECTION_ROOT_MASK]
104+
105+
def pfn_to_section_nr(self, pfn):
106+
return pfn >> self.PFN_SECTION_SHIFT
107+
108+
def section_nr_to_pfn(self, sec):
109+
return sec << self.PFN_SECTION_SHIFT
110+
111+
def __pfn_to_section(self, pfn):
112+
return self.__nr_to_section(self.pfn_to_section_nr(pfn))
113+
114+
def pfn_to_section(self, pfn):
115+
return self.__pfn_to_section(pfn)
116+
117+
def subsection_map_index(self, pfn):
118+
return (pfn & ~(self.PAGE_SECTION_MASK)) // self.PAGES_PER_SUBSECTION
119+
120+
def pfn_section_valid(self, ms, pfn):
121+
if constants.LX_CONFIG_SPARSEMEM_VMEMMAP:
122+
idx = self.subsection_map_index(pfn)
123+
return test_bit(idx, ms['usage']['subsection_map'])
124+
else:
125+
return True
126+
127+
def valid_section(self, mem_section):
128+
if mem_section != None and (mem_section['section_mem_map'] & self.SECTION_HAS_MEM_MAP):
129+
return True
130+
return False
131+
132+
def early_section(self, mem_section):
133+
if mem_section != None and (mem_section['section_mem_map'] & self.SECTION_IS_EARLY):
134+
return True
135+
return False
136+
137+
def pfn_valid(self, pfn):
138+
ms = None
139+
if self.PHYS_PFN(self.PFN_PHYS(pfn)) != pfn:
140+
return False
141+
if self.pfn_to_section_nr(pfn) >= self.NR_MEM_SECTIONS:
142+
return False
143+
ms = self.__pfn_to_section(pfn)
144+
145+
if not self.valid_section(ms):
146+
return False
147+
return self.early_section(ms) or self.pfn_section_valid(ms, pfn)
148+
149+
def PFN_PHYS(self, pfn):
150+
return pfn << self.PAGE_SHIFT
151+
152+
def PHYS_PFN(self, phys):
153+
return phys >> self.PAGE_SHIFT
154+
155+
def __phys_to_virt(self, pa):
156+
return pa + self.PAGE_OFFSET
157+
158+
def __virt_to_phys(self, va):
159+
if va >= self.START_KERNEL_map:
160+
return va - self.START_KERNEL_map + self.PHYS_BASE
161+
else:
162+
return va - self.PAGE_OFFSET
163+
164+
def virt_to_phys(self, va):
165+
return self.__virt_to_phys(va)
166+
167+
def virt_to_page(self, va):
168+
return self.pfn_to_page(self.virt_to_pfn(va))
169+
170+
def __pa(self, va):
171+
return self.__virt_to_phys(va)
172+
173+
def __va(self, pa):
174+
return self.__phys_to_virt(pa)
175+
176+
def pfn_to_kaddr(self, pfn):
177+
return self.__va(pfn << self.PAGE_SHIFT)
178+
179+
def virt_to_pfn(self, va):
180+
return self.PHYS_PFN(self.__virt_to_phys(va))
181+
182+
def sym_to_pfn(self, x):
183+
return self.PHYS_PFN(self.__virt_to_phys(x))
184+
185+
def page_to_pfn(self, page):
186+
return int(page.cast(utils.get_page_type().pointer()) - self.vmemmap)
187+
188+
def pfn_to_page(self, pfn):
189+
return self.vmemmap + pfn
190+
191+
def page_to_phys(self, page):
192+
return self.PFN_PHYS(self.page_to_pfn(page))
193+
194+
def page_to_virt(self, page):
195+
return self.__va(self.page_to_phys(page))
196+
197+
def page_address(self, page):
198+
return self.page_to_virt(page)
199+
200+
def folio_address(self, folio):
201+
return self.page_address(folio['page'].address)
31202

32203
class aarch64_page_ops():
33204
def __init__(self):

tools/accounting/getdelays.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -196,20 +196,20 @@ static int get_family_id(int sd)
196196
#define delay_ms(t) (t / 1000000ULL)
197197

198198
/*
199-
* Format timespec64 to human readable string (YYYY-MM-DD HH:MM:SS)
199+
* Format __kernel_timespec to human readable string (YYYY-MM-DD HH:MM:SS)
200200
* Returns formatted string or "N/A" if timestamp is zero
201201
*/
202-
static const char *format_timespec64(struct timespec64 *ts)
202+
static const char *format_timespec(struct __kernel_timespec *ts)
203203
{
204204
static char buffer[32];
205205
struct tm tm_info;
206-
time_t time_sec;
206+
__kernel_time_t time_sec;
207207

208208
/* Check if timestamp is zero (not set) */
209209
if (ts->tv_sec == 0 && ts->tv_nsec == 0)
210210
return "N/A";
211211

212-
time_sec = (time_t)ts->tv_sec;
212+
time_sec = ts->tv_sec;
213213

214214
/* Use thread-safe localtime_r */
215215
if (localtime_r(&time_sec, &tm_info) == NULL)
@@ -257,7 +257,7 @@ static const char *format_timespec64(struct timespec64 *ts)
257257
average_ms((double)(t)->cpu_delay_total, (t)->cpu_count), \
258258
delay_ms((double)(t)->cpu_delay_max), \
259259
delay_ms((double)(t)->cpu_delay_min), \
260-
format_timespec64(&(t)->cpu_delay_max_ts)); \
260+
format_timespec(&(t)->cpu_delay_max_ts)); \
261261
} else if (version >= 16) { \
262262
printf("%-10s%15s%15s%15s%15s%15s%15s%15s\n", \
263263
"CPU", "count", "real total", "virtual total", \
@@ -316,7 +316,7 @@ static const char *format_timespec64(struct timespec64 *ts)
316316
average_ms((double)(t)->total, (t)->count), \
317317
delay_ms((double)(t)->max), \
318318
delay_ms((double)(t)->min), \
319-
format_timespec64(&(t)->max_ts)); \
319+
format_timespec(&(t)->max_ts)); \
320320
} else if (version >= 16) { \
321321
printf("%-10s%15s%15s%15s%15s%15s\n", \
322322
name, "count", "delay total", "delay average", \

0 commit comments

Comments
 (0)