先准备busybox
busybox cd ~ wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2 tar -xvf busybox-1.36.1.tar.bz2 cd busybox-1.36.1 # 配置 BusyBox make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- defconfig # 启用静态编译(关键:无需动态库) make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig # 勾选:Settings -> Build static binary (no shared libs) # 编译并安装 BusyBox make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- install -j$(nproc) # 创建根文件系统目录 mkdir -p ~/rootfs cd ~/rootfs # 复制 BusyBox 生成的文件 cp -r ~/busybox-1.36.1/_install/* ./ # 创建必要目录 mkdir -p dev proc sys tmp etc/init.d mnt root # 创建 init 启动脚本(核心) cat > etc/init.d/rcS << EOF #!/bin/sh mount -t proc proc /proc mount -t sysfs sysfs /sys mount -t tmpfs tmpfs /tmp mdev -s # 自动创建设备节点 echo "Welcome to QEMU ARM Linux!" EOF # 赋予执行权限 chmod +x etc/init.d/rcS # 创建 inittab(指定启动脚本) cat > etc/inittab << EOF ::sysinit:/etc/init.d/rcS ::respawn:/bin/sh ::ctrlaltdel:/sbin/reboot EOF # 创建设备节点(控制台/串口) sudo mknod dev/console c 5 1 sudo mknod dev/ttyAMA0 c 204 64 # QEMU 串口节点 dd if=/dev/zero of=a64rootfs.ext4 bs=1M count=128 # 3. 格式化空镜像为ext4格式(必须格式化,否则无法挂载和使用) sudo mkfs.ext4 a64rootfs.ext4 # 4. 创建临时挂载目录(已创建可跳过) mkdir -p tmp_mount # 5. 挂载新建的空ext4镜像到tmp_mount sudo mount a64rootfs.ext4 tmp_mount/ # 6. 复制a64rootfs目录下所有文件到镜像中(保留文件权限和结构) sudo cp -rf a64rootfs/* tmp_mount/ # 7. 同步数据(确保所有文件写入镜像,避免丢失) sudo sync # 8. 卸载镜像(完成打包) sudo umount tmp_mount/准备ubuntu22
ubuntu22 make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfig make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig make -j$(nproc) ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- Image dtbs准备qemu
#!/bin/bash qemu-system-aarch64 -M virt -cpu cortex-a53 \ -kernel linux-5.15.146/arch/arm64/boot/Image \ -drive file=busybox-1.36.1/a64rootfs.ext4,format=raw,id=hd0,if=none \ -device virtio-blk-device,drive=hd0 \ -append "root=/dev/vda rw console=ttyAMA0 loglevel=8 init=/linuxrc nokaslr" \ -nographic \ -S -s准备调试
// 这个cmd启动到cmd阶段有问题 但是不影响start_kernel阶段的调试.. gdb-multiarch -ex 'target remote :1234' vmlinux arch/arm64/kernel/vmlinux.lds.S reserved_pg_dir = .; . += PAGE_SIZE; swapper_pg_dir = .; . += PAGE_SIZE; . = ALIGN(SEGMENT_ALIGN); __init_begin = .; __inittext_begin = .; (gdb) p &swapper_pg_dir $6 = (pgd_t (*)[512]) 0xffff8000096e8000 (gdb) p &reserved_pg_dir $7 = (pgd_t (*)[512]) 0xffff8000096e7000 (gdb) p &__init_begin $8 = (char (*)[]) 0xffff8000096f0000 <primary_entry> ///////////// (gdb) bt #0 free_area_init_core (pgdat=<optimized out>) at mm/page_alloc.c:7525 #1 free_area_init_node (nid=0) at mm/page_alloc.c:7663 #2 0xffff800009705824 in free_area_init (max_zone_pfn=0xffff800009d09d88 <node_states+8>) at mm/page_alloc.c:8103 #3 0xffff8000096f6c84 in zone_sizes_init (min=<optimized out>, max=<optimized out>) at arch/arm64/mm/init.c:184 #4 bootmem_init () at arch/arm64/mm/init.c:380 #5 0xffff8000096f3ca8 in setup_arch (cmdline_p=0xfffffbfffdc00084) at arch/arm64/kernel/setup.c:350 #6 0xffff8000096f0c54 in start_kernel () at init/main.c:959 Breakpoint 1, 0xffff8000081e42d4 in add_to_free_list (migratetype=<optimized out>, order=<optimized out>, zone=<optimized out>, page=<optimized out>) at mm/page_alloc.c:968 968 list_add(&page->lru, &area->free_list[migratetype]); (gdb) bt #0 0xffff8000081e42d4 in add_to_free_list (migratetype=<optimized out>, order=<optimized out>, zone=<optimized out>, page=<optimized out>) at mm/page_alloc.c:968 #1 expand (migratetype=<optimized out>, high=10, low=<optimized out>, page=<optimized out>, zone=<optimized out>) at mm/page_alloc.c:2308 #2 __rmqueue_smallest (migratetype=<optimized out>, order=<optimized out>, zone=<optimized out>) at mm/page_alloc.c:2462 #3 __rmqueue (alloc_flags=<optimized out>, migratetype=<optimized out>, order=<optimized out>, zone=<optimized out>) at mm/page_alloc.c:2995 #4 rmqueue_bulk (zone=0xffff000007fb3c00, order=0, count=18446462598866746560, list=0x1, migratetype=30, alloc_flags=0) at mm/page_alloc.c:3027 #5 0xffff8000081e69d4 in __rmqueue_pcplist (list=<optimized out>, pcp=<optimized out>, alloc_flags=<optimized out>, migratetype=<optimized out>, order=<optimized out>, zone=<optimized out>) at mm/page_alloc.c:3624 #6 rmqueue_pcplist (gfp_flags=<optimized out>, alloc_flags=<optimized out>, migratetype=<optimized out>, order=<optimized out>, zone=<optimized out>, preferred_zone=<optimized out>) at mm/page_alloc.c:3662 #7 rmqueue (migratetype=<optimized out>, alloc_flags=<optimized out>, gfp_flags=<optimized out>, order=<optimized out>, zone=<optimized out>, preferred_zone=<optimized out>) at mm/page_alloc.c:3690 #8 get_page_from_freelist (gfp_mask=589824, order=1, alloc_flags=133911808, ac=0x1) at mm/page_alloc.c:4156 #9 0xffff8000081e72e4 in __alloc_pages (gfp=589824, order=0, preferred_nid=10, nodemask=0x0) at mm/page_alloc.c:5421 #10 0xffff80000820f114 in __alloc_pages_node (order=<optimized out>, gfp_mask=<optimized out>, nid=<optimized out>) at ./include/linux/gfp.h:570 #11 alloc_slab_page (s=<optimized out>, oo=..., node=<optimized out>, flags=<optimized out>) at mm/slub.c:1777 #12 allocate_slab (node=<optimized out>, flags=<optimized out>, s=<optimized out>) at mm/slub.c:1912 #13 new_slab (s=0xffff8000097a2dc8 <boot_kmem_cache_node>, flags=589832, node=0) at mm/slub.c:1975 #14 0xffff800008216544 in early_kmem_cache_node_alloc (node=<optimized out>) at mm/slub.c:3915 #15 init_kmem_cache_nodes (s=<optimized out>) at mm/slub.c:3970 #16 kmem_cache_open (flags=<optimized out>, s=<optimized out>) at mm/slub.c:4216 #17 __kmem_cache_create (s=0xffff8000097a2dc8 <boot_kmem_cache_node>, flags=589832) at mm/slub.c:4892 #18 0xffff800009703bb0 in create_boot_cache (s=0xffff8000097a2dc8 <boot_kmem_cache_node>, name=0xffff8000094d4a90 "kmem_cache_node", size=64, flags=8192, useroffset=0, usersize=0) at mm/slab_common.c:671 --Type <RET> for more, q to quit, c to continue without paging-- #19 0xffff800009708c14 in kmem_cache_init () at mm/slub.c:4824 #20 0xffff8000096f0fbc in mm_init () at init/main.c:853 #21 start_kernel () at init/main.c:994 #22 0xffff8000096f03f0 in __primary_switched () at arch/arm64/kernel/head.S:468 Backtrace stopped: previous frame identical to this frame (corrupt stack?) ///////////// (gdb) p node_data $8 = 0xffff800009d0d818 <node_data> (gdb) p node_data[0] $9 = (struct pglist_data *) 0xffff000007fb3c00 (gdb) p node_data[1] $10 = (struct pglist_data *) 0x0 (gdb) p *node_data[0] $11 = {node_zones = {{_watermark = {0, 0, 0}, watermark_boost = 0, nr_reserved_highatomic = 0, lowmem_reserve = {0, 0, 0, 0}, node = 0, zone_pgdat = 0xffff000007fb3c00, per_cpu_pageset = 0xffff800009839718 <boot_pageset>, per_cpu_zonestats = 0xffff800009839818 <boot_zonestats>, pageset_high = 0, pageset_batch = 1, zone_start_pfn = 262144, managed_pages = <incomplete type>, spanned_pages = 32768, present_pages = 32768, cma_pages = 0, name = 0xffff8000095a2ca0 "DMA", nr_isolate_pageblock = 0, initialized = 1, _pad1_ = { x = 0xffff000007fb3cc0 "\310\006\t"}, free_area = {{free_list = 0xffff000007fb3cc0, nr_free = 2}, { free_list = 0xffff000007fb3d28, nr_free = 5}, {free_list = 0xffff000007fb3d90, nr_free = 2}, { free_list = 0xffff000007fb3df8, nr_free = 2}, {free_list = 0xffff000007fb3e60, nr_free = 4}, { free_list = 0xffff000007fb3ec8, nr_free = 3}, {free_list = 0xffff000007fb3f30, nr_free = 4}, { free_list = 0xffff000007fb3f98, nr_free = 2}, {free_list = 0xffff000007fb4000, nr_free = 5}, { free_list = 0xffff000007fb4068, nr_free = 4}, {free_list = 0xffff000007fb40d0, nr_free = 11}}, flags = 0, lock = <incomplete type>, _pad2_ = {x = 0xffff000007fb4180 ""}, percpu_drift_mark = 0, compact_cached_free_pfn = 0, compact_cached_migrate_pfn = {0, 0}, compact_init_migrate_pfn = 0, compact_init_free_pfn = 0, compact_considered = 0, compact_defer_shift = 0, compact_order_failed = 0, compact_blockskip_flush = false, contiguous = false, _pad3_ = {x = 0xffff000007fb41c0 "\304;"}, vm_stat = 0xffff000007fb41c0, vm_numa_event = 0xffff000007fb4210}, {_watermark = {0, 0, 0}, watermark_boost = 0, nr_reserved_highatomic = 0, lowmem_reserve = {0, 0, 0, 0}, node = 0, zone_pgdat = 0xffff000007fb3c00, per_cpu_pageset = 0xffff800009839718 <boot_pageset>, per_cpu_zonestats = 0xffff800009839818 <boot_zonestats>, pageset_high = 0, pageset_batch = 1, zone_start_pfn = 0, managed_pages = <incomplete type>, spanned_pages = 0, present_pages = 0, cma_pages = 0, name = 0xffff8000094d2af0 "DMA32", nr_isolate_pageblock = 0, initialized = 0, _pad1_ = {x = 0xffff000007fb4300 ""}, free_area = {{free_list = 0xffff000007fb4300, (gdb) (gdb) p (node_data[0].node_zones)[0].present_pages $15 = 32768 (gdb) p (node_data[0].node_zones)[1].present_pages $16 = 0 (gdb) p (node_data[0].node_zones)[2].present_pages $17 = 0 (gdb) p (node_data[0].node_zones)[2].name $18 = 0xffff8000094d2af8 "Normal" (gdb) p (node_data[0].node_zones)[3].name $19 = 0xffff8000094d2ab8 "Movable" (gdb) p (node_data[0].node_zones)[4].name $20 = 0x0 (gdb) p (node_data[0].node_zones)[1].name $21 = 0xffff8000094d2af0 "DMA32" (gdb) p (node_data[0].node_zones)[0].name $22 = 0xffff8000095a2ca0 "DMA" (gdb)