rootfs_init_fs_context
在执行到alloc_fs_context()
/**
* alloc_fs_context - Create a filesystem context.
* @fs_type: The filesystem type.
* @reference: The dentry from which this one derives (or NULL)
* @sb_flags: Filesystem/superblock flags (SB_*)
* @sb_flags_mask: Applicable members of @sb_flags
* @purpose: The purpose that this configuration shall be used for.
*
* Open a filesystem and create a mount context. The mount context is
* initialised with the supplied flags and, if a submount/automount from
* another superblock (referred to by @reference) is supplied, may have
* parameters such as namespaces copied across from that superblock.
*/
static struct fs_context *alloc_fs_context(struct file_system_type *fs_type,
struct dentry *reference,
unsigned int sb_flags,
unsigned int sb_flags_mask,
enum fs_context_purpose purpose)
{
int (*init_fs_context)(struct fs_context *);
struct fs_context *fc;
int ret = -ENOMEM;
printk(" in alloc_fs_context()\n");
fc = kzalloc(sizeof(struct fs_context), GFP_KERNEL);
if (!fc)
return ERR_PTR(-ENOMEM);
fc->purpose = purpose;
fc->sb_flags = sb_flags;
fc->sb_flags_mask = sb_flags_mask;
fc->fs_type = get_filesystem(fs_type);
fc->cred = get_current_cred();
fc->net_ns = get_net(current->nsproxy->net_ns);
fc->log.prefix = fs_type->name;
mutex_init(&fc->uapi_mutex);
switch (purpose) {
case FS_CONTEXT_FOR_MOUNT:
fc->user_ns = get_user_ns(fc->cred->user_ns);
break;
case FS_CONTEXT_FOR_SUBMOUNT:
fc->user_ns = get_user_ns(reference->d_sb->s_user_ns);
break;
case FS_CONTEXT_FOR_RECONFIGURE:
atomic_inc(&reference->d_sb->s_active);
fc->user_ns = get_user_ns(reference->d_sb->s_user_ns);
fc->root = dget(reference);
break;
}
/* TODO: Make all filesystems support this unconditionally */
init_fs_context = fc->fs_type->init_fs_context;
printk(" init_fs_context() init_fs_context=0x%x, legacy_init_fs_context=0x%x\n", (int)init_fs_context, (int)legacy_init_fs_context);
if (!init_fs_context)
init_fs_context = legacy_init_fs_context;
ret = init_fs_context(fc);
if (ret < 0)
goto err_fc;
fc->need_free = true;
return fc;
err_fc:
printk(" put_fs_context()\n");
put_fs_context(fc);
printk(" put_fs_context() finish\n");
return ERR_PTR(ret);
}
里面调用init_fs_context(), 这个函数应该是rootfs_init_fs_context()。
但奇怪的是,系统执行到这里会执行不下去。因为soc2我还有很多东西没实现,所以卡在这里也许是因为访问内存出错什么的。
所以我在这个函数里加了句printk,看看执行的什么情况。结果是这段程序直接跑过去了。也就是说在函数开始只加了句printk,导致执行结果是不同的。
开始想可能是有什么竞争情况?但是在想不出来,printk是我自己接管了后直接写显存,本来就不拿锁。应该也和中断没关系。
但这个函数的地址很奇怪,0x2000040,非常靠近内核起点。
la_build/vmlinux: file format elf32-loongarch
Disassembly of section .text:
02000000 <_stext>:
2000000: 02bfc063 addi.w $r3,$r3,-16(0xff0)
2000004: 29802076 st.w $r22,$r3,8(0x8)
2000008: 29803061 st.w $r1,$r3,12(0xc)
200000c: 02804076 addi.w $r22,$r3,16(0x10)
2000010: 1c0037c7 pcaddu12i $r7,446(0x1be)
2000014: 0289a0e7 addi.w $r7,$r7,616(0x268)
2000018: 02833006 addi.w $r6,$r0,204(0xcc)
200001c: 1c00aa05 pcaddu12i $r5,1360(0x550)
2000020: 02bf90a5 addi.w $r5,$r5,-28(0xfe4)
2000024: 1c0056c4 pcaddu12i $r4,694(0x2b6)
2000028: 02bf7084 addi.w $r4,$r4,-36(0xfdc)
200002c: 54ba3402 bl 571956(0x8ba34) # 208ba60 <free_reserved_area>
2000030: 28803061 ld.w $r1,$r3,12(0xc)
2000034: 28802076 ld.w $r22,$r3,8(0x8)
2000038: 02804063 addi.w $r3,$r3,16(0x10)
200003c: 4c000020 jirl $r0,$r1,0
02000040 <rootfs_init_fs_context>:
2000040: 02bfc063 addi.w $r3,$r3,-16(0xff0)
2000044: 29802076 st.w $r22,$r3,8(0x8)
2000048: 29803061 st.w $r1,$r3,12(0xc)
200004c: 02804076 addi.w $r22,$r3,16(0x10)
2000050: 54b9c004 bl 1096128(0x10b9c0) # 210ba10 <ramfs_init_fs_context>
2000054: 28803061 ld.w $r1,$r3,12(0xc)
2000058: 28802076 ld.w $r22,$r3,8(0x8)
200005c: 02804063 addi.w $r3,$r3,16(0x10)
2000060: 4c000020 jirl $r0,$r1,0
2000064: 03400000 andi $r0,$r0,0x0
2000068: 03400000 andi $r0,$r0,0x0
200006c: 03400000 andi $r0,$r0,0x0
一但加了printk,这个函数的位置就变了。
021846e4 <rootfs_init_fs_context>:
21846e4: 02bfc063 addi.w $r3,$r3,-16(0xff0)
21846e8: 29803061 st.w $r1,$r3,12(0xc)
21846ec: 29802076 st.w $r22,$r3,8(0x8)
21846f0: 29801077 st.w $r23,$r3,4(0x4)
21846f4: 02804076 addi.w $r22,$r3,16(0x10)
21846f8: 00150097 move $r23,$r4
21846fc: 1c000744 pcaddu12i $r4,58(0x3a)
2184700: 02b64084 addi.w $r4,$r4,-624(0xd90)
2184704: 54253400 bl 9524(0x2534) # 2186c38 <printk>
2184708: 001502e4 move $r4,$r23
218470c: 5472e7fe bl -494876(0xff872e4) # 210b9f0 <ramfs_init_fs_context>
2184710: 28803061 ld.w $r1,$r3,12(0xc)
2184714: 28802076 ld.w $r22,$r3,8(0x8)
2184718: 28801077 ld.w $r23,$r3,4(0x4)
218471c: 02804063 addi.w $r3,$r3,16(0x10)
2184720: 4c000020 jirl $r0,$r1,0
这个函数位置就比较正常。但我不明白的是,就算是在0x2000040执行rootfs_init_fs_context, 也不至于跑不下去。
它们中间调用的ramfs_init_fs_context的地址也都很正常。
现在做个实现,rootfs_init_fs_context里不加printk,在ramfs_init_fs_context里printk,看看程序跑成什么情况。
结果是不行,不在rootfs_init_fs_context里加printk程序执行的就不正常。
0x2000040确实不在我在dtb里描述的memory的范围,因为我把vmlinux占用的几mb排除了,从0x2800000-0x3ffffff。但直接的jirl应该不会有什么代码会检查这个范围。