解析linux内核的reserve_crashkernel函数,对源码进行注释解析
时间: 2024-05-24 13:10:30 浏览: 230
/* Linux内核中reserve_crashkernel函数的定义 */
int __init reserve_crashkernel(void)
{
unsigned long long crash_size;
unsigned long long start_crashkernel, end_crashkernel;
unsigned long long start_pfn, end_pfn;
int ret = 0;
unsigned long flags;
/*
* 如果已经设置了crashkernel的参数,则使用该参数的值;
* 否则默认使用2个物理页的大小作为crashkernel的大小。
*/
if (!crashk_res.start && !crashk_res.end) {
crash_size = 2 * (unsigned long long)PAGE_SIZE;
printk(KERN_INFO "Reserving %lluMB of memory at %lluMB for crashkernel (System RAM: %lluMB)\n",
crash_size >> 20, PFN_PHYS(max_pfn) >> 20, PFN_PHYS(max_pfn) >> 20);
} else {
crash_size = PFN_PHYS(crashk_res.end - crashk_res.start + 1);
printk(KERN_INFO "Reserving %lluMB of memory at %lluMB for crashkernel (System RAM: %lluMB)\n",
crash_size >> 20, PFN_PHYS(crashk_res.start) >> 20, PFN_PHYS(max_pfn) >> 20);
}
/* 获取crashkernel的起始地址和结束地址 */
start_crashkernel = PFN_PHYS(crashk_res.start);
end_crashkernel = start_crashkernel + crash_size;
/* 获取start_crashkernel和end_crashkernel所对应的物理页框号 */
start_pfn = start_crashkernel >> PAGE_SHIFT;
end_pfn = end_crashkernel >> PAGE_SHIFT;
/* 如果crashkernel的结束地址超过了系统的最大物理地址,则返回错误 */
if (end_pfn > max_pfn) {
printk(KERN_ERR "crashkernel reservation failed - memory beyond limit of %llx\n",
(unsigned long long)max_pfn << PAGE_SHIFT);
return -EINVAL;
}
/* 设置crashkernel所在的物理页框为Reserved类型 */
for (; start_pfn < end_pfn; start_pfn++) {
SetPageReserved(pfn_to_page(start_pfn));
num_poisoned_pages++;
}
/*
* 设置crashkernel的保留区域不能被swap out,这样可以确保crashkernel的
* 内存不会被清空。
*/
flags = VM_RESERVED | VM_READ | VM_WRITE | VM_PFNMAP | VM_IOREMAP;
if (mmap_write_lock_killable(mm))
return -EINTR;
vma = mmap(NULL, crash_size, PROT_NONE, flags, -1, 0);
if (IS_ERR(vma)) {
printk(KERN_ERR "crashkernel: Can't reserve %lluMB of memory at %llx\n",
crash_size >> 20, start_crashkernel);
ret = -ENOMEM;
goto out;
}
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
vma->vm_private_data = &crash_pfn;
vma->vm_ops = &crash_mmap_ops;
ret = 0;
out:
mmap_write_unlock(mm);
return ret;
}
/*
reserve_crashkernel函数的作用是为crashkernel保留一段物理内存区域,并将该区域的物理页框设置为Reserved类型。
该函数会先判断是否已经设置了crashkernel的参数,如果没有,则默认使用2个物理页的大小作为crashkernel的大小。
然后获取crashkernel所占用的物理内存的起始地址和结束地址,并将其所对应的物理页框设置为Reserved类型。
最后,设置crashkernel的保留区域不能被swap out,这样可以确保crashkernel的内存不会被清空。
*/
阅读全文