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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CPU中的DVFS

發布時間:2023/12/16 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CPU中的DVFS 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載CPU動態調頻二:interactive governor

加入了自己的一些看法,看源碼可以用source insight軟件。

Linux提供了多種governor供用戶選擇,這里以interactive為例,畢竟現在的android手機中都是采用該governor.。基于linux 3.14
以下代碼若未指明位置則默認在drivers/cpufreq/cpufreq_interactive.c中.

首先需要定義一個cpufreq_governor類型的結構體用來描述interactive governor.
?

/*創建一個結構體,保存我們所需要的策略*/ struct cpufreq_governor cpufreq_gov_interactive = {.name = "interactive",.governor = cpufreq_governor_interactive,//策略的主體函數.max_transition_latency = 10000000,.owner = THIS_MODULE, };

看一下cpufreq_governor結構體:

struct cpufreq_governor {char name[CPUFREQ_NAME_LEN];int initialized;int (*governor) (struct cpufreq_policy *policy,unsigned int event);ssize_t (*show_setspeed) (struct cpufreq_policy *policy,char *buf);int (*store_setspeed) (struct cpufreq_policy *policy,unsigned int freq);unsigned int max_transition_latency; /* HW must be able to switch tonext freq faster than this value in nano secs or wewill fallback to performance governor */struct list_head governor_list;struct module *owner; };

name:governor的名字,這里被賦值為interactive
initialized:初始化標志位
max_transition_latency:注釋說的很清楚了,硬件從當前頻率切換到下一個頻率時所用的時間必須比max_transition_latency規定的時間小,否則governor將切換到performance.該數值以納秒為單位.
governor_list:所有注冊的governor都會被add到這個鏈表里面。
governor:這個calback用于控制governor的行為,比較重要,是governor的一個去切入點,后面會詳解.

好了,現在我們靜態的定義了一個interactive governor,在governor工作之前還要做一些初始化工作

static int __init cpufreq_interactive_init(void)//初始化策略 {unsigned int i;struct cpufreq_interactive_cpuinfo *pcpu;struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };/* Initalize per-cpu timers */for_each_possible_cpu(i) {pcpu = &per_cpu(cpuinfo, i);//cpu messageinit_timer_deferrable(&pcpu->cpu_timer);pcpu->cpu_timer.function = cpufreq_interactive_timer;//功能pcpu->cpu_timer.data = i;init_timer(&pcpu->cpu_slack_timer); //初始化定時器pcpu->cpu_slack_timer.function = cpufreq_interactive_nop_timer;spin_lock_init(&pcpu->load_lock);init_rwsem(&pcpu->enable_sem);}spin_lock_init(&speedchange_cpumask_lock);mutex_init(&gov_lock);speedchange_task =kthread_create(cpufreq_interactive_speedchange_task, NULL,"cfinteractive");//創建一個線程用于策略if (IS_ERR(speedchange_task))return PTR_ERR(speedchange_task);sched_setscheduler_nocheck(speedchange_task, SCHED_FIFO, &param);get_task_struct(speedchange_task);/* NB: wake up so the thread does not look hung to the freezer */wake_up_process(speedchange_task); /* 注冊interactive governor,函數在drivers/cpufreq/cpufreq.c中,對策略進行初始化并保存*/return cpufreq_register_governor(&cpufreq_gov_interactive); }

遍歷可能的CPU
get到每個CPU的cpuinfo成員
初始化可延時定時器
設置定時器的function,定時器超時時會調用該函數
設置定時器的data,這里表示CPU ID
初始化slack定時器
設置該定時器的function,定時器超時時會調用該函數
初始化兩個定時器的spin_lock
初始化可讀信號量
創建一個線程cpufreq_interactive_speedchange_task,返回的進程描述符用speedchange_task保存,這個很重要,是改變速度的任務
設置該線程的調度策略和調度參數
該線程的引用計數加1,沒有看出來
喚醒speedchange_task
調用cpufreq_register_governor注冊interactive governor,在drivers/cpufreq/cpufreq.c中

static LIST_HEAD(cpufreq_governor_list);int cpufreq_register_governor(struct cpufreq_governor *governor) {int err;if (!governor)return -EINVAL;if (cpufreq_disabled())return -ENODEV;mutex_lock(&cpufreq_governor_mutex);governor->initialized = 0;err = -EBUSY;if (__find_governor(governor->name) == NULL) {err = 0;list_add(&governor->governor_list, &cpufreq_governor_list);}mutex_unlock(&cpufreq_governor_mutex);return err; } EXPORT_SYMBOL_GPL(cpufreq_register_governor);

pufreq_governor_list用來保存已注冊的governor
__find_governor會在cpufreq_governor_list中遍歷尋找是否有與需要register的governor重名的governor,如果沒有則將該governor添加到cpufreq_governor_list中
好的,簡單介紹了一下governor的定義,初始化,注冊。
現在我們已經擁有了一個interactive governor,CPUFREQ core如果想操作governor進行選頻,那么interactive governor必須對外提供一個interface以供調用,這就是cpufreq_governor結構體中的governor callback,下面來以這個interface為切入點分析governor是如何工作的.
?

The governor->governor callback is called with the current (or to-be-set) cpufreq_policy struct for that CPU, and an unsigned int event. The following events are currently defined:CPUFREQ_GOV_START: This governor shall start its duty for the CPUpolicy->cpu CPUFREQ_GOV_STOP: This governor shall end its duty for the CPUpolicy->cpu CPUFREQ_GOV_LIMITS: The limits for CPU policy->cpu have changed topolicy->min and policy->max.

在前面的定義中有如下,這就是函數的入口

.governor = cpufreq_governor_interactive,

?下面來看一下cpufreq_governor_interactive,分段分析:

static int cpufreq_governor_interactive(struct cpufreq_policy *policy,unsigned int event) {int rc;unsigned int j;struct cpufreq_interactive_cpuinfo *pcpu;struct cpufreq_frequency_table *freq_table;//頻率表格struct cpufreq_interactive_tunables *tunables;//策略的參數

定義了一堆變量:pcpu描述了cpu相關信息,結構體如下,用到的時候在看。

struct cpufreq_interactive_cpuinfo {struct timer_list cpu_timer;struct timer_list cpu_slack_timer;spinlock_t load_lock; /* protects the next 4 fields */u64 time_in_idle;u64 time_in_idle_timestamp;u64 cputime_speedadj;u64 cputime_speedadj_timestamp;struct cpufreq_policy *policy;struct cpufreq_frequency_table *freq_table;spinlock_t target_freq_lock; /*protects target freq */unsigned int target_freq;unsigned int floor_freq;unsigned int max_freq;u64 floor_validate_time;u64 hispeed_validate_time;struct rw_semaphore enable_sem;int governor_enabled; };

freq_tab表示頻率表,結構體如下,你會發現這是一個node,每個node代表一個頻點,很多node關聯在一起就成了一個tab:

struct cpufreq_frequency_table {unsigned int driver_data; /* driver specific data, not used by core */unsigned int frequency; /* kHz - doesn't need to be in ascending* order */ };

?struct cpufreq_interactive_tunables *tunables;這個結構體很重要,貫穿了整個governor callback,先給出結構體,接下來在函數中邊看邊分析。可以看出來,這策略的一些參數的定義

struct cpufreq_interactive_tunables {int usage_count;/* Hi speed to bump to from lo speed when load burst (default max) */unsigned int hispeed_freq;/* Go to hi speed when CPU load at or above this value. */#define DEFAULT_GO_HISPEED_LOAD 99unsigned long go_hispeed_load;/* Target load. Lower values result in higher CPU speeds. */spinlock_t target_loads_lock;unsigned int *target_loads;int ntarget_loads;/** The minimum amount of time to spend at a frequency before we can ramp* down.*/#define DEFAULT_MIN_SAMPLE_TIME (80 * USEC_PER_MSEC)unsigned long min_sample_time;/** The sample rate of the timer used to increase frequency*/unsigned long timer_rate;/** Wait this long before raising speed above hispeed, by default a* single timer interval.*/spinlock_t above_hispeed_delay_lock;unsigned int *above_hispeed_delay;int nabove_hispeed_delay;/* Non-zero means indefinite speed boost active */int boost_val;/* Duration of a boot pulse in usecs */int boostpulse_duration_val;/* End time of boost pulse in ktime converted to usecs */u64 boostpulse_endtime;bool boosted;/** Max additional time to wait in idle, beyond timer_rate, at speeds* above minimum before wakeup to reduce speed, or -1 if unnecessary.*/#define DEFAULT_TIMER_SLACK (4 * DEFAULT_TIMER_RATE)int timer_slack_val;bool io_is_busy; };

?回到cpufreq_governor_interactive函數,繼續往下看

if (have_governor_per_policy()) //判斷是否每個cpu都有策略tunables = policy->governor_data;elsetunables = common_tunables; //只有一個策略的(一個策略控制所有核)

have_governor_per_policy判斷是否每個policy都有自己的governor,當沒有設置have_governor_per_policy時,表示所有的policy使用了同一種governor,該字段指向該governor的dbs_data結構。

/* For cases where we have single governor instance for system */ static struct cpufreq_interactive_tunables *common_tunables;

但是沒有分配內存和初始化。繼續往下看。

switch (event) {

判斷event的類型,并根據event進行不同的操作。
在include/linux/cpufreq.h中定義了幾種Governor Events

/* Governor Events */ #define CPUFREQ_GOV_START 1 #define CPUFREQ_GOV_STOP 2 #define CPUFREQ_GOV_LIMITS 3 #define CPUFREQ_GOV_POLICY_INIT 4 #define CPUFREQ_GOV_POLICY_EXIT 5

?


第一個是:CPUFREQ_GOV_POLICY_INIT

case CPUFREQ_GOV_POLICY_INIT://初始化if (have_governor_per_policy()) {WARN_ON(tunables);} else if (tunables) {//這個好像是判斷tunables有沒有分配內存tunables->usage_count++;policy->governor_data = tunables;return 0;}tunables = kzalloc(sizeof(*tunables), GFP_KERNEL);//分配內存if (!tunables) {pr_err("%s: POLICY_INIT: kzalloc failed\n", __func__);return -ENOMEM;}/*然后初始化*/tunables->usage_count = 1;tunables->above_hispeed_delay = default_above_hispeed_delay; //高速度向更高情況下的延時tunables->nabove_hispeed_delay =ARRAY_SIZE(default_above_hispeed_delay);tunables->go_hispeed_load = DEFAULT_GO_HISPEED_LOAD;//負載閾值tunables->target_loads = default_target_loads;//目標負載tunables->ntarget_loads = ARRAY_SIZE(default_target_loads);tunables->min_sample_time = DEFAULT_MIN_SAMPLE_TIME;//最小采樣時間tunables->timer_rate = DEFAULT_TIMER_RATE;//采樣率tunables->boostpulse_duration_val = DEFAULT_MIN_SAMPLE_TIME;//超頻最少持續時間?tunables->timer_slack_val = DEFAULT_TIMER_SLACK;//空閑時間的采樣率spin_lock_init(&tunables->target_loads_lock);spin_lock_init(&tunables->above_hispeed_delay_lock);policy->governor_data = tunables; //??if (!have_governor_per_policy())common_tunables = tunables;rc = sysfs_create_group(get_governor_parent_kobj(policy),get_sysfs_attr());//attribute_group??if (rc) {kfree(tunables);policy->governor_data = NULL;if (!have_governor_per_policy())common_tunables = NULL;return rc;}if (!policy->governor->initialized) {idle_notifier_register(&cpufreq_interactive_idle_nb);cpufreq_register_notifier(&cpufreq_notifier_block,CPUFREQ_TRANSITION_NOTIFIER);}break;

該event表示要init governor policy.
首先判斷have_governor_per_policy(),前面分析過了,返回false,并且tunables并沒有被分配內存,所以執行下一條語句

tunables = kzalloc(sizeof(*tunables), GFP_KERNEL);

?終于為tunables分配內存了~~
接下來就是對tunables的初始化:

tunables->usage_count = 1;tunables->above_hispeed_delay = default_above_hispeed_delay;tunables->nabove_hispeed_delay =ARRAY_SIZE(default_above_hispeed_delay);tunables->go_hispeed_load = DEFAULT_GO_HISPEED_LOAD;tunables->target_loads = default_target_loads;tunables->ntarget_loads = ARRAY_SIZE(default_target_loads);tunables->min_sample_time = DEFAULT_MIN_SAMPLE_TIME;tunables->timer_rate = DEFAULT_TIMER_RATE;tunables->boostpulse_duration_val = DEFAULT_MIN_SAMPLE_TIME;tunables->timer_slack_val = DEFAULT_TIMER_SLACK;spin_lock_init(&tunables->target_loads_lock);spin_lock_init(&tunables->above_hispeed_delay_lock);

?usage_count表示引用計數,初始化的時候設置為1

above_hispeed_delay,內核文檔: /Documention/cpu-freq/governors.txt

above_hispeed_delay: When speed is at or above hispeed_freq, wait for this long before raising speed in response to continued high load. The format is a single delay value, optionally followed by pairs of CPU speeds and the delay to use at or above those speeds. Colons can be used between the speeds and associated delays for readability. For example:80000 1300000:200000 1500000:40000uses delay 80000 uS until CPU speed 1.3 GHz, at which speed delay 200000 uS is used until speed 1.5 GHz, at which speed (and above) delay 40000 uS is used. If speeds are specified these must appear in ascending order. Default is 20000 uS.

下面是我自己的理解,有錯誤請務必指出:當CPU頻率大于等于hispeed_freq,并且此時workload仍在不停增加(continued high load),系統將等待一個above_hispeed_delay的時間。above_hispeed_delay一般是這樣一種格式,一個單個的延時數值,后面跟上一組由CPU speeds 和 delay組成的數組,由冒號隔開。例如:
80000 1300000:200000 1500000:40000
當頻率低于1.3G時,above_hispeed_delay的值取80000,1.3G到1.5G之間取20000,大于1.5G取40000.默認取20000us.如果頻率被指定,那么這些數值必須必須是升序的。(最后一句不是很確定很理解)

#define DEFAULT_TIMER_RATE (20 * USEC_PER_MSEC) #define DEFAULT_ABOVE_HISPEED_DELAY DEFAULT_TIMER_RATE static unsigned int default_above_hispeed_delay[] = {DEFAULT_ABOVE_HISPEED_DELAY };

可以看到default_above_hispeed_delay是一個數組,我的環境下只有一個數值,above_hispeed_delay的數值就是ta了。

nabove_hispeed_delay:default_above_hispeed_delays數組中元素的個數。

go_hispeed_load: The CPU load at which to ramp to hispeed_freq.Default is 99%。高頻閾值。當系統的負載超過該值,升頻,否則降頻。

#define DEFAULT_GO_HISPEED_LOAD 99

調頻的時候會用到這個數值,后面會說到.

順便說一下hispeed_freq: Hi speed to bump to from lo speed when load burst (default max)。當workload達到 go_hispeed_load時,頻率將被拉高到這個值,默認的大小由policy來決定。
target_loads:

CPU load values used to adjust speed to influence the current CPU load toward that value. In general, the lower the target load, the more often the governor will raise CPU speeds to bring load below the target. The format is a single target load, optionally followed by pairs of CPU speeds and CPU loads to target at or above those speeds. Colons can be used between the speeds and associated target loads for readability. For example:85 1000000:90 1700000:99targets CPU load 85% below speed 1GHz, 90% at or above 1GHz, until 1.7GHz and above, at which load 99% is targeted. If speeds are specified these must appear in ascending order. Higher target load values are typically specified for higher speeds, that is, target load values also usually appear in an ascending order. The default is target load 90% for all speeds.

target_loads使得CPU調整頻率來影響當前的CPU workload,促使當前的CPU workload向target_loads靠近。通常,target_loads的值越小,CPU就會越頻繁地拉高頻率使當前workload低于target_loads。例如:頻率小于1G時,取85%;1G—-1.7G,取90%;大于1.7G,取99%。默認值取90%。

/* Target load. Lower values result in higher CPU speeds. */ #define DEFAULT_TARGET_LOAD 90 static unsigned int default_target_loads[] = {DEFAULT_TARGET_LOAD};

ntarget_loads:target_loads的個數

min_sample_time:最小采樣時間,剛好80000us.

#define DEFAULT_MIN_SAMPLE_TIME (80 * USEC_PER_MSEC) /include/linux/time.h #define USEC_PER_MSEC 1000L

boostpulse_duration_val:

boost: If non-zero, immediately boost speed of all CPUs to at least hispeed_freq until zero is written to this attribute. If zero, allow CPU speeds to drop below hispeed_freq according to load as usual. Default is zero.boostpulse: On each write, immediately boost speed of all CPUs to hispeed_freq for at least the period of time specified by boostpulse_duration, after which speeds are allowed to drop below hispeed_freq according to load as usual.boostpulse_duration: Length of time to hold CPU speed at hispeed_freq on a write to boostpulse, before allowing speed to drop according to load as usual. Default is 80000 uS.

boost:即超頻,在linux中我們可以操作方法是,但內核中不知道怎么弄

echo 1 > /sys/devices/system/cpu/cpufreq/interactive/boost

此時會立即將所有CPU的頻率提高到至少hispeed_freq.寫入0時,根據workload降低頻率.默認為0.

boostpulse,每次觸發boost功能時,立即拉高所有CPU的頻率到hispeed_freq并保持在該頻率至少boostpulse_duration的時間,在這段時間以后,根據當前的workload,頻率才允許被降低。

boostpulse_duration:默認值80000 uS.這里我的值也是80000 uS.

timer_ratetimer_slack_val:當CPU不處于idel狀態時,timer_rate作為采樣速率來計算CPU的workload.
當CPU處于idel狀態,此時使用一個可延時定時器,會導致CPU不能從idel狀態蘇醒來響應定時器.
定時器的最大的可延時時間用timer_slack表示,默認值80000 uS.

timer_rate: Sample rate for reevaluating CPU load when the CPU is not idle. A deferrable timer is used, such that the CPU will not be woken from idle to service this timer until something else needs to run. (The maximum time to allow deferring this timer when not running at minimum speed is configurable via timer_slack.) Default is 20000 uS.timer_slack: Maximum additional time to defer handling the governor sampling timer beyond timer_rate when running at speeds above the minimum. For platforms that consume additional power at idle when CPUs are running at speeds greater than minimum, this places an upper bound on how long the timer will be deferred prior to re-evaluating load and dropping speed. For example, if timer_rate is 20000uS and timer_slack is 10000uS then timers will be deferred for up to 30msec when not at lowest speed. A value of -1 means defer timers indefinitely at all speeds. Default is 80000 uS.

繼續向下看

spin_lock_init(&tunables->target_loads_lock);spin_lock_init(&tunables->above_hispeed_delay_lock);policy->governor_data = tunables; //??if (!have_governor_per_policy())common_tunables = tunables;rc = sysfs_create_group(get_governor_parent_kobj(policy),get_sysfs_attr());//attribute_group??if (rc) {kfree(tunables);policy->governor_data = NULL;if (!have_governor_per_policy())common_tunables = NULL;return rc;}if (!policy->governor->initialized) {idle_notifier_register(&cpufreq_interactive_idle_nb);cpufreq_register_notifier(&cpufreq_notifier_block,CPUFREQ_TRANSITION_NOTIFIER);}break;

初始化tunables結構體中的兩個自旋鎖。
將tunables指針賦值給policy->governor_data
將tunables指針賦值給common_tunables,這個全局變量會在一些文件的show和store函數中被調用,沒有深入研究.
繼續

rc = sysfs_create_group(get_governor_parent_kobj(policy),get_sysfs_attr());

看一下get_governor_parent_kobj和get_sysfs_attr,在drivers/cpufreq/cpufreq.c中

struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy) {if (have_governor_per_policy())return &policy->kobj;elsereturn cpufreq_global_kobject; } EXPORT_SYMBOL_GPL(get_governor_parent_kobj);struct kobject *cpufreq_global_kobject; EXPORT_SYMBOL(cpufreq_global_kobject); static struct attribute_group *get_sysfs_attr(void) {if (have_governor_per_policy())return &interactive_attr_group_gov_pol;elsereturn &interactive_attr_group_gov_sys; }static struct attribute_group interactive_attr_group_gov_sys = {.attrs = interactive_attributes_gov_sys,.name = "interactive", };/* One Governor instance for entire system */ static struct attribute *interactive_attributes_gov_sys[] = {&target_loads_gov_sys.attr,&above_hispeed_delay_gov_sys.attr,&hispeed_freq_gov_sys.attr,&go_hispeed_load_gov_sys.attr,&min_sample_time_gov_sys.attr,&timer_rate_gov_sys.attr,&timer_slack_gov_sys.attr,&boost_gov_sys.attr,&boostpulse_gov_sys.attr,&boostpulse_duration_gov_sys.attr,&io_is_busy_gov_sys.attr,NULL, };

OK,我們把上述代碼簡化一下得到

rc = sysfs_create_group(cpufreq_global_kobject,interactive_attr_group_gov_sys);

在cpufreq_global_kobject所對應的目錄cpufreq下創建一個名為interactive的目錄,并創建與之關聯的屬性文件。通過以下方式可以看到這些屬性文件

ls /sys/devices/system/cpu/cpufreq/interactive/

最后注冊了兩個notification,分別是idle相關和頻率改變相關.
回顧一下CPUFREQ_GOV_POLICY_INIT都做了什么:
1.定義并初始化了一個cpufreq_interactive_tunables結構體,將該結構體指針賦值給policy->governor_data,在struct cpufreq_policy結構體中,policy->governor_data為void *指針,現在我們知道它的作用是指向tunables,而tunablesa對應的內存中存放了governor調節頻率的參數,這就是policy->governor_data的作用.
2.創建對應的目錄和屬性文件


第二個是:CPUFREQ_GOV_POLICY_EXIT

這個event對應的操作比較簡單一些,主要是做一些policy和governor的“善后”工作,不必贅述了。

case CPUFREQ_GOV_POLICY_EXIT://退出if (!--tunables->usage_count) {//對每一個都釋放注冊if (policy->governor->initialized == 1) {cpufreq_unregister_notifier(&cpufreq_notifier_block,CPUFREQ_TRANSITION_NOTIFIER);idle_notifier_unregister(&cpufreq_interactive_idle_nb);}sysfs_remove_group(get_governor_parent_kobj(policy),get_sysfs_attr());kfree(tunables);//釋放內存common_tunables = NULL;//釋放內存}policy->governor_data = NULL;break;

第三個是:CPUFREQ_GOV_START

啟動一個governor

case CPUFREQ_GOV_START://開始工作mutex_lock(&gov_lock); //鎖住進程freq_table = cpufreq_frequency_get_table(policy->cpu);//得到CPU頻率表if (!tunables->hispeed_freq)//高頻的頻率tunables->hispeed_freq = policy->max;for_each_cpu(j, policy->cpus) {//遍歷CPU進行設置??pcpu = &per_cpu(cpuinfo, j);pcpu->policy = policy;pcpu->target_freq = policy->cur;pcpu->freq_table = freq_table;pcpu->floor_freq = pcpu->target_freq;pcpu->floor_validate_time =ktime_to_us(ktime_get());pcpu->hispeed_validate_time =pcpu->floor_validate_time;down_write(&pcpu->enable_sem);del_timer_sync(&pcpu->cpu_timer);del_timer_sync(&pcpu->cpu_slack_timer);cpufreq_interactive_timer_start(tunables, j);//開啟定時器,賊重要pcpu->governor_enabled = 1; //開啟up_write(&pcpu->enable_sem);}mutex_unlock(&gov_lock);break;

首先獲取freq_tab.
如果沒有設置hispeed_freq的值的話,就設置hispeed_freq為policy->max,和之前介紹hispeed_freq時說的一樣.
接下來是一個for循環,policy->cpus表示所有處于online狀態的CPU,for循環遍歷所有處于online狀態的CPU,在這個循環中:
get到cpu的cpuinfo結構體并把指針賦值給pcpu,一個struct cpufreq_interactive_cpuinfo結構體指針.
然后對pcpu的一些成員進行初始化,本質上還是設置online cpus的cpuinfo結構體成員.
然后調用cpufreq_interactive_timer_start啟動相關的定時器
啟動定時器以后governor就可以工作了,所以設置pcpu->governor_enabled為1
來看代碼:

static void cpufreq_interactive_timer_start(//還沒細看struct cpufreq_interactive_tunables *tunables, int cpu) {struct cpufreq_interactive_cpuinfo *pcpu = &per_cpu(cpuinfo, cpu);//讀取CPU狀態信息unsigned long expires = jiffies +usecs_to_jiffies(tunables->timer_rate);unsigned long flags;pcpu->cpu_timer.expires = expires;add_timer_on(&pcpu->cpu_timer, cpu);if (tunables->timer_slack_val >= 0 &&pcpu->target_freq > pcpu->policy->min) {expires += usecs_to_jiffies(tunables->timer_slack_val);pcpu->cpu_slack_timer.expires = expires;add_timer_on(&pcpu->cpu_slack_timer, cpu);}spin_lock_irqsave(&pcpu->load_lock, flags);pcpu->time_in_idle =get_cpu_idle_time(cpu, &pcpu->time_in_idle_timestamp,tunables->io_is_busy);pcpu->cputime_speedadj = 0;pcpu->cputime_speedadj_timestamp = pcpu->time_in_idle_timestamp;spin_unlock_irqrestore(&pcpu->load_lock, flags); }

注釋中有解釋:The cpu_timer and cpu_slack_timer must be deactivated when calling this function.
所以在進入cpufreq_interactive_timer_start之前有一些deactive的操作:
?

del_timer_sync(&pcpu->cpu_timer); del_timer_sync(&pcpu->cpu_slack_timer);

看看cpufreq_interactive_timer_start究竟做了什么
設置定時器的到期時間expire
調用add_timer_on添加定時器,”start a timer on a particular CPU”
在指定的CPU上start一個定時器,假如我的手機上有4個CPU,那么將有四個定時器被添加到pcpu->cpu_timer鏈表中
cpu_slack_timer也是同樣的操作
然后獲取該CPU的idle時間,這個數值在統計更新時間的時候會被用到.

pcpu->time_in_idle = get_cpu_idle_time(cpu, &pcpu->time_in_idle_timestamp,tunables->io_is_busy);

隨后就是

pcpu->cputime_speedadj = 0;pcpu->cputime_speedadj_timestamp = pcpu->time_in_idle_timestamp;

time_in_idle_timestamp的數值在get_cpu_idle_time函數中被更新,在代碼中形參的名字為last_update_time,可以理解為更新time_in_idle的時間戳。網上有人解釋為計算機啟動到現在的時間,是一樣的.

OK,到這里start governor的工作就完成了,主要就是啟動了兩個定時器,定時器到期的話,會執行相關的操作最終選定要set的頻率.
本來到這里我們應該回到cpufreq_governor_interactive中分析event為CPUFREQ_GOV_LIMITS的情況。
但是為了思路的流暢性,我們順著定時器繼續追代碼,看定時器如何實現選頻.


__init cpufreq_interactive_init函數中

cpu->cpu_timer.function = cpufreq_interactive_timer;pcpu->cpu_timer.data = i;

定時器到期時,調用 cpufreq_interactive_timer,
這里data是cpu的索引號,在cpufreq_interactive_init中cpu_timer的data成員被賦值成為CPU的索引號,之后調用cpu_timer.function的時候作為實參。最主要的
分段看:

static void cpufreq_interactive_timer(unsigned long data) {u64 now;unsigned int delta_time;u64 cputime_speedadj;int cpu_load;struct cpufreq_interactive_cpuinfo *pcpu =&per_cpu(cpuinfo, data); //得到信息struct cpufreq_interactive_tunables *tunables =pcpu->policy->governor_data;//得到信息unsigned int new_freq;unsigned int loadadjfreq;unsigned int index;unsigned long flags;bool boosted;if (!down_read_trylock(&pcpu->enable_sem))return;if (!pcpu->governor_enabled)goto exit;spin_lock_irqsave(&pcpu->load_lock, flags);now = update_load(data);//更新負載,總時間delta_time = (unsigned int)(now - pcpu->cputime_speedadj_timestamp);//兩次統計之間的時間cputime_speedadj = pcpu->cputime_speedadj;//頻率的積分總和??spin_unlock_irqrestore(&pcpu->load_lock, flags);if (WARN_ON_ONCE(!delta_time))goto rearm;do_div(cputime_speedadj, delta_time);//loadadjfreq(類似于積分)=(運行時間 -空閑時間)* policy->cur / 運行時間 * 100loadadjfreq = (unsigned int)cputime_speedadj * 100;//cpu_load=非idle的時間比例*當前頻率占目標頻率的比例cpu_load = loadadjfreq / pcpu->target_freq;//超頻是否允許boosted = tunables->boost_val || now < tunables->boostpulse_endtime;

首先調用update_load,更新工作負載

static u64 update_load(int cpu) {struct cpufreq_interactive_cpuinfo *pcpu = &per_cpu(cpuinfo, cpu);struct cpufreq_interactive_tunables *tunables =pcpu->policy->governor_data;u64 now;//現在的時間??u64 now_idle;unsigned int delta_idle;unsigned int delta_time;u64 active_time;now_idle = get_cpu_idle_time(cpu, &now, tunables->io_is_busy);//總空閑時間delta_idle = (unsigned int)(now_idle - pcpu->time_in_idle);//兩次空閑時間之間的時間delta_time = (unsigned int)(now - pcpu->time_in_idle_timestamp);//兩次統計之間系統運行的總時間??if (delta_time <= delta_idle)active_time = 0;//說明運行期間CPU一直在idle,active_time賦值為0 elseactive_time = delta_time - delta_idle;//處于運行狀態的時間pcpu->cputime_speedadj += active_time * pcpu->policy->cur;//計算頻率的積分??限制的一種??pcpu->time_in_idle = now_idle;//總空閑時間pcpu->time_in_idle_timestamp = now;return now; }

now_idle:系統啟動以后運行的idle的總時間

the cummulative idle time (since boot) for a given CPU, in microseconds.

pcpu->time_in_idle:上次統計時的idle的總時間
delta_idle:兩次統計之間的idle總時間

now:本次計時的時間,本次的update time

variable to store update time in.

pcpu->time_in_idle_timestamp,上次統計idle時的時間戳
delta_time:兩次統計之間系統運行的總時間

若delta_time <= delta_idle,說明運行期間CPU一直在idle,active_time賦值為0.
否則,active_time = delta_time - delta_idle;計算出兩次統計之間CPU處于active的總時間.

然后更新pcpu的一些成員變量的值:
pcpu->cputime_speedadj 這個數值的計算方式是本身加上active_time * pcpu->policy->cur,是一共改變了多少頻率的意思?不確定.
pcpu->time_in_idle = now_idle; 更新系統啟動后運行的總idle時間.
pcpu->time_in_idle_timestamp = now;更新統計時的時間戳.
上面這兩個數值被更新留作下次update_load使用
回到cpufreq_interactive_timer,update_load返回了最新一次統計idle時的時間戳,賦值給now.

delta_time = (unsigned int)(now - pcpu->cputime_speedadj_timestamp);

再次計算兩次統計之間的運行時間
在update_load中是now - pcpu->time_in_idle_timestamp,但是隨后在update_load更新了time_in_idle_timestamp的值,所以now和time_in_idle_timestamp應該相等,不能再這么算.
這里用cputime_speedadj_timestamp,我在函數cpufreq_interactive_timer_resched和cpufreq_interactive_timer_start發現cputime_speedadj_timestamp都被賦值為time_in_idle_timestamp,所以我認為:cputime_speedadj_timestamp是作為time_in_idle_timestamp的一個“備份”,保存上次統計時的time_in_idle_timestamp.

然后取pcpu->cputime_speedadj賦值給局部變量cputime_speedadj,cpu->cputime_speedadj在update_load中已被計算并更新過了.

接下來的幾行代碼都是用來計算cpu_load,把這些數值展開看就變得很清晰了

loadadjfreq = (unsigned int)cputime_speedadj * 100;

替換后

cputime_speedadj = active_time * policy->cur * 100 cputime_speedadj = (delta_time - delta_idle)* policy->cur * 100 cputime_speedadj = [(now -time_in_idle_timestamp) - (now_idle - time_in_idle)] * policy->cur * 100

now -time_in_idle_timestamp是兩次統計間的運行時間,用x表示;
now_idle - time_in_idle是兩次統計間CPU處于idle的時間,用y表示。
之前分析過,cputime_speedadj_timestamp是time_in_idle_timestamp的備份,且
?

do_div(cputime_speedadj, delta_time);

所以,可以替換為

cputime_speedadj = cputime_speedadj / delta_time delta_time = now - pcpu->cputime_speedadj_timestamp delta_time = now - time_in_idle_timestamp

now -time_in_idle_timestamp是兩次統計間的運行時間,用x表示;
now_idle - time_in_idle是兩次統計間idle的總時間,用y表示
所以

cputime_speedadj = (x - y)* policy->cur / x * 100 cpu_load = [(x - y) / x ] * [ policy->cur / pcpu->target_freq] * 100 cpu_load = (1 - x / y) * ( policy->cur / pcpu->target_freq ) * 100

(1 - x / y)是統計時間內CPU處于非idle的時間比例,policy->cur / pcpu->target_freq 表示當前頻率占目標頻率的比例,至于為什么要乘以100,是因為內核不支持浮點運算.

ok,到這里我們終于發現,影響cpu_load的兩個因素
1. idle時間
2. 當前頻率/目標頻率

有一個疑問:
cpufreq_interactive_timer函數的目的是為了根據當前的workload選頻,得到目標頻率,然后傳給cpufreq driver來設置頻率。如果已經有了目標頻率,那么直接調driver設置好了,所以這里的pcpu->target_freq不是本次選頻得到的target_freq
在cpufreq_interactive_timer的后面代碼中,我們看到
?

pcpu->target_freq = new_freq;

new_freq 是本次選頻后得到的新頻率,最后賦值給pcpu->target_freq,所以在cpufreq_interactive_timer中,該賦值語句之前的所有pcpu->target_freq都表示是上一次選頻的target_freq

所以更正一下,影響cpu_load的兩個因素

1. idle時間的頻率
2. 當前頻率/上一次選頻頻率

OK,帶著這個思路就比較好分析了

if (cpu_load >= tunables->go_hispeed_load || tunables->boosted) {if (pcpu->target_freq < tunables->hispeed_freq) {new_freq = tunables->hispeed_freq;} else {new_freq = choose_freq(pcpu, loadadjfreq);if (new_freq < tunables->hispeed_freq)new_freq = tunables->hispeed_freq;}} else {new_freq = choose_freq(pcpu, loadadjfreq);if (new_freq > tunables->hispeed_freq &&pcpu->target_freq < tunables->hispeed_freq)new_freq = tunables->hispeed_freq;}

當cpu_load大于tunables->go_hispeed_load或者tunables->boosted的值為非0,此時我們需要拉高頻率.
如果上一次選頻頻率比tunables->hispeed_freq小,那么直接設置new_freq為tunables->hispeed_freq;
如果上一次選頻頻率不小于tunables->hispeed_freq,調用choose_freq函數選頻,若選頻后仍然達不到tunables->hispeed_freq,那么直接設置new_freq為tunables->hispeed_freq。
可以看到,tunables->go_hispeed_load時,new_freq的頻率要不小于tunables->hispeed_freq.

當cpu_load小于等于tunables->go_hispeed_load并且tunables->boosted的值為0,調用choose_freq選頻.
若選頻后new_freq的值大于tunables->hispeed_freq并且上一次選頻頻率小于tunables->hispeed_freq,那么直接設置new_freq為tunables->hispeed_freq.


關于choose_freq是如何選頻的,請看函數

static u64 update_load(int cpu) {struct cpufreq_interactive_cpuinfo *pcpu = &per_cpu(cpuinfo, cpu);struct cpufreq_interactive_tunables *tunables =pcpu->policy->governor_data;u64 now;//現在的時間??u64 now_idle;unsigned int delta_idle;unsigned int delta_time;u64 active_time;now_idle = get_cpu_idle_time(cpu, &now, tunables->io_is_busy);//總空閑時間delta_idle = (unsigned int)(now_idle - pcpu->time_in_idle);//兩次空閑時間之間的時間delta_time = (unsigned int)(now - pcpu->time_in_idle_timestamp);//兩次統計之間系統運行的總時間??if (delta_time <= delta_idle)active_time = 0;//說明運行期間CPU一直在idle,active_time賦值為0 elseactive_time = delta_time - delta_idle;//處于運行狀態的時間pcpu->cputime_speedadj += active_time * pcpu->policy->cur;//計算頻率的積分??限制的一種??pcpu->time_in_idle = now_idle;//總空閑時間pcpu->time_in_idle_timestamp = now;return now; }

freq的初始數值是pcpu->policy->cur
prevfreq保存著上次的freq,freq表示本次選頻的結果,當二者相等時,就表示已經達到了最佳的選頻結果.

順便說一下:

#define CPUFREQ_RELATION_L 0 /* lowest frequency at or above target CPUFREQ_RELATION_L,表示要取大于等于target的最小值*/ #define CPUFREQ_RELATION_H 1 /* highest frequency below or at target CPUFREQ_RELATION_H,表示要取小于等于target的最大值*/

之后是一個循環:
把上次的freq賦值給prevfreq
通過freq_to_targetload得到target load——tl
然后調用cpufreq_frequency_table_target,取大于等于loadadjfreq / tl,即target freq的最小值.
loadadjfreq是兩次采樣統計間的平均頻率,除以target load就得到target freq.

freq = pcpu->freq_table[index].frequency;

我覺得情景應該是這樣的,剛開始freq = pcpu->policy->cur,備份到prevfreq,調用cpufreq_frequency_table_target得到新的freq,然后執行下面的if判斷,在這個判斷中可能會調整freq,先不管這些.
到了下一次循環,上一次的freq又被備份到prevfreq,然后又調用cpufreq_frequency_table_target得到新的freq,如此往復循環,prevfreq和freq的數值會越來越接近,直到相等,就完成了選頻.
總體思路是這樣,那么來看if判斷做了什么.
拿freq和prevfreq比較:
若freq > prevfreq,則
freqmin = prevfreq;
否則
freqmax = prevfreq;

如果freq > prevfreq,說明比上次大,但是不能比之前的記錄最大值大,否則調節就沒有意義了,所以
如果freq >= freqmax,那么調用cpufreq_frequency_table_target,找小于freqmax的最近一個頻點,如果該頻點正好是最小頻點,說明只有freqmax可以用了,直接break;

如果freq < prevfreq,說明比上次小,但是不能比之前記錄的最小值小,否則調節就沒有意義了,所以
如果freq <= freqmax,那么調用cpufreq_frequency_table_target,找大于freqmax的最近一個頻點,如果該頻點正好是最大頻點,直接break,;
最后返回選好的頻點freq.


繼續探究cpufreq_interactive_timer

if (pcpu->target_freq >= tunables->hispeed_freq &&new_freq > pcpu->target_freq &&now - pcpu->hispeed_validate_time <freq_to_above_hispeed_delay(tunables, pcpu->target_freq)) {trace_cpufreq_interactive_notyet(data, cpu_load, pcpu->target_freq,pcpu->policy->cur, new_freq);spin_unlock_irqrestore(&pcpu->target_freq_lock, flags);goto rearm;}

freq_to_above_hispeed_delay,只是返回了tunables->above_hispeed_delay[i]的數值,我們只設置了一個數值default_above_hispeed_delay.
重點是這個成員的含義,可以回頭看一下INIT階段的解釋.
如果滿足
?

pcpu->target_freq >= tunables->hispeed_freq &&new_freq > pcpu->target_freq

now是本次采樣時間戳,pcpu->hispeed_validate_time是上次hispeed生效的時間戳,如果兩次時間間隔比above_hispeed_delay小,那么直接goto rearm,不調節頻率.

pcpu->hispeed_validate_time = now;

更新hispeed_validate_time為now

if (cpufreq_frequency_table_target(pcpu->policy, pcpu->freq_table,new_freq, CPUFREQ_RELATION_L,&index)) {spin_unlock_irqrestore(&pcpu->target_freq_lock, flags);goto rearm;}new_freq = pcpu->freq_table[index].frequency;

取freq table中大于或等于new_freq的最小頻率,返回index,再由index得到new freq,前面已經得到new freq了,這里為什么要再來一次,不是很理解.

/** Do not scale below floor_freq unless we have been at or above the* floor frequency for the minimum sample time since last validated.*/if (new_freq < pcpu->floor_freq) {if (now - pcpu->floor_validate_time <tunables->min_sample_time) {trace_cpufreq_interactive_notyet(data, cpu_load, pcpu->target_freq,pcpu->policy->cur, new_freq);spin_unlock_irqrestore(&pcpu->target_freq_lock, flags);goto rearm;}}

當new_freq < pcpu->floor_freq,并且兩次floor_validate_time的間隔小于min_sample_time,此時不需要更新頻率.網上有大神說,“在最小抽樣周期間隔內,CPU的頻率是不會變化的.”

/** Update the timestamp for checking whether speed has been held at* or above the selected frequency for a minimum of min_sample_time,* if not boosted to hispeed_freq. If boosted to hispeed_freq then we* allow the speed to drop as soon as the boostpulse duration expires* (or the indefinite boost is turned off).*/if (!tunables->boosted || new_freq > tunables->hispeed_freq) {pcpu->floor_freq = new_freq;pcpu->floor_validate_time = now;}

做一些更新數據的工作

if (pcpu->target_freq == new_freq &&pcpu->target_freq <= pcpu->policy->cur) {trace_cpufreq_interactive_already(data, cpu_load, pcpu->target_freq,pcpu->policy->cur, new_freq);spin_unlock_irqrestore(&pcpu->target_freq_lock, flags);goto rearm_if_notmax;} rearm_if_notmax:/** Already set max speed and don't see a need to change that,* wait until next idle to re-evaluate, don't need timer.*/if (pcpu->target_freq == pcpu->policy->max)goto exit;

如果兩次選頻頻率一樣并且上一次選頻頻率不大于當前頻率,那么進入rearm_if_notmax判斷是否pcpu->target_freq == pcpu->policy->max,如果相等,那么直接退出,不需要調頻,當前頻率已經處于max speed

pcpu->target_freq = new_freq;spin_unlock_irqrestore(&pcpu->target_freq_lock, flags);spin_lock_irqsave(&speedchange_cpumask_lock, flags);cpumask_set_cpu(data, &speedchange_cpumask);spin_unlock_irqrestore(&speedchange_cpumask_lock, flags);wake_up_process(speedchange_task);

將new_freq賦值給target_freq,更新目標頻率的數值.
設置需要調節頻率的CPUcore的cpumask
喚醒speedchange_task線程,改變CPU頻率
speedchange_task被定義在

/* realtime thread handles frequency scaling */ static struct task_struct *speedchange_task;

對應的線程是

speedchange_task =kthread_create(cpufreq_interactive_speedchange_task, NULL,"cfinteractive");
static int cpufreq_interactive_speedchange_task(void *data) {unsigned int cpu;cpumask_t tmp_mask;unsigned long flags;struct cpufreq_interactive_cpuinfo *pcpu;while (1) {set_current_state(TASK_INTERRUPTIBLE);spin_lock_irqsave(&speedchange_cpumask_lock, flags);if (cpumask_empty(&speedchange_cpumask)) {spin_unlock_irqrestore(&speedchange_cpumask_lock,flags);schedule();if (kthread_should_stop())break;spin_lock_irqsave(&speedchange_cpumask_lock, flags);}set_current_state(TASK_RUNNING);tmp_mask = speedchange_cpumask;cpumask_clear(&speedchange_cpumask);spin_unlock_irqrestore(&speedchange_cpumask_lock, flags);for_each_cpu(cpu, &tmp_mask) {unsigned int j;unsigned int max_freq = 0;pcpu = &per_cpu(cpuinfo, cpu);if (!down_read_trylock(&pcpu->enable_sem))continue;if (!pcpu->governor_enabled) {up_read(&pcpu->enable_sem);continue;}for_each_cpu(j, pcpu->policy->cpus) {struct cpufreq_interactive_cpuinfo *pjcpu =&per_cpu(cpuinfo, j);if (pjcpu->target_freq > max_freq)max_freq = pjcpu->target_freq;}if (max_freq != pcpu->policy->cur)__cpufreq_driver_target(pcpu->policy,max_freq,CPUFREQ_RELATION_H);trace_cpufreq_interactive_setspeed(cpu,pcpu->target_freq,pcpu->policy->cur);up_read(&pcpu->enable_sem);}}return 0; }

這個函數比較簡單,在一個while循環中,遍歷speedchange_cpumask相關的CPU,然后再次遍歷所有online CPU,得到最大的target_freq,將target_freq賦值給max_freq,即我們需要設置的CPU頻率.
若max_freq != pcpu->policy->cur,說明當前頻率不等于我們需要設置的頻率,調用__cpufreq_driver_target完成頻率設置.
__cpufreq_driver_target會調用對應的callback完成頻率設置,具體和cpufreq driver相關,需要driver工程師根據自己的平臺實現.

回顧一下之前的工作,我們分析了interactive governor的創建,初始化
如果CPUFREQ core想要啟用interactive governor,就要調用interactive governor提供的interface——.governor
在這個callback中,分析了governor在policy方面的初始化,start一個governor,然后調頻的工作就交給了定時器(定時器在start governor的時候被啟動).
在定時器中,計算cpu_load,然后根據cpu_load來選頻,然后更新pcpu的一些數據,選頻得到的頻率交由CPUFREQ driver來設置到硬件中去.


接下去一個是:CPUFREQ_GOV_STOP

case CPUFREQ_GOV_STOP:mutex_lock(&gov_lock);for_each_cpu(j, policy->cpus) {pcpu = &per_cpu(cpuinfo, j);down_write(&pcpu->enable_sem);pcpu->governor_enabled = 0;del_timer_sync(&pcpu->cpu_timer);del_timer_sync(&pcpu->cpu_slack_timer);up_write(&pcpu->enable_sem);}mutex_unlock(&gov_lock);break;

遍歷所有online的cpu:
獲取cpuinfo
設置pcpu->governor_enabled為0
刪除兩個定時器


下一個是:CPUFREQ_GOV_LIMITS

case CPUFREQ_GOV_LIMITS:if (policy->max < policy->cur)__cpufreq_driver_target(policy,policy->max, CPUFREQ_RELATION_H);else if (policy->min > policy->cur)__cpufreq_driver_target(policy,policy->min, CPUFREQ_RELATION_L);for_each_cpu(j, policy->cpus) {pcpu = &per_cpu(cpuinfo, j);down_read(&pcpu->enable_sem);if (pcpu->governor_enabled == 0) {up_read(&pcpu->enable_sem);continue;}spin_lock_irqsave(&pcpu->target_freq_lock, flags);if (policy->max < pcpu->target_freq)pcpu->target_freq = policy->max;else if (policy->min > pcpu->target_freq)pcpu->target_freq = policy->min;spin_unlock_irqrestore(&pcpu->target_freq_lock, flags);up_read(&pcpu->enable_sem);/* Reschedule timer only if policy->max is raised.* Delete the timers, else the timer callback may* return without re-arm the timer when failed* acquire the semaphore. This race may cause timer* stopped unexpectedly.*/if (policy->max > pcpu->max_freq) {down_write(&pcpu->enable_sem);del_timer_sync(&pcpu->cpu_timer);del_timer_sync(&pcpu->cpu_slack_timer);cpufreq_interactive_timer_start(tunables, j);up_write(&pcpu->enable_sem);}pcpu->max_freq = policy->max;}break;

這個我沒怎么看,應該是做一些限制,

該event被調用的場景是:change or update limits.
當policy的max或min被改變時,會調用cpufreq_update_policy—>cpufreq_set_policy—>__cpufreq_governor,在__cpufreq_governor中policy->governor->governor調用governor的governor callback
然后進入CPUFREQ_GOV_LIMITS
此時傳入cpufreq_governor_interactive的policy指針已經是min或max被改變后的新policy了
對于新policy的處理如下:
改變當前頻率,使其符合新policy的范圍
遍歷所有online CPU:
判斷pcpu->target_freq的值,確保其在新policy的范圍內
如果之前的policy->max,即pcpu->max_freq小于新的policy->max,那么刪除兩個定時器鏈表
調用cpufreq_interactive_timer_start,重新add定時器
將pcpu->max_freq的值更新為新policy的最大值
?

總結

以上是生活随笔為你收集整理的CPU中的DVFS的全部內容,希望文章能夠幫你解決所遇到的問題。

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

91麻豆精品国产91久久久使用方法 | 91av在线电影| 午夜精品三区 | 亚洲激情视频 | 久久网站av | 久草电影网 | 日韩av伦理片 | 久久av影视| 国产黄色播放 | 狠狠狠色丁香婷婷综合激情 | 久久久久久黄色 | 伊人狠狠色 | 中国精品一区二区 | 夜夜夜夜爽 | 久亚洲精品 | 日韩精品一区在线观看 | 丁香av| 97爱| 免费在线激情电影 | 国产精品99久久久 | 免费在线观看一区 | 69视频永久免费观看 | 天天天天天天天天操 | 五月婷婷综合色拍 | 久久久久久久久久久国产精品 | 在线性视频日韩欧美 | 久久91久久久久麻豆精品 | 成人91在线观看 | www.香蕉视频 | 久久亚洲福利视频 | av在线网站观看 | 国语麻豆 | 91精品视频一区 | 国产成人精品亚洲a | 视频在线精品 | 在线视频日韩欧美 | 久久午夜免费视频 | 久久不见久久见免费影院 | 国产一区二区在线精品 | 又爽又黄又刺激的视频 | 国产精品人人做人人爽人人添 | 国产精品毛片一区视频播 | 天天拍天天干 | 成人教育av | 亚洲激情网站免费观看 | 欧美精品亚洲精品日韩精品 | 日韩欧美一区二区三区免费观看 | 日韩系列在线观看 | 最近日韩免费视频 | 成人在线播放视频 | 国产成人亚洲精品自产在线 | 热99久久精品 | 97视频在线看| 伊色综合久久之综合久久 | 久久 亚洲视频 | 亚洲精品乱码久久久久久 | 精品亚洲一区二区三区 | 探花视频免费观看高清视频 | 国产剧情亚洲 | 婷婷丁香综合 | 午夜精品一区二区三区在线播放 | .国产精品成人自产拍在线观看6 | 亚洲精品视频免费 | 一区二区三区免费网站 | 国产日韩欧美中文 | 毛片美女网站 | 国产一级特黄毛片在线毛片 | 在线观看免费一区 | 在线视频成人 | 91精品国产91久久久久久三级 | 人人爽人人澡人人添人人人人 | 天天操狠狠干 | 午夜三级影院 | 亚洲视频2 | 二区三区av | 免费观看成人网 | 天天射天天拍 | 伊人色播| www久久精品 | 久久成人毛片 | 久久综合免费视频影院 | 日韩网站在线播放 | 国产乱对白刺激视频在线观看女王 | 国产精品入口麻豆www | 日日操日日插 | 成人免费视频免费观看 | 国产精品久久久久久久久久免费看 | 天天操天天色天天 | 中文字幕av日韩 | 免费在线观看一级片 | 欧美一进一出抽搐大尺度视频 | 日韩大片在线看 | 久久国产手机看片 | 97在线视频免费看 | 国产精久久久久久久 | 视频一区二区视频 | 91成人蝌蚪| 粉嫩av一区二区三区四区五区 | 亚洲国产精品一区二区尤物区 | 亚洲天天综合网 | 欧美久久99 | 欧美日韩有码 | 最近中文国产在线视频 | 97在线影视| 久久久久久看片 | 欧美做受高潮 | 国产成人福利在线 | 国产在线更新 | 一区二区三区免费在线播放 | 久久av免费 | 亚洲免费不卡 | 亚洲在线不卡 | 国产99在线免费 | 视频在线观看亚洲 | 五月开心婷婷网 | 日本 在线 视频 中文 有码 | 欧美日韩在线免费观看视频 | 国产精品美女久久久久久网站 | 久久国产精品免费 | 日韩精品中文字幕在线观看 | 色婷婷av在线| 超碰97国产在线 | 在线亚洲观看 | 182午夜在线观看 | 青春草视频在线播放 | 国产亚洲精品xxoo | 国产精品对白一区二区三区 | 精品视频免费在线 | 黄色片免费看 | 99爱视频在线观看 | 亚洲午夜久久久影院 | 狠狠躁天天躁 | 久久综合久久综合这里只有精品 | 91精品国产成人 | 超碰国产在线观看 | 日韩专区视频 | 日本黄色免费在线 | 中文字幕首页 | 国产精品美女视频网站 | 久久艹艹 | 免费观看性生活大片3 | 成人在线观看av | 草久视频在线观看 | 探花视频免费观看 | 国产高清在线免费 | 夜夜夜夜爽 | 精壮的侍卫呻吟h | 久久久久女人精品毛片九一 | 国产精品一区二区三区电影 | 久久草在线免费 | 狠狠干2018 | 婷婷丁香在线视频 | 69国产精品成人在线播放 | 国产麻豆视频在线观看 | 91免费高清在线观看 | 精品国产aⅴ麻豆 | 91av色| 久久久久久久久久久免费视频 | 欧美99热 | 一区视频在线 | 777视频在线观看 | 国产精品资源网 | av资源在线看 | 欧美 日韩精品 | 精品黄色片| 91在线看免费 | 51久久夜色精品国产麻豆 | 久久久久久国产精品亚洲78 | 亚洲永久av | 亚洲黑丝少妇 | 免费视频99 | 亚洲桃花综合 | 精品国产欧美 | 免费看的黄色小视频 | 日韩一区二区三区不卡 | 国产一区二区久久 | 日韩资源在线 | 岛国大片免费视频 | 808电影| 日日干日日 | 亚洲精品毛片一级91精品 | h动漫中文字幕 | 国产视频丨精品|在线观看 国产精品久久久久久久久久久久午夜 | 夜夜高潮夜夜爽国产伦精品 | 久久久影视 | 99视频在线| 久久99国产综合精品 | 在线中文字幕网站 | 色爱区综合激月婷婷 | 国产成人精品亚洲 | 欧美高清视频不卡网 | 久久五月天综合 | 一区二区三区精品久久久 | 黄色h在线观看 | 国产视频99 | 福利视频 | 麻豆视频国产在线观看 | 亚洲精品福利在线 | 高清在线观看av | 免费看搞黄视频网站 | 精品久久久久一区二区国产 | 69精品久久 | 97碰在线 | 夜夜天天干 | 日韩高清不卡一区二区三区 | 婷婷久久网 | 免费午夜网站 | 狠狠操影视 | 欧美亚洲成人免费 | 国产青草视频在线观看 | 亚洲天堂网在线观看视频 | 国内精品视频在线 | 91最新地址永久入口 | 亚洲va天堂va欧美ⅴa在线 | 香蕉久草 | 久久综合中文字幕 | 一区二区精品视频 | 992tv在线成人免费观看 | 超碰人人av| 草久久av | 精品国产一区二区三区久久久久久 | 91在线观看欧美日韩 | 色激情五月 | 亚洲一级片免费观看 | 最近高清中文在线字幕在线观看 | 91自拍视频在线 | 国产亚洲人成网站在线观看 | 久久免费看视频 | 青春草免费在线视频 | 爱爱av网站 | 中文字幕一区二区三区在线播放 | 综合久久精品 | 精品国产精品一区二区夜夜嗨 | 国产精品成人久久久久久久 | 久久国产视屏 | 亚洲精品美女久久久久 | 97视频精品| 久久久片 | 国产高清在线免费 | 国产成人99av超碰超爽 | 亚洲a成人v | 国产在线高清精品 | 狠狠色噜噜狠狠狠合久 | 91精品视频网站 | 日韩精品一区二区三区免费观看视频 | 免费色网 | 青青草国产在线 | 国产黄大片在线观看 | 日本久久久久久久久 | 日韩精品一区二区三区外面 | 久久久伦理 | 久久在线一区 | 美女福利视频在线 | 一区二区三区精品在线视频 | 在线观看中文字幕一区二区 | 久久免费在线视频 | 99理论片| 天天综合网久久 | 摸bbb搡bbb搡bbbb | 国产精品96久久久久久吹潮 | www.天天干.com | 亚洲精品久久久久999中文字幕 | 国产精品手机在线观看 | 久久精品屋 | 国产尤物一区二区三区 | 超碰官网 | 亚洲a成人v | 国产成人精品三级 | 中文字幕中文字幕在线一区 | 日韩免费在线网站 | 国产精品欧美日韩 | 日韩一二区在线观看 | 一区二区三区日韩在线观看 | 超碰在线最新网址 | 亚洲资源视频 | 色操插| 五月婷婷久久综合 | 色.www| 久久久午夜精品福利内容 | www.天天成人国产电影 | 久草国产在线观看 | 久久少妇免费视频 | 欧美日一级片 | 欧洲一区二区在线观看 | 中文字幕免费在线看 | 日韩视频欧美视频 | 色搞搞| 久草在线在线精品观看 | 成人av电影网址 | 欧美一级欧美一级 | 美女视频是黄的免费观看 | 亚洲 欧洲 国产 精品 | 在线看污网站 | 美女视频a美女大全免费下载蜜臀 | 一区二区三区在线观看免费视频 | 久久精品久久精品久久39 | 99精品国产高清在线观看 | 国产精品久久久久久久久久东京 | 激情av五月婷婷 | 中文字幕一区二区三区乱码不卡 | 久草新在线| 九九九在线观看 | 97国产小视频 | 狠狠操狠狠干天天操 | 99精品视频精品精品视频 | 黄色免费在线视频 | 91成人精品一区在线播放69 | 免费在线黄| a在线观看国产 | 中文字幕日韩有码 | 色夜视频 | 欧美一级片免费观看 | 在线观看日本高清mv视频 | 国产精品一区二区62 | 亚洲国产中文字幕在线观看 | 久久久片 | 91伊人久久大香线蕉蜜芽人口 | 日韩免费播放 | 日韩中文字幕免费在线观看 | 亚洲国产高清视频 | 亚洲欧美少妇 | 久久婷婷影视 | 亚洲欧洲av在线 | 国产亚洲精品久久久久久久久久久久 | 中文字幕 国产视频 | 国产 日韩 在线 亚洲 字幕 中文 | 精品毛片一区二区免费看 | 黄色片免费看 | 免费高清在线视频一区· | 久久老司机精品视频 | 久久精品国产免费看久久精品 | 91mv.cool在线观看| 九九99| 亚洲精品xx | 看污网站 | 欧美日本在线观看视频 | 日韩中文字幕免费在线观看 | 国产精品扒开做爽爽的视频 | 91人人干| 91桃花视频| 久久视频国产精品免费视频在线 | 国产亚洲片 | 亚州精品在线视频 | 亚洲精品白浆高清久久久久久 | 91av在线精品| 久草免费电影 | 久久高清片 | 欧美一二区视频 | 国产精品久久久精品 | 精品a视频| 四虎天堂 | 久久狠狠婷婷 | 天天舔天天射天天操 | 日韩色综合网 | 正在播放国产一区二区 | 欧美a免费 | 在线观看中文字幕一区 | 五月婷婷六月丁香激情 | 成人观看 | 成人精品99| 国内外激情视频 | 亚洲国产精品99久久久久久久久 | 亚洲一区黄色 | 久久精品xxx | 日韩久久精品一区二区三区 | a在线一区 | 2022国产精品视频 | 天天五月天色 | 日韩中文字幕免费视频 | 色婷婷国产精品一区在线观看 | 在线电影播放 | 久久免费视频一区 | 一区二区三区在线免费观看视频 | 日本乱码在线 | 在线免费黄网站 | 久久99精品久久久久蜜臀 | 成人免费共享视频 | 欧美激情精品久久久久久变态 | 叶爱av在线 | 久久精品精品电影网 | 中文视频一区二区 | 人人澡人人爽 | 免费在线国产黄色 | 综合久久久久久久 | 久久免费电影 | 亚洲天堂精品视频 | 少妇自拍av | 色悠悠久久综合 | 国产亚洲精品成人 | 天天操天天射天天舔 | 国产成人久久久77777 | 人人爽人人做 | 超碰久热| 成人在线免费看视频 | 亚洲精品视频免费在线 | 天天色棕合合合合合合 | 久久精精品视频 | 亚洲精品视频免费看 | 不卡的av电影 | 久久黄色网页 | 人人舔人人爱 | 免费看黄电影 | 激情五月激情综合网 | 国产成人综合图片 | 婷婷中文在线 | 国产手机在线精品 | 久久小视频 | 国产精品一区二区三区在线 | 国产精品资源在线观看 | 中文乱码视频在线观看 | 亚洲人成免费 | 精品在线观看一区二区 | 日韩免费视频在线观看 | 成人污视频在线观看 | 99精品视频免费看 | 日韩午夜视频在线观看 | 欧美成人h版在线观看 | 一区二区 精品 | 亚洲综合国产精品 | 欧洲亚洲激情 | 国产精品成人一区 | 久久久久久久久久久国产精品 | 看片一区二区三区 | 日日弄天天弄美女bbbb | 久久男人免费视频 | 欧美日韩免费观看一区二区三区 | 亚洲伦理一区 | 国产一级片免费播放 | 国产精品国产自产拍高清av | 日韩精品欧美专区 | 日本深夜福利视频 | 日韩网站在线播放 | 激情五月婷婷综合 | 亚洲电影久久久 | 日韩高清黄色 | 精品久久久久久久久久久久久久久久久久 | 一区二区三区四区在线 | 天天操夜夜想 | 国产在线一区二区 | 中文在线字幕免费观看 | 成人一级电影在线观看 | 最近中文字幕mv | 婷婷激情五月 | 中文字幕在线观看第一区 | 天天想夜夜操 | 黄色av电影网 | 特级免费毛片 | www.夜夜操.com | 91在线一区 | 天天草视频 | 中文字幕资源网 国产 | 天天狠狠操 | 色中色亚洲 | 亚洲aⅴ乱码精品成人区 | 九九久久成人 | 久久情爱| 久久老司机精品视频 | 黄色免费观看网址 | 欧美日韩高清一区二区三区 | 91在线免费播放 | 国产午夜三级一二三区 | 亚洲国产日韩在线 | 色综合天天狠天天透天天伊人 | 中文字幕亚洲欧美日韩 | 国产免费一区二区三区最新6 | 狠狠干中文字幕 | 亚洲成人午夜在线 | 日韩在线观看一区二区 | 91亚洲网| 国产精品一区二区三区在线 | 日韩精品一区二区三区在线播放 | 国产精品电影在线 | 国产一区在线观看免费 | 日韩二区在线 | 在线观看av国产 | 日韩激情视频在线观看 | 黄色一区二区在线观看 | 97人人射 | 亚洲免费观看视频 | 欧美综合国产 | 在线精品观看国产 | 国产一级大片在线观看 | www.午夜色.com | 国产精品久久久久影视 | 久久综合干| 午夜久久精品 | 亚洲涩涩涩 | 国产成人精品久久久 | 日韩av中文 | 午夜视频在线观看一区二区 | 欧美午夜久久久 | 免费看一级黄色 | 波多野结衣视频一区二区 | 在线观看国产v片 | 亚洲国产精品成人精品 | 99精品乱码国产在线观看 | 99亚洲视频 | 91成年人网站 | 欧美成年网站 | www.天天色.com | 欧美大香线蕉线伊人久久 | 亚洲综合激情 | 国产成人一区二区三区影院在线 | 国产精品原创视频 | 免费福利影院 | 国产理论一区二区三区 | 免费观看成人av | 国产免费二区 | 一区二区丝袜 | 成人三级av | 日韩久久午夜一级啪啪 | 福利在线看片 | 国产精品一区二区白浆 | av黄色亚洲| 在线国产精品一区 | 国产精品久久久久久久久婷婷 | 91av视频在线播放 | 天天想夜夜操 | 国产美女视频网站 | 久久99精品一区二区三区三区 | 日韩av免费在线电影 | 超碰在线94 | 片网站| 天天骚夜夜操 | 99中文字幕| 国产中文字幕在线免费观看 | 这里只有精品视频在线观看 | av福利在线导航 | 日韩中文字幕在线观看 | 五月天综合色 | 国产一区二区免费看 | 国产精品乱码高清在线看 | wwwav视频| 中文字幕二区在线观看 | 国产精品久久 | 欧美精品一区二区蜜臀亚洲 | 免费观看一级一片 | 免费观看性生交 | 日韩动态视频 | 精品a在线 | 国产亚洲免费观看 | 欧美a影视 | 97国产一区 | 欧美日韩国产网站 | 青青草国产免费 | 99视频播放| 国产成人精品日本亚洲999 | 亚洲aⅴ在线| 国内精品久久久久久中文字幕 | 91爱爱视频 | 激情av一区二区 | 天天操夜夜摸 | 久草在线免| 天天综合网久久综合网 | 免费黄色一区 | 久久视频在线观看中文字幕 | 久久av网址 | 国产在线自 | 中文字幕电影高清在线观看 | 色婷婷丁香 | 色.com| 久久精品免费播放 | 中文字幕在线视频精品 | 久久夜夜夜| 久草在线欧美 | 国产大片免费久久 | 中文字幕免费高清在线观看 | 四虎在线影视 | 国产精品久久久久久久久久久久午夜 | 在线你懂的视频 | 中文字幕在线免费观看 | 久久综合给合久久狠狠色 | 久久好看 | 99视频在线免费 | 日韩亚洲在线 | 亚洲国产人午在线一二区 | 九九热久久免费视频 | 久青草影院| 欧美一级性生活片 | 亚洲欧美日本国产 | 天天弄天天操 | 在线国产中文字幕 | 91xav| 99热日本 | 丁香六月综合网 | 国产婷婷精品 | 久久电影国产免费久久电影 | 97**国产露脸精品国产 | 久草在线视频首页 | 九九久久久 | 国产精品久久久久av免费 | 人人舔人人舔 | 在线欧美a | 91精品导航| 精品亚洲午夜久久久久91 | 成人久久18免费网站麻豆 | 久久日韩精品 | 成人av电影免费 | 中文在线中文a | 激情五月婷婷综合网 | 国产日韩视频在线播放 | 91超碰在线播放 | 在线免费观看国产黄色 | 91亚色视频在线观看 | 97超碰在线资源 | 日日夜夜狠狠干 | 久久国产女人 | 久久久久久中文字幕 | 欧美日韩一区二区在线 | 国产激情小视频在线观看 | 玖玖在线免费视频 | 在线精品一区二区 | 欧美大码xxxx | 成人午夜性影院 | 欧美日韩性 | 精品国产1区2区 | 91久久国产露脸精品国产闺蜜 | 一区二区三区视频 | www.国产精品 | 狠狠躁夜夜躁人人爽视频 | 婷婷丁香视频 | 最近久乱中文字幕 | 中文字幕高清有码 | 欧美国产日韩在线视频 | 亚洲乱亚洲乱亚洲 | 夜夜操天天操 | 色福利网 | 成人在线免费小视频 | 97免费在线视频 | 五月天中文在线 | 欧美日韩视频免费看 | 免费精品| 精品久久久久一区二区国产 | 欧美在一区 | 天躁狠狠躁| 一区二区三区免费在线观看视频 | 又黄又爽又无遮挡的视频 | 国产一二区精品 | 久久99影院| 亚洲不卡av一区二区三区 | 欧美一区在线观看视频 | 丁香影院在线 | 国产精品黑丝在线观看 | 2023年中文无字幕文字 | 亚洲精品一区二区三区四区高清 | 园产精品久久久久久久7电影 | 欧美日韩一区二区免费在线观看 | 99日精品 | 午夜视频99 | 亚洲成人精品在线观看 | av中文在线 | 午夜精品电影 | av在线激情 | 日韩精品综合在线 | av黄色影院 | 国产精品乱码在线 | 亚洲精品女人 | 97免费在线观看视频 | 国产成人精品午夜在线播放 | 国产视频日韩视频欧美视频 | 不卡电影免费在线播放一区 | 国内精品视频在线 | 久久久久高清 | 9久久精品 | 国产一二区免费视频 | 超碰在线观看97 | 91精品一区二区三区蜜臀 | 91传媒在线 | 一区二区三区久久 | 日本久久91 | 91视频在线 | 97视频在线观看成人 | 日韩精品国产一区 | 91漂亮少妇露脸在线播放 | 在线视频日韩一区 | 久久福利影视 | av电影免费在线播放 | 国产四虎在线 | 亚洲国产午夜精品 | 国内精品视频久久 | 天天想夜夜操 | 日韩专区中文字幕 | 日本性视频 | 日韩在线观看一区二区三区 | 国产精品久久久区三区天天噜 | 91在线超碰 | 手机av在线网站 | 性色av香蕉一区二区 | 岛国av在线免费 | 91av在线免费视频 | 99久久久成人国产精品 | 激情久久伊人 | 久久视频免费观看 | 91亚州| 国产黄色a| 亚州av免费 | 国内综合精品午夜久久资源 | 久久理论电影网 | 国产黄色资源 | 亚洲国产精品免费 | 97人人模人人爽人人喊网 | 日日夜夜精品免费 | 亚洲精品在线一区二区 | 狠狠做深爱婷婷综合一区 | 成人午夜网 | 欧美精品国产综合久久 | 美女免费电影 | 麻豆免费看片 | 成人资源在线观看 | 欧美最爽乱淫视频播放 | 69成人在线 | 久久福利剧场 | 在线电影a | 69性欧美 | 黄色毛片一级片 | 中文在线天堂资源 | 精品国产一区二区三区久久 | 中文字幕在线观看视频一区二区三区 | 伊人狠狠干 | 国产 日韩 在线 亚洲 字幕 中文 | 久久国产免费 | 91av视频导航 | 婷婷久久一区二区三区 | 中文字幕亚洲综合久久五月天色无吗'' | 亚洲男人天堂a | 91黄在线看 | 一区二区三区在线观看中文字幕 | 成人av免费在线看 | 欧美日韩视频在线一区 | 中文字幕在线观看网 | 免费福利视频导航 | 探花视频在线观看+在线播放 | 91av视频在线观看免费 | 一区二区精品在线观看 | 久久狠狠亚洲综合 | 欧美日本中文字幕 | 国语对白少妇爽91 | 天天插天天操天天干 | 一级久久精品 | 91精品在线观看入口 | 久久久久久久久艹 | 婷婷国产视频 | 91经典在线 | 91视频com| 黄色av大片| 狠狠干夜夜爽 | 午夜美女福利 | 欧美日韩一区二区三区在线免费观看 | 日韩亚洲国产精品 | 久久国产精品久久精品国产演员表 | 欧美一二三视频 | 狠狠的干狠狠的操 | 四虎影视精品成人 | 日韩在线观看一区 | 午夜视频在线瓜伦 | 狠狠躁夜夜a产精品视频 | 久久精品中文视频 | av黄色免费网站 | 婷色在线 | 国产主播大尺度精品福利免费 | 国产在线欧美日韩 | 亚洲自拍偷拍色图 | 在线观看国产永久免费视频 | 91大神电影| 国产一线二线三线性视频 | 天天天天爱天天躁 | 一本一道波多野毛片中文在线 | 五月天国产 | 色婷婷久久久综合中文字幕 | 四虎免费在线观看 | 天天干.com| 欧美日韩国产在线精品 | 中文字幕免费观看视频 | 天天天天天天操 | 国产一区在线免费 | 亚洲 精品在线视频 | 欧美日韩免费在线观看视频 | 免费观看性生交 | 免费av视屏 | 极品美女被弄高潮视频网站 | 欧美在线日韩在线 | 欧美日韩一区二区三区免费视频 | 色婷婷av国产精品 | 日韩h在线观看 | 精品久久国产精品 | 一二三区高清 | 成片免费观看视频 | 香蕉色综合 | 激情久久久久久久久久久久久久久久 | 久久精品视频4 | a天堂一码二码专区 | 狠狠躁夜夜躁人人爽超碰97香蕉 | 992tv又爽又黄的免费视频 | 又色又爽又黄高潮的免费视频 | 中文字幕一区二区三区四区在线视频 | 色综合中文综合网 | 一区二区三区 亚洲 | 午夜国产一区二区三区四区 | 一区二区精品视频 | 国产亚洲精品成人av久久ww | 亚洲一级电影视频 | 特级毛片网 | 国产超碰在线 | 免费麻豆网站 | 日本一区二区三区视频在线播放 | 在线观看av免费 | 国产精选在线观看 | 欧美大荫蒂xxx | 91久久黄色 | 韩国av免费 | 日韩二区在线观看 | 69av网| 丁香六月五月婷婷 | 美女视频黄在线 | 99久久精品免费看国产 | 国产分类视频 | av成人在线电影 | 超级碰碰免费视频 | 欧美一级专区免费大片 | 日韩欧美高清 | 亚洲视频 一区 | 成人毛片在线视频 | 国产99爱 | 国产高清一区二区 | 久久久久久高潮国产精品视 | 国产黄色精品视频 | 色网站视频 | 欧美天堂视频在线 | 久久久久久久免费看 | 国产h在线播放 | a v在线观看 | 久久久久久久久久久精 | 国内精品视频在线播放 | 亚洲日韩中文字幕 | 国产亚洲综合在线 | 日韩一级片观看 | 国产视频中文字幕在线观看 | 91精品在线观看视频 | 一本一本久久a久久精品牛牛影视 | 国偷自产中文字幕亚洲手机在线 | 四虎在线免费观看视频 | 成人禁用看黄a在线 | 99中文在线| 天堂va欧美va亚洲va老司机 | 一区二区三区精品在线视频 | 国产成人61精品免费看片 | 91福利免费 | 天天操福利视频 | 1000部国产精品成人观看 | 黄色日本片 | 欧美一二区视频 | 中文字幕在线观看日本 | 午夜精品久久久99热福利 | 久久精品99国产精品酒店日本 | 中文字幕色站 | 91成人网在线 | 色综合久久久久综合99 | 日本婷婷色| 亚洲国产字幕 | 日本精品va在线观看 | 日韩最新中文字幕 | 亚洲资源网 | 97国产在线视频 | 欧美性色黄 | 精品成人a区在线观看 | 天天插综合 | 色狠狠综合天天综合综合 | 首页国产精品 | 911久久 | 久久成人国产精品免费软件 | 色综合夜色一区 | 91精品啪在线观看国产81旧版 | 日韩大片在线免费观看 | 99久久精品一区二区成人 | a级成人毛片 | 波多野结衣视频一区二区 | 999视频在线播放 | 久久色在线观看 | 欧美日韩一区二区三区不卡 | 精品一二区 | 91精品秘密在线观看 | 一本一本久久a久久精品综合妖精 | 特级片免费看 | 中文字幕免费国产精品 | 久久免费黄色网址 | 国产97在线视频 | 亚洲视频免费视频 | 日韩精品一区二区三区第95 | 国产高清99| 久亚洲精品 | 久久综合久久久久88 | 国产精品九九九九九九 | 中文字幕在线观看视频一区二区三区 | 亚洲日本欧美在线 | 五月激情丁香婷婷 | 精品中文字幕在线 | 亚洲精品久久久久久久不卡四虎 | 国产精品美女视频 | 久一在线 | 麻花豆传媒一二三产区 | 狠狠躁天天躁综合网 | 国产精品观看视频 | 黄av免费| 亚洲美女精品视频 | 黄色福利网站 | 亚洲毛片一区二区三区 | 欧美尹人 | 麻豆激情电影 | 日日夜夜噜噜噜 | 成人网看片 | 看片网站黄 | 天天干天天色2020 | 久久国产经典视频 | 婷婷国产v亚洲v欧美久久 | 黄在线免费观看 | 中文字幕首页 | 国产日韩精品一区二区 | 狠狠色丁香久久婷婷综合_中 | 亚洲激情视频在线观看 | 操处女逼| 91精品久久久久久综合乱菊 | 日韩在线视频一区二区三区 | 色婷婷综合久久久久 | 亚州av成人 | 婷婷亚洲综合五月天小说 | 亚洲欧美少妇 | 国产97在线观看 | 精品综合久久久 | 亚洲成人在线免费 | 一级黄色电影网站 | 亚洲国产合集 | 激情综合色播五月 | 一区二区三区观看 | 九九九免费视频 | 黄色大全视频 | 黄色片网站av | 日韩一级电影在线 | 在线看岛国av | 福利视频第一页 | 西西444www| 亚洲情影院 | 亚洲国产片 | 日日干网址| 久久免费高清视频 | 久久久久久久久久久综合 | 九九九九免费视频 | 国产精品精品国产色婷婷 | av中文在线影视 | 色综合网在线 | 久久久久国产成人免费精品免费 | 国产精品一码二码三码在线 | 日韩av在线高清 | 伊人婷婷激情 | 国产一线天在线观看 | 国产黑丝袜在线 | 国产精品www| 99精品国产高清在线观看 | www.夜夜爽 | 69国产盗摄一区二区三区五区 | 园产精品久久久久久久7电影 | 久av在线 | 久久国产亚洲 | 精品一二三区视频 | 欧美激情视频一二三区 | 亚洲性少妇性猛交wwww乱大交 | 国产偷在线 | zzijzzij亚洲成熟少妇 | 美女性爽视频国产免费app | 免费成人av | 精品久久久影院 | 69精品视频在线观看 | 蜜桃视频在线观看一区 | 日韩av免费一区二区 | 成人在线超碰 | 精品久久免费看 | 久久久久久久久久久网 | 久久久免费电影 | 91九色在线 | 亚洲码国产日韩欧美高潮在线播放 | 一区中文字幕电影 | 又黄又刺激又爽的视频 | 最近2019年日本中文免费字幕 | 狠狠操狠狠插 | 成人欧美亚洲 | 丁香影院在线 | 91麻豆国产福利在线观看 | 在线视频手机国产 | 国产麻豆传媒 | 韩国中文三级 | 九九在线国产视频 | 亚洲一区网站 | 久久久久久久久久久久电影 | 亚洲在线a | 国产精品福利一区 | 特黄特色特刺激视频免费播放 | 国产美女免费观看 | 国产精品99久久久久久久久 | 色多视频在线观看 |