日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

arm linux内核启动过程,ARM64的启动过程之(一):内核第一个脚印

發(fā)布時(shí)間:2024/1/8 linux 66 豆豆
生活随笔 收集整理的這篇文章主要介紹了 arm linux内核启动过程,ARM64的启动过程之(一):内核第一个脚印 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

ARM64的啟動(dòng)過程之(一):內(nèi)核第一個(gè)腳印

作者:linuxer 發(fā)布于:2015-10-10 15:06

分類:ARMv8A Arch

一、前言

kernel的整個(gè)啟動(dòng)過程涉及的內(nèi)容很多,不可能每一個(gè)細(xì)節(jié)都描述清楚,因此我打算針對(duì)部分和ARM64相關(guān)的啟動(dòng)步驟進(jìn)行學(xué)習(xí)、整理,并方便后續(xù)查閱。本文實(shí)際上描述在系統(tǒng)啟動(dòng)最開始的時(shí)候,bootloader和kernel的交互以及kernel如何保存bootloader傳遞的參數(shù)并進(jìn)行校驗(yàn),此外,還有一些最基礎(chǔ)的硬件初始化的內(nèi)容。

本文中的source來自4.1.10內(nèi)核,這是一個(gè)long term的版本,后續(xù)一段時(shí)間的文章都會(huì)基于這個(gè)long term版本進(jìn)行。

二、進(jìn)入kernel之前

系統(tǒng)啟動(dòng)過程中,linux kernel不是一個(gè)人在戰(zhàn)斗,在kernel之前bootloader會(huì)執(zhí)行若干的動(dòng)作,然后把控制權(quán)轉(zhuǎn)移給linux kernel。需要特別說明的是:這里bootloader是一個(gè)寬泛的概念,其實(shí)就是為kernel準(zhǔn)備好執(zhí)行環(huán)境的那些軟件,可能是傳統(tǒng)意義的bootloader(例如Uboot),也可能是Hypervisor或者是secure monitor。具體bootloader需要執(zhí)行的動(dòng)作包括:

1、初始化系統(tǒng)中的RAM并將RAM的信息告知kernel

2、準(zhǔn)備好device tree blob的信息并將dtb的首地址告知kernel

3、解壓內(nèi)核(可選)

4、將控制權(quán)轉(zhuǎn)交給內(nèi)核。當(dāng)然,bootloader和kernel的交互的時(shí)候需求如下:

MMU = off, D-cache = off, I-cache = on or off

x0 = physical address to the FDT blob

這里需要對(duì)data cache和instruction cache多說幾句。我們知道,具體實(shí)現(xiàn)中的ARMv8處理器的cache是形成若干個(gè)level,一般而言,可能L1是分成了data cache和instruction cache,而其他level的cache都是unified cache。上面定義的D-cache off并不是說僅僅disable L1的data cache,實(shí)際上是disable了各個(gè)level的data cache和unified cache。同理,對(duì)于instruction cache亦然。

此外,在on/off控制上,MMU和data cache是有一定關(guān)聯(lián)的。在ARM64中,SCTLR, System Control Register用來控制MMU icache和dcache,雖然這幾個(gè)控制bit是分開的,但是并不意味著MMU、data cache、instruction cache的on/off控制是彼此獨(dú)立的。一般而言,這里MMU和data cache是綁定的,即如果MMU 是off的,那么data cache也必須要off。因?yàn)槿绻蜷_data cache,那么要設(shè)定memory type、sharebility attribute、cachebility attribute等,而這些信息是保存在頁表(Translation table)的描述符中,因此,如果不打開MMU,如果沒有頁表翻譯過程,那么根本不知道怎么來應(yīng)用data cache。當(dāng)然,是不是說HW根本不允許這樣設(shè)定呢?也不是了,在MMU OFF而data cache是ON的時(shí)候,這時(shí)候,所有的memory type和attribute是固定的,即memory type都是normal Non-shareable的,對(duì)于inner cache和outer cache,其策略都是Write-Back,Read-Write Allocate的。

更詳細(xì)的ARM64 boot protocol請(qǐng)參考Documentation/arm64/booting.txt文檔。

三、參數(shù)的保存和校驗(yàn)

最開始的ARM64啟動(dòng)代碼位于arch/arm64/kernel/head.S文件中,代碼如下:

ENTRY(stext)

bl??? preserve_boot_args

bl??? el2_setup??????????? // Drop to EL1, w20=cpu_boot_mode

adrp??? x24, __PHYS_OFFSET

bl??? set_cpu_boot_mode_flag

bl??? __vet_fdt

……

ENDPROC(stext)

1、preserve_boot_args

preserve_boot_args:

mov??? x21, x0------將dtb的地址暫存在x21寄存器中,釋放出x0以便后續(xù)做臨時(shí)變量使用

adr_l??? x0, boot_args---x0保存了boot_args變量的地址

stp??? x21, x1, [x0]----保存x0和x1的值到boot_args[0]和boot_args[1]

stp??? x2, x3, [x0, #16] ---保存x2和x3的值到boot_args[2]和boot_args[3]

dmb??? sy---------full system data memory barrier

add??? x1, x0, #0x20----x0和x1是傳遞給__inval_cache_range的參數(shù)

b??? __inval_cache_range

ENDPROC(preserve_boot_args)

由于MMU = off, D-cache = off,因此寫入boot_args變量的操作都是略過data cache的,直接寫入了RAM中(前面說過了,這里的D-cache并不是特指L1的data cache,而是各個(gè)level的data cache和unified cache),為了安全起見(也許bootloader中打開了D-cache并操作了boot_args這段memory,從而在各個(gè)level的data cache和unified cache有了一些舊的,沒有意義的數(shù)據(jù)),需要將boot_args變量對(duì)應(yīng)的cache line進(jìn)行清除并設(shè)置無效。在調(diào)用__inval_cache_range之前,x0是boot_args這段memory的首地址,x1是末尾的地址(boot_args變量長(zhǎng)度是4x8byte=32byte,也就是0x20了)。

為何要保存x0~x3這四個(gè)寄存器呢?因?yàn)锳RM64 boot protocol對(duì)啟動(dòng)時(shí)候的x0~x3這四個(gè)寄存器有嚴(yán)格的限制:x0是dtb的物理地址,x1~x3必須是0(非零值是保留將來使用)。在后續(xù)setup_arch函數(shù)執(zhí)行的時(shí)候會(huì)訪問boot_args并進(jìn)行校驗(yàn)。

對(duì)于invalidate cache的操作而言,我們可以追問幾個(gè)問題:如果boot_args所在區(qū)域的首地址和尾部地址沒有對(duì)齊到cache line怎么辦?具體invalidate cache需要操作到那些level的的cache?這些問題可以通過閱讀__inval_cache_range的代碼獲得答案,這里就不描述了。

還有一個(gè)小細(xì)節(jié)是如何訪問boot_args這個(gè)符號(hào)的,這個(gè)符號(hào)是一個(gè)虛擬地址,但是,現(xiàn)在沒有建立好頁表,也沒有打開MMU,如何訪問它呢?這是通過adr_l這個(gè)宏來完成的。這個(gè)宏實(shí)際上是通過adrp這個(gè)匯編指令完成,通過該指令可以將符號(hào)地址變成運(yùn)行時(shí)地址(通過PC relative offset形式),因此,當(dāng)運(yùn)行的MMU OFF mode下,通過adrp指令可以獲取符號(hào)的物理地址。不過adrp是page對(duì)齊的(adrp中的p就是page的意思),boot_args這個(gè)符號(hào)當(dāng)然不會(huì)是page size對(duì)齊的,因此不能直接使用adrp,而是使用adr_l這個(gè)宏進(jìn)行處理,如果讀者有興趣可以自己看source code。

最后,我們來解釋一下dmb?? ?sy這一條指令。在ARM ARM文檔中,有關(guān)于數(shù)據(jù)訪問指令和 data cache指令之間操作順序的約定,原文如下:

All data cache instructions, other than DC ZVA, that specify an address can execute in any order relative to loads or stores that access any address with the Device memory attribute,or with Normal memory with Inner Non-cacheable attribute unless a DMB or DSB is executed between the instructions.

因此,在Non-cacheable的情況下,必須要使用DMB來保證stp指令在dc ivac指令之前執(zhí)行完成。

2、el2_setup

程序執(zhí)行至此,CPU處于哪一個(gè)exception level呢?根據(jù)ARM64 boot protocol,CPU要么處于EL2(推薦)或者non-secure EL1。如果在EL1,情形有些類似過去arm處理器的感覺,處于EL2稍微復(fù)雜一些,需要對(duì)virtualisation extensions進(jìn)行基本的設(shè)定,然后將cpu退回到EL1。代碼太長(zhǎng)了,我們分成兩段來閱讀,第一段如下:

ENTRY(el2_setup)

mrs??? x0, CurrentEL------------------------(1)

cmp??? x0, #CurrentEL_EL2------判斷是否處于EL2

b.ne??? 1f--------------不是的話,跳到1f

mrs??? x0, sctlr_el2-------------------------(2)

CPU_BE(??? orr??? x0, x0, #(1 << 25)??? )??? // Set the EE bit for EL2

CPU_LE(??? bic??? x0, x0, #(1 << 25)??? )??? // Clear the EE bit for EL2

msr??? sctlr_el2, x0----寫回sctlr_el2寄存器

b??? 2f

1:??? mrs??? x0, sctlr_el1-------------------------(3)

CPU_BE(??? orr??? x0, x0, #(3 << 24)??? )??? // Set the EE and E0E bits for EL1

CPU_LE(??? bic??? x0, x0, #(3 << 24)??? )??? // Clear the EE and E0E bits for EL1

msr??? sctlr_el1, x0

mov??? w20, #BOOT_CPU_MODE_EL1----w20寄存器保存了cpu啟動(dòng)時(shí)候的Eexception level

isb---------instruction memory barrier

ret

2:??? mov??? x0, #(1 << 31) ------------------------(4)

msr??? hcr_el2, x0

mrs??? x0, cnthctl_el2 -------------------------(5)

orr??? x0, x0, #3???????????????? // Enable EL1 physical timers

msr??? cnthctl_el2, x0

msr??? cntvoff_el2, xzr??????? // Clear virtual offset

mrs??? x0, id_aa64pfr0_el1 -----------------------(6)

ubfx??? x0, x0, #24, #4 ----取出24 bit開始的4個(gè)bit的值并將該值賦給x0

cmp??? x0, #1

b.ne??? 3f -----不支持system register接口

mrs_s??? x0, ICC_SRE_EL2

orr??? x0, x0, #ICC_SRE_EL2_SRE??? // Set ICC_SRE_EL2.SRE==1

orr??? x0, x0, #ICC_SRE_EL2_ENABLE??? // Set ICC_SRE_EL2.Enable==1

msr_s??? ICC_SRE_EL2, x0

isb??????????????????? // Make sure SRE is now set

msr_s??? ICH_HCR_EL2, xzr??????? // Reset ICC_HCR_EL2 to defaults

3:?????????????? ……

(1)當(dāng)前的exception level保存在PSTATE中,程序可以通過MRS或者M(jìn)SR來訪問PSTATE,當(dāng)然需要傳遞一個(gè)Special-purpose register做為參數(shù),CurrentEL就是獲取PSTATE中current exception level域的特殊寄存器。

(2)sctlr_el2也是一個(gè)可以通過MRS/MSR指令訪問的寄存器,當(dāng)CPU處于EL2狀態(tài)的時(shí)候,該寄存器可以控制整個(gè)系統(tǒng)的行為。當(dāng)然,這里僅僅是設(shè)定EL2下的數(shù)據(jù)訪問和地址翻譯過程中的endianess配置,也就是EE bit[25]。根據(jù)配置,CPU_BE和CPU_LE包圍的指令只會(huì)保留一行。對(duì)于little endian而言,實(shí)際上就是將sctlr_el2寄存器的EE(bit 25)設(shè)定為0。順便說一下,這個(gè)bit不僅僅控制EL2數(shù)據(jù)訪問的endianess以及EL2 stage 1的地址翻譯過程中的endianess(當(dāng)然,EL2只有stage 1),還可以控制EL1和EL0 stage 2地址翻譯的過程的endianess(這時(shí)候有兩個(gè)stage的地址翻譯過程)。

(3)執(zhí)行到這里說明CPU處于EL1,這種狀態(tài)下沒有權(quán)限訪問sctlr_el2,只能是訪問sctlr_el1。sctlr_el1可以通過EE和E0E來控制EL1和EL0狀態(tài)下是little endian還是big endian。EE bit控制了EL1下的數(shù)據(jù)訪問以及EL1和EL0 stage 1地址翻譯的過程的endianess。E0E bit用來控制EL0狀態(tài)下的數(shù)據(jù)訪問的endianess。此外,需要注意的是:由于修改了system control register(設(shè)定endianess狀態(tài)),因此需要一個(gè)isb來同步(具體包括兩部分的內(nèi)容,一是確認(rèn)硬件已經(jīng)執(zhí)行完畢了isb之前的所有指令,包括修改system control寄存器的那一條指令,另外一點(diǎn)是確保isb之后的指令從新來過,例如取指,校驗(yàn)權(quán)限等)。

(4)執(zhí)行到這里說明CPU處于EL2,首先設(shè)定的是hcr_el2寄存器,Hypervisor Configuration Register。該寄存器的大部分bit 值在reset狀態(tài)的時(shí)候就是0值,只不過bit 31(Register Width Control)是implementation defined,因此這里set 31為1,確保Low level的EL1也是Aarch64的

(5)這一段代碼是對(duì)Generic timers進(jìn)行配置。要想理解這段代碼,我們需要簡(jiǎn)單的了解一些ARMv8上Generic timer的運(yùn)作邏輯。一個(gè)全局范圍的system counter、各個(gè)PE上自己專屬的local timer以及連接這些組件之間的bus或者信息傳遞機(jī)制組成了Generic Timer。對(duì)于PE而言,通過寄存器訪問,它能看到的是physical counter(實(shí)際的system counter計(jì)數(shù))、virtual counter(physical counter基礎(chǔ)上的offset)、physical timer、virtual timer等。NTHCTL_EL2,Counter-timer Hypervisor Control register,用來控制系統(tǒng)中的physical counter和virutal counter如何產(chǎn)生event stream以及在EL1和EL0狀態(tài)訪問physical counter和timer的硬件行為的。在EL1(EL0)狀態(tài)的時(shí)候訪問physical counter和timer有兩種配置,一種是允許其訪問,另外一種就是trap to EL2。這里的設(shè)定是:不陷入EL2(對(duì)應(yīng)的bit設(shè)置為1)。更詳細(xì)的信息可以參考ARMv8 ARM文檔。cntvoff_el2是virtual counter offset,所謂virtual counter,其值就是physical counter的值減去一個(gè)offset的值(也就是cntvoff_el2的值了),這里把offset值清零,因此virtual counter的計(jì)數(shù)和physical counter的計(jì)數(shù)是一樣的。

(6)這一段代碼是對(duì)GIC V3進(jìn)行配置。ID_AA64PFR0_EL1,AArch64 Processor Feature Register 0,該寄存器描述了PE實(shí)現(xiàn)的feature。GIC bits [27:24]描述了該P(yáng)E是否實(shí)現(xiàn)了system register來訪問GIC,如果沒有(GIC bits 等于0)那么就略過GIC V3的設(shè)定。ICC_SRE_EL2,Interrupt Controller System Register Enable register (EL2),該寄存器用來(在EL2狀態(tài)時(shí)候)控制如何訪問GIC CPU interface模塊的,可以通過memory mapped方式,也可以通過system register的方式。將SRE bit設(shè)定為1確保通過system register方式進(jìn)行GIC interface cpu寄存器的訪問。將enable bit設(shè)定為1確保在EL1狀態(tài)的時(shí)候可以通過ICC_SRE_EL1寄存器對(duì)GIC進(jìn)行配置而不是陷入EL2。

下面我們進(jìn)入第二段代碼:

mrs??? x0, midr_el1 -----------------------------(1)

mrs??? x1, mpidr_el1

msr??? vpidr_el2, x0

msr??? vmpidr_el2, x1

mov??? x0, #0x0800??????????? // Set/clear RES{1,0} bits ---------------(2)

CPU_BE(??? movk??? x0, #0x33d0, lsl #16??? )??? // Set EE and E0E on BE systems

CPU_LE(??? movk??? x0, #0x30d0, lsl #16??? )??? // Clear EE and E0E on LE systems

msr??? sctlr_el1, x0

mov??? x0, #0x33ff-------Disable Coprocessor traps to EL2

msr??? cptr_el2, x0??????????? // Disable copro. traps to EL2

#ifdef CONFIG_COMPAT-----是否支持64 bit kernel上運(yùn)行32bit 的application

msr??? hstr_el2, xzr??????????? // Disable CP15 traps to EL2

#endif

mrs??? x0, pmcr_el0------------------------------(3)

ubfx??? x0, x0, #11, #5??????????? // to EL2 and allow access to

msr??? mdcr_el2, x0??????????? // all PMU counters from EL1

msr??? vttbr_el2, xzr ----清除Stage-2 translation table base address register

adrp??? x0, __hyp_stub_vectors

add??? x0, x0, #:lo12:__hyp_stub_vectors

msr??? vbar_el2, x0 ---------------設(shè)定EL2的異常向量表的基地址

mov??? x0, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\

PSR_MODE_EL1h)

msr??? spsr_el2, x0 ------------------------------(4)

msr??? elr_el2, lr

mov??? w20, #BOOT_CPU_MODE_EL2??????? // This CPU booted in EL2

eret-------------------------------------(5)

ENDPROC(el2_setup)

(1)midr_el1和mpidr_el1都屬于標(biāo)識(shí)該P(yáng)E信息的read only寄存器。MIDR_EL1,Main ID Register主要給出了該P(yáng)E的architecture信息,Implementer是誰等等信息。MPIDR_EL1,Multiprocessor Affinity Register,該寄存器保存了processor ID。vpidr_el2和vmpidr_el2是上面的兩個(gè)寄存器是對(duì)應(yīng)的,只不過是for virtual processor的。

(2)這段代碼實(shí)際上是將0x33d00800(BE)或者0x30d00800(LE)寫入sctlr_el1寄存器。BE和LE的設(shè)定和上面第一段代碼中的描述是類似的,其他bit的設(shè)定請(qǐng)參考ARMv8 ARM文檔

(3)PMCR_EL0,Performance Monitors Control Register,該寄存器的[15:11]標(biāo)識(shí)了支持的Performance Monitors counter的數(shù)目,并將其設(shè)定到MDCR_EL2(Monitor Debug Configuration Register (EL2))中。MDCR_EL2中其他的bit都設(shè)定為0,其結(jié)果就是允許EL0和EL1進(jìn)行debug的操作(而不是trap to EL2),允許EL1訪問Performance Monitors counter(而不是trap to EL2)。

(4)當(dāng)系統(tǒng)發(fā)生了異常并進(jìn)入EL2,SPSR_EL2,Saved Program Status Register (EL2)會(huì)保存處理器狀態(tài),ELR_EL2,Exception Link Register (EL2)會(huì)保存返回發(fā)生exception的現(xiàn)場(chǎng)的返回地址。這里是設(shè)定SPSR_EL2和ELR_EL2的初始值。w20寄存器保存了cpu啟動(dòng)時(shí)候的Eexception level ,因此w20被設(shè)定為BOOT_CPU_MODE_EL2。

(5)eret指令是用來返回發(fā)生exception的現(xiàn)場(chǎng)。實(shí)際上,這個(gè)指令僅僅是模擬了一次異常返回而已,SPSR_EL2和ELR_EL2都已經(jīng)設(shè)定OK,執(zhí)行該指令會(huì)使得CPU返回EL1狀態(tài),并且將SPSR_EL2的值賦給PSTATE,ELR_ELR就是返回地址(實(shí)際上也恰好是函數(shù)的返回地址)。

完成了el2_setup這個(gè)函數(shù)分析之后,我們?cè)倩仡^思考這樣的問題:為何是el2_setup?為了沒有el3_setup?當(dāng)一個(gè)SOC的實(shí)現(xiàn)在包括了EL3的支持,那么CPU CORE缺省應(yīng)該進(jìn)入EL3狀態(tài),為何這里只是判斷EL2還是EL1,從而執(zhí)行不同的流程,如果是EL3狀態(tài),代碼不就有問題了嗎?實(shí)際上,即便是由于SOC支持TrustZone而導(dǎo)致cpu core上電后進(jìn)入EL3,這時(shí)候,接管cpu控制的一定不是linux kernel(至少目前來看linux kernel不會(huì)做Secure monitor),而是Secure Platform Firmware(也就是傳說中的secure monitor),它會(huì)進(jìn)行硬件平臺(tái)的初始化,loading trusted OS等等,等到完成了secure world的構(gòu)建之后,把控制權(quán)轉(zhuǎn)交給non-secure world,這時(shí)候,CPU core多半處于EL2(如果支持虛擬化)或者EL1(不支持虛擬化)。因此,對(duì)于linux kernel而言,它感知不到secure world(linux kernel一般也不會(huì)做Trusted OS),僅僅是在non-secure world中呼風(fēng)喚雨,可以是Hypervisor或者rich OS。

3、set_cpu_boot_mode_flag

在進(jìn)入這個(gè)函數(shù)的時(shí)候,有一個(gè)前提條件:w20寄存器保存了cpu啟動(dòng)時(shí)候的Eexception level ,具體代碼如下:

ENTRY(set_cpu_boot_mode_flag)

adr_l??? x1, __boot_cpu_mode

cmp??? w20, #BOOT_CPU_MODE_EL2

b.ne??? 1f

add??? x1, x1, #4

1:??? str??? w20, [x1]??????????? // This CPU has booted in EL1

dmb??? sy

dc??? ivac, x1??????????? // Invalidate potentially stale cache line

ret

ENDPROC(set_cpu_boot_mode_flag)

由于系統(tǒng)啟動(dòng)之后仍然需要了解cpu啟動(dòng)時(shí)候的Eexception level(例如判斷是否啟用hyp mode),因此,有一個(gè)全局變量__boot_cpu_mode用來保存啟動(dòng)時(shí)候的CPU mode。代碼很簡(jiǎn)單,大家自行體會(huì)就OK了,我這里補(bǔ)充幾點(diǎn)描述:

(1)本質(zhì)上我們希望系統(tǒng)中所有的cpu在初始化的時(shí)候處于同樣的mode,要么都是EL2,要么都是EL1,有些EL2,有些EL1是不被允許的(也許只有那些精神分裂的bootloader才會(huì)這么搞)。

(2)所有的cpu core在啟動(dòng)的時(shí)候都處于EL2 mode表示系統(tǒng)支持虛擬化,只有在這種情況下,kvm模塊可以順利啟動(dòng)。

(3)set_cpu_boot_mode_flag和el2_setup這兩個(gè)函數(shù)會(huì)在各個(gè)cpu上執(zhí)行。

(4)變量__boot_cpu_mode定義如下:

ENTRY(__boot_cpu_mode)

.long?? ?BOOT_CPU_MODE_EL2--------A

.long?? ?BOOT_CPU_MODE_EL1--------B

如果cpu啟動(dòng)的時(shí)候是EL1 mode,會(huì)修改變量__boot_cpu_mode A域,將其修改為BOOT_CPU_MODE_EL1。如果cpu啟動(dòng)的時(shí)候是EL2 mode,會(huì)修改變量__boot_cpu_mode B域,將其修改為BOOT_CPU_MODE_EL2。

4、__vet_fdt

在進(jìn)入具體函數(shù)之前,x21和x24都被設(shè)定成了指定的值。x21被設(shè)定為fdt在RAM中的物理地址(參考preserve_boot_args函數(shù)),x24被設(shè)定為__PHYS_OFFSET,定義為:

#define __PHYS_OFFSET??? (KERNEL_START - TEXT_OFFSET)

#define KERNEL_START??? _text

KERNEL_START是kernel開始運(yùn)行的虛擬地址,更確切的說是內(nèi)核正文段開始的虛擬地址。 在鏈接腳本文件中(參考arch/arm64/kernel下的vmlinux.lds.S),KERNEL_START被設(shè)定為:

. = PAGE_OFFSET + TEXT_OFFSET;

.head.text : {

_text = .;

HEAD_TEXT

}

因此,KERNEL_START的值和PAGE_OFFSET以及TEXT_OFFSET這兩個(gè)offset的設(shè)定有關(guān)。TEXT_OFFSET標(biāo)識(shí)了內(nèi)核正文段的offset,其實(shí)如果該宏被定義為KERNEL_TEXT_OFFSET會(huì)更好理解。我們知道,操作系統(tǒng)運(yùn)行在內(nèi)核空間,應(yīng)用程序運(yùn)行在用戶空間,假設(shè)內(nèi)核空間的首地址是x(一般也是RAM的首地址),那么是否讓kernel運(yùn)行在x地址呢?對(duì)于arm,在內(nèi)核空間的開始有32kB(0x00008000)的空間用于保存內(nèi)核的頁表(也就是進(jìn)程0的PGD)以及bootload和kernel之間參數(shù)的傳遞,對(duì)于ARM64,在其Makefile中定義了這個(gè)offset是512KB(0x00080000)。

ifeq ($(CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET), y)

TEXT_OFFSET := $(shell awk 'BEGIN {srand(); printf "0x%03x000\n", int(512 * rand())}')

else

TEXT_OFFSET := 0x00080000

endif

kernel image的開始部分包括了一個(gè)ARM64 image header的內(nèi)容,這個(gè)header定義了bootloader如何來copy kernel image。ARM64 image header中有一個(gè)域(text_offset)就是告知bootloader,它應(yīng)該按照多大的偏移來copy kernel image。當(dāng)然了,也許有些bootloader不鳥這些,對(duì)于ARM64平臺(tái),反正大家一直都是固定為0x80000,因此,bootloader也沒有什么太大的動(dòng)力來修改支持這個(gè)特性。怎么破?雖然目前ARM64的kernel的TEXT_OFFSET就是固定為0x80000,但是也許將來內(nèi)核會(huì)修改這個(gè)offset啊。在這種情況下,內(nèi)核的開發(fā)者提供了一個(gè)CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET選項(xiàng),在編譯內(nèi)核的時(shí)候可以randomize內(nèi)核的TEXT_OFFSET值,以此來測(cè)試bootloader是否能夠正確的copy kernel image到正確的內(nèi)存偏移位置上去。通過這樣一個(gè)配置項(xiàng),可以盡快的暴露問題,確保了整個(gè)系統(tǒng)(bootloader + kernel)穩(wěn)定的運(yùn)行。

搞定了TEXT_OFFSET,我們?cè)賮砜纯碢AGE_OFFSET,在arch/arm64/include/asm/memory.h中,PAGE_OFFSET被定義為:

#define VA_BITS??????????? (CONFIG_ARM64_VA_BITS)

#define PAGE_OFFSET??????? (UL(0xffffffffffffffff) << (VA_BITS - 1))

VA_BITS定義了虛擬地址空間的bit數(shù)(該值也就是定義了用戶態(tài)程序或者內(nèi)核能夠訪問的虛擬地址空間的size),假設(shè)VA_BITS被設(shè)定為39個(gè)bit,那么PAGE_OFFSET就是0xffffffc0-00000000。PAGE_OFFSET的名字也不好(個(gè)人觀點(diǎn),可能有誤),OFFSET表明的是一個(gè)偏移,內(nèi)核空間被劃分成一個(gè)個(gè)的page,PAGE_OFFSET看起來應(yīng)該是定義以page為單位的偏移。但是,以什么為基準(zhǔn)的偏移呢?PAGE_OFFSET的名字中沒有給出,當(dāng)然實(shí)際上,這個(gè)符號(hào)是定義以整個(gè)address space的起始地址(也就是0)為基準(zhǔn)。另外,雖然這個(gè)地址是要求page對(duì)齊,但是實(shí)際上,這個(gè)符號(hào)仍然定義的是虛擬地址的offset(而不是page的offset)。根據(jù)上面的理由,我覺得定義成KERNEL_IMG_OFFSET會(huì)更好理解一些。一句話總結(jié):PAGE_OFFSET定義了將kernel image安放在虛擬地址空間的哪個(gè)位置上。

OK,經(jīng)過漫長(zhǎng)的說明之后,__PHYS_OFFSET實(shí)際上就是kernel image的首地址(并不是__PHYS_OFFSET的位置開始就是真實(shí)的kernel image,實(shí)際上從__PHYS_OFFSET開始,首先是TEXT_OFFSET的保留區(qū)域,然后才是真正的kernel image)。實(shí)際上,__PHYS_OFFSET定義的是一個(gè)虛擬地址而不是物理地址,這里的PHYS嚴(yán)重影響了該符號(hào)的含義,實(shí)際上adrp這條指令可以將一個(gè)虛擬地址轉(zhuǎn)換成物理地址(在沒有打開MMU的時(shí)候)。而函數(shù)__vet_fdt主要是對(duì)這個(gè)bootloader傳遞給kernel的fdt參數(shù)進(jìn)行驗(yàn)證,看是否OK,主要驗(yàn)證的內(nèi)容包括:

(1)是否是8字節(jié)對(duì)齊的

(2)是否在kernel space的前512M內(nèi)

__vet_fdt:

tst??? x21, #0x7----是否是8字節(jié)對(duì)齊的

b.ne??? 1f

cmp??? x21, x24-----是否在小于kernel space的首地址

b.lt??? 1f

mov??? x0, #(1 << 29)

add??? x0, x0, x24

cmp??? x21, x0

b.ge??? 1f-------是否大于kernel space的首地址+512M

ret

1:

mov??? x21, #0----------傳遞的fdt地址有誤,清零

ret

ENDPROC(__vet_fdt)

四、參考文獻(xiàn)

1、Documentation/arm64/booting.txt

2、ARM Architecture Reference Manual

change log:

1、2015-11-30,增加對(duì)el2_setup的思考。

2、2015-12-1,(1)修正對(duì)PAGE_OFFSET的描述。(2)增加adrp和adr_l的描述(3)增加對(duì)__PHYS_OFFSET符號(hào)名字的置疑

3、2016-6-28,(1)增加對(duì)MMU、data cache的依賴關(guān)系描述。(2)增加對(duì)preserve_boot_args中dmb sy指令的描述。

4、2016-7-7,(1)增加對(duì)set_cpu_boot_mode_flag的描述。

5、2016-7-8,(1)修正對(duì)CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET的描述

原創(chuàng)文章,轉(zhuǎn)發(fā)請(qǐng)注明出處。蝸窩科技

評(píng)論:

linuxxx

2020-05-19 09:16

wowo,你好:

根據(jù)我個(gè)人的理解,kernel代碼段的起始地址是

VA_START + KASAN_SHADOW_SIZE+MODULES_SIZE+TEXT_OFFSET =

(0xffffffffffffffff - 1 << 39 + 1) + 0 + 0x8000000 + 0x80000 = 0xffffff8008080000

根據(jù)我通過aarch64-linux-readelf命令讀取Image頭的信息里 Entry point address,這兩個(gè)值也是一致的。

是不是PAGE_OFFSET有其他理解方式呢?

2020-05-20 10:43

@linuxxx:代碼在變化更新,所以文章只能參考。

2019-02-19 19:17

感謝作者寫了這么好的文檔, 我在們的產(chǎn)品上用的arm64架構(gòu),??我發(fā)現(xiàn)CONFIG_RANDOMIZE_BASE配置了(CONFIG_RANDOMIZE_BASE=y),CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET沒有配置(is not set), 我編譯個(gè)若干次內(nèi)核進(jìn)行測(cè)試, 發(fā)現(xiàn)kernel image會(huì)被load到固定的位置(0xffff000010080000~0xffff000010c95000), 其中vmalloc區(qū)域的地址是0xffff000010000000~0xffff7bffbfff0000。

這樣看來即使配置了CONFIG_RANDOMIZE_BASE,也沒有實(shí)現(xiàn)kernel image會(huì)被隨機(jī)copy到不同的位置。 反倒時(shí)我覺得配置了CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET才能實(shí)現(xiàn)kernel image被隨機(jī)copy到不同的位置。 因CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET會(huì)決定TEXT_OFFSET的值。

感謝能解答一下

matchchen

2017-07-17 00:45

@linuxer

你好,對(duì)于ARM64下uboot啟動(dòng)kernel傳參我有點(diǎn)疑惑未理清:

從kernel_entry入口來看,uboot jump 到linux傳遞的唯一信息就只有dtb的地址即X0,不再傳遞cmdline/ramdisk地址等atags了。

那么ramdisk數(shù)據(jù)地址是如何傳遞;如果我要在uboot和linux之間傳遞一些數(shù)據(jù)文件該如何實(shí)現(xiàn)為妥?

2017-07-17 10:05

@matchchen:既然能夠把dtb傳遞給kernel,還有什么不能傳呢?

都加到dtb里面就行了啊。

至于ramdisk,做法也類似,不過可能會(huì)有一些小技巧,例如緊隨dtb的結(jié)尾啦(可參考fdt_initrd函數(shù)的實(shí)現(xiàn))。

matchchen

2017-07-23 18:58

@wowo:并沒看到這樣的實(shí)例,是否像image tree中的內(nèi)核、ramdisk、dtb一樣的語法指定數(shù)據(jù)文件的路徑,把文件打包到dtb中?

2017-07-24 09:09

@matchchen:舉個(gè)簡(jiǎn)單的例子:dtb里面有命令行參數(shù),你可以增加一個(gè)參數(shù),xxx=XXXX。這樣的話,什么都可以傳遞啊!

see

2019-09-20 14:55

@wowo:images->ep和readelf vmlinux的的Entry point address是同一地址碼?

raceant

2017-06-22 13:20

@linuxer

#define __PHYS_OFFSET????(KERNEL_START - TEXT_OFFSET)

難道在arm64中所有的物理地址都是從0開始的? 我記得arm中好像mach-xxx/中有個(gè)文件配置物理地址的,

但在arm64中卻沒有找到這個(gè)物理地址怎樣配置

2017-06-23 09:27

@raceant:需要定義內(nèi)存物理地址的起始位置嗎?一般情況下,kernel image被copy到(內(nèi)存首地址+TEXT_OFFSET)這樣的一個(gè)位置上去,因此,在沒有打開MMU的時(shí)候,代碼中實(shí)際上是有技巧可以獲取自己執(zhí)行在哪一個(gè)地址上的。

adrp????x24, __PHYS_OFFSET

x24中即保存了內(nèi)存的物理地址。

編譯器在編譯這一條指令的時(shí)候,把該指令所在的虛擬地址和__PHYS_OFFSET的offset保存在了指令的imm域。當(dāng)實(shí)際運(yùn)行的時(shí)候,x24被賦值為當(dāng)前PC值+offset,也就是內(nèi)存的物理地址了。BTW,上面說的實(shí)際上是需要對(duì)齊到page size的。

raceant

2017-06-23 13:43

@linuxer:@linuxer: 謝謝你的解答,我現(xiàn)在明白了,所以kernel的地址(image地址 - TEXT_OFFSET)一定是放在物理地址的首地址處,才能將正確的物理地址位置放到x24中

zhusbj

2017-03-24 16:01

針對(duì) MMU OFF / Cache ON有一些不同的見解。摘自ARMv8-A TRM

---------------------------------------------------------

Behavior when stage 1 address translation is disabled

When a stage 1 address translation is disabled, memory accesses that would otherwise be translated by that stage of

translation are treated as follows:

Non-secure EL1 and EL0 accesses if the HCR_EL2.DC bit is set to 1

For the Non-secure EL1&0 translation regime, when the value of HCR_EL2.DC is 1, the stage 1

translation assigns the Normal Non-shareable, Inner Write-Back Read-Write-Allocate, Outer

Write-Back Read-Write-Allocate memory attributes.

Note

This applies for both instruction and data accesses.

All other accesses

For all other accesses, when stage 1 address translation is disabled, the assigned attributes depend

on whether the access is a data access or an instruction access, as follows:

Data access

The stage 1 translation assigns the Device-nGnRnE memory type.

Instruction access

The stage 1 translation assigns the Normal memory attribute, with the cacheability and

shareability attributes determined by the value of the SCTLR.I bit for the translation

regime, as follows:

When the value of I is 0

The stage 1 translation assigns the Non-cacheable and Outer Shareable

attributes.

When the value of I is 1

The stage 1 translation assigns the Cacheable, Inner Write-Through no

Write-Allocate Read-Allocate, Outer Write-Through no Write-Allocate

Read Allocate Outer Shareable attribute.

---------------------------------------------------------

DC, bit [12]

Default Cacheable. When this bit is set to 1, this causes:

? The SCTLR_EL1.M bit to behave as 0 when in the Non-secure state for all purposes other

than reading the value of the bit.

? The HCR_EL2.VM bit to behave as 1 when in the Non-secure state for all purposes other

than reading the value of the bit.

The memory type produced by the first stage of translation used by EL1 and EL0 is Normal

Non-Shareable, Inner WriteBack Read-WriteAllocate, Outer WriteBack Read-WriteAllocate.

When this bit is 0 and the stage 1 MMU is disabled, the default memory attribute for Data accesses

is Device-nGnRnE.

This bit is permitted to be cached in a TLB.

---------------------------------------------------------

樓主的解釋需要一個(gè)前提條件,就是HCR_EL2.DC 必須已經(jīng)置1。但是這個(gè)bit默認(rèn)值很可能是0,并且代碼中也沒有置1的操作,所以memory的屬性應(yīng)該是Device-nGnRnE for data access。對(duì)于 instruction access,取決于SCTLR.I bit。

zhusbj

2017-03-24 15:16

從英文表述來看,因?yàn)閐evice屬性的memory store指令和cache 指令沒有數(shù)據(jù)依賴關(guān)系,所以可以亂序執(zhí)行。

但是源代碼中明顯是考慮到了 cache on的情況,否則也不必要在最后調(diào)用一下 cache invalidate操作。

所以我覺得在能保證 non-cacheable 的情況下,可以不必插入dmb指令。

newjourney

2017-03-15 09:52

請(qǐng)問??在Non-cacheable的情況下,必須要使用DMB來保證stp指令在dc ivac指令之前執(zhí)行完成?? 是為何呢?

2017-03-16 16:10

@newjourney:文章中的那段英文說的就是數(shù)據(jù)訪問指令和data cache操作指令的順序,處理器設(shè)計(jì)就是這樣的,具體為何這樣設(shè)計(jì),這個(gè)問題太深?yuàn)W了,超出我的能力范圍了。

2018-11-08 10:08

@linuxer:@linuxer

那段英文應(yīng)該說的是要么用devcie memory attribute,如果使用normal nocache,那么必須加上DMB或者DSB吧

deven

2019-01-11 17:53

@linuxer:關(guān)鍵是為什么要保證這種順序?即使先無效了d-cache后寫變量的值感覺也沒啥問題,實(shí)驗(yàn)了下確實(shí)沒發(fā)生問題

deven

2019-01-11 20:12

@linuxer:關(guān)鍵為什么stp指令要先完成?當(dāng)前cache沒有enable~

eric

2017-01-24 14:53

個(gè)人覺得樓主對(duì) adrp????x24, __PHYS_OFFSET 這里的寫法可能有點(diǎn)歧義,參考ARM手冊(cè),adrp的格式是adrp ,其中l(wèi)abel的定義是Is the program label whose 4KB page address is to be calculated. Its offset from the page address of this instruction, in the range +/-4GB, is encoded as "immhi:immlo" times 4096.所以這里宏展開后是adrp x24, _text-TEXT_OFFSET,_text這個(gè)label表示的是當(dāng)前指令地址所在的“page address”與text段開始位置的偏移,稱作虛擬地址有點(diǎn)不太合適,這里其實(shí)并不需要再繼續(xù)宏展開到KIMAGE_VADDR去得到一個(gè)0xffffffxxxx的虛擬地址,只是一個(gè)相對(duì)位置而已。

2017-01-25 09:13

@eric:我覺得,這段英文只是在解釋“l(fā)abel在adrp中的含義以及操作方式”。對(duì)label本身而言,肯定不會(huì)只是一個(gè)偏移(你可以去System.map中看看_text的值)。

haibin

2019-01-24 16:12

@wowo:1. __PHYS_OFFSET是內(nèi)核加載的偏移地址,因?yàn)閎ootloader沒有傳遞這個(gè)值,實(shí)際也不需要,通過這個(gè)方式可以計(jì)算出來

2. adrp在這個(gè)環(huán)境下得到的是物理地址,因?yàn)榇藭r(shí)MMU沒有開啟,不是你說的system.map里面的地址

3. arm32中有一條ldr的偽指令,ldr reg,=label,這條指令才是獲取system.map中的地址,arm64中好像沒有類似的

2016-12-13 10:41

從kernel 代碼看

這一切地址范圍的起始都是由ARM64_4K_PAGES 引起的。

choice

prompt "Page size"

default ARM64_4K_PAGES

config ARM64_VA_BITS

int

default 39 if ARM64_VA_BITS_39

config PGTABLE_LEVELS

int

default 3 if ARM64_4K_PAGES && ARM64_VA_BITS_39

#define VA_BITS????????????(CONFIG_ARM64_VA_BITS)

#define VA_START????????(UL(0xffffffffffffffff) << VA_BITS)??//0xffffff8000000000

#define PAGE_OFFSET????????(UL(0xffffffffffffffff) << (VA_BITS - 1)) //0xffffffc000000000

#define PAGE_OFFSET????????(UL(0xffffffffffffffff) << (VA_BITS - 1))

但是為啥用ARM64_4K_PAGES 做引子想不通為啥,也不知道聯(lián)系。

2016-12-14 09:07

@lover713814:4K的page是經(jīng)典的設(shè)置,缺省情況下當(dāng)然選用4K頁了

dashan

2016-10-28 23:25

謝謝樓主分享這么好的文章。我想問一個(gè)問題,在armv8 Linux Kernel啟動(dòng)過程中能不能一直關(guān)閉data cache?如果可以的花能否告知怎么做?謝謝

2016-10-31 09:51

@dashan:你可以參考ARM ARM文檔中關(guān)于SCTLR_EL1寄存器的描述。

dashan

2016-10-31 12:35

@linuxer:謝謝,我直接把bit2清掉了在匯編中:

crval:

.word????0xfcffffff????????????// clear

.word????0x34d5d919????????????// set

我目前準(zhǔn)備把soc 上cpu的頻率調(diào)高,比如由1GHz跑到1.2G(芯片是支持這個(gè)頻率的),uboot能跑起來,但內(nèi)核總是跑一會(huì)就停了,這個(gè)時(shí)候jtag也連不上,從打印上看停的位置不固定, 基本上從start_kernel開始跑個(gè)8秒左右就會(huì)停。

請(qǐng)問你能否提供點(diǎn)建議?謝謝

1 2

發(fā)表評(píng)論:

昵稱

郵件地址 (選填)

個(gè)人主頁 (選填)

總結(jié)

以上是生活随笔為你收集整理的arm linux内核启动过程,ARM64的启动过程之(一):内核第一个脚印的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

欧美日韩超碰 | 美女网站在线观看 | 日韩午夜小视频 | 在线观看自拍 | 国产一级片免费视频 | 热久久这里只有精品 | 日韩专区在线播放 | www.五月天婷婷 | 91精品啪 | 伊人丁香 | 亚洲成人一二三 | 国产精品日韩在线 | 久久香蕉一区 | 亚洲美女免费视频 | 久久一区91 | 中文字幕av最新 | 国产精品久久久久久久久久久久久 | 一区二区三区免费在线观看 | 免费的黄色av| 一本一本久久a久久精品牛牛影视 | 国产精品久久久久av福利动漫 | 狠狠的日| 又粗又长又大又爽又黄少妇毛片 | 久草综合在线观看 | 日韩色高清 | 国产精品福利午夜在线观看 | 狠狠狠狠狠狠狠干 | 美女黄频在线观看 | 免费在线观看av不卡 | 日韩va欧美va亚洲va久久 | 久久精品精品电影网 | 国产精品成人a免费观看 | 亚洲午夜av | 久草久草在线观看 | 午夜国产在线 | 久久露脸国产精品 | 亚洲精品永久免费视频 | 一区二区观看 | 9在线观看免费高清完整版 玖玖爱免费视频 | 激情综合五月 | av中文字幕在线电影 | 一级免费观看 | 五月激情久久 | 久久精品2 | 国产又粗又硬又长又爽的视频 | 久久精品99精品国产香蕉 | 欧美成人a在线 | 高清视频一区 | 午夜av免费看 | 色综合久久88色综合天天6 | 国产福利91精品张津瑜 | 久久综合激情 | 国产成人精品久久久久 | 国产精品视频免费看 | 久久怡红院| 日本电影久久 | 免费看黄色毛片 | 欧美日韩在线视频免费 | 国产精品原创在线 | 日韩av片免费在线观看 | 亚洲精品国偷拍自产在线观看蜜桃 | 日韩精品中文字幕在线 | 综合久久久久久久 | 91av看片| 99精品欧美一区二区 | 欧美坐爱视频 | 92国产精品久久久久首页 | 国产丝袜网站 | 午夜成人免费电影 | 99久久超碰中文字幕伊人 | 国产精品 日本 | 日韩欧美精品在线观看 | 99久久久久久国产精品 | www.黄色在线 | 97色免费视频 | 99 色| 中文字幕乱码一区二区 | 亚洲精品在线观看av | 色的网站在线观看 | 精品国产aⅴ麻豆 | 狠狠色丁香久久婷婷综合丁香 | 中文字幕欧美激情 | 欧美日韩视频 | 久久久三级视频 | 日韩欧美国产激情在线播放 | 日韩成人高清在线 | 久久av福利| 在线观看免费版高清版 | 青草视频在线看 | 狠狠的操狠狠的干 | 欧美九九九 | 国产青春久久久国产毛片 | 欧美日产一区 | 国产伦理一区 | 久草网在线 | 天天爽天天做 | 免费在线观看黄色网 | 免费a网| 精品国产精品一区二区夜夜嗨 | 国产无吗一区二区三区在线欢 | 精品成人免费 | 日日夜夜精品免费视频 | bbbbb女女女女女bbbbb国产 | 麻豆视频在线 | 欧美亚洲国产精品久久高清浪潮 | 99久久婷婷国产综合亚洲 | 精品久久久久久久久久久久 | 国产免费观看高清完整版 | 丁香六月在线观看 | 日韩欧美在线播放 | 天天摸天天操天天舔 | 日韩电影中文字幕在线观看 | 亚洲小视频在线 | 成人小视频在线观看免费 | 亚洲乱码久久 | 日日夜夜人人精品 | 一 级 黄 色 片免费看的 | 亚洲第一成网站 | 蜜臀久久99精品久久久无需会员 | 日韩精品久久久久久中文字幕8 | 天天综合成人网 | 伊人色**天天综合婷婷 | 福利二区视频 | 国产高清福利在线 | 久久精品国产免费看久久精品 | 精品一区二区在线观看 | 成人h动漫在线看 | 超碰av在线播放 | 四虎在线免费观看 | 一区二区三区免费在线观看 | 777视频在线观看 | 草久久久 | 99精品国产成人一区二区 | 成人免费电影 | 午夜av在线电影 | 青青河边草免费观看 | 日本中文字幕视频 | 国内小视频 | 伊人黄色网 | 久久久免费播放 | 中文字幕在线观看免费高清完整版 | www黄| 天天干天天搞天天射 | 天天爽天天爽天天爽 | 在线观看日韩精品视频 | 午夜电影中文字幕 | 中文字幕黄网 | 黄色成年片 | 免费视频资源 | 久99久久 | 成人亚洲综合 | 久久久国产99久久国产一 | 最近能播放的中文字幕 | 丁香婷婷色综合亚洲电影 | 三级av网站| 中文字幕人成一区 | 在线成人免费 | 久久观看最新视频 | 国产无套精品久久久久久 | 欧美精品少妇xxxxx喷水 | 天天添夜夜操 | 在线观看电影av | 久久九九免费视频 | 国产亚洲精品久久久久久无几年桃 | 在线视频欧美精品 | 毛片美女网站 | 99精品国产在热久久下载 | 在线成人免费电影 | 亚洲欧洲成人 | 99亚洲精品| 久草免费在线观看视频 | 特级西西www44高清大胆图片 | 97超碰在线人人 | 国产麻豆成人传媒免费观看 | 国产91综合一区在线观看 | 操操操人人 | 免费看麻豆| 日韩av手机在线观看 | 欧美精品久久久久久久免费 | 国产一区二区三区免费视频 | 国产一线在线 | 日韩精品久久中文字幕 | 一区二区三区中文字幕在线观看 | 91最新在线 | 亚洲欧美在线综合 | 新版资源中文在线观看 | 五月开心网 | 又紧又大又爽精品一区二区 | 狠狠色狠狠色综合日日小说 | 国产中文在线视频 | 91精品视频观看 | 久99视频 | 国产不卡在线视频 | 国产一卡二卡在线 | 91插插插网站 | 开心激情久久 | 欧美久久99 | 激情综合色播五月 | 婷婷激情5月天 | 久久久久国| 99欧美视频| 久久久久久久久久久免费av | 97在线观看视频免费 | 亚洲精品播放 | 日韩欧美网址 | 久久精品96 | 国产自产在线视频 | 九九热免费视频在线观看 | 96国产精品视频 | 青青久草在线视频 | 麻豆观看| 日韩午夜小视频 | 成年人网站免费在线观看 | 国产一级二级在线播放 | 一区二区三区日韩在线观看 | 久久伊人91 | 2019免费中文字幕 | 日韩在线免费高清视频 | 精品一区二区免费在线观看 | 久久视频在线 | 九九免费观看全部免费视频 | 午夜美女wwww | 美女视频黄频大全免费 | 婷婷六月天在线 | av在线播放亚洲 | 久久婷五月 | 二区中文字幕 | 日日夜夜狠狠 | 午夜精品福利在线 | 久久精品女人毛片国产 | aav在线 | 久久永久视频 | 日韩二级毛片 | 91久久国产露脸精品国产闺蜜 | 日韩av资源在线观看 | 欧美日本在线视频 | 日韩在线观看影院 | 97成人超碰 | 99久久精 | 国产涩图 | 国产精品成人av久久 | 久久xx视频 | 国产精品免费在线观看视频 | 亚洲最大av网站 | 超碰97公开 | 久操操 | 中文字幕有码在线播放 | 日韩在线第一 | 欧美在线视频一区二区三区 | 精品国内 | 少妇bbbb揉bbbb日本 | 九九九国产 | 久久久国产精华液 | 色视频在线 | 国内成人综合 | 欧美午夜精品久久久久 | 蜜桃av人人夜夜澡人人爽 | 久久中文字幕导航 | 欧美俄罗斯性视频 | 亚洲人成免费网站 | 亚洲精品在线资源 | 在线视频 区 | 伊人网站 | 中文字幕在线视频一区二区三区 | 91禁看片| 99精品在线视频观看 | 亚洲精品视频在线观看免费视频 | a级国产片 | 免费色网 | 欧美91精品久久久久国产性生爱 | 精品久久五月天 | www五月天com| 五月婷色| 国产女人18毛片水真多18精品 | 成人午夜影视 | 波多野结衣视频一区 | 香蕉影视app | 国产精品麻 | 91色视频| 色综合久久天天 | 毛片的网址 | 免费99| 亚洲三级黄 | 国产精品久久久久国产a级 激情综合中文娱乐网 | 免费影视大全推荐 | 久久国产成人午夜av影院潦草 | 色欧美88888久久久久久影院 | 久草精品视频 | 成人av高清 | 久久精品一区二区三 | 国产精品99在线观看 | 亚洲精品久久久蜜桃直播 | 高清精品视频 | 国产精品一区二区你懂的 | 美女网站在线观看 | 色999在线 | 亚洲欧洲xxxx | 色国产精品一区在线观看 | 日批视频在线播放 | 亚洲亚洲精品在线观看 | 在线v片免费观看视频 | 在线免费观看黄 | 91成人免费看 | 国产精品美女免费视频 | 精品国产久| 久久久国产精品一区二区中文 | 国产一区二区在线免费播放 | 久久综合久久88 | 欧美资源在线观看 | 久久免费高清 | 日韩欧美高清一区二区三区 | 久久国产精品第一页 | av黄色大片 | 探花视频在线观看 | 涩五月婷婷 | 在线免费观看黄色大片 | 欧美一级片免费在线观看 | 久草综合视频 | 91成人在线视频观看 | 久久人人爽人人爽人人片 | 国产一级一片免费播放放a 一区二区三区国产欧美 | 亚洲精品国产精品国 | 免费视频二区 | 婷婷丁香社区 | 黄色一区二区在线观看 | 国产黄色观看 | 成人欧美一区二区三区在线观看 | 午夜黄色一级片 | bbw av| 一区二区中文字幕在线观看 | 色妞色视频一区二区三区四区 | 国产高清在线免费观看 | 99在线国产 | 四虎影视国产精品免费久久 | 久久夜色网 | 亚洲毛片在线观看. | 久久国产热 | 免费三级黄色片 | 国产一区二区三区免费视频 | 久久久久国产成人精品亚洲午夜 | 国产在线色 | 特黄特色特刺激视频免费播放 | 一区 在线观看 | 九九99视频 | 成人国产精品久久久 | 日本不卡123区 | 国产精品久久久久久高潮 | 久久不卡av | 91麻豆精品国产91久久久久久久久 | 欧美福利在线播放 | 97精品视频在线播放 | 午夜精品99久久免费 | 久草免费资源 | 久99精品| 六月丁香激情网 | 国产精品99久久久久久久久 | 蜜桃麻豆www久久囤产精品 | 激情五月看片 | 中文字幕黄色 | 欧美一级黄大片 | 精品在线你懂的 | 91精品啪啪 | 久久电影中文字幕视频 | 99色亚洲 | 日韩有码专区 | 天天舔天天射天天操 | 久久精品高清 | 亚洲伊人第一页 | 亚洲精品免费在线观看 | 国产精久久久久久久 | 欧美一区二区三区不卡 | 人人草人 | 欧美一级激情 | 日韩中文字幕国产 | 国产精品久久二区 | 久久影院一区 | 天天射日 | 久久99久久99精品免观看软件 | 九月婷婷人人澡人人添人人爽 | 欧美伊人网 | 一级α片免费看 | 国产美女免费 | 91禁在线观看 | 中文字幕在线观看视频一区 | 亚洲午夜激情网 | 成人av久久 | 国产999| 99热最新| 狠狠色香婷婷久久亚洲精品 | 亚洲国产三级在线 | 亚洲精品视频在线观看免费 | 西西大胆免费视频 | 久久精品国产成人 | 在线视频电影 | 国产福利久久 | 日韩久久激情 | 狠狠色香婷婷久久亚洲精品 | 99国产精品 | 探花视频在线版播放免费观看 | 天天操操操操操 | 日韩电影一区二区在线观看 | 六月丁香综合网 | 亚洲欧洲成人精品av97 | 国产尤物在线视频 | 国产美女在线免费观看 | 日韩色视频在线观看 | 成人a级网站 | 欧美精品乱码久久久久久 | 黄色片免费在线 | 色婷婷视频在线 | 麻豆影视网 | 精品国产免费观看 | 亚洲视屏在线播放 | 久久精品视频在线观看免费 | 日韩伦理片一区二区三区 | 综合网在线视频 | av解说在线观看 | 97精品国产97久久久久久 | 国产精品一二三 | 成人午夜电影在线观看 | 国产精品黄色在线观看 | 免费观看十分钟 | 在线观看国产永久免费视频 | 国产不卡在线观看视频 | 久草视频在线资源 | 久久成年视频 | 日韩高清在线一区二区三区 | 欧美日韩亚洲在线观看 | 热久在线 | 99精品国产成人一区二区 | 欧美91精品国产自产 | 精品国产1区2区3区 国产欧美精品在线观看 | 毛片永久新网址首页 | 91视频亚洲 | 久久久久一区二区三区 | 国产视频精品免费 | 婷婷五月在线视频 | 婷婷福利影院 | 成人欧美在线 | 精品福利网站 | www.久久色| 91大片成人网 | 久草视频在 | 婷婷六月综合网 | 天天做夜夜做 | 一区二区三区高清在线 | 91麻豆国产 | 成人在线免费视频观看 | 日本三级国产 | 国产色婷婷在线 | 精品国产乱码久久久久久三级人 | 99精品国产高清在线观看 | 久久性生活片 | 久久精品亚洲 | 97视频在线看 | 中文字幕在线视频第一页 | 激情综合久久 | 国产精品免费一区二区三区 | 日韩精品中文字幕在线不卡尤物 | 天天操天天爱天天爽 | 丁香色婷婷 | 国内外激情视频 | 亚洲在线资源 | 久久精品xxx| 成人av一区二区在线观看 | 中文字幕一区二区三区四区在线视频 | 久久天堂影院 | 国产不卡免费 | 天天射天天操天天色 | 国产天天综合 | a√天堂资源 | 精品久久久久久久久久 | 欧美国产91| 成人蜜桃 | 91久久久久久久一区二区 | 亚洲视频精选 | 国产精品免费高清 | 免费看v片 | 超碰在线中文字幕 | 国产性xxxx| 麻豆高清免费国产一区 | 午夜精品久久久99热福利 | 日本特黄一级片 | 日批视频国产 | 人人干网站 | 九九免费精品视频在线观看 | 日韩大片在线 | 在线观看日韩一区 | 国产视频 亚洲视频 | 天天搞天天 | 日韩aa视频 | 久久久久 免费视频 | 五月婷在线播放 | 日韩免费一区二区 | 国产偷在线 | 亚洲视频aaa | 亚洲成人在线免费 | 99精品欧美一区二区蜜桃免费 | 99精品国产免费久久久久久下载 | 操操日| 久久久99久久 | 一区二区视频免费在线观看 | 日日操操 | 成人在线免费av | 色婷在线 | 精品国产乱码一区二区三区在线 | 中文字幕在线视频一区 | 国产精品孕妇 | 亚洲激情五月 | 国产婷婷视频在线 | 亚洲第一区精品 | 亚洲夜夜综合 | av在线播放中文字幕 | 国产一区二区视频在线播放 | 四虎在线免费观看 | 午夜在线观看 | 国产不卡在线观看视频 | 99精品免费视频 | 久久天堂精品视频 | 一区二区三区免费网站 | 国产精品美女久久久久久久久 | 亚洲精品久久久久久国 | 青青视频一区 | 91av播放| 久久五月天婷婷 | 黄色亚洲精品 | www.大网伊人 | 四虎免费在线观看视频 | 四虎成人精品永久免费av | 亚洲视频久久久久 | 91porny九色在线播放 | 亚洲va欧美va人人爽 | 91av在线免费看 | 麻豆传媒电影在线观看 | 久久99精品国产一区二区三区 | av资源免费看 | 久久综合九色综合欧美狠狠 | 久热久草在线 | 国内精品久久久久久中文字幕 | 日韩1级片 | 亚洲免费成人 | 久二影院 | 久久免费视频7 | 欧美日韩伦理一区 | 久免费 | 999成人| 日本特黄一级片 | a黄色影院 | 国产精久久久 | 日韩免费在线网站 | 在线观看中文 | 91精品国产乱码久久 | 911久久| 九色琪琪久久综合网天天 | 成人亚洲免费 | 国产精品xxxx18a99 | 麻豆视频91 | 精品国产乱码久久久久久1区2匹 | 九九综合久久 | 在线小视频你懂的 | 在线观看韩国av | 亚洲一级影院 | 国产精品久久麻豆 | 国产99在线 | 一区二区精品在线 | 欧美日本啪啪无遮挡网站 | 夜夜操网 | 国产在线观看一 | 国产一区二区在线免费播放 | 日韩一区二区三区免费视频 | 欧美日韩精品在线观看 | 久久这里只有精品久久 | 国产喷水在线 | 在线观看www视频 | 亚洲乱码中文字幕综合 | av网站在线观看免费 | 日日夜夜天天综合 | 久久国产精品成人免费浪潮 | 国产涩涩网站 | 国产资源免费在线观看 | 久久精品4 | 久久伊人国产精品 | 免费又黄又爽的视频 | 成人一级免费视频 | 欧美精彩视频在线观看 | 黄色视屏在线免费观看 | 国产亚洲欧美精品久久久久久 | 99tvdz@gmail.com | 色播五月激情综合网 | 国产伦理久久精品久久久久_ | 免费黄色av电影 | 日韩av免费在线看 | 高清免费av在线 | 狠狠色综合网站久久久久久久 | 91精品入口 | 国产精品一区二区久久 | av免费网站观看 | 91探花系列在线播放 | 欧美日韩免费在线观看视频 | 九九99靖品| av片中文字幕 | 亚洲精品视频免费看 | 涩涩在线 | 亚洲综合视频在线 | 欧美视频不卡 | 日韩欧美99 | www免费视频com━ | 国产精品 日韩 | 日韩国产欧美在线播放 | 波多野结衣在线观看一区二区三区 | 久久爽久久爽久久av东京爽 | 在线观看中文av | 中文字幕 国产视频 | 在线中文字幕av观看 | 久在线| 在线播放av网址 | 欧美精品一区二区蜜臀亚洲 | 在线观看网站你懂的 | 欧洲精品在线视频 | 日日日日日 | 婷婷丁香色综合狠狠色 | 一区在线观看视频 | 亚洲精品综合一区二区 | 激情五月婷婷丁香 | 精品一区精品二区高清 | 亚洲黄色片在线 | 91日韩国产| 久久精品久久久久 | 99久久久久 | 亚洲一区久久 | 欧美日韩伦理一区 | 激情动态| 国产精品手机在线观看 | 日韩视频欧美视频 | 欧美精品乱码久久久久久按摩 | 免费看v片网站 | 色网站在线免费观看 | 在线看片中文字幕 | 久久久久久美女 | 国产成人精品a | 国产在线播放一区二区三区 | 开心激情网五月天 | 久久久久免费网站 | 亚洲精品美女 | 日韩欧美电影 | 日韩av网站在线播放 | 日本久久综合视频 | 欧美色插| 国产精品一区二区免费 | 97超碰在线资源 | 日韩免费小视频 | 亚洲黄色在线观看 | 国产又粗又猛又黄又爽视频 | 91久久久久久久一区二区 | 精品久久久久亚洲 | 蜜臀av夜夜澡人人爽人人 | 啪啪凸凸 | 成人欧美在线 | av成人动漫在线观看 | 在线精品一区二区 | 国产又粗又猛又黄 | 米奇四色影视 | 色婷婷成人 | 色噜噜狠狠狠狠色综合久不 | 国产精品久久在线 | 99久久久久久久久 | 日韩精品一区二区在线观看 | 国产精品久久一区二区三区, | 91久久久久久国产精品 | 很黄很污的视频网站 | 免费观看国产视频 | 久久国产精品免费一区 | 欧美在线不卡一区 | 婷婷av电影 | 精品久久久成人 | 亚洲精品黄色 | 欧美一区二区三区在线看 | 亚洲美女在线一区 | 精品亚洲成人 | 夜夜爽夜夜操 | 91久久爱热色涩涩 | 91一区啪爱嗯打偷拍欧美 | 日韩三级一区 | 91精品国产乱码 | 欧美孕交vivoestv另类 | 亚洲.www | 91福利社区在线观看 | 麻豆视频大全 | 午夜精品福利一区二区 | 99 视频 高清 | 国产成人av福利 | 四虎影视成人永久免费观看亚洲欧美 | 国产97免费 | 天堂网一区二区三区 | 久久精品站 | 天天爱天天操天天干 | 丁香婷婷色月天 | 欧美精品国产综合久久 | 成人资源在线播放 | 在线看一区二区 | 精品视频在线免费 | 久草在线免费资源站 | 最新国产视频 | 日本性视频 | 日韩在线高清免费视频 | 国产69精品久久久久99 | 久久精品一区 | 丁香激情网| 欧美精品999 | 中文字幕资源在线观看 | 久99久精品视频免费观看 | 99久久日韩精品视频免费在线观看 | 亚洲精品日韩一区二区电影 | 一区二区三区中文字幕在线观看 | 在线观看va | 久久视频这里只有精品 | 亚洲美女在线国产 | 超碰大片| 91久久国产自产拍夜夜嗨 | 日本不卡123区 | 欧美日韩在线观看视频 | 国产福利精品在线观看 | 日p视频在线观看 | 麻豆视频在线免费看 | 中文字幕国产在线 | 91视频在线国产 | 伊人夜夜 | 欧美精彩视频在线观看 | 精品在线亚洲视频 | 亚洲黄色一级视频 | 国产精品一区二区果冻传媒 | 久草在线免费资源 | 日本最新高清不卡中文字幕 | 操操操日日日 | 91av手机在线观看 | 久久精品这里热有精品 | 成人在线免费看 | 亚洲视频免费在线看 | 中文字幕资源网 国产 | 国产精品成人免费一区久久羞羞 | 天天天天综合 | 精品毛片久久久久久 | 国产特级毛片 | 正在播放国产一区 | 99色| 色偷偷av男人天堂 | 99热.com| 99久久99久久精品国产片 | 手机看片国产 | 久久精品爱爱视频 | 97视频一区 | 国产日韩中文在线 | 欧美一区二区日韩一区二区 | 久久伊人操 | 日韩成人中文字幕 | 欧美成人在线免费 | 欧美成人亚洲 | 中文字幕传媒 | 久久精品这里都是精品 | 亚洲人成在线电影 | 日日夜夜狠狠操 | 国产精品高潮在线观看 | a成人v在线| 美女福利视频一区二区 | 精品视频不卡 | 中文字幕一区二区三区精华液 | 91高清视频免费 | 97国产在线 | 一区二区不卡 | 久久精品国产一区二区 | 国产日产精品一区二区三区四区的观看方式 | 国产精品不卡av | 亚洲乱码中文字幕综合 | 国产 日韩 欧美 中文 在线播放 | 91在线网址 | 久久这里只精品 | 丝袜美腿在线播放 | 丝袜足交在线 | 午夜久久电影网 | 日韩免费在线视频 | 欧美孕妇视频 | 99免费精品 | 最近更新中文字幕 | 国产视频一区二区在线观看 | 久久精品—区二区三区 | 97福利视频 | 久久免费观看少妇a级毛片 久久久久成人免费 | 欧美aaaxxxx做受视频 | 欧美性色综合网站 | 久久久久久久av | 97超碰中文 | 亚洲国产精品电影在线观看 | 九九激情视频 | 精品一区三区 | 久久国产电影院 | 久久成人一区二区 | 国产精品观看在线亚洲人成网 | 亚洲欧洲精品一区二区精品久久久 | 国产成人精品一区二区三区福利 | 字幕网资源站中文字幕 | a级片韩国 | 四虎免费av | 精品久久一 | 久久人人爽视频 | 久久久久免费电影 | 中文字幕中文字幕在线中文字幕三区 | 日本婷婷色 | 国产高清av在线播放 | 日韩免费在线一区 | 亚洲第一成网站 | 日日夜夜网站 | 久久开心激情 | 欧美日韩调教 | 国产精品国产三级国产不产一地 | 久久不射电影网 | 久热av| 91看片网址 | 国产福利在线免费观看 | 97超碰人人澡人人爱学生 | 色在线观看网站 | 日韩视频免费 | 在线观看日本高清mv视频 | 亚洲精品午夜国产va久久成人 | 亚洲狠狠婷婷综合久久久 | 操综合| 日本中文不卡 | 久久久国产影视 | 国产一级片免费播放 | 中文字幕永久在线 | 国产日韩欧美视频在线观看 | 久久久久免费精品视频 | av电影不卡在线 | 97人人人人 | 国产精品久久久久久一区二区三区 | 色99在线 | 亚洲精品一区二区三区新线路 | 天天插综合网 | 国产激情免费 | 免费看一级特黄a大片 | 欧美一区二区在线 | 久久久国产毛片 | 国产精品12345 | 蜜臀久久99静品久久久久久 | 四虎免费在线观看视频 | 久久在线电影 | 久久久综合精品 | 日本一区二区三区免费观看 | 国产91精品一区二区麻豆网站 | 国产成人精品一区二区三区福利 | 亚洲无人区小视频 | 一级欧美一级日韩 | 91麻豆看国产在线紧急地址 | 狠狠色丁香久久综合网 | 9999精品免费视频 | 免费在线观看不卡av | 九九久久久久久久久激情 | 中文字幕日韩无 | 国产精品久久片 | 午夜精品一区二区三区可下载 | 成人h视频| 久久久久成人精品亚洲国产 | 免费av片在线 | 看毛片网站 | 美女网站免费福利视频 | 婷婷国产在线 | 黄色一级大片免费看 | 午夜私人影院久久久久 | 欧美小视频在线观看 | 亚洲一区天堂 | 亚洲精品乱码久久久久久 | 性色av香蕉一区二区 | 最新中文在线视频 | 中文字幕免费国产精品 | 综合激情 | 欧美调教网站 | 亚洲精品综合一二三区在线观看 | 日日干夜夜爱 | 日韩精品在线视频免费观看 | 日韩在线观看一区二区三区 | 亚洲精品毛片一级91精品 | 中文在线www | 欧美一级视频一区 | 99爱在线 | 日韩字幕| 国内综合精品午夜久久资源 | 久久免费福利 | 午夜精品久久一牛影视 | 少妇性xxx| 亚洲欧美婷婷六月色综合 | 看国产黄色片 | 国产小视频免费在线网址 | 国产色网站 | 久久99视频免费 | 欧美性黄网官网 | 丁香影院在线 | 高清av免费一区中文字幕 | 亚洲aⅴ久久精品 | 日韩电影在线视频 | 精品主播网红福利资源观看 | 日韩深夜在线观看 | 美女很黄免费网站 | 黄色一级片视频 | 精品国产一区二区三区久久 | 成人免费亚洲 | 亚洲激情免费 | 香蕉网在线观看 | 免费色视频网站 | 国产精品乱码久久久久 | 超碰在线观看av.com | 国产成人精品午夜在线播放 | 欧美黑吊大战白妞欧美 | 国产视频精品在线 | 国产1区2区3区在线 亚洲自拍偷拍色图 | 亚洲久在线 | 日韩精品免费在线观看 | 国产精品久久久久免费 | 视频国产 | 欧美在线视频一区二区三区 | 一区二区电影在线观看 | 亚洲精品黄网站 | 午夜精品久久久久久久久久久久久久 | 国产黄色av | 天天草天天干天天射 | 日韩精品无码一区二区三区 | 亚洲国产欧洲综合997久久, | 免费看黄在线看 | 91成人免费观看视频 | 久久综合久久鬼 | 国产精品美女久久久久久免费 | 日韩99热 | 久久久国产精品视频 | 高清不卡毛片 | 亚洲成人影音 | 国产视频网站在线观看 | 日本超碰在线 | 美女搞黄国产视频网站 | 午夜在线国产 | 一区av在线播放 | 成人av资源网站 | 久久精品2 | 日本黄色免费播放 | 久久精品系列 | 激情综合网五月婷婷 | 欧美一区视频 | 日韩中文字幕视频在线 | 日韩综合一区二区三区 | 国产1区在线观看 | 久久精品视| 少妇性xxx | 欧美一区二区日韩一区二区 | 欧美综合在线观看 | 亚洲精品视频免费 | 激情欧美网| 亚洲色图 校园春色 | 91福利在线观看 | 婷婷www | 日韩免费成人 | www.久热 | 国产精品99久久久久久人免费 | 激情丁香久久 | 国产精品扒开做爽爽的视频 | 天天av天天 | 久久女教师| 99免费观看视频 | 日韩欧美在线播放 | 人人干免费 | 精品视频久久久 | 中文字幕日韩高清 | 久草在线最新 | 五月婷婷电影网 | 精品国产综合区久久久久久 | 午夜成人免费电影 | 玖玖爱国产在线 | 免费在线观看成年人视频 | 久久这里精品视频 | 国产一级大片在线观看 | 日本精品视频网站 | 亚洲黄色免费观看 | 中文字幕乱码亚洲精品一区 | 91pony九色丨交换 | 久久久久中文 | 国产a级片免费观看 | 午夜精品一区二区三区在线观看 | 久久久www| www.香蕉视频 | 欧美一区免费观看 | 国内精品亚洲 | 中文字幕国产一区二区 | 久久久网址| 182午夜在线观看 | 欧美日本啪啪无遮挡网站 | 91av福利视频| 久久一区91 | 在线 国产一区 | 久久精品一二区 | 欧美日韩aa | 91日韩免费 | 丁香激情五月婷婷 |