日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux内核支持浮点吗,【转】Linux内核浮点计算支持

發布時間:2025/3/21 linux 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux内核支持浮点吗,【转】Linux内核浮点计算支持 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

00000000 __divdf3

references this function??? ??? ??? ??? ??? // 這里有調用__divdf3地址

So what is happening is that, gcc replaced the expression (arg1/arg2) by a call to __divdf3 function which is supposed to carry out the floating point division using integer arithmetic. Why did gcc do that ? and not generate actual assembly instructions to do floating point divide.

這里出現了什么情況呢,gcc使用一個對__divdf3的函數調用代替了(arg1/arg2)這個原本可能引發浮點數除法的函數調用,gcc為什么要這么做,而不是直接產生浮點數除法的匯編代碼?

This is because, the module code was compiled with -msoft-float gcc option, which instructs gcc to not generate floating point assembly instructions and instead generate calls to the glibc s/w floating point emulation functions. -msoft-float is useful when compiling programs for platforms that do not have hardware floating point support. Nothing is wrong with this. Infact if you compile an equivalent user program with -msoft-float, it should work (pls read note below)

這是因為,這個模塊在編譯的時候加入了 -msoft-float 的gcc選項,這個選項使得gcc不直接產生浮點運算的匯編代碼而是通過產生glibc中的s/w模擬浮點運算的函數調用來實現浮點數運算. -msoft-float在當前的運行平臺沒有浮點數運算硬件支持的時候,非常的有用.

P.S. Actually it depends on whether your glibc is compiled with software floating point emulation support. Usually x86 based default glibc distributions come w/o soft floating point emulation, as almost all x86 platforms have h/w floating point support. If h/w floating point support is present, it is preferred because of its speed and the fact that it puts less load on the CPU (for applications with extensive floating point usage, f.e. sone gaming applications or CAD design applications etc).

P.S. 事實上,是否使用硬件計算浮點數運算取決于你的glibc是否使用軟件浮點數模擬編譯出來的.通常x86基礎的默認glibc版本帶有w/o軟件浮點計算模擬器,同時幾乎所有的x86平臺都有h/w浮點數支持.如果h/w浮點數支持存在,那么優先選擇硬件的浮點數運算器件,因為時間開銷更小,同時會減少CPU的負荷.

You can use the following command to see if your glibc distribution has software floating point emulation support

# ldd /bin/ls | grep libc | awk '{print $3}' | xargs readlink -f | xargs nm -D | grep __divdf3

下面命令可以察看你自己的glibc版本是否有軟件的浮點數模擬器.

I believe the reason why default glibc does not come with soft float support enabled, is to prevent applications from accidentally using soft float. Otherwise if some application is unintentionally compiled with -msoft-float, the user will never know and the application will be using the inefficient soft float, even though h/w float support is available :-( So, till now we know the following things :

1. Linux kernel (and all its modules) are compiled with -msoft-float gcc option (to know why, read on)

2. Linux kernel (and all its modules) are _not_ linked with glibc and hence we do not have access to soft floating point emulation functions (like __divdf3).

3. Linux kernel itself does not provide its own implementation of __divdf3 (and other soft floating point functions).

我相信默認的glibc沒有軟件浮點數運算器主要是防止應用程序偶然的使用軟浮點數運算.或者可能是如果某些軟件沒有顯示的使用 -msoft-float選項編譯,那么用戶就不會知道了解到當前的這個應用程序使用了低效率的浮點數運算方式.現在我們知道,

1 linux內核以及它所有模塊在編譯階段都有-msoft-float選項

2 linux內核以及他所有模塊沒有和gblic鏈接,所以我們不能直接訪問軟件浮點數模擬器

3 Linux內核沒有提供自己的浮點數運算實現方法)

The above explains why we get the error while compiling and loading the module, but the inquisitive of us will still be having few questions. Lets try to find answers to those questions. What is floating point and how is it handled ?Before we get into the main topic of the discussion, i.e. the state of floating point support in Linux, and the reasons behind that, lets take a quick look at what it takes to support floating point operations.

以上的解釋是針對在編譯和載入模塊的時候產生的錯誤,但是我們的好奇使得我們還有幾個未解決的問題.什么是浮點數以及如何handled?

Floating point usage is not very common. So much so that x86 designers did not make the floating point unit (the CPU real estate needed for floating point operations) part of the original CPU. In-fact floating point instructions were supported by a special coprocessor. For the 8086 this was called 8087. Similarly for other 80×86 processors the corresponding floating point coprocessor was called 80×87. Till the 80386 processor, this coprocessor came as a separate chip which used to sit alongside the main CPU and all the floating point calculations were directed to it, which then could use its floating point unit (FPU) to do the calculations and pass the result back to the main processor. Starting 80486, the FPU was integrated with the main CPU, but still the FPU was a logically separate unit, i.e. it used a separate register set to load/store the floating point values and it used a different ALU for carrying out the floating point calculations.

浮點數運算很不普遍.以至于x86設計者讓浮點運算部件成為CPU的部件.事實上,浮點運算指令由一個特殊的協處理器支持.8086中,這個協處理器叫8087.其他的x86結構的處理器,對應的部件都是x87.直到80386處理器,這個協處理器作為一個單獨芯片,位于CPU旁邊并且所有的浮點數運算都會發送到這個協處理器芯片上,使用協處理器的運算部件進行運算,并將結果傳回給CPU.從80486開始,FPU(Floating Process Unit)被整合進主CPU,但是同時FPU是一個邏輯獨立的部件.例如,它使用一個獨立的寄存器來輸入數據傳出結果,使用與CPU不同的ALU來進行浮點運算.

The reason for keeping the FPU separate is twofold.

1. floating point operations are very rarely used, and

2. floating point operations are expensive.

This design has a very important impact on how floating point is handled in the present operating systems. Had the floating point support been native to a processor, just like the integer support, then it would not be treated any differently and we would use them just like we use the integer operations. This blog would not exist !

保留FPU的獨立的原因主要分為兩點:

1 浮點運算很少使用

2 浮點運算相對開銷較大

這種設計方式有一個很重要的方面是,如何當前操作系統中的處理浮點運算.假使在本地的CPU就有浮點運算支持,那么就如同對待整數運算一樣,沒有什么不同的,那么也就不會有這篇文章存在了.

In this article, wherever necessary, we will take the x87 FPU as an example, but all this should apply to any other processor and its corresponding FPU.

我們在本文中將以x87FPU作為例子,但是通用于其他FPU.

Other ways of handling floating point

其他的處理浮點運算的辦法

What we just discussed above is called the hardware floating point support, as the floating point operations are handled in the hardware. Since the FPU is separate from the processor there is a possibility that we do not have the FPU in a certain system. Note that this does not apply to modern x86 based systems since FPU comes on the same die as the main processor, so if you buy the processor, you get the FPU also. Other architectures, especially those used for embedded system design, might still make the FPU as an add-on for cost reasons. In such cases, where the FPU is not present in the system and we need to still do a few floating point calculations, we have the following options.

上面討論的是浮點運行的硬件支持.由于FPU被從CPU中獨立出來,所以在特定系統中可能會沒有FPU(這條不適用于現代x86處理器系統,現在的CPU基本上都有FPU).在非x86體系下,尤其是有些被用于嵌入式系統的體系中,可能仍然把FPU作為一個附加的東西.在這樣條件下,如果沒有FPU,我們還需要做一些浮點運算,那么我們還有下面這寫選擇.

1??? Do not use floating point

Instead use the fixed point arithmetic using integer operations. This can be used if our floating point usage is not much and we do not need very high precision. Also, every application does it in its own way leading to lots of inconsitencies and possible errors.

1 不用浮點運算

使用整數操作的定點運算來代替浮點運算.當你的浮點運算不太多,而且不需要太高精度的時候,可以采用.

2??? Use a floating point emulation library

The application program written in high-level language uses the floating point operations asis, but the compiler, instead of generating floating point instructions for them, generates calls to the floating point emulation functions. These emulation functions are provided by some library, against which the program is then linked. The GNU C Library glibc also comes with support for floating point emulation. Note that the default glibc distribution might not have the floating point emultion (FPE) support, but glibc has a configure option using which we can compile glibc with FPE support.

2 使用浮點運算模擬庫

如果一個應用程序需要使用浮點運算操作,此時編譯器不生成浮點運算指令,而是調用浮點運算模擬函數.這些函數由某些庫提供,同時要鏈接進去.GNU C庫的glibc提供浮點運算模擬.默認的glibc是沒有浮點運算模擬支持的,但是在編譯配置的時候可以編譯生成浮點運算模擬支持(FPE Float Prcess Emulation)

This needs support from the compiler, as it has to identify floating point operations and generate FPE calls for them. Usually compilers provide some commandline option for this.gcc provides the -msoft-float option for this purpose. This is not the default and w/o this option gcc generates floating point instructions.

這種方法需要編譯器支持,編譯器來決定哪些操作產生FPE調用.通常編譯器會提供某些選項, 類似gcc的 -msoft-float,達到這個目的.

3??? Kernel floating point emulation

If we need to emulate floating point operations and we want to hide it from the applications, we can have the kernel emulate them. This can be kept completely transparent from the applications and they won’t even know if the underlying processor has a h/w FPU or not, but for the slowness that it might cause.

3 內核浮點數模擬

如果我們需要模擬浮點數操作,并且我們想對應用程序隱藏實現,我們可以使用內核來模擬.這種方法可以對應用程序完全隱藏當前浮點數的實現方法,但是會有性能損失.

This is implemented by the CPU generating an exception every time it encounters a floating point instruction, and the kernel exception handler then emulating the instruction using integer arithmetic.

這種方法的實現是:在每次碰到浮點數運算指令時,CPU產生異常,此時CPU捕獲異常同時使用整數運算來模擬浮點數指令功能.

For this we need support from the CPU, i.e. it should generate an exception on encountering a floating point instruction. x86 processors provide this support by means of an Emulation bit(bit #2 in CR0 register). If the h/w FPU is not present then this bit will be set. When theEmulation bit (abbreviated as EM) is set, the x86 CPU will raise the Device Not Available(#NM) exception every single time it encounters a floating point instruction. A Linux kernelcompiled with floating point emulation support, will then handle the emulation inside theexception handler, and the application will run seamlessly. If the Linux kernel is notcompiled with FPE support, it raises SIGFPE to the application.

達到這種目的需要CPU的支持,CPU能夠在遇到浮點運算指令的時候產生異常.x86的處理器提供這種支持是通過一個模擬位 Emulation bit(CR0寄存器的第二位).如果h/wFPU沒有,那么這個bit就會被置1.當Emulation bit被設置之后,x86的CPU在碰到浮點運算的指令時就會發出Device Not Available的異常.Linux內核在編譯過程中加入了對模擬器支持,會處理這個異常,應用程序會正常運行.如果Linux內核編譯時候沒有加入FPE支持,則會發送SIGFPE信號給應用程序.

The Floating Point ContextFloating point unit, uses its own set of registers for doing the floating point arithmetic, f.e. thex87 FPU (coprocessor unit for x86 processor) uses the following registers for floating pointarithmetic

* 8 data registers (ST0-ST7)??? ??? ??? 8個數據寄存器

* The status register??? ??? ??? ??? 狀態寄存器

* The control register??? ??? ??? ??? 控制寄存器

* The tag word register??? ??? ??? ??? tag寄存器

* The last instruction point register??? ??? 最后一條指令的寄存器

* Last data (operand) pointer register??? ??? 最后一個數據寄存器指針寄存器

* Opcode register??? ??? ??? ??? 運算寄存器

浮點數運算部件的上下文,(在做浮點運算過程中)使用自己的寄存器.

These are registers used specifically for floating point arithmetic and are completely separate from the native x86 registers used for integer arithmetic. These constitute the floating point context of the CPU. This (apart from the native processor context) need to be saved/restored with each process context switch. This seems like a big price to pay :-(

這些寄存器僅限于進行浮點運算中,完全獨立于本地x86的整數寄存器.這些寄存器構成了浮點運算的CPU上下文.每次process上下文切換的時候,需要保存恢復,可能需要比較大的開銷.

Cheer up ! we have a smart way to handle this. Read on ...

go on...

Because floating point usage is not very common (infact many times a process will not execute any floating point instruction in its whole quantum) and because floating point registers are so large and plentiful, it does not make sense to save and restore floating point registers on every context switch.

由于浮點運算本身不是很普遍,而且浮點寄存器相對比較大比較充足,所以就沒有必要在每次進行上下文切換的時候進行保存恢復了.

Most of the times this save/restore effort will be wasted, as the registers would not have been dirtied. x86 designers were smart enough to think about this beforehand and hence they added a bit in the CR0 register which can be used by the operating system to do this save/restore efficiently, i.e. floating point registers are saved at context switch out time, only if the going-out process executed some floating point instruction in that quantum, hence modifying the CPU FP registers. Similarly, the floating point registers are restored only when the process wants to execute some floating point instruction, hence needing the FP registers.

大多數情況下,保存回復都沒有作用,由于寄存器沒有變成dirty. x86設計者聰明的考慮了這點,所以他們在CR0中加入了1bit讓操作系統來決定是否進行保存回復操作.類似的,浮點寄存器只有在當前進程需要進行執行浮點操作的時候,才會進行保存回復操作,所以需要FP寄存器.

I was referring to the Task Switched bit (bit #3) in the CR0 register. As the name implies, the processor sets this bit on every task switch. Pls note that since Linux does not use the CPU provided task switching facility, but instead does the task switch by hand, Linux has to set the TS bit explicitly as part of the task switch. Irrespective of how the TS bit is set, its significance is that when this bit is set the CPU generates a Device Not Available (#NM) exception, when a floating point instruction is executed (for the TS bit to have effect the EM bit should be cleared, else irrespective of the TS bit the CPU raises the #NM exception for every floating point instruction). This one feature provided by the CPU can be used by the OS to do efficient context switches involving floating point context.

CR0的第三個bit,Task Switched bit. 如其名字所示,處理器在每次任務切換的時候設置這個bit. Linux沒有使用CPU提供的任務切換的便利,而是手工做的人物切換.Linux需要自己去社這TS bit作為進程切換的部分. 無論TS bit是如何進行設置的,它都意味著當這個bit被設置時,CPU產生一個Device Not Available的異常,或者在一個浮點數指令要執行的時候會產生一個Device Not Available. 這個由CPU提供的特性可以被OS用于有效的進行浮點數運算的上下文切換.

How ?

怎么做到的

Lets look at how Linux uses this to do intelligent save and restore of FP registers. Lets first see how and when is the TS bit set in the CR0 register, since if the TS bit is not set, the Device Not Available (#NM) exception will not be generated and we won’t be notified of floating point instruction execution.

首先看下什么時候,TS bit(CRO寄存器中保存)怎么被設置的.如果TS bit沒有設置,Device Not Available的異常不會產生,我們也無法在碰到浮點運算的時候得到通知.

The TS bit is set from cpu_init() initially, so that the first process that runs a floating point instruction causes the Device Not Available (#NM) exception. TS bit is then cleared from the Device Not Available (#NM) exception handler, so that no further floating point instructions executing from the current process, in its current quantum, cause the Device Not Available (#NM) exception. The TS bit is then set again when the current process is scheduled out. so that the new process executing a floating point instruction also causes the Device Not Available (#NM) exception. This is done from the context switch-out path — __switch_to()->__unlazy_fpu().

TS bit在cpu_init()中初始化,這樣第一個進程運行浮點運算的時候就會產生Device Not Available異常. TS bit在Device Not Available處理函數中被清理掉,這樣可以接受下面的浮點運算的異常發出. TS bit在當前的進程被調度出的時候再度設置,這樣在新的進程運行浮點指令的時候,同樣會產生Device Not Available異常. 這個步驟

In short, the Linux kernel wants to be notified of (and only) the first floating point instruction that a process executes in a quantum. It then takes appropriate action to restore the floating point state of that process. This ensures that the floating point state of a process is restored (i.e. saved FP state of the process loaded on to the CPU FP state) only (and only) when the process executes at least one floating point instruction. If a process does not execute any floating point instruction in a certain quantum, there is no need to restore the saved floating point state of that process. Also, since the saved FPU state of the current process did not change, we need not save the FPU state when this process is switched out. In such case the CPU FPU state remains the same as it was before the current process started running and if that corresponds to the next-to-run process’ FPU state, we need not even restore its FPU state, as the CPU’s FPU is already has that state. What this means is that if a process does not execute any floating point instruction in a certain quantum, we neither restore nor save the floating point context of that process. So we incur the FP context save/restore overhead when really required :-)

簡要說,Linux內核希望在第一次浮點運算指令的時候被通知到. 然后內核會采取合理的行為保存這個進程的浮點運算的狀態. 當進程執行僅僅至少一條浮點運算指令的時候,保證此進程浮點運算的狀態被保留.如果進程不執行任何浮點運算指令,沒有必要保存回復浮點運算的狀態.同樣,因為保存了進程的FPU狀態,我們就無需在進程換出的時候保存FPU狀態了. 在這種情況下,CPU FPU狀態會一直保留之前的狀態,如果對應的下一個進程的FPU狀態一致的話,就無需再恢復FPU狀態. 總的來說就是,如果當前進程沒有執行任何浮點運算指令,那么我們既不會保存也不會回復浮點運算上下文.只有在真正需要浮點運算的阿時候哦,才回進行FP的上下文的回復保存操作.

Kernel function math_state_restore() is at the heart of all this. It is called from the Device

Not Available (#NM) exception handler, which as we saw before, is called when the TS bit is

set and some floating point instruction is executed.

math_state_restore()函數完成上述邏輯,此函數在Device Not Available處理中調用,只有在TS bit設置并且某些浮點運算指令被執行的時候才會被調用.

asmlinkage void math_state_restore(void)

{

...

clts();

// we do not want to be called again in this process quantum

/*

* Now that we are going to use the FPU load this process' FPU state in the FPU

*/

if (unlikely(restore_fpu_checking(tsk))) {

stts();

force_sig(SIGSEGV, tsk);

return;

}

thread->status |= TS_USEDFPU; // so that __switch_to->unlazy_fpu can save the FP state of this process

}

...

clts() clears the TS bit as we do not want to be called for all floating point instructions, just the first one. It marks the TS_USEDFPU bit in the current process’ thread->status field. This bit is later checked by the context switch-out code to decide whether to save the FP registers as part of the scheduled out task’s context. Thus Linux kernel ensures that it saves the FP context for a process only if that process executes at least one floating point instruction in its last quantum, hence changing its already saved FPU state. This is the conditional save.

當只相應第一次的浮點運算指令時候,clts()函數清理TS bit.***.這個bit稍后會在進程上下文換出的時候用到,用來決定手否存儲FP寄存器到進程上下文.內核保證,如果當前進程至少執行過一次浮點數運算指令,那么就為此進程保存FP寄存器,并且改變進程保存了的FPU的狀態.

This is about the save optimization. The restore optimization is also present in the math_state_restore() function shown above. Note that, unlike other integer registers, we do not restore the FPU state unconditionally from the context switch-in code. Instead the FP restore is done from the math_state_restore() function, which signifies that the process has executed some floating point instruction, and hence it is necessary to restore the FP state of the process. As we see the floating point state is restored not at the context switch-in time. but just before the process is going to use the floating point state. This is called the lazy restore.

***.內核并不會無條件從還如的上下文中恢復FPU的狀態.如果FP在math_state_restore()函數中被處理,表明當前的process會有浮點指令,因此有必要將FP狀態恢復.

Using floating point in kernel

內核中使用浮點運算

We learnt how Linux uses conditional save and lazy restore techniques to allow application programs to use the hardware floating point support while avoiding the unnecessary overhead of saving/restoring the FP context on every context switch (even when not required). The assumption in the above discussion is that the only way the FP state of the CPU can change is by the application executing floating point instructions. It assumes that the kernel code will not modify the FP state of the CPU. This effectively means that the kernel code cannot use floating point instructions.

Well.. to be more precise, we cannot use floating point operations in the kernel just like that.

在kernel中也可以使用浮點運算

We have to follow some discipline. The good news is that the Linux kernel developers have made it very easy to use floating point operations inside the kernel. You just need to surround the floating point code with kernel_fpu_begin() and kernel_fpu_end() and you can safely use floating point operations in the kernel code.

kernel使用浮點運算 主要是用 kernel_fpu_begin()和kernel_fpu_end()包圍,就可以安全使用浮點操作在kernel代碼中(這里用法有點類似臨界區代碼)

So what magic do these two functions do. Note how the Linux kernel had solved the problem of avoiding unneeded save and restore of FP context when scheduling in/out the user processes. In short the Linux kernel does the following

這個使用方法:

* It sets the TS bit in the CR0 register, before a new process can start execution. This is so that the CPU raises the Device Not Available (#NM) exception when that process runs its first floating point instruction. The kernel can then do the lazy restore of the floating point context of the process.

在一個新的進程啟動的時候,兩個函數設置TS bit(CR0中的一bit).在進程第一執行浮點數運算的時候,可使得CPU可發出Device Not Available異常.

* From the Device Not Available (#NM) exception handler, it sets the TS_USEDFPU flag in the thread->status field. This can then be used by the context switch out code to conditionally save the floating point state of this process.

在Device Not Available異常的處理函數中,它設置TS_USEDFPU標志在thread->status項目中.這樣做使得進程上下文切換的時候,當前浮點運算的狀態可以有條件的寫入到進程中去.

If we treat the kernel mode also like another process (i.e. something that is capable of changing the FP state of the CPU), we can extend the above logic to allow kernel to use floating point operations safely. This is exactly what kernel_fpu_begin() and kernel_fpu_end() do.

可以設想內核態是另外一個進程,我們擴展上面的邏輯方式使得進程可以使用浮點運算.

static inline void kernel_fpu_begin(void)

{

struct thread_info *me = current_thread_info();

preempt_disable();

if (me->status & TS_USEDFPU)

__save_init_fpu(me->task);

else

clts();

}

static inline void kernel_fpu_end(void)

{

stts();

preempt_enable();

}

So if you want to use some floating point operations in the kernel, which can change the FP state of the CPU, we need to first save the FP state of the current process (__save_init_fpu() does that), but only if the current process was doing some floating point operations (me->status & TS_USEDFPU). Then we need to clear the TS bit, so that the CPU does not raise the Device Not Available (#NM) exception anymore.

如果你想在kernel中使用浮點運算(會改變FP的狀態),那么首先需要將當前的FP狀態寫入到正在運行的進程的狀態中去(當前進程需要有浮點數運算).然后清楚TS bit,使得cpu不會發送 Device Not Available 異常.

Once the kernel is done with the floating point operations, it can call kernel_fpu_end() which again sets the TS bit. This causes the Device Not Available (#NM) exception when a new process runs some floating point operations and hence we need to restore its floating point state (since the kernel modified the CPU FP state).

一旦kernel做完了浮點運算,它可以調用kernel_fpu_end(),這個函數會重新設置TS bit.CPU重新回復對 Device Not Available 異常的相應處理,同時需要將進程的浮點運算狀態恢復.

kernel_fpu_begin() and kernel_fpu_end() make sense only if you are using the hardware floating point support in the kernel. For this you will have to compile the kernel (or the module) with -mhard-float option.

kernel_fpu_begin() and kernel_fpu_end()保證了CPU可以使用浮點運算的硬件.在編譯內核或者模塊的時候需要加入 -mhard-float的選項

One more important thing to keep in mind is that while we are inside kernel_fpu_begin() and kernel_fpu_end() we should not sleep. This is because while we are modifying the CPU FP state, we do not want anyother context to use that FP state.

當Kernel運行在kernel_fpu_begin() 和 kernel_fpu_end()之間的時候,不能使用sleep.

總結

以上是生活随笔為你收集整理的linux内核支持浮点吗,【转】Linux内核浮点计算支持的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 成人免费一级视频 | 被灌满精子的波多野结衣 | 色综合中文网 | 国产成人无码AA精品区 | 日日夜夜国产 | 四虎精品影视 | 尹人香蕉网| 亚洲天天综合 | 亚洲色图制服诱惑 | 色播在线视频 | 在线 日本 制服 中文 欧美 | 丁香色欲久久久久久综合网 | 日本人妻换人妻毛片 | 黑色丝袜吻戏亲胸摸腿 | 国产色婷婷一区二区三区竹菊影视 | 91久色蝌蚪 | 大肉大捧一进一出好爽视频动漫 | 国产伦理一区二区 | 国产一级一区二区 | 香蕉视频成人在线观看 | 亚洲区精品 | 草草影院最新地址 | 亚洲 欧美 日韩 在线 | 69免费| 日韩精品免费电影 | 干干天天 | 成人综合网址 | 精品成人在线视频 | 日韩不卡一二三 | aa毛片视频 | 国产精品aⅴ | 先锋影音男人 | 欧洲亚洲另类 | 亚洲美女性生活 | 国产毛片毛片毛片毛片毛片 | 中国免费一级片 | 久爱视频在线观看 | 嫩草视频在线观看 | 黑人中文字幕一区二区三区 | 日韩在线视频免费 | 午夜影视在线观看 | 欧美三区在线观看 | 成人网入口 | 一本色道久久综合精品婷婷 | 色综合99久久久无码国产精品 | 96精品视频 | 国产一区在线免费 | 欧美一级爽aaaaa大片 | 一区二区激情视频 | 可以免费观看的毛片 | 伊人222成人综合网 亚洲日本中文 | 国产性xxx| 天天干天天碰 | 国产欧美一区二区精品忘忧草 | 9999久久久久 | 精品国产一二三四区 | 欧美在线视频网站 | se综合 | 日本免费一区视频 | 自拍偷在线精品自拍偷无码专区 | 午夜爽视频| 婷婷射丁香 | 樱花影院最新免费观看攻略 | 亚洲天码中字 | 四虎黄色| 星空无限mv国产剧入选 | 国产对白videos麻豆高潮 | 五月婷婷激情在线 | 午夜久久久久久噜噜噜噜 | 国产va视频 | 内射合集对白在线 | 人妻视频一区二区三区 | 国内毛片毛片毛片毛片毛片 | 日本三级吃奶头添泬 | 成人一级片视频 | 农村少妇久久久久久久 | 69xav| 星空大象mv高清在线观看免费 | 动漫大乳美女 | 最新中文字幕在线播放 | 中文字幕国产日韩 | 高清在线一区二区三区 | 中文字幕在线日本 | 美女黄色录像 | 国产成人自拍视频在线观看 | 在线观看99| 中国成熟妇女毛茸茸 | 日本成人久久 | 日韩无码专区 | 国产无套丰满白嫩对白 | 鸭子av| 免费欧美日韩 | 黄色尤物视频 | 韩国电影大尺度在线观看 | 中文无码日韩欧 | 久久久久久久久久电影 | 国产精品一区二区欧美 | 久国产视频| 日韩123区 |