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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Libvirt CPU Feature

發(fā)布時(shí)間:2023/12/20 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Libvirt CPU Feature 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • 硬件基礎(chǔ)
    • vendor
    • signature
    • feature
  • 數(shù)據(jù)結(jié)構(gòu)
    • 物理抽象
      • virCPUx86CPUID
      • virCPUx86DataItem
      • virCPUx86Data
    • 配置信息
      • virCPUx86Vendor
      • virCPUx86Feature
      • virCPUx86Model
      • virCPUx86Map
    • 概念抽象
      • virCPUFeatureDef
      • virCPUDef
  • 工具函數(shù)
    • 數(shù)據(jù)加載
      • virCPUx86LoadMap
    • 基本操作
      • virCPUx86DataItemCmp
      • virCPUx86DataNext
      • virCPUx86DataGet
      • virCPUx86DataItemAndBits
      • virCPUx86DataItemClearBits
    • 集合操作
      • x86DataAdd
      • x86DataSubtract
      • x86DataIntersect
    • 信息提取
      • x86DataToCPUFeatures
      • x86DataToVendor
  • virsh 工具
    • capabilities
    • cpu-baseline
    • cpu-compare

硬件基礎(chǔ)

  • 虛擬機(jī)的遷移需要保證兩端的主機(jī)能夠暴露給虛機(jī)的cpu feature相同,如果不相同無法保證遷移后虛機(jī)能夠正常運(yùn)行,因此遷移前會(huì)判斷兩端虛機(jī)特性,不同會(huì)報(bào)錯(cuò),終止遷移。為了讓資源池中新加入一臺(tái)服務(wù)器并能夠順利將虛機(jī)遷移過去,需要計(jì)算源和目的兩端服務(wù)器的cpu feature交集,然后暴露給虛機(jī),保證遷移順利,這是虛擬化組件需要解決的事情。本節(jié)主要介紹其硬件基礎(chǔ)。
  • Intel通過cpuid指令查詢cpu的signature和feature,signature標(biāo)識(shí)著cpu的版本信息,feature包含了cpu的支持的硬件特性,比如虛擬化相關(guān)的vmx(Virtual Machine Extensions)特性,內(nèi)存管理相關(guān)的pae(Physical Address Extension)特性,或者M(jìn)SR(Model Specific Registers)等。通過cpuid指令可以查到兩類信息,一類是cpu基本(Basic)信息,一類是cpu擴(kuò)展(Extended)信息。
  • cpuid指令雖然沒有操作數(shù),但它的輸出較其它有操作數(shù)的指令更為復(fù)雜,它將寄存器(EAX,ECX)作為輸入,將寄存器(EAX,EBX,ECX,EDX)作為輸出。輸入的不同,執(zhí)行cpuid指令得到的輸出信息不同。比如,在EAX=0,ECX=0的情況下,如果執(zhí)行cpuid指令,得到的是cpu的vendor信息和輸入EAX的最大值;在EAX=1,ECX=0的情況下,如果執(zhí)行cpuid指令,得到的是cpu的signature和feature。CPU feature相關(guān)的cpuid指令就是上面這兩個(gè),下面具體介紹它們的輸出格式,以及如何獲取vendor、signature和feature信息。

vendor

  • 當(dāng)EAX被設(shè)置成0,作為輸入時(shí),執(zhí)行cpuid指令,它的輸出分別是EAX,保存EAX作為輸入的最大值和vendor信息。Intel手冊(cè)中關(guān)于vendor信息的獲取說明如下:
  • 假設(shè)最大輸入值為Maximum,那么EAX作為輸入的取值范圍就是[0, Maximum]。當(dāng)EAX在這區(qū)間范圍內(nèi)作為輸入時(shí),執(zhí)行cpuid指令輸出的信息為Basic類信息。vendor為廠商信息,由EBX/ECX/ECX三個(gè)寄存器共同提供。對(duì)于x86架構(gòu)有三個(gè)廠商信息,分別是:GenuineIntel(Intel)、AuthenticAMD(AMD)和HygonGenuine(Hygon)

signature

  • 當(dāng)EAX被設(shè)置成1,作為輸入時(shí),執(zhí)行cpuid指令,它的輸出寄存器中,EAX保存cpu的signature的信息。ECX和EDX報(bào)錯(cuò)cpu的feature信息,Intel手冊(cè)說明如下:
  • EAX的signature信息格式如下:

feature

  • feature信息和signature一樣,通過設(shè)置EAX為1執(zhí)行cpuid指令得到。它的信息保存在兩個(gè)寄存器ECX、EDX中,寄存器的每個(gè)bit標(biāo)識(shí)著一個(gè)cpu的特性,如果該bit被置位,表示cpu支持該特性,反之,如果該bit被清零,標(biāo)志cpu不支持該特性。
  • ECX和ECX表示的feature格式如下:

數(shù)據(jù)結(jié)構(gòu)

  • Libvirt提供了探測(cè)主機(jī)cpu feature的工具、計(jì)算指定cpu feature集合與主機(jī)cpu feature集合關(guān)系的工具,以及計(jì)算不同cpu feature交集的工具。通過這些工具,上層應(yīng)用可以計(jì)算出兩個(gè)cpu之間feature的交集,從而決定如何暴露給虛擬機(jī),順利實(shí)現(xiàn)虛機(jī)的遷移。本節(jié)主要介紹Libvirt中與cpu feature相關(guān)的數(shù)據(jù)結(jié)構(gòu)。

物理抽象

virCPUx86CPUID

  • virCPUx86CPUID用于描述執(zhí)行一條cpuid指令前后的輸入和輸出。
typedef struct _virCPUx86CPUID virCPUx86CPUID; typedef virCPUx86CPUID *virCPUx86CPUIDPtr; struct _virCPUx86CPUID {uint32_t eax_in; /* 輸入:寄存器EAX的值 */uint32_t ecx_in; /* 輸入:寄存器ECX的值 */uint32_t eax; /* 輸出:寄存器EAX的值 */uint32_t ebx; /* 同上 */uint32_t ecx;uint32_t edx; };
  • 在Libvirt中,使用嵌入式匯編調(diào)用cpuid指令,在執(zhí)行過程中用到了virCPUx86CPUID結(jié)構(gòu),如下:
cpuidCall(virCPUx86CPUID *cpuid) {asm("xor %%ebx, %%ebx;" /* clear the other registers as some cpuid */"xor %%edx, %%edx;" /* functions may use them as additional arguments */"cpuid;": "=a" (cpuid->eax), /* 將eax的值作為輸出保存到cpuid->eax中*/"=b" (cpuid->ebx), /* 原理同上 */"=c" (cpuid->ecx),"=d" (cpuid->edx): "a" (cpuid->eax_in), /* 指定寄存器eax的值從cpuid->eax_in中讀取 */"c" (cpuid->ecx_in)); /* 指定寄存器ecx的值從cpuid->ecx_in中讀取 */ }

virCPUx86DataItem

  • virCPUx86DataItem在type為VIR_CPU_X86_DATA_CPUID時(shí),保存的是一條cpuid指令輸入輸出。
typedef struct _virCPUx86DataItem virCPUx86DataItem; typedef virCPUx86DataItem *virCPUx86DataItemPtr; struct _virCPUx86DataItem {virCPUx86DataType type; /* 當(dāng)type=VIR_CPU_X86_DATA_CPUID時(shí),data的cpuid值有效 */union {virCPUx86CPUID cpuid; /* 保存一條cpuid的輸入輸出*/virCPUx86MSR msr;} data; };

virCPUx86Data

  • 對(duì)于一個(gè)cpu來說,當(dāng)使用cpuid指令查詢它的相關(guān)信息時(shí),它會(huì)有很多的輸出,每改變一次輸入的值,執(zhí)行cpuid查到的輸出值意義就不一樣,因此cpuid的輸入輸出組成的條目非常多,Libvirt通過virCPUx86Data來描述執(zhí)行cpuid的所有輸入輸出組成的數(shù)組。virCPUx86Data可以認(rèn)為保存的是cpuid指令查詢后,得到的原始數(shù)據(jù)。
typedef struct _virCPUx86Data virCPUx86Data; struct _virCPUx86Data {size_t len; /* 數(shù)組的大小,數(shù)組的每個(gè)元素表示cpuid指令的一個(gè)輸入輸出 */virCPUx86DataItem *items; /* 數(shù)組的基地址 */ };

配置信息

  • Libvirt為了管理cpu feature,將支持的所有架構(gòu)的所有feature組織成xml文件,持久化到磁盤上,同時(shí)將支持的所有model和vendor也組織成xml文件,持久化到磁盤上。在libvirt獲取host capabilities或者計(jì)算feature交集時(shí),會(huì)首先將支持的所有feature,vendor,model都加載到內(nèi)存中,用于feature集合的計(jì)算。xml所在目錄為/usr/share/libvirt/cpu_map/,下面主要介紹這些xml格式在內(nèi)存中的數(shù)據(jù)結(jié)構(gòu)。

virCPUx86Vendor

  • vendor信息可以通過cpuid指令查詢得到,virCPUx86Vendor結(jié)構(gòu)用于存放查詢vendor的cpuid指令的輸入輸出,組成的一個(gè)item。
typedef struct _virCPUx86Vendor virCPUx86Vendor; typedef virCPUx86Vendor *virCPUx86VendorPtr; struct _virCPUx86Vendor {char *name; /* 廠商名稱,對(duì)于x86架構(gòu),可能的名稱就是Intel、AMD和Hygon */virCPUx86DataItem data; /* cpuid查詢得到的條目,它的輸出EBX、ECX和EDX就是廠商名稱的accii碼值 */ };
  • Libvirt保存了支持的vendor信息到xml中,當(dāng)virsh工具需要處理vendor相關(guān)信息時(shí),Libvirt從xml中讀取支持的vendor信息,加載到內(nèi)存,對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu)就是virCPUx86Vendor。Libvirt的vendor信息保存在/usr/share/libvirt/cpu_map/x86_vendors.xml 中,如下:
<cpus><vendor name='Intel' string='GenuineIntel'/> /* 廠商名: Intel; 輸出EBX/ECX/EDX組成的字符串為'GenuineIntel' */<vendor name='AMD' string='AuthenticAMD'/><vendor name='Hygon' string='HygonGenuine'/> </cpus>

virCPUx86Feature

  • cpu的feature信息也通過cpuid指令查詢得到,virCPUx86Feature的data域存放的數(shù)組通常只有一個(gè)元素,代表一個(gè)bit對(duì)應(yīng)的feature。
typedef struct _virCPUx86Feature virCPUx86Feature; typedef virCPUx86Feature *virCPUx86FeaturePtr; struct _virCPUx86Feature {/* feature名 */char *name; /* feature對(duì)應(yīng)的寄存器值,對(duì)應(yīng)寄存器中的一個(gè)bit* 這里看上去data包含的是一個(gè)item數(shù)組* 但實(shí)際上通常情況下只有一個(gè)元素 */virCPUx86Data data; /* 如果該feature不影響遷移(可遷移)* 設(shè)置為true,反之,設(shè)置為false */bool migratable; };
  • libvirt將所有feature以一定格式組織起來,存放到/usr/share/libvirt/cpu_map/x86_features.xml中,這個(gè)xml描述了x86架構(gòu)下所有廠商的feature屬性,包括該通過什么輸入得到,輸出的feature值對(duì)應(yīng)寄存器的哪一位;該feature是否可以遷移等。每當(dāng)Libvirt需要計(jì)算feature時(shí),將這些feature加載到內(nèi)存,進(jìn)行操作。xml中一個(gè)典型的feature描述如下:
<feature name='vmx'> /* feature名字: vmx*/<cpuid eax_in='0x01' ecx='0x00000020'/> /* 獲取feature時(shí)輸入EAX的值為0x01,該feature對(duì)應(yīng)輸出ECX的第5bit */</feature>

virCPUx86Model

  • cpu的model信息通過cpuid指令查到,得到的原始數(shù)據(jù)被保存到一個(gè)virCPUx86Data數(shù)據(jù)結(jié)構(gòu)中。同時(shí),virCPUx86Model結(jié)構(gòu)中還將原數(shù)據(jù)解析出來,分別存放到vendor和signature中。
typedef struct _virCPUx86Model virCPUx86Model; typedef virCPUx86Model *virCPUx86ModelPtr; struct _virCPUx86Model {char *name; /* Model名 */virCPUx86VendorPtr vendor;size_t nsignatures;uint32_t *signatures;virCPUx86Data data; };

virCPUx86Map

typedef struct _virCPUx86Map virCPUx86Map; typedef virCPUx86Map *virCPUx86MapPtr; struct _virCPUx86Map {size_t nvendors;virCPUx86VendorPtr *vendors;size_t nfeatures;virCPUx86FeaturePtr *features;size_t nmodels;virCPUx86ModelPtr *models;size_t nblockers;virCPUx86FeaturePtr *migrate_blockers; };

概念抽象

virCPUFeatureDef

  • 使用cpuid指令查詢得到的cpu feature被保存到兩個(gè)寄存器中,寄存器的每個(gè)bit代表一個(gè)feature,Libvirt對(duì)應(yīng)地將每個(gè)feature抽象成一個(gè)virCPUFeatureDef數(shù)據(jù)結(jié)構(gòu)。結(jié)構(gòu)中的policy描述了vcpu采用該feature的策略。
typedef enum {VIR_CPU_FEATURE_FORCE, /* vcpu需要強(qiáng)行應(yīng)用該feature,無論主機(jī)是否支持此feature */VIR_CPU_FEATURE_REQUIRE, /* vcpu請(qǐng)求使用該feature,如果主機(jī)不支持或者h(yuǎn)ypervisor無法模擬,虛機(jī)在start的時(shí)候會(huì)報(bào)錯(cuò) */VIR_CPU_FEATURE_OPTIONAL, /* vcpu只有在探測(cè)到主機(jī)支持該feature時(shí),才使用該feature,因此這種策略不會(huì)虛機(jī)啟動(dòng)不會(huì)報(bào)錯(cuò) */VIR_CPU_FEATURE_DISABLE, /* vcpu被主機(jī)禁止使用該feature */VIR_CPU_FEATURE_FORBID, /* 禁止主機(jī)支持該feature。如果主機(jī)支持,虛機(jī)啟動(dòng)時(shí)報(bào)錯(cuò)*/VIR_CPU_FEATURE_LAST } virCPUFeaturePolicy; typedef struct _virCPUFeatureDef virCPUFeatureDef; typedef virCPUFeatureDef *virCPUFeatureDefPtr; struct _virCPUFeatureDef {char *name; /* feature名字,比如'vmx'、'msr'等 */int policy; /* enum virCPUFeaturePolicy */ };

virCPUDef

  • cpu的capabilities信息展示給用戶,通常包含架構(gòu)、廠商、Model、特性等等,Libvirt將這些cpu相關(guān)的信息包含在virCPUDef結(jié)構(gòu)中。
typedef struct _virCPUDef virCPUDef; typedef virCPUDef *virCPUDefPtr; struct _virCPUDef { int type; /* enum virCPUType */int mode; /* enum virCPUMode */int match; /* enum virCPUMatch */virCPUCheck check;virArch arch;char *model;char *vendor_id; /* vendor id returned by CPUID in the guest */int fallback; /* enum virCPUFallback */char *vendor; /* 廠商名 */......size_t nfeatures;size_t nfeatures_max;virCPUFeatureDefPtr features; /* CPU包含的除Model外的所有feature集合 */...... };

工具函數(shù)

數(shù)據(jù)加載

virCPUx86LoadMap

  • 該函數(shù)主要負(fù)責(zé)將/usr/share/libvirt/cpu_map目錄下的所有信息加載到內(nèi)存中,最終保存在靜態(tài)全局變量cpuMap中,virCPUx86LoadMap函數(shù)只在Libvirtd啟動(dòng)時(shí)執(zhí)行一次。一旦cpuMap被加載到內(nèi)存中,后續(xù)的所有關(guān)于cpu feature集合的計(jì)算都使用這個(gè)結(jié)構(gòu)

基本操作

virCPUx86DataItemCmp

int virCPUx86DataItemCmp(const virCPUx86DataItem *item1, const virCPUx86DataItem *item2)
  • 比較item1和item2是否相同,比較的標(biāo)準(zhǔn)是判斷查詢cpuid的輸入寄存器eax_in和ecx_in的值,如果值相等表示相同,反之則不同。

virCPUx86DataNext

virCPUx86DataItemPtr virCPUx86DataNext(virCPUx86DataIteratorPtr iterator)
  • 根據(jù)迭代器中的位置pos,取出其指向的非零item。

virCPUx86DataGet

virCPUx86DataItemPtr virCPUx86DataGet(const virCPUx86Data *data, const virCPUx86DataItem *item)
  • 根據(jù)item中的eax_in和ecx_in,查找data集合中對(duì)應(yīng)的item,取出data集合中對(duì)應(yīng)的item。

virCPUx86DataItemAndBits

void virCPUx86DataItemAndBits(virCPUx86DataItemPtr item, const virCPUx86DataItem *mask)
  • 將item中對(duì)應(yīng)的eax,ebx,ecx,edx中與mask中eac,ebx,ecx,edx進(jìn)行位與操作

virCPUx86DataItemClearBits

void virCPUx86DataItemClearBits(virCPUx86DataItemPtr item, const virCPUx86DataItem *mask)
  • 根據(jù)mask提供的掩碼位,將item中對(duì)應(yīng)的eax,ebx,ecx,edx中對(duì)應(yīng)的位請(qǐng)零

集合操作

x86DataAdd

int x86DataAdd(virCPUx86Data *data1, const virCPUx86Data *data2)
  • 函數(shù)將data2集合中的所有非空的item添加到data1集合中,所謂空item,item中的eax,ebx,ecx,edx都為0。添加有兩種情況,如果data1中已經(jīng)存在對(duì)應(yīng)的item,將data2中的item與data1中對(duì)應(yīng)的item取并集操作,否則直接將data2中的item內(nèi)容拷貝到data1集合中。該函數(shù)提供了feature集合的加操作。
static int x86DataAdd(virCPUx86Data *data1,const virCPUx86Data *data2) {virCPUx86DataIterator iter;virCPUx86DataItemPtr item;/* 初始化遍歷data2集合的迭代器* 為遍歷data2做準(zhǔn)備 */virCPUx86DataIteratorInit(&iter, data2); /* 將data2中所有非空的item取出 */ while ((item = virCPUx86DataNext(&iter))) {/* 將item添加到data1中 */if (virCPUx86DataAddItem(data1, item) < 0)return -1;}return 0; }

x86DataSubtract

void x86DataSubtract(virCPUx86Data *data1, const virCPUx86Data *data2)
  • 從data1集合中,減去data2集合中包含的所有item。該函數(shù)提供了feature集合的減操作。
static void x86DataSubtract(virCPUx86Data *data1,const virCPUx86Data *data2) {virCPUx86DataIterator iter;virCPUx86DataItemPtr item1;virCPUx86DataItemPtr item2;/* 初始化遍歷data1集合的迭代器 */virCPUx86DataIteratorInit(&iter, data1);/* 遍歷data1,依次取出它包含的item */while ((item1 = virCPUx86DataNext(&iter))) {/* 遍歷data2集合中的item,* 如果有與data1中item相等的* 將data1中的對(duì)應(yīng)item清零 */item2 = virCPUx86DataGet(data2, item1);virCPUx86DataItemClearBits(item1, item2);} }

x86DataIntersect

void x86DataIntersect(virCPUx86Data *data1, const virCPUx86Data *data2)
  • 該函數(shù)將data1集合中的item依次與data2集合中的item比較,如果data1集合中的item在data2集合中沒有,則將data1中的Item刪除掉,如果有,則將data2中的對(duì)應(yīng)item也取出來,兩個(gè)item取交集,結(jié)果存放在data1中。該函數(shù)實(shí)現(xiàn)了取集合交集的操作。
static void x86DataIntersect(virCPUx86Data *data1,const virCPUx86Data *data2) {virCPUx86DataIterator iter;virCPUx86DataItemPtr item1;virCPUx86DataItemPtr item2;/* 初始化遍歷data1集合的迭代器 */virCPUx86DataIteratorInit(&iter, data1);/* 遍歷data1,依次取出它包含的item */while ((item1 = virCPUx86DataNext(&iter))) {/* 查找data2,如果集合中有包含data1中的item將其取出 */item2 = virCPUx86DataGet(data2, item1);if (item2)/* 如果data2中有相同的item,與data1中的item進(jìn)行位與操作 */virCPUx86DataItemAndBits(item1, item2);else/* 如果data2中沒有對(duì)應(yīng)item,將data1中的item清零 */virCPUx86DataItemClearBits(item1, item1);} }

信息提取

x86DataToCPUFeatures

int x86DataToCPUFeatures(virCPUDefPtr cpu, int policy, virCPUx86Data *data, virCPUx86MapPtr map)
  • 將data集合中包含的所有屬于map的feature添加到cpu的features域中。遍歷map中包含的所有feature,檢查它的每一個(gè)item是否屬于data集合的子集,如果是,將data中對(duì)應(yīng)的item減去,同時(shí)將feature添加加入到cpu的features中。注意,加入到cpu的features中的feature在data集合中就被刪除了
/* also removes all detected features from data */ static int x86DataToCPUFeatures(virCPUDefPtr cpu,int policy,virCPUx86Data *data,virCPUx86MapPtr map) {size_t i;for (i = 0; i < map->nfeatures; i++) {/* 依次取出x86_features.xml中的所有feature */virCPUx86FeaturePtr feature = map->features[i];/* 如果取出的feature屬于data表示的集合 */if (x86DataIsSubset(data, &feature->data)) {/* 將feature從data集合中刪除 */x86DataSubtract(data, &feature->data);/* 同時(shí)將feature添加到cpu->features中 */if (virCPUDefAddFeature(cpu, feature->name, policy) < 0)return -1;}}return 0; }

x86DataToVendor

  • 返回map中與data集合中匹配的第一個(gè)vendor。從data集合取出vendor,與map中包含的所有vendor比較,如果有相同的item,首先清零data中對(duì)應(yīng)的item,同時(shí)返回map中指向的vendor。注意,在map匹配到對(duì)應(yīng)vendor后,同時(shí)會(huì)刪除data中對(duì)應(yīng)的vendor。
/* also removes bits corresponding to vendor string from data */ static virCPUx86VendorPtr x86DataToVendor(const virCPUx86Data *data,virCPUx86MapPtr map) {virCPUx86DataItemPtr item;size_t i;for (i = 0; i < map->nvendors; i++) {/* 依次取出x86_vendors.xml中所有的vendor */virCPUx86VendorPtr vendor = map->vendors[i];/* 如果data集合中包含了該vendor對(duì)應(yīng)的item(輸入值相同) */if ((item = virCPUx86DataGet(data, &vendor->data)) &&/* 同時(shí)取出的item與vendor中對(duì)應(yīng)item的輸出值也相同 */virCPUx86DataItemMatchMasked(item, &vendor->data)) {/* 將data中包含的vendor對(duì)應(yīng)的item清零 */virCPUx86DataItemClearBits(item, &vendor->data);/* 返回map中包含的vendor */return vendor;}}return NULL; }

virsh 工具

  • Libvirt提供了三個(gè)與cpu feature相關(guān)的接口,分別是:
  • virsh capabilites: 探測(cè)主機(jī)包含的cpu feature。該接口可以搜集主機(jī)支持的cpu feature集合。
  • virsh cpu-baseline: 給出多個(gè)cpu feature的集合,計(jì)算這些cpu feature集合的基線,實(shí)際上就是取給出的所有cpu feature集合的交集。該接口可以用于計(jì)算多個(gè)主機(jī)共同的的cpu feature集合,從而得到可以保證遷移成功的虛擬機(jī)cpu feature配置。
  • virsh cpu-compare: 給出一個(gè)cpu feature的集合,將它與主機(jī)的cpu feature作集合的比較,得到兩個(gè)集合的關(guān)系(超集、子集、相等或者非包含關(guān)系)。該接口可以用于判斷遠(yuǎn)端的一個(gè)host上的虛機(jī)是否可以遷移到本地。
    • 下面分別介紹三個(gè)virsh命令的內(nèi)部實(shí)現(xiàn)流程,三個(gè)virsh命令的前半段代碼路徑是類似的。

    capabilities

    • virsh capabilities命令用于顯示主機(jī)的能力,其中一項(xiàng)顯示主機(jī)cpu支持的feature集合。這個(gè)feature以model加feature的形式顯示出來,以下面的一個(gè)命令輸出為例,Model為SandyBridge的cpu本身包含了一個(gè)feature集合,這個(gè)集合可以隱式地通過/usr/share/libvirt/cpu_map/x86_SandyBridge.xml查詢得到,同時(shí)通過顯示地也指定了一個(gè)feature集合。兩個(gè)集合取并集,就是整個(gè)cpu包含的feature集合。
    <capabilities><host><cpu><!-- 主機(jī)cpu匹配到的架構(gòu) --><arch>x86_64</arch><!-- 主機(jī)cpu匹配到的Model,該Model隱式地包含一系列的feature集合 --><model>SandyBridge</model><!-- 主機(jī)cpu的生產(chǎn)廠商 --><vendor>Intel</vendor>......<!-- 顯示指定的主機(jī)包含的feature --><feature name='vme'/><feature name='ds'/><feature name='acpi'/>......</cpu>......</host>...... </capabilities>
    • capabilities流程首先通過cpuid命令查詢主機(jī)包含的所有feature,然后遍歷Libvirt在xml中預(yù)定義的所有Model,找到最匹配主機(jī)的那一個(gè)Model,最后用主機(jī)的feature集合減去Model包含的feature集合,得到需要顯示指定的feature集合或者顯示禁止的feature集合,將其增加到virCPUDef的features域中。所謂最匹配的model,就是簽名和主機(jī)cpu相同,同時(shí)包含盡可能多的feature的那個(gè)預(yù)定義model。
    1. 總體流程 cmdCapabilities......qemuConnectGetCapabilities....../* 調(diào)用x86上的driver接口搜集host相關(guān)的capabilities */cpuDriverX86.getHostvirCPUx86GetHost/* 首先通過嵌入式匯編執(zhí)行cpuid指令* 獲取主機(jī)cpu feature,之后的所有操作* 就是要在預(yù)定義的model之中找到最匹配* 該feature集合的model,將其封裝成virCPUDef* 作為結(jié)果輸出,所有通過cpuid查詢得到的信息被存放到cpuData中 */cpuidSet(CPUX86_BASIC, cpuData)cpuidSet(CPUX86_EXTENDED, cpuData)/* 解析cpuid查詢得到的數(shù)據(jù)集合cpudata,找到最合適的model* 將其封裝到指向virCPUDef的cpu指針中 */x86DecodeCPUData(cpu, cpuData, models)x86Decode/* 加載/usr/share/libvirt/cpu_map下的所有預(yù)定義信息 */map = virCPUx86GetMap()/* 根據(jù)data中的vendor信息,在map中找到對(duì)應(yīng)的預(yù)定義vendor信息* 比如主機(jī)的vendor信息是intel,那么map中找到的就是x86_vendors.xml中* <vendor name='Intel' string='GenuineIntel'/>這一個(gè)item加載到內(nèi)存中的信息 */vendor = x86DataToVendor(&data, map)/* 從cpudata中找到簽名信息,我們知道簽名信息是通過eax_in=1,ecx_in=0查詢cpuid得到* 因此x86DataToSignature的核心內(nèi)容就是從data中查找匹配eax_in=1,ecx_in=0的這個(gè)item* 返回對(duì)應(yīng)的結(jié)果 */signature = x86DataToSignature(&data)/* 簽名找到之后,解析出其中的family,model和stepping信息,因?yàn)樵谥蟊闅v預(yù)定義Model* 的過程中,會(huì)使用Model信息和簽名信息來做判斷,獲取最匹配的預(yù)定義Model */virCPUx86SignatureFromCPUID(signature, &sigFamily, &sigModel, &sigStepping)/* 遍歷預(yù)定義的cpu model */for (i = map->nmodels - 1; i >= 0; i--) {/* 取出候選的model */candidate = map->models[i]/* 如果主機(jī)的vendro和預(yù)定義model的vendor不同,首先pass掉 */if (vendor && candidate->vendor && vendor != candidate->vendor) {VIR_DEBUG("CPU vendor %s of model %s differs from %s; ignoring",candidate->vendor->name, candidate->name, vendor->name);continue;}/* 將data中的feature集合'變成'預(yù)定義的model+feature集合的形式* 存放在virCPUDef指針cpuCandidate中,其中virCPUDef.model存放預(yù)定義的* model名字,virCPUDef.features存放需要顯示指明的主機(jī)cpu feature集合 */cpuCandidate = x86DataToCPU(&data, candidate, map, hvModel)/* 判斷預(yù)定義的model是否是最匹配主機(jī)cpu feature的 */if ((rc = x86DecodeUseCandidate(model, cpuModel,candidate, cpuCandidate,signature, preferred,cpu->type == VIR_CPU_TYPE_HOST))) {virCPUDefFree(cpuModel);cpuModel = cpuCandidate;model = candidate;if (rc == 2)break;}} 2. 具體算法: 2.1 怎么把主機(jī)查詢得到的cpu feature集合轉(zhuǎn)化成預(yù)定義的model+feature集合? x86DataToCPU(const virCPUx86Data *data,virCPUx86ModelPtr model,virCPUx86MapPtr map,virDomainCapsCPUModelPtr hvModel,virCPUType cpuType) data:主機(jī)cpuid數(shù)據(jù) model:預(yù)定義的model map:libvirt預(yù)定義的所有信息/* 首先拷貝一份cpuid查詢得到的數(shù)據(jù)到copy中 */x86DataCopy(&copy, data)/* 再拷貝一份預(yù)定義的model包含的cpuid數(shù)據(jù)到modelData中 */x86DataCopy(&modelData, &model->data)/* 核心步驟:* 讓主機(jī)包含的feature集合減去預(yù)定義model包含的feature集合* copy是主機(jī)feature集合,modelData是預(yù)定義model包含的feature集合* 操作完成后,copy中剩下的就是不包含model的feature集合* 這些集合會(huì)被添加到virCPUDef.features中,這些feature都是主機(jī)* 擁有的,因此虛機(jī)vcpu可以使用,policy被設(shè)置為VIR_CPU_FEATURE_REQUIRE */x86DataSubtract(&copy, &modelData)/* 同上,將model包含的feature集合減去data包含的feature集合* 操作完成后,model中剩下的集合就是data中不包含的,這些feature是主機(jī)* 不具備的feature,因此如果使用預(yù)定義的model,需要顯示的禁止掉這些feature* policy需要被設(shè)置為VIR_CPU_FEATURE_DISABLE */x86DataSubtract(&modelData, data)/* 將主機(jī)包含的、但預(yù)定義model中不包含的feature集合顯示地添加到virCPUDef.features中* 策略是vcpu可以使用:VIR_CPU_FEATURE_REQUIRE */x86DataToCPUFeatures(cpu, VIR_CPU_FEATURE_REQUIRE, &copy, map)/* 將預(yù)定義model包含的、但主機(jī)cpu不包含的feature集合顯示地添加到virCPUDef.features中* 顯示地禁止:VIR_CPU_FEATURE_DISABLE */x86DataToCPUFeatures(cpu, VIR_CPU_FEATURE_DISABLE, &modelData, map) 2.2 怎么選擇最優(yōu)的預(yù)定義model x86DecodeUseCandidate/* 首先判斷簽名:首先要找到和主機(jī)cpu相同簽名的預(yù)定義model *//* Ideally we want to select a model with family/model equal to* family/model of the real CPU. Once we found such model, we only* consider candidates with matching family/model.*/if (signature &&virCPUx86SignaturesMatch(current->signatures, signature) &&!virCPUx86SignaturesMatch(candidate->signatures, signature)) {VIR_DEBUG("%s differs in signature from matching %s",cpuCandidate->model, cpuCurrent->model);return 0;}/* 如果存在簽名相同的多個(gè)model情況:選取包含feature集合多的那個(gè)預(yù)定義model */if (cpuCurrent->nfeatures > cpuCandidate->nfeatures) {VIR_DEBUG("%s results in shorter feature list than %s",cpuCandidate->model, cpuCurrent->model);return 1;}

    cpu-baseline

    • cpu-baseline命令接受多個(gè)feature集合作為輸入(以model+顯式feature集的形式給出),它從這些feature集合中,在預(yù)定義的model中找到最合適的哪一個(gè)model,將其作為基線返回,如果多個(gè)feature集合沒有任何交集,那么返回不兼容的cpu model。
    1. 總體流程 cmdCPUBaseline......qemuConnectBaselineCPU......cpuDriverX86.baselinevirCPUx86Baseline/* 首先取第一個(gè)feature集作為輸入,將其'變成'Libvirt預(yù)定義的model,* 將此model作為基線model */base_model = x86ModelFromCPU(cpus[0], map, -1)modelName = cpus[0]->model/* 處理所有輸入cpu model隱式包含的feature集合 */for (i = 1; i < ncpus; i++) {/* 依次取出所有的輸入feature集合,將其'變成'預(yù)定義的model形式 */model = x86ModelFromCPU(cpus[i], map, -1)/* 對(duì)所有這些feature集合進(jìn)行取交集操作,base_model中最后剩下的就是所有feature集合的交集 */x86DataIntersect(&base_model->data, &model->data)}/* 處理所有輸入cpu 顯示指定的feature集合 */if (features) {for (i = 0; features[i]; i++) {if ((feat = x86FeatureFind(map, features[i])) &&x86DataAdd(&featData->data.x86, &feat->data) < 0)goto cleanup;}x86DataIntersect(&base_model->data, &featData->data.x86)}/* 最終,將所有的這些輸入feature集合取交集后,base model沒有數(shù)據(jù)了* 說明這些feature集合之間沒有任何交集,返回不兼容的cpu */if (x86DataIsEmpty(&base_model->data)) {virReportError(VIR_ERR_OPERATION_FAILED,"%s", _("CPUs are incompatible"));goto error;}/* 如果輸入feature集合有交集,將這些數(shù)據(jù)轉(zhuǎn)化成virCPUDef作為輸出 */x86Decode(cpu, &base_model->data, models, modelName, migratable) 2. 具體算法 怎么將輸入的feature集合轉(zhuǎn)化成預(yù)定義的cpu model? x86ModelFromCPU/* 首先處理model中隱式包含的feature集合* 取出要比較的cpu的model,該model隱式指明了feature的集合* 在預(yù)定義的model中查找是否有相同的model,沒有則報(bào)錯(cuò) */if (cpu->model &&(policy == VIR_CPU_FEATURE_REQUIRE || policy == -1)) {if (!(model = x86ModelFind(map, cpu->model))) {virReportError(VIR_ERR_INTERNAL_ERROR,_("Unknown CPU model %s"), cpu->model);return NULL;}/* 拷貝匹配到的預(yù)定義model的cpuid數(shù)據(jù) */model = x86ModelCopy(model);/* 處理輸入中顯式指定的feature */for (i = 0; i < cpu->nfeatures; i++) {/* 如果輸入的feature沒有指定使用策略,默認(rèn)使用require策略 */if (cpu->features[i].policy == -1)fpol = VIR_CPU_FEATURE_REQUIRE;/* 否則使用指定的策略 */elsefpol = cpu->features[i].policy;/* 首先在預(yù)定義的feature中檢查,是否有輸入的feature,如果沒有報(bào)錯(cuò) */if (!(feature = x86FeatureFind(map, cpu->features[i].name))) {virReportError(VIR_ERR_INTERNAL_ERROR,_("Unknown CPU feature %s"), cpu->features[i].name);return NULL;}/* 根據(jù)feature的策略,將輸入的feature添加到model中,或者從model刪除 */ switch (fpol) {case VIR_CPU_FEATURE_FORCE:case VIR_CPU_FEATURE_REQUIRE:/* 如果策略是require,添加到model包含的feature集合中 */if (x86DataAdd(&model->data, &feature->data) < 0)return NULL;break;case VIR_CPU_FEATURE_DISABLE:case VIR_CPU_FEATURE_FORBID:/* 將feature從model包含的feature集合中刪除 */x86DataSubtract(&model->data, &feature->data);break;/* coverity[dead_error_condition] */case VIR_CPU_FEATURE_OPTIONAL:case VIR_CPU_FEATURE_LAST:break;}

    cpu-compare

    • virsh cpu-compare工具用于將輸入的feature集合與主機(jī)cpu的feature集合比較,輸出的結(jié)果有4個(gè):
    typedef enum {VIR_CPU_COMPARE_ERROR = -1, /* 比較出錯(cuò) *//* 與主機(jī)不兼容,這里包含兩種集合關(guān)系:* 一是兩者不相關(guān)* 二是主機(jī)cpu feature是輸入cpu feature的子集* 子集說明輸入cpu feature集合中包含了主機(jī)無法提供的feature* 因此無法遷移,返回不兼容 */VIR_CPU_COMPARE_INCOMPATIBLE = 0, VIR_CPU_COMPARE_IDENTICAL = 1, /* 與主機(jī)相同 *//* 主機(jī)的cpu feature是輸入cpu feature的超集,說明可以遷移*/VIR_CPU_COMPARE_SUPERSET = 2, } virCPUCompareResult; 1. 總體流程 cmdCPUCompare......qemuConnectCompareCPU/* 獲取主機(jī)的cpu feature集合 */cpu = virQEMUDriverGetHostCPU(driver)/* 將主機(jī)的cpu feature集合與xmlDesc中描述的cpu feature集合比較 */virCPUCompareXML(driver->hostarch, cpu, xmlDesc, failIncompatible, validateXML) ......cpuDriverX86.comparevirCPUx86Comparex86Compute(host, cpu, NULL, &message)/* 如果做比較的cpu與主機(jī)的cpu廠商不同,報(bào)錯(cuò)不兼容 */if (cpu->vendor &&(!host->vendor || STRNEQ(cpu->vendor, host->vendor))) {VIR_DEBUG("host CPU vendor does not match required CPU vendor %s",cpu->vendor);return VIR_CPU_COMPARE_INCOMPATIBLE;}/* 加載Libvirt預(yù)定義的信息,并且根據(jù)要比較的cpu feature集合* 在預(yù)定義的model中組裝各個(gè)屬性的feature集合* 將要比較的要求提供的cpu feature集合存放在cpu_require中 */if (!(map = virCPUx86GetMap()) ||!(host_model = x86ModelFromCPU(host, map, -1)) ||!(cpu_force = x86ModelFromCPU(cpu, map, VIR_CPU_FEATURE_FORCE)) ||!(cpu_require = x86ModelFromCPU(cpu, map, VIR_CPU_FEATURE_REQUIRE)) ||!(cpu_optional = x86ModelFromCPU(cpu, map, VIR_CPU_FEATURE_OPTIONAL)) ||!(cpu_disable = x86ModelFromCPU(cpu, map, VIR_CPU_FEATURE_DISABLE)) ||!(cpu_forbid = x86ModelFromCPU(cpu, map, VIR_CPU_FEATURE_FORBID))) return VIR_CPU_COMPARE_ERROR;/* 如果主機(jī)的cpu feature集合中包含了要比較的cpu feature中禁止提供的feature* 返回不兼容 */x86DataIntersect(&cpu_forbid->data, &host_model->data)if (!x86DataIsEmpty(&cpu_forbid->data)) {virX86CpuIncompatible(N_("Host CPU provides forbidden features"),&cpu_forbid->data); return VIR_CPU_COMPARE_INCOMPATIBLE;}/* 首先獲取比較cpu feature集合中實(shí)際需要提供的feature集合 */x86DataSubtract(&cpu_require->data, &cpu_force->data);x86DataSubtract(&cpu_require->data, &cpu_optional->data);x86DataSubtract(&cpu_require->data, &cpu_disable->data);/* 比較host_model與cpu_require包含的集合關(guān)系 */result = x86ModelCompare(host_model, cpu_require);/* 如果host_model是cpu_require的子集,返回不兼容* 說明要比較的cpu feature集合中包含了主機(jī)中無法提供的feature */if (result == SUBSET || result == UNRELATED) {x86DataSubtract(&cpu_require->data, &host_model->data);virX86CpuIncompatible(N_("Host CPU does not provide required ""features"),&cpu_require->data);return VIR_CPU_COMPARE_INCOMPATIBLE;}/* 至此,host與輸入cpu的集合關(guān)系只有兩種:* 一是相同、二是host是cpu的超集* 下面的步驟就是判斷應(yīng)該屬于那種情況 *//* 首先取出host的所有feature集合 */diff = x86ModelCopy(host_model);/* 減去輸入cpu中涉及到的所有feature集合 */x86DataSubtract(&diff->data, &cpu_optional->data);x86DataSubtract(&diff->data, &cpu_require->data);x86DataSubtract(&diff->data, &cpu_disable->data);x86DataSubtract(&diff->data, &cpu_force->data);/* 減去之后,如果還存在一些feature* 說明這些feature與輸入的cpu feature集合無關(guān)的* host就是輸入cpu feature的超集* 如果不存在feature了,說明兩者一樣 */if (x86DataIsEmpty(&diff->data))ret = VIR_CPU_COMPARE_IDENTICAL;elseret = VIR_CPU_COMPARE_SUPERSET; 2. 具體算法 怎么比較兩個(gè)集合model1、model2的關(guān)系 x86ModelCompare(virCPUx86ModelPtr model1,virCPUx86ModelPtr model2)virCPUx86CompareResult result = EQUAL;/* 首先遍歷model1中的feature,將其與model2集合比較* 如果它不存在于model2中,那model1肯定不是model2的子集了* 如果是的話,model1的任何元素都應(yīng)該存在于model2中 */while ((item1 = virCPUx86DataNext(&iter1))) {virCPUx86CompareResult match = SUPERSET;if ((item2 = virCPUx86DataGet(&model2->data, item1))) {if (virCPUx86DataItemMatch(item1, item2))continue;else if (!virCPUx86DataItemMatchMasked(item1, item2))match = SUBSET;}/* 如果result為初始值,將其賦值為SUPERSET */if (result == EQUAL)result = match;/* 如果model1中存在model2中沒有的元素* match肯定被賦值為SUBSET,兩者不相同返回不相關(guān) */else if (result != match)return UNRELATED;}/* 如果程序走到這里,model2集合必然大于等于model1* 判斷具體的兩種情況:等于或者大于 */while ((item2 = virCPUx86DataNext(&iter2))) {virCPUx86CompareResult match = SUBSET;if ((item1 = virCPUx86DataGet(&model1->data, item2))) {if (virCPUx86DataItemMatch(item2, item1))continue;else if (!virCPUx86DataItemMatchMasked(item2, item1))match = SUPERSET;}if (result == EQUAL)result = match;else if (result != match)return UNRELATED;}

    總結(jié)

    以上是生活随笔為你收集整理的Libvirt CPU Feature的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

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

    9i看片成人免费看片 | 特级毛片网 | 一区二区三区在线免费观看 | 日韩av播放在线 | 精品999国产| 国产69精品久久久久久久久久 | 久久特级毛片 | 热久久99这里有精品 | 亚洲成人一二三 | 欧美日韩免费一区二区三区 | 在线免费观看黄色 | 日韩av免费在线电影 | 在线视频观看成人 | 一区 在线观看 | 久久免费视频在线观看30 | 亚洲一区美女视频在线观看免费 | 久久激情日本aⅴ | 亚洲波多野结衣 | 亚洲视频久久久 | 国产一区国产精品 | 亚洲精品www久久久久久 | 一区二区三区免费网站 | 亚洲欧美va | 婷婷精品在线视频 | 在线观看视频99 | 一区二区三区四区精品 | 国产精品久久久久一区二区三区共 | 免费a视频在线 | 亚洲美女在线国产 | 亚洲激情p| 在线小视频你懂得 | 亚洲精品美女 | 国产精品专区在线 | 午夜久久福利 | a黄色大片| www.com.黄| 色婷婷激婷婷情综天天 | 欧美在线视频二区 | 最近中文字幕在线中文高清版 | 国产成人精品一区二区在线观看 | 国产高清免费 | 亚洲欧美日韩国产一区二区 | 亚洲九九九 | 日韩精品视频免费专区在线播放 | 一区二区三区中文字幕在线观看 | 久久黄色a级片 | 天天射天天干 | 手机av看片 | 色多多在线观看 | 日本字幕网| 91精品福利在线 | 免费99视频 | 99热官网 | 一级a性色生活片久久毛片波多野 | 成人精品一区二区三区中文字幕 | 中文字幕在线观看资源 | 99精品欧美一区二区蜜桃免费 | 韩国精品在线观看 | 日韩欧美精品在线观看视频 | 欧美一级片在线 | 99热最新在线 | 激情五月婷婷激情 | 欧美极品少妇xbxb性爽爽视频 | 国产亚洲精品久久久久久大师 | 天天干夜夜夜操天 | 国产福利免费看 | 国产精国产精品 | 国产精品久久久久一区 | 99精品免费久久久久久久久日本 | 手机在线观看国产精品 | 综合色狠狠 | 成年人在线观看视频免费 | 日韩电影一区二区三区 | 99av在线视频 | 久久精品精品 | 国产最新在线观看 | 91精品国产网站 | 99热这里只有精品在线观看 | 久久中文字幕视频 | 808电影免费观看三年 | 国产精品你懂的在线观看 | 麻豆影视在线播放 | 一级做a爱片性色毛片www | 日韩在线看片 | 久久人人做 | 欧美一区二视频在线免费观看 | 亚洲综合日韩在线 | 国产一区欧美一区 | 黄色亚洲大片免费在线观看 | 国产黄a三级三级三级三级三级 | 91免费试看| 国产免费区| 久久超碰99 | 国产精品去看片 | 亚洲区精品| 久久久精品国产一区二区 | 亚洲伊人婷婷 | 国产精品久久久久久久久婷婷 | 亚洲精品在线观看的 | 黄色大片日本免费大片 | 制服丝袜在线 | 97精品国产97久久久久久 | 成人在线观看影院 | 日韩av电影免费观看 | 久久综合综合久久综合 | 国产a视频免费观看 | 一区二区三区手机在线观看 | 午夜在线观看一区 | 国产一区二区免费在线观看 | 久草在线视频网 | 中国一级片在线播放 | 亚洲一区av | 免费国产在线精品 | 国产拍揄自揄精品视频麻豆 | 精品伦理一区二区三区 | 青青草在久久免费久久免费 | 狠狠色丁香久久婷婷综 | 精产嫩模国品一二三区 | 日韩免费一二三区 | 久久综合九色综合97_ 久久久 | 一区二区三区在线免费观看 | 亚洲三级国产 | 久久成人精品视频 | 欧美五月婷婷 | 日本资源中文字幕在线 | 麻豆视屏 | 亚洲天天摸日日摸天天欢 | 中文字幕在线看视频 | a特级毛片| 久久久久在线 | 久久艹免费| 国产精品自产拍在线观看蜜 | 欧美一级片在线 | 麻豆播放 | 久久国产精品99久久久久久丝袜 | 在线精品国产 | 日韩精品一区二区三区丰满 | 99久久99久久免费精品蜜臀 | 欧美一级免费黄色片 | 丁香狠狠| 国产91精品高清一区二区三区 | 91看片一区二区三区 | 日韩精品一区二区三区外面 | 中文字幕永久在线 | 99视频免费 | 中文字幕第 | 在线免费国产视频 | 亚洲精品女 | 在线亚州 | 99久久夜色精品国产亚洲 | 亚洲精品视频中文字幕 | 在线国产福利 | 国产一级片观看 | 国产成人久久精品一区二区三区 | 97视频在线观看成人 | 手机在线欧美 | 欧美伊人网 | 色播激情五月 | 亚洲最新合集 | 一色屋精品视频在线观看 | 久99热| 一级免费片 | 黄色三级免费片 | 91精品久久久久久综合乱菊 | 国产精品一区二区免费在线观看 | 最新av中文字幕 | 91最新在线 | 97福利视频 | 天天色天天射天天干 | 精品一二三四在线 | www久久国产 | 精品在线观看视频 | 男女视频91 | 日韩国产精品一区 | 在线观看免费成人av | 精品久久久久久久久亚洲 | av在线播放免费 | 日一日干一干 | 深爱激情久久 | 一区二区三区在线视频观看58 | 久久久精品国产一区二区 | 久草在线中文888 | 四虎影视4hu4虎成人 | 国产精品国产三级国产不产一地 | 玖玖在线播放 | 青春草免费视频 | 激情综合网在线观看 | 久久精品一区二区三区国产主播 | 亚洲国产精品传媒在线观看 | 91视频首页 | 9999国产精品| 国产精品久免费的黄网站 | 亚洲国产高清在线观看视频 | wwwwww色| 人人爽久久久噜噜噜电影 | 三级动态视频在线观看 | 亚洲激情视频在线 | 色操插 | 免费看的国产视频网站 | 亚洲理论电影 | 国产最新精品视频 | 日本性高潮视频 | 国产一区二区在线视频观看 | 国产一区二区在线免费 | 精品久久久久久亚洲综合网 | 丁香婷婷激情国产高清秒播 | 国产一区在线视频播放 | 国产一区二区三区四区大秀 | 国产一性一爱一乱一交 | 免费在线色电影 | 精品免费视频 | 久久人人爽人人爽人人片av免费 | 亚洲区精品视频 | 久久99精品久久久久婷婷 | 国产精品久久毛片 | 91麻豆精品国产91久久久久久久久 | 91在线看网站 | 欧洲视频一区 | 日韩三级不卡 | 欧美激情精品一区 | 丁香婷婷色综合亚洲电影 | 国产成人资源 | 日韩在线无 | 欧美国产日韩一区二区三区 | 欧美日韩免费一区二区 | 日韩精品一区二区三区电影 | 国产精品男女啪啪 | 久久少妇av | 日韩av在线免费播放 | 色亚洲激情 | 精品黄色片 | 国产黄色资源 | 亚洲欧洲国产日韩精品 | 国产拍揄自揄精品视频麻豆 | 2023亚洲精品国偷拍自产在线 | 超碰人人乐 | 少妇bbw搡bbbb搡bbb | 91在线看视频| 日韩一级成人av | 久久的色| 久久久精品视频成人 | 欧美精品久久久久久久亚洲调教 | 婷婷视频在线 | 成人欧美一区二区三区在线观看 | 激情综合啪 | 激情文学丁香 | 日韩精品久久久久久中文字幕8 | 久久免费毛片视频 | 激情偷乱人伦小说视频在线观看 | 久久热亚洲 | 日韩欧美黄色网址 | 色吊丝在线永久观看最新版本 | 91成人看片| 天天干,天天射,天天操,天天摸 | 91日韩在线播放 | 香蕉97视频观看在线观看 | 国产精品99蜜臀久久不卡二区 | 成人性生交大片免费观看网站 | 久久久精品网站 | 久久久久久久久久久高潮一区二区 | 国产专区在线视频 | 欧美精品天堂 | 成年人免费在线观看网站 | 麻豆一区在线观看 | 国产高清视频免费最新在线 | 81国产精品久久久久久久久久 | 日本少妇高清做爰视频 | 超碰97在线资源 | 精品亚洲视频在线观看 | 欧美一级在线看 | 国产黄色理论片 | 久草视频国产 | 999久久久欧美日韩黑人 | 国产不卡一二三区 | 手机成人免费视频 | av网站免费在线 | 色av色av色av| www久久精品 | 中文字幕永久免费 | 毛片基地黄久久久久久天堂 | 国产成人三级在线播放 | 国产丝袜一区二区三区 | www.少妇| 久久激情日本aⅴ | 国产精品一区二区免费在线观看 | 免费国产ww | 蜜桃麻豆www久久囤产精品 | 欧美a影视 | 狠狠色丁香婷婷综合最新地址 | 久久久黄色av | 丁香电影小说免费视频观看 | 91精品久久久久久久久 | 一级免费片| 欧美日韩中文国产一区发布 | 99精品国产福利在线观看免费 | 中文字幕乱码在线播放 | 最近字幕在线观看第一季 | 日韩中字在线 | 免费看片色| 婷婷色网站 | 色婷婷综合久久久中文字幕 | 亚洲高清久久久 | 久久无码精品一区二区三区 | 久久美女免费视频 | 久久久午夜精品福利内容 | 在线观看色网站 | 免费福利小视频 | 三级在线视频观看 | 久草在线免费看视频 | 射久久久 | 99久久久国产精品免费观看 | 91精品免费在线视频 | 精品视频999 | 亚洲激情久久 | 国产美女被啪进深处喷白浆视频 | 久久精品视频4 | 一区二区久久 | 麻花天美星空视频 | 精品国产a | 色网站中文字幕 | 美女很黄免费网站 | 九九热1 | 亚洲免费国产视频 | 国产99久久久国产 | 在线免费看片 | 欧美一级片免费在线观看 | 69国产精品视频 | 欧美国产日韩久久 | 五月天久久| 欧美人交a欧美精品 | 在线久热 | 亚洲成年人在线播放 | 久久免费视频观看 | 久久国产精品久久w女人spa | av黄色在线| 在线免费观看黄色 | sesese图片| 五月丁香 | 免费av大片 | 操操碰 | 免费看搞黄视频网站 | 欧美成年黄网站色视频 | 国产成人av免费在线观看 | 超级碰碰碰碰 | 2021av在线 | 在线观看完整版 | 99久久这里有精品 | 成人av资源在线 | 精品国产一二三四区 | 99热精品视 | 精品久久久久国产免费第一页 | 新av在线| 激情黄色av | 久草色在线观看 | 中文字幕一区二区三区四区视频 | 天堂成人在线 | 欧美老女人xx | 欧美激情视频一二区 | 免费福利在线 | 一区二区电影网 | 国产又粗又长的视频 | 欧洲精品视频一区二区 | av成人动漫 | 91精品国产欧美一区二区 | 色干干| 欧美精品国产精品 | 欧美日韩国产在线一区 | 中文字幕频道 | 国产群p视频 | 一区电影| 久久精品国产免费 | av不卡在线看 | 日韩精品大片 | 97视频在线观看播放 | 激情综合啪啪 | 91久久在线观看 | 免费高清av在线看 | 天天操天天干天天操天天干 | 国产主播大尺度精品福利免费 | 免费网站看av片 | 视频国产一区二区三区 | 色综合久久精品 | 亚洲日韩中文字幕在线播放 | 五月天天天操 | 亚洲综合激情网 | 91试看 | 狠狠狠色丁香综合久久天下网 | 99国产免费网址 | 日韩免费b | www色| 亚洲三级网 | 日日夜夜精品免费视频 | 国产日产精品一区二区三区四区的观看方式 | 久久综合免费视频影院 | 久草在线 | 人人爽人人爽人人片av | 亚洲国产视频网站 | 国产在线高清精品 | 国产一级电影在线 | 狠狠色网 | 免费精品人在线二线三线 | 久久综合久久综合久久综合 | 久久精品久久99精品久久 | 精品久久一区二区三区 | av在线免费播放 | 91探花在线 | 久久超级碰 | 高清中文字幕 | 黄色aa久久 | 精品一二三区视频 | www.com久久久| 91av亚洲| 欧美 另类 交| 九色激情网 | 国产成人久久av | 黄色特级毛片 | av日韩国产| 久久久久久久久久久免费视频 | 午夜神马福利 | 91香蕉视频720p| 久久久精品视频成人 | av手机版 | 久久精品免费看 | 五月婷婷另类国产 | 国产精品久久久久高潮 | 亚洲综合激情五月 | 色综合婷婷久久 | 日本精品视频一区 | 午夜视频久久久 | 色爽网站 | 欧美性爽爽 | 狠狠操天天干 | 美女网站在线观看 | 狠狠干夜夜操 | 91在线视频一区 | 毛片网站在线看 | 国产原创在线观看 | av黄色一级片 | 婷婷亚洲最大 | 国语自产偷拍精品视频偷 | 蜜桃av综合网 | 国产香蕉视频 | 91福利视频免费 | 91九色视频在线播放 | 免费观看9x视频网站在线观看 | 成人小视频在线观看免费 | 日韩久久久久 | 欧美一区二区在线免费观看 | 久久成人一区 | 92国产精品久久久久首页 | 欧美日韩免费观看一区=区三区 | 日本午夜免费福利视频 | 国产一区二区在线免费观看 | 最新精品视频在线 | 亚洲免费精品视频 | 狠狠色丁香婷婷综合久久片 | 国产免费观看高清完整版 | 免费高清无人区完整版 | 91视频国产免费 | 天天干天天玩天天操 | 91九色在线视频观看 | 在线看国产一区 | 人人澡超碰碰97碰碰碰软件 | 精品国产1区 | 国产精品二区在线 | 人人操日日干 | 国产精品美女久久 | 在线激情小视频 | 久久任你操 | 在线观看av小说 | 男女啪啪视屏 | 国产精品国产三级国产aⅴ入口 | 91精品在线观看视频 | 97免费公开视频 | 国产第一页在线播放 | 激情久久五月 | 精品国产乱码久久 | 国产精品www | 揉bbb玩bbb少妇bbb | 91精品国产麻豆国产自产影视 | 在线亚洲天堂网 | 黄色软件网站在线观看 | 一区二区三区高清 | 中文字幕在线免费97 | 亚洲天堂视频在线 | www黄色com | 久久不卡电影 | 国产精品一区二区三区99 | 久艹视频免费观看 | 精品国内自产拍在线观看视频 | 日韩欧美国产视频 | 国产中文字幕精品 | 香蕉视频国产在线观看 | 91天天视频| 91视频在线观看大全 | 天天操夜夜操国产精品 | 亚洲人在线7777777精品 | 中文字幕在线观看资源 | 激情综合中文娱乐网 | 国产高清永久免费 | 免费在线观看午夜视频 | 久久公开免费视频 | 日韩欧美电影网 | 国产拍揄自揄精品视频麻豆 | 亚洲一一在线 | 狠狠操夜夜操 | 亚洲国产中文字幕 | 在线免费观看视频一区二区三区 | 国内精品久久久久久中文字幕 | 日韩欧美大片免费观看 | 国产精品久久久久久久免费观看 | 亚洲精品1区2区3区 超碰成人网 | 深爱五月网 | 成人一级电影在线观看 | 狠狠综合网| 91在线最新| 久草免费在线视频 | 亚洲永久精品国产 | 精品亚洲一区二区 | 国产精品18久久久久久不卡孕妇 | 韩国av免费在线观看 | 日韩在线观看中文字幕 | 久久婷婷国产色一区二区三区 | 99久久日韩精品视频免费在线观看 | 免费看黄在线 | 国产麻豆精品久久 | 开心婷婷色| 在线视频手机国产 | 国产自产高清不卡 | 午夜精品电影一区二区在线 | 国产精品久久久久久一区二区 | 日韩av视屏在线观看 | 激情综合网在线观看 | 日韩欧美一区二区三区在线 | 午夜精品久久久久久久99无限制 | 午夜狠狠干 | 成片人卡1卡2卡3手机免费看 | 国产品久精国精产拍 | 国产精品一区二区三区久久 | 456免费视频 | 视频在线观看入口黄最新永久免费国产 | 色综合天天射 | 九九热国产视频 | 亚洲欧美日本国产 | h网站免费在线观看 | 国产精品欧美日韩在线观看 | 五月婷婷中文网 | 黄色的视频网站 | www.com久久| 久久国产精品二国产精品中国洋人 | 久久99久久精品 | 伊人五月天婷婷 | 色多视频在线观看 | 在线一二三区 | 国产麻豆视频免费观看 | 亚洲成av人影院 | 国产在线理论片 | 国产精品va在线观看入 | 五月天伊人 | 国产一区视频在线观看免费 | 99爱国产精品 | 久久艹艹 | 婷婷亚洲综合五月天小说 | 亚洲国产成人av网 | 国产午夜精品av一区二区 | 久久深夜福利免费观看 | 欧美一性一交一乱 | 久久久91精品国产一区二区精品 | 久久久久久久久久久久久久电影 | 欧洲精品码一区二区三区免费看 | 色婷婷av一区二 | 天天天干天天射天天天操 | 久久99国产综合精品 | 久久久片| 日日夜夜天天射 | 日韩av电影中文字幕 | 四虎影视精品 | 中文字幕美女免费在线 | 又黄又色又爽 | 9草在线| 99久久婷婷 | 午夜视频99| 五月综合激情 | 国产精品9999久久久久仙踪林 | 国产一性一爱一乱一交 | 免费日韩 精品中文字幕视频在线 | 91看片成人| 五月天综合 | 在线观看国产日韩 | 欧美一区二区三区在线观看 | 日韩高清在线一区 | 黄色特级片 | 国产精品久久99综合免费观看尤物 | 国产精品手机在线 | 亚洲国产剧情 | 亚洲日本va午夜在线电影 | 国产免费久久av | 2021国产在线 | 久久久av免费 | 手机av看片| 亚洲va欧美va人人爽春色影视 | 中文字幕乱偷在线 | 国产分类视频 | 天天综合狠狠精品 | 亚洲精品在线视频网站 | 久久精品91视频 | 在线播放一区二区三区 | 国产69久久精品成人看 | 樱空桃av| 成人免费共享视频 | 亚洲精品中文在线观看 | 成年人在线免费看 | av黄在线播放 | 精品久久国产 | 国产在线视频资源 | av片子在线观看 | av色一区 | 国产v视频| 国产精品v a免费视频 | 国产一区二区三区免费视频 | 国产精品精品国产色婷婷 | 免费观看丰满少妇做爰 | 色a4yy| 一区二区三区免费在线观看视频 | 伊人精品在线 | 三级av在线免费观看 | 天天爱天天射 | 9999亚洲| 可以免费看av | free,性欧美 九九交易行官网 | 国产毛片aaa | 在线观看a视频 | 国产日韩欧美在线免费观看 | 国产精品久久久久久爽爽爽 | 超碰97久久 | 人人干人人干人人干 | 成人黄色在线播放 | 久久久鲁 | 精品视频久久 | 黄色一级免费网站 | 久久久久在线观看 | 亚洲国产美女精品久久久久∴ | 国产伦精品一区二区三区高清 | 国产精品短视频 | 国产一区二区三区高清播放 | 99精品免费久久久久久久久日本 | 欧美午夜一区二区福利视频 | 一级黄色大片在线观看 | 久久精品一区二 | 国产专区一 | 午夜精品久久久久久久99热影院 | 亚洲伦理中文字幕 | 99久久一区| 亚洲女在线 | 欧美性高跟鞋xxxxhd | 97人人精品 | 久久精品欧美一区二区三区麻豆 | 视频1区2区 | 久久欧美视频 | 波多野结衣小视频 | 在线观看免费观看在线91 | 伊人久久五月天 | 欧美做受高潮电影o | www.夜夜骑.com | 免费污片| 国产精品男女啪啪 | 综合激情婷婷 | 欧美一级片 | 欧美一区二区三区在线 | 最近的中文字幕大全免费版 | 一区免费观看 | 99视屏| 日日操夜夜操狠狠操 | 亚洲天堂网在线视频 | 97视频久久久 | 亚洲韩国一区二区三区 | 日韩欧美高清视频在线观看 | 丁香婷婷在线观看 | 国产精品视频 | 99久久久久久 | 精品国产黄色片 | 九色自拍视频 | 成人黄色短片 | 九九热视频在线播放 | 天天爱天天干天天爽 | 国产在线欧美日韩 | 亚洲伊人成综合网 | 欧美日韩国产精品久久 | a视频在线观看免费 | 国产精品高清在线观看 | 日本三级国产 | 久久视奸 | 人人玩人人爽 | 欧美不卡视频在线 | 色婷婷免费视频 | 又污又黄网站 | 国产成人精品一区二 | 免费在线观看日韩欧美 | 91视频电影 | 一区二区视频免费在线观看 | 在线黄色av| 九九热在线免费观看 | 97在线看| 大胆欧美gogo免费视频一二区 | 99久久国产免费,99久久国产免费大片 | 精品99久久 | 国产在线视频资源 | 91丨九色丨蝌蚪丨老版 | 一二区精品 | 网站免费黄 | 国产在线视频一区 | 成人黄色电影在线播放 | 日日摸日日 | 啪啪凸凸 | 在线视频18在线视频4k | 毛片视频电影 | 操操操综合 | 日韩素人在线观看 | 成年人毛片在线观看 | 夜夜操网站 | 久久久久久久久久久国产精品 | 国产精品视频久久 | 免费一级毛毛片 | av大全免费在线观看 | 精品一区二区在线观看 | 中文字幕av专区 | 欧美日韩视频精品 | 国产不卡av在线播放 | 九九九九免费视频 | 中文字幕在线观看第一页 | 日本黄区免费视频观看 | 日韩经典一区二区三区 | 亚洲黄色在线播放 | 999久久久精品视频 日韩高清www | 免费开视频| 五月开心网 | 手机在线看片日韩 | 色综合婷婷 | 六月婷色 | 日韩免费播放 | 亚洲一区二区三区精品在线观看 | 久久久久9999亚洲精品 | 国产成人三级在线播放 | 最近中文字幕在线中文高清版 | 亚洲午夜精品久久久久久久久 | 99久久精品久久久久久动态片 | 五月婷婷av | 午夜精品久久久久久久99 | 久久久国产电影 | 五月婷婷一级片 | 96久久久 | 99久久成人 | 久久久国产精品久久久 | 国产精品毛片完整版 | 亚洲精品在线免费 | 丁香九月婷婷 | 99精品视频免费观看视频 | 97高清视频 | 国产激情电影综合在线看 | 亚洲成人精品国产 | 日韩电影中文,亚洲精品乱码 | 国产精品入口久久 | 日韩影视在线 | 一性一交视频 | 麻豆国产精品视频 | 中文字幕精品www乱入免费视频 | 欧美人人爱 | 国产成人福利 | 国产成人一区二区三区免费看 | 婷婷色综合网 | 久草手机视频 | 9999激情 | 欧美日韩国产在线 | 免费看精品久久片 | 成人动漫一区二区三区 | 久久久久国产精品午夜一区 | 欧美午夜激情网 | 综合网中文字幕 | 久久久久久久久久久影院 | 92中文资源在线 | 精品在线一区二区 | 香蕉在线影院 | 激情欧美xxxx| 国产一级在线视频 | 欧美精选一区二区三区 | 精品国产亚洲一区二区麻豆 | 久久综合五月婷婷 | 国产精品99久久久久久武松影视 | 日本精品一区二区 | 国产午夜精品一区二区三区嫩草 | 亚洲综合在线五月天 | 在线小视频 | 久久福利国产 | 久草视频在线新免费 | 天天操夜操视频 | 亚洲一区天堂 | 麻豆免费观看视频 | 高潮久久久久久 | 久久久国产精品成人免费 | 久草网视频在线观看 | 四虎在线免费观看 | 精品国产伦一区二区三区观看方式 | 色综合天天色 | 日韩1页 | 91毛片在线| 精品国产一区二区三区日日嗨 | 91免费版在线观看 | 欧美日韩中文字幕在线视频 | 99精品国产aⅴ | 欧美在线久久 | 久久99精品国产99久久6尤 | 中文字幕视频观看 | 国产成人无码AⅤ片在线观 日韩av不卡在线 | 国产免费区 | 国产高清永久免费 | 免费福利片2019潦草影视午夜 | 91精品在线看 | 在线一二区 | 天天插天天干 | 91免费在线看片 | 天天射天天射天天射 | 91av视频导航| 日韩精品视频网站 | 97国产精品 | 国产视频在线观看一区 | 808电影| 日韩免费一区二区三区 | 在线免费高清 | 麻豆精品传媒视频 | 97在线观看视频免费 | 久久综合九色综合久久久精品综合 | 中文字幕永久免费 | 欧美99久久| 日本三级久久久 | 国内精品视频免费 | 亚洲精品国产精品99久久 | 日韩精品视 | 天天爱天天射天天干天天 | 日韩精品一区二区免费视频 | 亚洲欧洲精品一区二区 | 特级大胆西西4444www | 有码中文字幕在线观看 | 一区二区电影在线观看 | 国产美女被啪进深处喷白浆视频 | 国产精品久久久久久妇 | 91成人网页版| 欧美在线18 | 91av资源在线 | 国产成人三级在线 | 亚洲va天堂va欧美ⅴa在线 | 中文乱码视频在线观看 | 亚洲日本韩国一区二区 | 日本三级全黄少妇三2023 | 日韩在观看线 | 久久精品电影 | 色婷婷www | 久久专区| 福利视频精品 | 色综合久久久 | 国产一区二区视频在线 | 公开超碰在线 | 日韩精品无 | 精品视频久久久 | 中文字幕免费观看全部电影 | 91精品在线免费观看视频 | 中文字幕在线播放av | 国产日韩精品一区二区三区在线 | 91新人在线观看 | 免费在线观看av不卡 | 欧美久久久久久久久中文字幕 | 欧美激情视频一二三区 | 国产99久久99热这里精品5 | 国产小视频在线播放 | 国产一区二区免费看 | 国内精品美女在线观看 | 国产黑丝袜在线 | 中文日韩在线 | 国产福利免费在线观看 | 国产剧情在线一区 | 国产一级二级三级视频 | 天天操天天综合网 | 色97在线 | 一区二区三区免费在线观看视频 | 欧美精品乱码久久久久久 | 免费成人在线视频网站 | 91精品久久久久久久久 | 97在线精品| 丁香六月五月婷婷 | 国产精品 视频 | 午夜精品成人一区二区三区 | av资源在线观看 | 中文字幕精品一区二区精品 | 黄色免费网 | 国产999精品久久久久久麻豆 | 麻豆果冻剧传媒在线播放 | 国产一区欧美一区 | 久久精品专区 | 四月婷婷在线观看 | 一区二区三区四区精品视频 | 成人黄色免费观看 | 久久久久久国产精品亚洲78 | 欧美日韩一区二区三区在线免费观看 | 99久视频 | 国产精品va在线观看入 | 天天爱天天操天天干 | 久久国产二区 | 天天摸日日操 | av在线a| 久久综合久久久 | 奇米影视8888在线观看大全免费 | 久久久国产精品电影 | 91久久久久久国产精品 | 免费观看久久 | 色一级片 | 毛片1000部免费看 | 久香蕉| 亚洲开心激情 | 97超碰中文字幕 | 91爱爱中文字幕 | www.超碰97.com| 丁香电影小说免费视频观看 | 国产丝袜 | 91亚洲在线 | 久久精品欧美视频 | 国产精品美女久久久久久久 | 黄色av成人在线 | 亚洲va欧美va国产va黑人 | 欧美日韩免费一区二区 | 欧美色888| 六月婷操| av三级av | 五月婷网 | 51久久夜色精品国产麻豆 | 久久免费视频在线观看6 | 久久视频中文字幕 | 日韩高清免费无专码区 | 三上悠亚在线免费 | 黄色大片视频网站 | 中文有码在线视频 | 国产特级毛片aaaaaa毛片 | 亚洲伊人色 | 黄色毛片网站在线观看 | 永久免费看av | 亚洲日韩中文字幕在线播放 | 国产人成在线视频 | 黄色一级大片在线免费看产 | 久久久观看 | 蜜臀久久99精品久久久久久网站 | 极品美女被弄高潮视频网站 | 美女网站色在线观看 | 夜夜操天天干 | 人人澡人人爽欧一区 | 最近中文字幕高清字幕在线视频 | 久久精品成人 | 国产第一页在线播放 | 1000部18岁以下禁看视频 | 91香蕉视频 mp4 | 久久se视频| 国产99久久久国产精品成人免费 | 久久69精品久久久久久久电影好 | 国产福利91精品张津瑜 | 色悠悠久久综合 | 日本在线中文在线 | 不卡在线一区 | 久国产在线播放 | 日韩亚洲在线 | 91精品国产92久久久久 | 日韩久久精品一区二区 | 色资源在线观看 | 久久精品一区二区三区四区 | 欧美日韩在线播放一区 | 99热精品在线观看 | 人人爱在线视频 | 日韩一区二区免费在线观看 | 欧美极品在线播放 | 九七在线视频 | 国产午夜一级毛片 | 日韩av在线高清 | 久久久国产成人 | 久久不射影院 | www.天天干 | 国产剧情一区二区在线观看 | 天天综合网在线 | 日韩在线播放av | 国产视频首页 | 特黄特色特刺激视频免费播放 | www.国产高清 | 久久久久久久久久久电影 | 国产99久久精品一区二区永久免费 | 国产精品中文久久久久久久 | 久久有精品 | 久久精品中文视频 | 一级黄色毛片 | 在线免费av网| 欧美91av| 综合中文字幕 | 五月综合婷 | 国产精品一区二区62 |