尊龙凯时人生就是搏

RISC-V Linux»ã±àÆô¶¯Àú³ÌÆÊÎö

RISC-V LinuxµÄ»ã±àÆô¶¯²¿·Ö½ÏÁ¿¼òÆÓ £¬²»ËãÖØ´ó ¡£ÓÐÁ½¸ö²¿·Ö½ÏÁ¿½¹µã£ºÒ³±í½¨ÉèºÍÖض¨Ïò ¡£Ò³±í½¨ÉèÊÇÓÃCÓïÑÔдµÄ £¬½ñÌìÏÈÆÊÎö»ã±à²¿·Ö £¬ÏÈ´ø¸÷ÈËÆÊÎöÕûÌå»ã±àÆô¶¯Á÷³Ì £¬È»ºóÆÊÎöÖض¨Ïò ¡£

×¢ÖØ£º±¾ÎÄ»ùÓÚlinux5.10.111ÄÚºË

»ã±àÆô¶¯Á÷³Ì

ÏÈ´ÓÕûÌåÆÊÎö»ã±à×öµÄÊÂÇé £¬Óиö¸ÅÂÔ¿ò¼Ü ¡£

·¾¶£ºarch/riscv/kernel/head.S £¬Èë¿ÚÊÇENTRY(_start_kernel)

´ÓENTRY(_start_kernel)×îÏȾÙÐÐÆô¶¯Ç°µÄһЩ³õʼ»¯ £¬½¨ÉèÒ³±íÇ°µÄÖ÷ÒªÊÂÇ飺

¹Ø±ÕËùÓÐÖÐÖ¹

/* ¹Ø±ÕËùÓÐÖÐÖ¹ */
    csrw CSR_IE, zero
    csrw CSR_IP, zero

µÇ¼ºó¸´ÖÆ

¼ÓÔØÈ«¾ÖÖ¸Õëgp

/* ¼ÓÔØÈ«¾ÖÖ¸Õëgp */
.option push
.option norelax
    la gp, __global_pointer$
.option pop

µÇ¼ºó¸´ÖÆ

disable FPU

/* ½ûÓà FPU ÒÔ¼ì²âÄں˿ռäÖи¡µãµÄ²»·¨Ê¹ÓÃ*/
    li t0, SR_FS
    csrc CSR_STATUS, t0

µÇ¼ºó¸´ÖÆ

Ñ¡ÔñÒ»¸öºËÆô¶¯

/* Ñ¡ÔñÒ»¸öºËÆô¶¯ */
    la a3, hart_lottery
    li a2, 1
    amoadd.w a3, a2, (a3)
    bnez a3, .Lsecondary_start

µÇ¼ºó¸´ÖÆ

ÇåÎúbss¶Î

/* ɨ³ýbss */
    la a3, __bss_start
    la a4, __bss_stop
    ble a4, a3, clear_bss_done

µÇ¼ºó¸´ÖÆ

ÉúÑÄhart idºÍdtbµØµã

/* ÉúÑÄhatr idºÍdtbµØµã£¬hart idÉúÑĵ½a0£¬dtbµØµãÉúÑĵ½a1 */
    mv s0, a0
    mv s1, a1
    la a2, boot_cpu_hartid

µÇ¼ºó¸´ÖÆ

ÉèÖÃspÖ¸Õë

    la sp, init_thread_union + THREAD_SIZE

µÇ¼ºó¸´ÖÆ

ÉÏÊöÊÂÇéÍê³É £¬»á×îÏÈÔÝʱҳ±íµÄ½¨Éè £¬Ìøתµ½Cº¯Êýsetup_vm½¨ÉèÔÝʱҳ±í

    mv a0, s1
    call setup_vm // Ìøתµ½Cº¯Êýsetup_vm£¬setup_vm»á½¨ÉèÔÝʱҳ±í

µÇ¼ºó¸´ÖÆ

Öض¨Ïò

#ifdef CONFIG_MMU
    la a0, early_pg_dir
    call relocate	//Öض¨Ïò£¬ÏÖʵ¾ÍÊÇ¿ªÆôMMU
#endif

µÇ¼ºó¸´ÖÆ

ÉèÖÃÒì³£ÏòÁ¿µØµã £¬ÖØÔØCÇéÐÎ

    call setup_trap_vector
/* ÖØÔØCÇéÐÎ */
    la tp, init_task
    sw zero, TASK_TI_CPU(tp)
    la sp, init_thread_union + THREAD_SIZE

µÇ¼ºó¸´ÖÆ

×îºóÌøתµ½Cº¯Êýstart_kernel £¬×îÏÈCÓïÑÔ²¿·Ö³õʼ»¯ £¬»ã±à²¿·ÖÖ´ÐÐÍê±Ï

tail start_kernel

µÇ¼ºó¸´ÖÆ

ÍêÕû_start_kernel»ã±à´úÂ룺

ENTRY(_start_kernel)
	/* ¹Ø±ÕËùÓÐÖÐÖ¹ */
	csrw CSR_IE, zero
	csrw CSR_IP, zero

	/* ÔÚÔ´ÂëÖÐ£¬ÕâÀïÓÐÒ»¸öMģʽ´¦ÀíµÄºê£¬ÕâÀïûÓÐÓõ½£¬Ö±½ÓÌø¹ý*/

	/* ¼ÓÔØÈ«¾ÖÖ¸Õëgp */
.option push
.option norelax
	la gp, __global_pointer$
.option pop

	/* ½ûÓà FPU ÒÔ¼ì²âÄں˿ռäÖи¡µãµÄ²»·¨Ê¹ÓÃ*/
	li t0, SR_FS
	csrc CSR_STATUS, t0

#ifdef CONFIG_SMP
	li t0, CONFIG_NR_CPUS
	blt a0, t0, .Lgood_cores
	tail .Lsecondary_park
.Lgood_cores:
#endif

	/* Ñ¡ÔñÒ»¸öºËÆô¶¯ */
	la a3, hart_lottery
	li a2, 1
	amoadd.w a3, a2, (a3)
	bnez a3, .Lsecondary_start

	/* ɨ³ýbss */
	la a3, __bss_start
	la a4, __bss_stop
	ble a4, a3, clear_bss_done
clear_bss:
	REG_S zero, (a3)
	add a3, a3, RISCV_SZPTR
	blt a3, a4, clear_bss
clear_bss_done:

	/* ÉúÑÄhatr idºÍdtbµØµã£¬hart idÉúÑĵ½a0£¬dtbµØµãÉúÑĵ½a1 */
	mv s0, a0
	mv s1, a1
	la a2, boot_cpu_hartid
	REG_S a0, (a2)

	/* ³õʼ»¯Ò³±í£¬È»ºóÖض¨Ïòµ½ÐéÄâµØµã */
	la sp, init_thread_union + THREAD_SIZE
	mv a0, s1
	call setup_vm // Ìøתµ½Cº¯Êýsetup_vm£¬setup_vm»á½¨ÉèÔÝʱҳ±í
#ifdef CONFIG_MMU
	la a0, early_pg_dir
	call relocate	//Öض¨Ïò£¬ÏÖʵ¾ÍÊÇ¿ªÆôMMU
#endif /* CONFIG_MMU */

	call setup_trap_vector
	/* ÖØÔØCÇéÐÎ */
	la tp, init_task
	sw zero, TASK_TI_CPU(tp)
	la sp, init_thread_union + THREAD_SIZE

#ifdef CONFIG_KASAN
	call kasan_early_init
#endif
	/* Start the kernel */
	call soc_early_init
	tail start_kernel	//Ìøתµ½Cº¯Êýstart_kernel£¬×îÏÈCÓïÑÔ²¿·Ö³õʼ»¯

µÇ¼ºó¸´ÖÆ

»ã±àÖкÜÊÇÖ÷ÒªµÄÒ»¸ö²¿·Ö¾ÍÊÇÒ³±íµÄ½¨Éè £¬¹ØºõןóÃæµÄ³ÌÐòÄܲ»¿É¼ÌÐøÍùÏÂÅÜ ¡£setup_vm½¨ÉèÒ³±íºó¾Í»á×îÏÈÖ´ÐÐrelocateÖض¨Ïò £¬Õâ¸öÖض¨ÏòÖ÷Òª¿ªÆômmu £¬ÏÂÃæÆÊÎörelocateµÄ»ã±à ¡£

relocate

relocateÖض¨Ïò £¬¾ÍÊÇÔÚ¿ªÆômmu ¡£¿ªÆômmuµÄ²Ù×÷¾ÍÊǽ«Ò»¼¶Ò³±íµÄµØµãÒÔ¼°È¨ÏÞдµ½satp¼Ä´æÆ÷ÖÐ £¬Õâ¾ÍË㿪ÆômmuÁË ¡£

#ifdef CONFIG_MMU
    la a0, early_pg_dir //Ìøתµ½relocateÇ°£¬ÏȰѵÚÒ»¼¶Ò³±íearly_pg_dirµÄµØµã´æÈëa0
    call relocate		//Ìøתµ½relocate,¿ªÆôMMU
#endif

µÇ¼ºó¸´ÖÆ

relocateÓÐÁ½´Î¿ªÆômmuµÄ²Ù×÷ £¬µÚÒ»´Î¿ªÆômmuʹÓõÄÊÇsetup_vm()½¨ÉèµÄtrampoline_gd_dirÒ³±í £¬ÕâÒ³±íÉúÑĵÄÊÇkernelµÄÇ°2MÄÚ´æ ¡£µÚ¶þ´Î¿ªÆôMMUʹÓõÄÊÇearly_pg_dirÒ³±í £¬Õâ¸öÒ³±íÓ³ÉäÁËÕû¸ökernelÄÚ´æÒÔ¼°dtbµÄ4M¿Õ¼ä ¡£

ÈôÊÇtrampoline_pg_dir»òÕßearly_pg_dirÕâÁ½¸öÒ³±íµÄÓ³ÉäûŪºÃµÄ»° £¬¿ªÆôMMUµÄʱ¼ä¾Í»áʧ°Ü £¬ÒÔÊÇÒ³±íµÄ½¨ÉèÊ®·ÖÒªº¦ ¡£Ò³±í½¨ÉèºóÐøÔÙÉ £¬ÏÂÃæÆÊÎörelocate»ã±à´úÂë ¡£

ÅÌËã·µ»ØµØµã

·µ»ØµØµã¾ÍÊÇra¼ÓÉÏÐéÄâµØµãºÍÎïÀíµØµãÖ®¼äµÄÆ«ÒÆÁ¿ £¬Õâ¸öÊÇÀο¿Æ«ÒÆÁ¿ ¡£PAGE_OFFSETÊÇkernelÈë¿ÚµØµã¶ÔÓ¦µÄÐéÄâµØµã £¬_start¾ÍÊÇkernelÈë¿ÚµØµãµÄÐéÄâµØµã £¬PAGE_OFFSET – _start¾Í»ñµÃËüÃÇÖ®¼äµÄÆ«ÒÆ £¬È»ºóÔÙºÍraÏà¼Ó £¬¾ÍÊÇ·µ»ØµØµã ¡£

/* Relocate return address */
	li a1, PAGE_OFFSET
	la a2, _start
	sub a1, a1, a2
	add ra, ra, a1

µÇ¼ºó¸´ÖÆ

½«Òì³£Èë¿Ú1fµÄÐéÄâµØµãдÈëstvec¼Ä´æÆ÷

ÓÉÓÚÒ»µ©¿ªÆôMMU £¬µØµã¶¼Äð³ÉÁËÐéÄâµØµã £¬Ô­À´»á¼ûµÄ¶¼ÊÇÎïÀíµØµã £¬¿ªÆôMMUʱ £¬µØµã±¬·¢Á˸ıä £¬VA != PA £¬´Ó¶ø½øÈëÒì³£ £¬ÒÔÊÇÒªÏÈÉèÖÃÒì³£Èë¿ÚµØµã £¬´ËʱµÄÒì³£Èë¿ÚΪ1f ¡£

/* Point stvec to virtual address of intruction after satp write */
	la a2, 1f
	add a2, a2, a1
	csrw CSR_TVEC, a2

µÇ¼ºó¸´ÖÆ

ÌáÇ°ÅÌËãÇл»µ½early_pg_dirÒ³±íҪдÈësatpµÄÖµ

ÔÙ½øÈërelocate֮ǰ £¬¾ÍÒѾ­°Ñearly_pg_dir¸³Öµ¸øa0ÁË £¬ÒÔÊÇa0ÊÇearly_pg_dir ¡£srlÊÇÂß¼­ÓÒÒÆ £¬mmuʹÓõÄÊÇsv39 £¬ÐéÄâµØµã39λ £¬ÎïÀíµØµã56λ£º

µÍ12λÊÇÆ«ÒÆÁ¿ £¬ÒÔÊÇPAGE_SHIFT¼´ÊÇ12 £¬½«early_pg_dirµØµãÓÒÒÆ12λ´æµ½a2 ¡£Æ¾Ö¤satp¼Ä´æÆ÷½ç˵£º

MODE¼´ÊÇ0x8´ú±íʹÓÃsv39 mmu £¬0x0´ú±í²»¾ÙÐеص㷭Òë £¬¼´²»¿ªÆôMMU ¡£ÕâÀïSTAP_MODEΪsv39 £¬¼´0x8 ¡£½«early_pg_dirµØµãºÍSATP_MODE¾ÙÐлòÔËËãºó £¬¼´¿É»ñµÃдÈësatp¼Ä´æÆ÷µÄÖµ £¬×îºóÉúÑĵ½a2 ¡£

/* Compute satp for kernel page tables, but don't load it yet */
	srl a2, a0, PAGE_SHIFT
	li a1, SATP_MODE	//sv39 mmu
	or a2, a2, a1

µÇ¼ºó¸´ÖÆ

µÚÒ»´Î¿ªÆôMMU £¬Ê¹ÓÃtrampoline_pg_dirÒ³±í

satpÖµµÄÅÌËãºÍÉÏÊöÊÇÒ»ÑùµÄ ¡£¿ªÆôMMU֮ǰ £¬Í¨¹ýsfence.vmaÏÂÁîÏÈË¢ÐÂTLB ¡£´Ëʱ¿ªÆôMMU £¬¾Í»á½øÈëÏÂÃæµÄ±êºÅΪ1µÄ»ã±à¶Î

	la a0, trampoline_pg_dir
	srl a0, a0, PAGE_SHIFT
	or a0, a0, a1
	sfence.vma	
	csrw CSR_SATP, a0

µÇ¼ºó¸´ÖÆ

½øÈëÒì³£1f¶Î £¬ÖØÐÂÉèÖÃÒì³£Èë¿ÚΪ.Lsecondary_park £¬È»ºóÇл»µ½early_pg_dirÒ³±í £¬Ï൱ÓÚµÚ¶þ´Î¿ªÆôMMU ¡£´Ëʱ £¬ÈôÊÇ֮ǰ½¨ÉèµÄearly_pg_dirÒ³±í²î³Ø £¬Ôò»á¾Í½øÈë.Lsecondary_park ¡£.Lsecondary_parkÄÚÀïÊǸöwfiÖ¸Áî £¬ÊǸöËÀÑ­»· ¡£

ÍêÕûrelocate»ã±à´úÂ룺

relocate:
	/* Relocate return address */
	li a1, PAGE_OFFSET
	la a2, _start
	sub a1, a1, a2
	add ra, ra, a1

	/* Point stvec to virtual address of intruction after satp write */
	la a2, 1f
	add a2, a2, a1
	csrw CSR_TVEC, a2

	/* Compute satp for kernel page tables, but don't load it yet */
	srl a2, a0, PAGE_SHIFT
	li a1, SATP_MODE
	or a2, a2, a1

	/*
	 * Load trampoline page directory, which will cause us to trap to
	 * stvec if VA != PA, or simply fall through if VA == PA.  We need a
	 * full fence here because setup_vm() just wrote these PTEs and we need
	 * to ensure the new translations are in use.
	 */
	la a0, trampoline_pg_dir
	srl a0, a0, PAGE_SHIFT
	or a0, a0, a1
	sfence.vma
	csrw CSR_SATP, a0
.align 2
1:
	/* Set trap vector to spin forever to help debug */
	la a0, .Lsecondary_park
	csrw CSR_TVEC, a0

	/* Reload the global pointer */
.option push
.option norelax
	la gp, __global_pointer$
.option pop

	/*
	 * Switch to kernel page tables.  A full fence is necessary in order to
	 * avoid using the trampoline translations, which are only correct for
	 * the first superpage.  Fetching the fence is guarnteed to work
	 * because that first superpage is translated the same way.
	 */
	csrw CSR_SATP, a2
	sfence.vma

	ret

µÇ¼ºó¸´ÖÆ

×ܽá

ÒÔÉϾÍÊÇRISC-V LinuxµÄ»ã±àÆô¶¯Á÷³Ì £¬Ëä˵RISC-VµÄÖ¸Áî²»ÖØ´ó £¬µ«ÒªÃ÷È·Õâ¸ö»ã±àÆô¶¯µÄ²¿·Ö £¬ÕÕ¾ÉÐèÒªÒ»µã»ù´¡ºÍʱ¼ä ¡£ÁíÍâ £¬´ó´ó¶¼ÈËÊÂÇéÖлù±¾Óò»ÉÏ»ã±à £¬Ö»ÓÐÕæÕýÓÃÉÏÁËÃ÷È·²Å»á½ÏÁ¿Éî ¡£Ï£Íû±¾ÎÄÄܹ»×ÊÖúµ½ÓÐÐèÒªµÄÈË ¡£

ÒÔÉϾÍÊÇRISC-V Linux»ã±àÆô¶¯Àú³ÌÆÊÎöµÄÏêϸÄÚÈÝ £¬¸ü¶àÇë¹Ø×¢±¾ÍøÄÚÆäËüÏà¹ØÎÄÕ£¡

ÃâÔð˵Ã÷£ºÒÔÉÏչʾÄÚÈÝȪԴÓÚÏàÖúýÌå¡¢ÆóÒµ»ú¹¹¡¢ÍøÓÑÌṩ»òÍøÂçÍøÂçÕûÀí £¬°æȨÕùÒéÓë±¾Õ¾ÎÞ¹Ø £¬ÎÄÕÂÉæ¼°¿´·¨Óë¿´·¨²»´ú±í尊龙凯时人生就是搏ÂËÓÍ»úÍø¹Ù·½Ì¬¶È £¬Çë¶ÁÕß½ö×ö²Î¿¼ ¡£±¾ÎĽӴýתÔØ £¬×ªÔØÇë˵Ã÷À´ÓÉ ¡£ÈôÄúÒÔΪ±¾ÎÄÇÖÕ¼ÁËÄúµÄ°æȨÐÅÏ¢ £¬»òÄú·¢Ã÷¸ÃÄÚÈÝÓÐÈκÎÉæ¼°ÓÐÎ¥¹«µÂ¡¢Ã°·¸Ö´·¨µÈÎ¥·¨ÐÅÏ¢ £¬ÇëÄúÁ¬Ã¦ÁªÏµ尊龙凯时人生就是搏ʵʱÐÞÕý»òɾ³ý ¡£

Ïà¹ØÐÂÎÅ

ÁªÏµ尊龙凯时人生就是搏

18523999891

¿É΢ÐÅÔÚÏß×Éѯ

ÊÂÇéʱ¼ä£ºÖÜÒ»ÖÁÖÜÎå £¬9:30-18:30 £¬½ÚãåÈÕÐÝÏ¢

QR code
sitemap¡¢ÍøÕ¾µØͼ