cuốn sách gpt4 ai đã làm

linux - Làm thế nào hoặc sửa đổi tệp nào trong mã mô phỏng CPUID của KVM để báo cáo chuỗi nhãn hiệu bộ xử lý hư cấu (lá CPUID 0x0)?

In lại Tác giả: Taklimakan Thời gian cập nhật: 2023-11-03 00:05:44 hai mươi bốn 4
mua khóa gpt4 Nike

Đây có phải là mã nhân Linux chính xác để sửa đổi không? Làm cách nào tôi có thể thực hiện các thay đổi để mô phỏng mã CPUID và tôi cần thay đổi chức năng nào. Cảm ơn

#include 
#include
#include
#include
#include

#include
#include
#include
#include "cpuid.h"
#include "lapic.h"
#include "mmu.h"
#include "dấu vết.h"
#include "pmu.h"

tĩnh u32 xstate_required_size(u64 xstate_bv, bool được nén)
{
int feature_bit = 0;
u32 ret = XSAVE_HDR_SIZE + XSAVE_HDR_OFFSET;

xstate_bv &= XFEATURE_MASK_EXTEND;
trong khi (xstate_bv) {
nếu (xstate_bv & 0x1) {
u32 eax, ebx, ecx, edx, offset;
cpuid_count(0xD, feature_bit, &eax, &ebx, &ecx, &edx);
offset = đã nén lại ret : ebx;
ret = max(ret, offset + eax);
}

xstate_bv >>= 1;
feature_bit++;
}

return ret;
}

bool kvm_mpx_supported(void)
{
trả về ((host_xcr0 & (XFEATURE_MASK_BNDREGS | XFEATURE_MASK_BNDCSR))
&& kvm_x86_ops->mpx_supported());
}
EXPORT_SYMBOL_GPL(kvm_mpx_supported);

u64 kvm_supported_xcr0(void)
{
u64 xcr0 = KVM_SUPPORTED_XCR0 & máy chủ_xcr0;

nếu (!kvm_mpx_supported())
xcr0 &= ~(XFEATURE_MASK_BNDREGS | XFEATURE_MASK_BNDCSR);

trả lại xcr0;
}

#define F(x) bit(X86_FEATURE_##x)

/* Đây là các tính năng rải rác trong cpufeatures.h */
#define KVM_CPUID_BIT_AVX512_4VNNIW 2
#define KVM_CPUID_BIT_AVX512_4FMAPS 3
#define bit KF(x)(KVM_CPUID_BIT_##x)

int kvm_update_cpuid(struct kvm_vcpu *vcpu)
{
cấu trúc kvm_cpuid_entry2 *tốt nhất;
struct kvm_lapic *apic = vcpu->arch.apic;

tốt nhất = kvm_find_cpuid_entry(vcpu, 1, 0);
nếu (!tốt nhất)
return 0;

/* Cập nhật bit OSXSAVE */
if (boot_cpu_has(X86_FEATURE_XSAVE) && best->function == 0x1) {
tốt nhất->ecx &= ~F(OSXSAVE);
nếu (kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE))
tốt nhất->ecx |= F(OSXSAVE);
}

tốt nhất->edx &= ~F(APIC);
nếu (vcpu->arch.apic_base & MSR_IA32_APICBASE_ENABLE)
tốt nhất->edx |= F(APIC);

nếu (apic) {
if (tốt nhất->ecx & F(TSC_DEADLINE_TIMER))
apic->lapic_timer.timer_mode_mask = 3 << 17;
khác
apic->lapic_timer.timer_mode_mask = 1 << 17;
}

tốt nhất = kvm_find_cpuid_entry(vcpu, 7, 0);
nếu (tốt nhất) {
/* Cập nhật bit OSPKE */
if (boot_cpu_has(X86_FEATURE_PKU) && best->function == 0x7) {
tốt nhất->ecx &= ~F(OSPKE);
nếu (kvm_read_cr4_bits(vcpu, X86_CR4_PKE))
tốt nhất->ecx |= F(OSPKE);
}
}

tốt nhất = kvm_find_cpuid_entry(vcpu, 0xD, 0);
nếu (!tốt nhất) {
vcpu->arch.guest_supported_xcr0 = 0;
vcpu->arch.guest_xstate_size = XSAVE_HDR_SIZE + XSAVE_HDR_OFFSET;
} khác {
vcpu->arch.guest_supported_xcr0 =
(tốt nhất->eax | ((u64)tốt nhất->edx << 32)) &
kvm_supported_xcr0();
vcpu->arch.guest_xstate_size = tốt nhất->ebx =
xstate_required_size(vcpu->arch.xcr0, false);
}

tốt nhất = kvm_find_cpuid_entry(vcpu, 0xD, 1);
if (tốt nhất && (tốt nhất->eax & (F(XSAVES) | F(XSAVEC))))
best->ebx = xstate_required_size(vcpu->arch.xcr0, true);

/*
* Mã hiện tại giả sử địa chỉ ảo là 48-bit hoặc 57-bit trong
* kiểm tra địa chỉ chuẩn sẽ thoát nếu nó được thay đổi.
*/
tốt nhất = kvm_find_cpuid_entry(vcpu, 0x80000008, 0);
nếu (tốt nhất) {
int vaddr_bits = (best->eax & 0xff00) >> 8;

if (vaddr_bits != 48 && vaddr_bits != 57 && vaddr_bits != 0)
trả về -EINVAL;
}

/* Cập nhật độ rộng địa chỉ vật lý */
vcpu->arch.maxphyaddr = cpuid_query_maxphyaddr(vcpu);
kvm_mmu_reset_context(vcpu);

kvm_pmu_refresh(vcpu);
return 0;
}

int tĩnh is_efer_nx(void)
{
unsigned long long efer = 0;

rdmsrl_safe(MSR_EFER, &efer);
trả lại efer & EFER_NX;
}

khoảng trống tĩnh cpuid_fix_nx_cap(struct kvm_vcpu *vcpu)
{
int i;
struct kvm_cpuid_entry2 *e, *entry;

mục nhập = NULL;
for (i = 0; i < vcpu->arch.cpuid_nent; ++i) {
e = &vcpu->arch.cpuid_entries[i];
nếu (e->hàm == 0x80000001) {
mục = e;
phá vỡ;
}
}
if (entry && (entry->edx & F(NX)) && !is_efer_nx()) {
mục->edx &= ~F(NX);
printk(KERN_INFO "kvm: khả năng NX của khách đã bị loại bỏ\n");
}
}

int cpuid_query_maxphyaddr(struct kvm_vcpu *vcpu)
{
cấu trúc kvm_cpuid_entry2 *tốt nhất;

tốt nhất = kvm_find_cpuid_entry(vcpu, 0x80000000, 0);
if (!tốt nhất || tốt nhất->eax < 0x80000008)
đã không tìm thấy;
tốt nhất = kvm_find_cpuid_entry(vcpu, 0x80000008, 0);
nếu (tốt nhất)
trả về tốt nhất->eax & 0xff;
không_tìm thấy:
trả lại 36;
}
XUẤT_SYMBOL_GPL(cpuid_query_maxphyaddr);

/* khi tiến trình vùng người dùng cũ lấp đầy mô-đun hạt nhân mới */
int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
cấu trúc kvm_cpuid *cpuid,
struct kvm_cpuid_entry __user *mục)
{
int r, tôi;
struct kvm_cpuid_entry *cpuid_entries = NULL;

r = -E2BIG;
nếu (cpuid->nent > KVM_MAX_CPUID_ENTRIES)
đi ra ngoài;
r = -ENOMEM;
nếu (cpuid->nent) {
cpuid_entries = vmalloc(sizeof(struct kvm_cpuid_entry) *
cpuid->nent);
nếu (! cpuid_entries)
đi ra ngoài;
r = -EFAULT;
if (copy_from_user(cpuid_entries, mục,
cpuid->nent * sizeof(struct kvm_cpuid_entry)))
đi ra ngoài;
}
for (i = 0; i < cpuid->nent; i++) {
vcpu->arch.cpuid_entries[i].function = cpuid_entries[i].function;
vcpu->arch.cpuid_entries[i].eax = cpuid_entries[i].eax;
vcpu->arch.cpuid_entries[i].ebx = cpuid_entries[i].ebx;
vcpu->arch.cpuid_entries[i].ecx = cpuid_entries[i].ecx;
vcpu->arch.cpuid_entries[i].edx = cpuid_entries[i].edx;
vcpu->arch.cpuid_entries[i].index = 0;
vcpu->arch.cpuid_entries[i].flags = 0;
vcpu->arch.cpuid_entries[i].padding[0] = 0;
vcpu->arch.cpuid_entries[i].padding[1] = 0;
vcpu->arch.cpuid_entries[i].padding[2] = 0;
}
vcpu->arch.cpuid_nent = cpuid->nent;
cpuid_fix_nx_cap(vcpu);
kvm_apic_set_version(vcpu);
kvm_x86_ops->cpuid_update(vcpu);
r = kvm_update_cpuid(vcpu);

ngoài:
vfree(cpuid_entries);
trả lại r;
}

int kvm_vcpu_ioctl_set_cpuid2(struct kvm_vcpu *vcpu,
cấu trúc kvm_cpuid2 *cpuid,
struct kvm_cpuid_entry2 __user *mục)
{
int r;

r = -E2BIG;
nếu (cpuid->nent > KVM_MAX_CPUID_ENTRIES)
đi ra ngoài;
r = -EFAULT;
if (copy_from_user(&vcpu->arch.cpuid_entries, mục,
cpuid->nent * sizeof(struct kvm_cpuid_entry2)))
đi ra ngoài;
vcpu->arch.cpuid_nent = cpuid->nent;
kvm_apic_set_version(vcpu);
kvm_x86_ops->cpuid_update(vcpu);
r = kvm_update_cpuid(vcpu);
ngoài:
trả lại r;
}

int kvm_vcpu_ioctl_get_cpuid2(struct kvm_vcpu *vcpu,
cấu trúc kvm_cpuid2 *cpuid,
struct kvm_cpuid_entry2 __user *mục)
{
int r;

r = -E2BIG;
if (cpuid->nent < vcpu->arch.cpuid_nent)
đi ra ngoài;
r = -EFAULT;
if (copy_to_user(entry, &vcpu->arch.cpuid_entries,
vcpu->arch.cpuid_nent * sizeof(struct kvm_cpuid_entry2)))
đi ra ngoài;
return 0;

ngoài:
cpuid->nent = vcpu->arch.cpuid_nent;
trả lại r;
}

tĩnh void cpuid_mask(u32 *word, int wordnum)
{
*word &= boot_cpu_data.x86_capability[wordnum];
}

static void do_cpuid_1_ent(struct kvm_cpuid_entry2 *entry, hàm u32,
chỉ số u32)
{
mục->chức năng = chức năng;
mục-> chỉ mục = chỉ mục;
cpuid_count(entry->function, entry->index,
&entry->eax, &entry->ebx, &entry->ecx, &entry->edx);
mục-> cờ = 0;
}

int tĩnh __do_cpuid_ent_emulated(struct kvm_cpuid_entry2 *entry,
u32 func, chỉ mục u32, int *nent, int maxnent)
{
chuyển đổi (chức năng) {
trường hợp 0:
entry->eax = 1; /* hiện tại chỉ có một lá */
++*nent;
phá vỡ;
trường hợp 1:
mục->ecx = F(MOVBE);
++*nent;
phá vỡ;
default:
phá vỡ;
}

mục->hàm = func;
mục-> chỉ mục = chỉ mục;

return 0;
}

int nội tuyến tĩnh __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, hàm u32,
chỉ mục u32, int *nent, int maxnent)
{
int r;
chưa ký f_nx = is_efer_nx() ? F(NX) : 0;
#ifdef CONFIG_X86_64
f_gbpages chưa được ký = (kvm_x86_ops->get_lpage_level() == PT_PDPE_LEVEL)
?F(GBPAGES): 0;
không dấu f_lm = F(LM);
#else
f_gbpages không dấu = 0;
không dấu f_lm = 0;
#endif
chưa ký f_rdtscp = kvm_x86_ops->rdtscp_supported() ? F(RDTSCP) : 0;
chưa ký f_invpcid = kvm_x86_ops->invpcid_supported() ? F(INVPCID) : 0;
không dấu f_mpx = kvm_mpx_supported() ? F(MPX) : 0;
chưa ký f_xsaves = kvm_x86_ops->xsaves_supported() ? F(XSAVES) : 0;

/* cpuid 1.edx */
const u32 kvm_cpuid_1_edx_x86_features =
F(FPU) | F(VME) F(DE) |
F(TSC) | F(MSR) F(PAE) |
F(CX8) | F(APIC) 0 /* Dự trữ */ |
F(MTRR) | F(PGE) F(MCA) |
F(PAT) | F(PSE36) |
0 /* Dành riêng, DS, ACPI */ F(MMX) |
F(FXSR) | F(XMM) F(XMM2) F(TỰ TIN) |
0 /* HTT, TM, Dự trữ, PBE */;
/* cpuid 0x80000001.edx */
const u32 kvm_cpuid_8000_0001_edx_x86_features =
F(FPU) | F(VME) F(DE) |
F(TSC) | F(MSR) F(PAE) |
F(CX8) | F(APIC) 0 /* Dành riêng */ |
F(MTRR) | F(PGE) F(MCA) |
F(PAT) | F(PSE36) 0 /* Dành riêng */ |
f_nx | 0 /* Dành riêng */ F(MMXEXT) |
F(FXSR) | F(FXSR_OPT) |
0 /* Dành riêng */ f_lm F(3DNOWEXT) |
/* cpuid 1.ecx */
const u32 kvm_cpuid_1_ecx_x86_features =
/* LƯU Ý: MONITOR (và MWAIT) được mô phỏng dưới dạng NOP,
* nhưng *không* được quảng cáo cho khách qua CPUID */
F(XMM3) | F(PCLMULQDQ) 0 /* DTES64, GIÁM SÁT */ |
0 /* DS-CPL, VMX, SMX, EST */ |
0 /* TM2 */ | F(SSSE3) 0 /* CNXT-ID */ 0 /* Dành riêng */ |
F(FMA) | F(CX16) 0 /* xTPR Cập nhật, PDCM */ |
F(PCID) | 0 /* Dự trữ, DCA */ F(XMM4_1) |
F(XMM4_2) | F(X2APIC) F(MOVBE) F(POPCNT) |
0 /* Dành riêng*/ | F(AES) F(XSAVE) 0 /* OSXSAVE */ |
F(F16C) | F(RDDRAND);
/* cpuid 0x80000001.ecx */
const u32 kvm_cpuid_8000_0001_ecx_x86_features =
F(LAHF_LM) | F(CMP_LEGACY) 0 /*SVM*/ 0 /* ExtApicSpace */ |
F(CR8_LEGACY) | F(ABM) F(SSE4A) F(MISALIGNSSE) |
F(3DNOWPREFETCH) | F(OSVW) |
0 /* SKINIT, WDT, LWP */ F(FMA4) ​​F(TBM);

/* cpuid 0xC0000001.edx */
const u32 kvm_cpuid_C000_0001_edx_x86_features =
F(XSTORE) | F(XSTORE_EN) F(XCRYPT) F(XCRYPT_EN) |
F(ACE2) | F(ACE2_EN) F(PHE) |
F(PMM) | F(PMM_EN);

/* cpuid 7.0.ebx */
const u32 kvm_cpuid_7_0_ebx_x86_features =
F(FSGSBASE) | F(BMI1) F(HLE) |
F(BMI2) | F(ERMS) | F_invpcid |
F(ADX) | F(SMAP) F(AVX512IFMA) |
F(AVX512ER) | F(AVX512CD) | F(CLFUSHOPT) F(CLWB) |
F(SHA_NI) | F(AVX512BW) | F(AVX512VL);

/* cpuid 0xD.1.eax */
const u32 kvm_cpuid_D_1_eax_x86_features =
F(XSAVEOPT) | F(XSAVEC) F(XGETBV1) |

/* cpuid 7.0.ecx*/
const u32 kvm_cpuid_7_0_ecx_x86_features =
F(AVX512VBMI) F(LA57) |
0 /*OSPKE*/ F(AVX512_VPOPCNTDQ);

/* cpuid 7.0.edx*/
const u32 kvm_cpuid_7_0_edx_x86_features =
KF(AVX512_4VNNIW) | KF(AVX512_4FMAPS);

/* tất cả lệnh gọi tới cpuid_count() phải được thực hiện trên cùng một cpu */
get_cpu();

r = -E2BIG;

nếu (*nent >= maxnent)
đi ra ngoài;

do_cpuid_1_ent(mục nhập, hàm, chỉ mục);
++*nent;

chuyển đổi (chức năng) {
trường hợp 0:
mục->eax = min(entry->eax, (u32)0xd);
phá vỡ;
trường hợp 1:
mục->edx &= kvm_cpuid_1_edx_x86_features;
cpuid_mask(&entry->edx, CPUID_1_EDX);
mục->ecx &= kvm_cpuid_1_ecx_x86_features;
cpuid_mask(&entry->ecx, CPUID_1_ECX);
/* chúng tôi hỗ trợ mô phỏng x2apic ngay cả khi máy chủ không hỗ trợ
* đó là do chúng tôi mô phỏng x2apic trong phần mềm */
mục->ecx |= F(X2APIC);
phá vỡ;
/* mục nhập hàm 2 là TRANG TRẠNG Nghĩa là, các lệnh cpuid được lặp lại.
* có thể trả về các giá trị khác nhau. Điều này buộc chúng ta phải get_cpu() trước đó.
* đưa ra lệnh đầu tiên và cũng để mô phỏng hành vi gây phiền nhiễu này
* trong kvm_emulate_cpuid() sử dụng KVM_CPUID_FLAG_STATE_READ_NEXT */
trường hợp 2: {
int t, lần = entry->eax & 0xff;

mục->cờ |= KVM_CPUID_FLAG_STATEFUL_FUNC;
mục->cờ |= KVM_CPUID_FLAG_STATE_READ_NEXT;
for (t = 1; t < lần; ++t) {
nếu (*nent >= maxnent)
đi ra ngoài;

do_cpuid_1_ent(&entry[t], hàm, 0);
mục [t].flags |= KVM_CPUID_FLAG_STATEFUL_FUNC;
++*nent;
}
phá vỡ;
}
/* hàm 4 có chỉ mục bổ sung */
trường hợp 4: {
int tôi, cache_type;

mục->cờ |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
/* đọc thêm mục cho đến khi cache_type bằng 0 */
vì (i = 1; ; ++i) {
nếu (*nent >= maxnent)
đi ra ngoài;

cache_type = entry[i - 1].eax & 0x1f;
nếu (!cache_type)
phá vỡ;
do_cpuid_1_ent(&entry[i], hàm, i);
entry[i].flags |=
KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
++*nent;
}
phá vỡ;
}
trường hợp 6: /* Quản lý nhiệt */
mục->eax = 0x4; /* cho phép ARAT */
mục->ebx = 0;
mục->ecx = 0;
mục->edx = 0;
phá vỡ;
trường hợp 7: {
mục->cờ |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
/* Che dấu ebx chống lại khả năng của từ máy chủ 9 */
nếu (chỉ mục == 0) {
mục->ebx &= kvm_cpuid_7_0_ebx_x86_features;
cpuid_mask(&entry->ebx, CPUID_7_0_EBX);
// TSC_ADJUST được mô phỏng
mục->ebx |= F(TSC_ADJUST);
mục->ecx &= kvm_cpuid_7_0_ecx_x86_features;
cpuid_mask(&entry->ecx, CPUID_7_ECX);
/* PKU chưa được triển khai cho phân trang bóng */
if (!tdp_enabled || !boot_cpu_has(X86_FEATURE_OSPKE))
mục->ecx &= ~F(PKU);
mục->edx &= kvm_cpuid_7_0_edx_x86_features;
entry->edx &= get_scattered_cpuid_leaf(7, 0, CPUID_EDX);
} khác {
mục->ebx = 0;
mục->ecx = 0;
mục->edx = 0;
}
mục->eax = 0;
phá vỡ;
}
trường hợp 9:
phá vỡ;
trường hợp 0xa: { /* Giám sát hiệu suất kiến ​​trúc */
giới hạn cấu trúc x86_pmu_capability;
liên kết cpuid10_eax eax;
liên đoàn cpuid10_edx edx;

perf_get_x86_pmu_capability(&cap);

/*
* Chỉ hỗ trợ pmu kiến ​​trúc khách trên máy chủ
* với pmu kiến ​​trúc.
*/
nếu (!cap.version)
bộ nhớ(&cap, 0, sizeof(cap));

eax.split.version_id = min(cap.version, 2);
eax.split.num_counters = cap.num_counters_gp;
eax.split.bit_width = cap.bit_width_gp;
eax.split.mask_length = cap.events_mask_len;

edx.split.num_counters_fixed = cap.num_counters_fixed;
edx.split.bit_width_fixed = cap.bit_width_fixed;
edx.split.reserved = 0;

mục->eax = eax.full;
mục->ebx = cap.events_mask;
mục->ecx = 0;
mục->edx = edx.full;
phá vỡ;
}
/* Hàm 0xb có chỉ mục bổ sung */
trường hợp 0xb: {
int tôi, cấp_type;

mục->cờ |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
/* đọc thêm mục cho đến khi Level_type bằng 0 */
vì (i = 1; ; ++i) {
nếu (*nent >= maxnent)
đi ra ngoài;

cấp_type = mục [i - 1].ecx & 0xff00;
nếu (!level_type)
phá vỡ;
do_cpuid_1_ent(&entry[i], hàm, i);
entry[i].flags |=
KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
++*nent;
}
phá vỡ;
}
trường hợp 0xd: {
int idx, tôi;
u64 được hỗ trợ = kvm_supported_xcr0();

mục->eax &= được hỗ trợ;
entry->ebx = xstate_required_size(được hỗ trợ, sai);
mục->ecx = mục->ebx;
entry->edx &= được hỗ trợ >> 32;
mục->cờ |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
nếu (!được hỗ trợ)
phá vỡ;

cho (idx = 1, i = 1; idx < 64; ++idx) {
mặt nạ u64 = ((u64)1 << idx);
nếu (*nent >= maxnent)
đi ra ngoài;

do_cpuid_1_ent(&entry[i], hàm, idx);
nếu (idx == 1) {
entry[i].eax &= kvm_cpuid_D_1_eax_x86_features;
cpuid_mask(&entry[i].eax, CPUID_D_1_EAX);
entry[i].ebx = 0;
if (entry[i].eax & (F(XSAVES)|F(XSAVEC)))
entry[i].ebx =
xstate_required_size(được hỗ trợ,
ĐÚNG VẬY);
} khác {
if (entry[i].eax == 0 || !(được hỗ trợ & mặt nạ))
continue;
if (WARN_ON_ONCE(entry[i].ecx & 1))
continue;
}
entry[i].ecx = 0;
entry[i].edx = 0;
entry[i].flags |=
KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
++*nent;
++tôi;
}
phá vỡ;
}
trường hợp KVM_CPUID_SIGNATURE: {
chữ ký const char tĩnh [12] = "KVMKVMKVM\0\0";
const u32 *sigptr = (const u32 *)chữ ký;
mục->eax = KVM_CPUID_FEATURES;
mục->ebx = sigptr[0];
mục->ecx = sigptr[1];
entry->edx = sigptr[2];
phá vỡ;
}
trường hợp KVM_CPUID_FEATURES:
mục->eax = (1 << KVM_FEATURE_CLOCKSOURCE) |
(1 << KVM_FEATURE_NOP_IO_DELAY) |
(1 << KVM_FEATURE_CLOCKSOURCE2) |
(1 << KVM_FEATURE_ASYNC_PF) |
(1 << KVM_FEATURE_PV_EOI) |
(1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT) |
(1 << KVM_FEATURE_PV_UNHALT);

nếu (lịch_info_on())
mục->eax |= (1 << KVM_FEATURE_STEAL_TIME);

mục->ebx = 0;
mục->ecx = 0;
mục->edx = 0;
phá vỡ;
trường hợp 0x80000000:
mục->eax = min(entry->eax, 0x8000001a);
phá vỡ;
trường hợp 0x80000001:
mục->edx &= kvm_cpuid_8000_0001_edx_x86_features;
cpuid_mask(&entry->edx, CPUID_8000_0001_EDX);
mục->ecx &= kvm_cpuid_8000_0001_ecx_x86_features;
cpuid_mask(&entry->ecx, CPUID_8000_0001_ECX);
phá vỡ;
trường hợp 0x80000007: /* Quản lý nguồn nâng cao */
/* TSC bất biến là CPUID.80000007H:EDX[8] */
mục->edx &= (1 << 8);
/* che dấu máy chủ */
entry->edx &= boot_cpu_data.x86_power;
mục->eax = mục->ebx = mục->ecx = 0;
phá vỡ;
trường hợp 0x80000008: {
unsigned g_phys_as = (entry->eax >> 16) & 0xff;
unsigned virt_as = max((entry->eax >> 8) & 0xff, 48U);
phys_as không dấu = entry->eax & 0xff;

nếu (!g_phys_as)
g_phys_as = Phys_as;
mục->eax = g_phys_as | (virt_as << 8);
mục->ebx = mục->edx = 0;
phá vỡ;
}
trường hợp 0x80000019:
mục->ecx = mục->edx = 0;
phá vỡ;
trường hợp 0x8000001a:
phá vỡ;
trường hợp 0x8000001d:
phá vỡ;
/*Thêm hỗ trợ cho lệnh CPUID của Centaur*/
trường hợp 0xC0000000:
/*Bây giờ chỉ hỗ trợ tối đa 0xC0000004*/
mục->eax = min(entry->eax, 0xC0000004);
phá vỡ;
trường hợp 0xC0000001:
mục->edx &= kvm_cpuid_C000_0001_edx_x86_features;
cpuid_mask(&entry->edx, CPUID_C000_0001_EDX);
phá vỡ;
trường hợp 3: /* Số sê-ri bộ xử lý */
trường hợp 5: /* MONITOR/MWAIT */
trường hợp 0xC0000002:
trường hợp 0xC0000003:
trường hợp 0xC0000004:
default:
entry->eax = entry->ebx = entry->ecx = entry->edx = 0;
phá vỡ;
}

kvm_x86_ops->set_supported_cpuid(hàm, mục nhập);

r = 0;

ngoài:
put_cpu();

trả lại r;
}

int tĩnh do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 func,
u32 idx, int *nent, int maxnent, kiểu int không dấu)
{
nếu (loại == KVM_GET_EMULATED_CPUID)
return __do_cpuid_ent_emulated(entry, func, idx, nent, maxnent);

return __do_cpuid_ent(entry, func, idx, nent, maxnent);
}

#undef F

cấu trúc kvm_cpuid_param {
chức năng u32;
u32idx;
bool has_leaf_count;
bool (*bộ định tính)(const struct kvm_cpuid_param *param);
};

bool tĩnh is_centaur_cpu(const struct kvm_cpuid_param *param)
{
trả về boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR;
}

bool tĩnh sanity_check_entries(struct kvm_cpuid_entry2 __user *entries,
__u32 num_entries, int ioctl_type không dấu)
{
int i;
__u32 đệm[3];

nếu (ioctl_type != KVM_GET_EMULATED_CPUID)
trả về sai;

/*
* Chúng tôi muốn đảm bảo rằng -> phần đệm được chuyển sạch khỏi
* không gian người dùng trong trường hợp chúng tôi muốn sử dụng nó cho việc gì đó trong tương lai.
*
* Đáng buồn thay, điều này không được thực thi đối với KVM_GET_SUPPORTED_CPUID và vì vậy chúng tôi
* chỉ phải hài lòng với phía được mô phỏng /tôi.
* rơi nước mắt.
*/
for (i = 0; i < num_entries; i++) {
if (copy_from_user(pad,entry[i].padding, sizeof(pad)))
trả về đúng sự thật;

if (pad[0] || pad[1] || pad[2])
trả về đúng sự thật;
}
trả về sai;
}

int kvm_dev_ioctl_get_cpuid(struct kvm_cpuid2 *cpuid,
struct kvm_cpuid_entry2 __user *mục,
kiểu int không dấu)
{
cấu trúc kvm_cpuid_entry2 *cpuid_entries;
giới hạn int, nent = 0, r = -E2BIG, i;
chức năng u32;
cấu trúc const tĩnh kvm_cpuid_param param[] = {
{ .func = 0, .has_leaf_count = true },
{ .func = 0x80000000, .has_leaf_count = true },
{ .func = 0xC0000000, .qualifier = is_centaur_cpu, .has_leaf_count = true },
{ .func = KVM_CPUID_SIGNATURE },
{ .func = KVM_CPUID_FEATURES },
};

nếu (cpuid->nent < 1)
đi ra ngoài;
nếu (cpuid->nent > KVM_MAX_CPUID_ENTRIES)
cpuid->nent = KVM_MAX_CPUID_ENTRIES;

if (sanity_check_entries(entries, cpuid->nent, type))
trả về -EINVAL;

r = -ENOMEM;
cpuid_entries = vzalloc(sizeof(struct kvm_cpuid_entry2) * cpuid->nent);
nếu (! cpuid_entries)
đi ra ngoài;

r = 0;
for (i = 0; i < ARRAY_SIZE(param); i++) {
const struct kvm_cpuid_param *ent = ¶m[i];

if (ent->bộ định tính && !ent->bộ định tính(ent))
continue;

r = do_cpuid_ent(&cpuid_entries[nent], ent->func, ent->idx,
&nent, cpuid->nent, loại);

nếu(r)
đi out_free;

if (!ent->has_leaf_count)
continue;

giới hạn = cpuid_entries[nent - 1].eax;
for (func = ent->func + 1; func <= limit && nent < cpuid->nent && r == 0; ++func)
r = do_cpuid_ent(&cpuid_entries[nent], func, ent->idx,
&nent, cpuid->nent, loại);

nếu(r)
đi out_free;
}

r = -EFAULT;
if (copy_to_user(entries, cpuid_entries,
nent * sizeof(struct kvm_cpuid_entry2)))
đi out_free;
cpuid->nent = nent;
r = 0;

out_free:
vfree(cpuid_entries);
ngoài:
trả lại r;
}

int tĩnh move_to_next_stateful_cpuid_entry(struct kvm_vcpu *vcpu, int i)
{
struct kvm_cpuid_entry2 *e = &vcpu->arch.cpuid_entries[i];
cấu trúc kvm_cpuid_entry2 *ej;
int j = i;
int nent = vcpu->arch.cpuid_nent;

e->cờ &= ~KVM_CPUID_FLAG_STATE_READ_NEXT;
/* khi không tìm thấy mục tiếp theo, mục hiện tại[i] sẽ được chọn lại */
LÀM {
j = (j + 1) % nent;
ej = &vcpu->arch.cpuid_entries[j];
} while (ej->function != e->function);

ej->cờ |= KVM_CPUID_FLAG_STATE_READ_NEXT;

trả lại j;
}

/* tìm một mục có hàm khớp, chỉ mục khớp (nếu cần) và mục đó
* nên đọc tiếp theo (nếu nó có trạng thái) */
int tĩnh is_matching_cpuid_entry(struct kvm_cpuid_entry2 *e,
hàm u32, chỉ mục u32)
{
if (e->function != function)
return 0;
if ((e->flags & KVM_CPUID_FLAG_SIGNIFCANT_INDEX) && e->index != chỉ mục)
return 0;
if ((e->flags & KVM_CPUID_FLAG_STATEFUL_FUNC) &&
!(e->cờ & KVM_CPUID_FLAG_STATE_READ_NEXT))
return 0;
return 1;
}

struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu,
hàm u32, chỉ mục u32)
{
int i;
cấu trúc kvm_cpuid_entry2 *tốt nhất = NULL;

for (i = 0; i < vcpu->arch.cpuid_nent; ++i) {
cấu trúc kvm_cpuid_entry2 *e;

e = &vcpu->arch.cpuid_entries[i];
if (is_matching_cpuid_entry(e, hàm, chỉ mục)) {
nếu (e->cờ & KVM_CPUID_FLAG_STATEFUL_FUNC)
move_to_next_stateful_cpuid_entry(vcpu, i);
tốt nhất = e;
phá vỡ;
}
}
trở lại tốt nhất;
}
EXPORT_SYMBOL_GPL(kvm_find_cpuid_entry);

/*
* Nếu không tìm thấy kết quả phù hợp, hãy kiểm tra xem chúng tôi có vượt quá giới hạn của vCPU không
* và thay vào đó trả về nội dung của lá _standard_ hợp lệ cao nhất.
* Điều này nhằm đáp ứng đặc tả CPUID.
*/
cấu trúc tĩnh kvm_cpuid_entry2* check_cpuid_limit(struct kvm_vcpu *vcpu,
hàm u32, chỉ mục u32)
{
cấu trúc kvm_cpuid_entry2 *maxlevel;

maxlevel = kvm_find_cpuid_entry(vcpu, hàm & 0x80000000, 0);
if (!maxlevel || maxlevel->eax >= chức năng)
trả về NULL;
nếu (hàm & 0x80000000) {
maxlevel = kvm_find_cpuid_entry(vcpu, 0, 0);
nếu (! mức tối đa)
trả về NULL;
}
trả về kvm_find_cpuid_entry(vcpu, maxlevel->eax, index);
}

bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx,
u32 *ecx, u32 *edx, bool check_limit)
{
hàm u32 = *eax, chỉ mục = *ecx;
cấu trúc kvm_cpuid_entry2 *tốt nhất;
bool entry_found = true;

tốt nhất = kvm_find_cpuid_entry(vcpu, hàm, chỉ mục);

nếu (!tốt nhất) {
entry_found = sai;
nếu (!check_limit)
đi ra ngoài;

tốt nhất = check_cpuid_limit(vcpu, hàm, chỉ mục);
}

ngoài:
nếu (tốt nhất) {
*eax = tốt nhất->eax;
*ebx = tốt nhất->ebx;
*ecx = tốt nhất->ecx;
*edx = tốt nhất->edx;
} else
*eax = *ebx = *ecx = *edx = 0;
trace_kvm_cpuid(hàm, *eax, *ebx, *ecx, *edx, entry_found);
trả lại entry_found;
}
XUẤT_SYMBOL_GPL(kvm_cpuid);

int kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
{
u32 eax, ebx, ecx, edx;

if (cpuid_fault_enabled(vcpu) && !kvm_require_cpl(vcpu, 0))
return 1;

eax = kvm_register_read(vcpu, VCPU_REGS_RAX);
ecx = kvm_register_read(vcpu, VCPU_REGS_RCX);
kvm_cpuid(vcpu, &eax, &ebx, &ecx, &edx, true);
kvm_register_write(vcpu, VCPU_REGS_RAX, eax);
kvm_register_write(vcpu, VCPU_REGS_RBX, ebx);
kvm_register_write(vcpu, VCPU_REGS_RCX, ecx);
kvm_register_write(vcpu, VCPU_REGS_RDX, edx);
trả về kvm_skip_emulated_instruction(vcpu);
}
EXPORT_SYMBOL_GPL(kvm_emulate_cpuid);

Tôi muốn thêm/chỉnh sửa mã vào KVM trong cây linux của bạn (tôi đã sao chép kernel từ github), xây dựng lại kernel và khởi động vào kernel đã sửa đổi và chạy các chương trình chế độ người dùng c như

#include 
#include
#include

int
chính(int argc, char **argv)
{
uint32_t eax, ebx, ecx, edx;

__cpuid(0x0, eax, ebx, ecx, edx);

printf("CPUID(0x0).EAX=0x%x\n", eax);
printf("CPUID(0x0).EBX=0x%x\n", ebx);
printf("CPUID(0x0).ECX=0x%x\n", ecx);
printf("CPUID(0x0).EDX=0x%x\n", edx);

return 0;
}

Nhận đầu ra tương tự như

Chuỗi thương hiệu CPUID(0x0) = Chính hãngIntel
CPUID(0x4FFFFFFF)
Chuỗi thương hiệu CPUID(0x0) = MỘT SỐ VĂN BẢN
CPUID(0x4FFFFFFF)

câu trả lời hay nhất

Bản thân hạt nhân không triển khai bất kỳ mô phỏng CPUID cụ thể nào; việc này được triển khai bởi các máy khách KVM, chẳng hạn như QEMU. Ví dụ,đây là mã có liên quan trong QEMU , đã được triển khai cho nhiều thương hiệu bộ xử lý hư cấu, chẳng hạn như "CPU ảo QEMU".

Ngoài ra, mô phỏng KVM CPUID chỉ ảnh hưởng đến các máy ảo được lưu trữ bởi máy chạy kernel đó. Nó không ảnh hưởng đến các ứng dụng không gian người dùng thông thường trên máy đó.

Về linux - Làm thế nào hoặc tệp nào được sửa đổi trong mã mô phỏng CPUID của KVM để báo cáo chuỗi thương hiệu bộ xử lý hư cấu (lá CPUID 0x0)? , chúng tôi đã tìm thấy một câu hỏi tương tự trên Stack Overflow: https://stackoverflow.com/questions/47065659/

hai mươi bốn 4 0
Taklimakan
Hồ sơ

Tôi là một lập trình viên xuất sắc, rất giỏi!

Nhận phiếu giảm giá taxi Didi miễn phí
Phiếu giảm giá taxi Didi
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress