青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

天衣有縫

冠蓋滿京華,斯人獨憔悴~
posts - 35, comments - 115, trackbacks - 0, articles - 0
   :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

2課:保護模式


聲明:轉載請保留:

譯者http://m.shnenglu.com/jinglexy

原作者:xiaoming.mo at skelix dot org

MSN & Email: jinglexy at yahoo dot com dot cn

目標        下載源程序

 

如前文所述,系統上電時處理器處于實模式。事實上,它還有另外一種工作模式:保護模式。skelix從磁盤啟動后即進入該模式。在本課中我們進入保護模式并打印"Hello World!"。



保護模式的優點

在實模式下,處理器不能簡單尋址1MB以外的物理地址(實際上用某些方法是可以的),這等內存實在是太少了。所以i386系列處理器提供了保護模式:基于特權級的保護和訪問更大的內存地址范圍。我們在這里講的是32位保護模式,16位保護模式不在討論之列。

保護模式最大的好處就是可以直接范圍最大4GB的地址空間,但是經過多年的更新換代,我們的機器還沒有達到4GB內存,于是引入了虛擬內存的概念,它可以使用硬盤存儲空間作為內存使用。保護模式下對內存訪問進行保護,它阻止用戶程序對內核代碼或數據的訪問,應用程序的crash也不會影響到整個系統。單個進程可以訪問自己獨有的4GB虛擬地址空間,而不是混亂在整個內存里面使用,它是通過地址映射來實現的,即邏輯地址轉換成虛擬地址的過程。更詳細的內容可以參考Intel的文檔。


概述運行原理

好了,讓我們結束無聊的理論知識吧,本課的目的是使我們的程序進入到保護模式。在保護模式中,我們仍然使用段(事實上,我們無法在處理器上禁用段特性),每個段可以訪問單獨的4GB地址空間。段轉載在寄存器中,它表示一個描述符選擇子,和實模式一樣使用cs,ds16位寄存器。這樣說吧:一個內存段描述符寄存器 CS = 0x8,我們可以直接訪問04G-1地址空間,注意我說的是可以,因為可以根據需要設置這個段有多大,而不是象實模式那樣限制在64KB。

 

我上面提到段是用選擇子來表示的,這個說法可能不是很準確,實際上選擇子是段描述符表的索引。這個描述符表是系統所有可以使用的段的地址和范圍表的入口,一個描述符包括段起始地址,長度,類型(數據/代碼/門),特權級等。為了范圍到特定的內存地址,段選擇子和偏移地址表示為如下形式:selector:offset,和實模式一樣。例如,我們讓 0x08選擇子指向B8000(視頻內存區域) 開始的內存范圍,這樣我們可以使用8:00000000來范圍視頻內存區域的第一個字節。在系統中存在以下幾種描述符表:GDT(全局描述符表),LDT(局部描述符表),IDT(中斷描述符表)。當進入到保護模式后,所有的內存范圍都通過GDTLDT

在本課中我們使用GDT,正如它的名字全局,GDT可以被所有任務共享?,F在我們來使用一個代碼段和一個數據段。

下面是代碼段/數據段描述符的格式,一個描述符是8字節長(64位):

 

 63_______________56__55__54__53__52__51_____________48_

基地址(3124位) | G |D/B| X | U | 長度(1916位) |

|_______________________________________________________|

 

 _47__46__45__44____41______40____39_________________32_

| P |  DPL |     類型    |  A   |  基地址(2316位)   |

|_______________________________________________________|

 

 31____________________________________________________16

|                    基地址(150位)                  |

|_______________________________________________________|

 

 16_____________________________________________________

|                    長度(150位)                    |

|_______________________________________________________|

 

解釋一下:為什么長度只有20位呢,這是因為粒度一般設置位4K,所以可以表示04GB大小的長度范圍。

 

 

                                   -域說明

 

長度( 15-0)

長度的低16

基地址( 15-0)

基地址的低16

基地址( 23-16)

基地址的中16

A

是否已訪問

類型

41

對于數據/堆棧段,為1表示可寫,為0表示只讀

對于代碼段,為1表示可讀可執行,為0表示不可讀可執行

42

對于代碼段,為0是一般段,為1是一致性代碼段。對于數據段,為0表示數據段,為1表示堆棧段。

43

1表示代碼段,0表示數據或堆棧段

44

1表示代碼或數據段,0表示系統段(中斷門,調用門,陷阱門)

DPL

特權級:我們只使用兩個,內核0級和用戶3

P

存在位,為1表示在內存中。一般在虛擬內存管理中會使用到這個位。

長度( 19-16)

長度的低8

U

用戶定義位

X

恒為0

D

32位代碼段還是16位代碼段

G

段長度的粒度:4k大小或1字節

基地址( 31-24)

基地址的高16

 

我們從上面看到,一個描述符保護32位基地址和20位段長界限等屬性。32位基地址表示32位物理地址,是一個段的開始地址,20位長度界限表示這個段的長度。讀者可能注意到2^20只能表示1M大小范圍。為了訪問4GB地址范圍,描述符中使用了G位來表示粒度。當G位為1時,粒度為4K,這是可以訪問的范圍是1M * 4K,即4GB大??;如果G為為0,粒度為1字節,可以訪問的范圍是1M字節大小。

 

特權級保護是保護模式的重要概念,為了解釋這個,我們來看一下描述符選擇子。上面已經提到了,選擇子是描述符表的一個索引:

 

 15______________________________3___2____1___0__

|              Index              | TI |   RPL  |

|_______________________________________________|

 

RPL

請求特權級:requester privilege level

TI

使用 GDT(=0) 或者 LDT(=1)

Index

描述符表索引值

 

應用程序特權級(PL)和 cs寄存器中的PL(即RPL)是類似的。程序在低的特權級(即PL值更高)不能訪問高特權級的數據段或執行高特權級的代碼段。當選擇子載入到寄存器中時,處理器會檢查CPLRPL,根據這兩個PL得到一個EPL(恕我直言,作者增加了一個新的概念并不明智),然后比較EPL和描述符中的DPL。當EPL的特權級更高時,才能正確訪問目標段。注意,這里只是大致遵循該法則,處理器還要檢測讀寫屬性,存在位等。正如上面圖所描述,選擇子Index13位的,所以最多可以索引2^13個描述符,即8096個。這只是在GDT中最多索引的描述符個數,另外每個進程都可以有自己的LDT。處理器會保留第一個GDT中的描述符,它應當被清0,不應當用作訪問內存使用。


進入保護模式

在上一課中,我們從軟盤啟動skelix?,F在我們可以執行到實模式代碼,并進入保護模式了,一些模式切換的代碼必不可少,并且不準備讓skelix在返回到那黑暗時代-實模式了。在進入保護模式之前,需要做一些準備工作,我們先創建GDT

02/bootsect.s

 

gdt:
        .quad    0x0000000000000000 # 
空描述符
        .quad    0x00cf9a000000ffff # cs
        .quad    0x00cf92000000ffff # ds
        .quad    0x0000000000000000 #
用作將來的段描述符
        .quad    0x0000000000000000 #
用作將來的段描述符

可以看到,我們在上面定義了5GDT描述符,但暫時只用到了第2個和第3個。第一個dummy描述符是Intel規定的,第2個是cs段(代碼段)描述符,下面我們仔細分析一下這個8字節值:(紅色表示cs描述符的值域)

 

Bits 15-0

FFFFh

長度界限低16

Bits 39-16

000000h

段基地址低24

Bit  40

0b

訪問位:設置為0

Bit  41

1b

/寫,或讀/執行(值表示可讀可執行代碼

Bit  42

0b

棧還是數據段,普通代碼段還是一致代碼段

Bit  43

1b

代碼段還是數據段

Bit  44

1b

代碼數據段,還是門描述符

Bits 45,46

00b

內核特權級

Bit  47

1b

存在位

Bits 48-51

Fh

長度界限高4

Bits 52

0b

軟件可用位,設置為0

Bits 53

0b

設置為恒0

Bits 54

1b

32位段還是16位段

Bits 55

1b

粒度為4k還是1字節

Bits 63-56

00h

段基地址高8

根據上面的解釋,這個段描述符描述的段從00000000地址開始,界限是FFFFF*4K,即4G32位代碼段。第3個描述符用于數據段或堆棧段,區別在于第43位,設置為0表示數據段。


好了,還是讓程序的使用來說明一切吧。處理器有幾個專門的寄存器用于保護模式,GDTR寄存器使用LGDT來加載,GDTR48位寄存器,低16位表示GDT的長度,高32位表示GDT的基地址。

 

02/bootsect.s

gdt_48:
        .word  .-gdt-1        
當前地址減gdt地址減1得到GDT的長度
        .long  GDT_ADDR       
這里使用了一些常量,如GDT_ADDR,定義在一個頭文件中

02/include/kernel.inc

.set CODE_SEL, 0x08        # 內核代碼段選擇子,二進制值是00001000,表示GDT的第2項(索引值為1
.set DATA_SEL, 0x10        #
內核代碼段選擇子
.set IDT_ADDR, 0x80000     # IDT
起始地址

我們將所有數據設置為固定地址,IDT表(后面課程會介紹到)是所有數據的起始部分。

.set IDT_SIZE, (256*8)     # IDT 大小
.set GDT_ADDR, (IDT_ADDR+IDT_SIZE)        # GDT
IDT的后面

我們用GDT_ADDR,而不是用bootsector.s文件中的gdt符合,是因為在進入保護模式后7c00地址將被覆蓋,于是我們把系統中用到的一些表搬移到固定地址。


.set GDT_ENTRIES, 5        # GDT 
5個描述符
                           # 
空描述符
                           # 
內核代碼段描述符
                           #
內核數據段描述符
                           #
當前進程tss
                           #
當前進程ldt

skelix我們使用了5GDT描述符,這里我們先介紹前3個,最后兩個將會在后面的課程中介紹。
.set GDT_SIZE, (8*GDT_ENTRIES)
                           # GDT
大小,每個描述符是8個字節大小,所以GDT大小是該值,但是我們用的并不是它
.set KERNEL_SECT, 72       #
內核大小,單位是,36k對于現在來說已經足夠了
.set STACK_BOT, 0xa0000    #
堆棧從640K 內存處開始向下增長,應該是STACK_TOP才對?

 

下載我們來看一下引導程序
02/bootsect.s

        .text
        .globl    start
        .include "kernel.inc"
include the above file
        .code16
start:
        jmp        code
gdt:  
        .quad    0x0000000000000000 # null descriptor
        .quad    0x00cf9a000000ffff # cs
        .quad    0x00cf92000000ffff # ds
        .quad    0x0000000000000000 # reserved for further use
        .quad    0x0000000000000000 # reserved for further use
gdt_48:
        .word    .-gdt-1
        .long    GDT_ADDR
code:
        xorw    %ax,    %ax
        movw    %ax,    %ds    # 
數據段 = 0x0000
        movw    %ax,    %ss    # 
堆棧段 = 0x0000
        movw    $0x1000,%sp    #
保護模式前用的堆棧,不要讓他覆蓋到7c00處的引導程序即可

        # 我們將加載內核到地址 0x10000
        movw    $0x1000,%ax
        movw    %ax,    %es
        xorw    %bx,    %bx    # es:bx 
加載內核的目標地址
        movw    $KERNEL_SECT,%cx
        movw    $1,     %si    # 0
,跳過去,所以是1
rd_kern:
        call    read_sect      #
入口參數:si是起始扇區數,es:bx是指定內存地址
        addw    $512,    %bx
        incw    %si
        loop    rd_kern

我們先把內核讀到0x10000這個臨時地址,然后再把它搬移到0x0(進入保護模式后搬移)。這個函數講起來有些煩,讀者可以自己分析:)


        cli                    #
就要進入保護模式了,所以關掉實模式下的中斷

        cld                    # 將內核的前512字節移到0x0
        movw    $0x1000,%ax
        movw    %ax,    %ds
        movw    $0x0000,%ax
        movw    %ax,    %es
        xorw    %si,    %si
        xorw    %di,    %di
        movw    $512>>2,%cx
        rep
        movsl

為什么要這樣做?因為內核的這個部分是load.s這個文件編譯出來的(本課后面會介紹到),load.s會讀取真正的內核0x200處,但是在這一課,我們只準備打印"Hello World!",除此之外什么都不做。

        xorw    %ax,    %ax
        movw    %ax,    %ds    #
復位 ds  0x0000


        movw    $GDT_ADDR>>4,%ax       # (0x80000 + 256 * 8) >> 2
        movw    %ax,    %es            # gdt
所在的數據段
        movw    $gdt,   %si
        xorw    %di,    %di            # 
ds:si 拷貝到 es:di
        movw    $GDT_SIZE>>2,%cx       #
拷貝數據段中的gdt到指定地址
        rep
        movsl

enable_a20:        
        inb    $0x64,   %al   
        testb  $0x2,    %al
        jnz    enable_a20

        movb   $0xbf,   %al
        outb   %al,     $0x64

這種開啟a20地址線的方法來自一本書:"The Undocumented PC",中文紙版是《PC技術內幕》,可惜已絕版。a20地址線通過鍵盤控制器一個端口使能(ibm早期這樣設計),當系統啟動時,該地址線是關閉的,使能它之后才能訪問1MB以外的地址空間。

        lgdt    gdt_48                 # 加載gdt地址到寄存器中
        #
進入保護模式
        movl   %cr0,    %eax
        orl    $0x1,    %eax
        movl   %eax,    %cr0           #
使能CR0 控制寄存器中的PE位(即第0位)

現在我們已經進入到保護模式了,是不是簡單的另你不敢相信?呵呵


        ljmp   $CODE_SEL, $0x0

我們還需要進行一個絕對地址跳轉,因為解碼管線中預取了16位指令,需要刷新成后面的32位指令。關于ia32的指令預取和解碼管線,網絡上有很多相關的文章,建議讀者閱讀一下相關文章。這個指令跳轉到0x08描述符選擇子指向的偏移0x的指令處,并開始執行,這個描述符即GDT中的第2項:內核代碼段描述符。代碼就是load.s的開始處,一會我們開始分析load.s這個程序。

 

 

bootsector.s中的函數:

        # 輸入:    si:    LBA 地址,從0開始
        # 
輸出     es:bx  讀取扇區到這個內存地址
read_sect:
        pushw   %ax
        pushw   %cx
        pushw   %dx
        pushw   %bx

        movw    %si,    %ax       
        xorw    %dx,    %dx
        movw    $18,    %bx    #
對于1.44M軟盤:每磁道18扇區


        divw    %bx
        incw    %dx
        movb    %dl,    %cl    # cl =
扇區號
        xorw    %dx,    %dx
        movw    $2,     %bx    #
每磁道2磁頭
        divw    %bx

        movb    %dl,    %dh    # 
磁頭
        xorb    %dl,    %dl    # 
軟驅號
        movb    %al,    %ch    #
柱面

        popw    %bx            # 讀取到:es:bx
rp_read:
        movb    $0x1,   %al    #
1個扇區
        movb    $0x2,   %ah
        int     $0x13
        jc      rp_read
        popw    %dx
        popw    %cx
        popw    %ax
        ret

 

.org    0x1fe,  0x90              # 填充nop指令,機器碼是0x90
.word   0xaa55

當我們進入到保護模式后,所有的通用寄存器和段寄存器保持原來實模式的值,代碼段從特權級0開始執行。load.s文件將從地址0處開始執行。
02/load.s

        .text
        .globl    pm_mode
        .include "kernel.inc"
        .org 0                    #
告訴加載器,該代碼將從邏輯地址0開始執行。它也是物理地址0

pm_mode:
        movl    $DATA_SEL,%eax
        movw    %ax,    %ds
        movw    %ax,    %es
        movw    %ax,    %fs
        movw    %ax,    %gs
        movw    %ax,    %ss
        movl    $STACK_BOT,%esp   #
所有數據段選擇子設置為0x10,即GDT的第3項,特權級為0。這個步驟非常重要!

        cld
        movl    $0x10200,%esi     #
bootsector程序中,我們將內核加載到了0x10200這個地址
        movl    $0x200, %edi      #
現在把內核搬移到0x200
        movl    $KERNEL_SECT<<7,%ecx        #
拷貝2^7次方個,注意下面是movsl,每次4個字節
        rep
        movsl


        movb    $0x07, %al                  #
顏色
        movl    $msg,  %esi
        movl    $0xb8000,%edi
1:
        cmp     $0,    (%esi)               #
打印"Hello World!"字符串
        je      1f
        movsb
        stosb
        jmp     1b
1:      jmp     1b
msg:
                .string "Hello World!\x0"

現在我們用圖來清晰的描述它,引導程序被加載在00007c00,它設置棧頂在00001000,然后讀取內核到00001000,然后把內核映象的前一個sector(即load.s)程序讀到地址0。在load.s程序中移到內核到地址0

 

        1                                        2

|                   |                    |___________________|a0000

|                   |                    |       內核棧      |

|       GDT         |                    |                   |

|       IDT         |                    |       GDT/IDT     |

|___________________| 8000:系統數據     |___________________|80000

|                   |                    |                   |

|                   |                    |                   |

|                   |                    |                   |

|       內核        |                    |                   |

|                   |                    |                   |

|___________________|10000               |                   |

|                   |                    |                   |

|                   |                    |                   |

|___________________|7e00                |                   |

|     bootsector.s  |                    |                   |

|___________________|7c00                |                   |

|                   |                    |                   |

|                   |                    |___________________|

|                   |                    |                   |

|                   |                    |                   |

|___________________|1000                |       內核        |

|      stack        |                    |                   |

|___________________|200                 |___________________|200

|      load.s       |                    |                   |

|___________________|0                   |___________________|0


當進入到保護模式后,load.s移到內核到它后面,設置內核棧,如圖2

最后,我們翻開Makefile看看:
02/Makefile

 

AS=as -Iinclude            -I選項告訴匯編工具查找頭文件的路徑
LD=ld

KERNEL_OBJS= load.o        
到現在為止,內核只保護load.s匯編文件
.s.o:
    ${AS} -a $< -o $*.o >$*.map

all: final.img

final.img: bootsect kernel
    cat bootsect kernel > final.img
    @wc -c final.img

bootsect: bootsect.o
    ${LD} --oformat binary -N -e start -Ttext 0x7c00 -o bootsect $<

kernel: ${KERNEL_OBJS}
    ${LD} --oformat binary -N -e pm_mode -Ttext 0x0000 -o $@ ${KERNEL_OBJS}
    @wc -c kernel

內核代碼段鏈接在0x0000
clean:
    rm -f *.img kernel bootsect *.o

執行make,用vmware運行一下剛才的image看看,是不是hello world呢。

 

Feedback

# re: 自己動手寫內核(第2課:保護模式)(原創)  回復  更多評論   

2007-07-13 10:09 by way
set CODE_SEL, 0x08 # 內核代碼段選擇子
.set DATA_SEL, 0x10 # 內核數據段選擇子
kernel.inc中有點小問題
請問這里為何知道選擇子分別是0x08及0x10
謝謝回答

# re: 自己動手寫內核(第2課:保護模式)(原創)[未登錄]  回復  更多評論   

2007-07-13 12:12 by 天衣有縫
0x08的二進制值是1000,0x10的二進制值是10000
第三位是屬性(一位表示gdt或者ldt,兩位表示特權級)
高13為是在gdt或ldt中的偏移,所以CODE_SEL和DATA_SEL分別表示偏移1項和偏移兩項。
可以在intel網站上找到ia32/64的三卷手冊下載,里面有詳細的描述。

# re: 自己動手寫內核(第2課:保護模式)(原創)  回復  更多評論   

2007-09-30 15:32 by way
請問以你的設計來講code,data段都是0~4G的尋址
然后你并沒有用data段,這兩個段完全重迭又沒有paging
所以進入保護模式這里將“ljmp $CODE_SEL, $0x0”
改為“ljmp $DATA_SEL, $0x0”是不是效果完全一樣呢?
這樣還會正常運作嗎?我看很多資料都沒提到為何要重迭
這問題也困擾我很久了
謝謝解答
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲国产精品女人久久久| 亚洲午夜精品久久久久久app| 精品不卡一区二区三区| 国产欧美一区二区三区另类精品| 国产精品永久| 在线观看日韩专区| 日韩一区二区免费高清| 亚洲在线一区二区三区| 午夜免费电影一区在线观看| 久久久久久久999| 欧美黑人国产人伦爽爽爽| 亚洲精选成人| 午夜免费在线观看精品视频| 久久国产综合精品| 老司机午夜精品视频| 欧美大片在线观看| 国产精品福利网| 在线免费观看一区二区三区| 一本综合久久| 久久九九电影| 亚洲精品偷拍| 久久伊人一区二区| 欧美午夜久久久| 亚洲高清二区| 欧美亚洲系列| 亚洲三级电影在线观看| 亚洲欧美视频一区二区三区| 另类成人小视频在线| 国产精品美女主播| 亚洲二区三区四区| 久久99在线观看| 日韩视频免费| 久久亚洲精品一区| 国产午夜精品久久久| 一区二区三区成人| 欧美freesex8一10精品| 亚洲欧美日韩系列| 欧美性猛交视频| 宅男噜噜噜66国产日韩在线观看| 老司机久久99久久精品播放免费 | 亚洲国产婷婷香蕉久久久久久| 亚洲一区一卡| 国产精品swag| 亚洲特级毛片| 日韩图片一区| 欧美日韩成人在线| 国产精品免费一区二区三区在线观看| 国产精品乱码人人做人人爱| 99精品国产高清一区二区| 美玉足脚交一区二区三区图片| 亚洲欧美制服中文字幕| 香蕉久久一区二区不卡无毒影院 | 欧美在线日韩精品| 国产精品啊啊啊| 亚洲素人一区二区| 日韩午夜激情av| 欧美日韩高清免费| 99成人精品| 亚洲人成在线播放| 欧美精品在线看| 亚洲视频在线观看视频| 一区二区三区精品视频在线观看| 欧美系列一区| 欧美一二三区在线观看| 亚洲一区二区在| 国产亚洲免费的视频看| 久久精品在线播放| 久久综合九色综合久99| 亚洲乱码精品一二三四区日韩在线| 亚洲第一页自拍| 欧美片第1页综合| 亚洲欧美区自拍先锋| 午夜激情综合网| 亚洲大黄网站| 亚洲人成人一区二区在线观看| 欧美国产激情二区三区| 在线视频精品| 亚洲女人av| 国内精品久久久久影院色| 乱码第一页成人| 欧美日韩国产小视频| 欧美一区二区高清| 久久青草欧美一区二区三区| 一本久久a久久免费精品不卡| 一区二区不卡在线视频 午夜欧美不卡在| 欧美日韩少妇| 久久久久国产一区二区三区四区| 久久久亚洲成人| 亚洲午夜激情免费视频| 久久av一区二区| 中日韩视频在线观看| 午夜久久久久| 日韩图片一区| 香蕉精品999视频一区二区| 亚洲韩国青草视频| 亚洲一级片在线观看| 亚洲国产免费看| 亚洲综合色网站| 亚洲精品日日夜夜| 欧美伊人久久久久久午夜久久久久 | 欧美诱惑福利视频| 免费久久99精品国产自在现线| 午夜国产一区| 欧美人与禽猛交乱配视频| 久久久美女艺术照精彩视频福利播放| 欧美裸体一区二区三区| 国产欧美日韩视频一区二区三区| 99这里只有精品| 久久精品免费观看| 亚洲欧美电影在线观看| 久久久欧美一区二区| 午夜精品一区二区三区四区| 欧美h视频在线| 噜噜爱69成人精品| 国产伦精品一区二区三区| 日韩视频一区二区三区| 亚洲日本一区二区三区| 久久一二三四| 麻豆亚洲精品| 黄色日韩网站视频| 香蕉视频成人在线观看| 欧美一级二区| 国产精品久久久久永久免费观看| 亚洲人线精品午夜| 亚洲精品一区二区三区樱花 | 久久久在线视频| 久久九九久久九九| 国产欧美一区二区三区国产幕精品| 99国产精品自拍| 99视频日韩| 欧美久久视频| 日韩视频一区二区三区| 9久草视频在线视频精品| 欧美成人免费网站| 亚洲国产成人av| 99精品福利视频| 欧美视频中文字幕在线| 亚洲视频在线观看| 欧美在线网址| 极品少妇一区二区| 久久视频免费观看| 欧美成人免费全部| 亚洲人成在线观看| 欧美日韩国产精品专区| 9色国产精品| 欧美一区二区视频在线观看| 国产日韩成人精品| 久久精品亚洲精品| 亚洲国产导航| 亚洲特黄一级片| 国产精品网红福利| 欧美在线视频导航| 欧美不卡一卡二卡免费版| 亚洲美女性视频| 国产精品美女久久久久久久 | 艳妇臀荡乳欲伦亚洲一区| 亚洲一区二区三区精品动漫| 国产精品每日更新| 久久激情视频久久| 亚洲国产精品成人久久综合一区| 亚洲午夜激情网站| 狠狠色丁香婷婷综合久久片| 免费观看不卡av| 亚洲午夜极品| 欧美电影免费观看高清| 亚洲愉拍自拍另类高清精品| 国产一区视频在线看| 欧美顶级少妇做爰| 亚洲资源在线观看| 亚洲成人自拍视频| 欧美一区二区高清| 亚洲另类黄色| 久久久xxx| 99热在线精品观看| 欧美性大战久久久久| 久久精品国产亚洲高清剧情介绍| 欧美高清视频一区二区| 亚洲自拍另类| 亚洲人成77777在线观看网| 国产精品视频观看| 欧美a级一区| 欧美在线综合视频| 一区二区三区四区五区精品| 乱人伦精品视频在线观看| 亚洲欧美日韩国产精品| 亚洲黄色免费网站| 国产主播一区| 国产精品日韩电影| 欧美日韩hd| 欧美99在线视频观看| 久久久精品欧美丰满| 午夜精品美女久久久久av福利| aa国产精品| 亚洲精品视频免费观看| 欧美激情视频一区二区三区在线播放 | 国产嫩草一区二区三区在线观看| 欧美韩日一区二区| 久久久www| 久久精品首页| 久久爱www.|