/* * The "cpuid" instruction is a way of querying both the CPU identity * (manufacturer, model, etc) and its features. It was introduced before the * Pentium in 1993 and keeps getting extended by both Intel, AMD and others. * As you might imagine, after a decade and a half this treatment, it is now a * giant ball of hair. Its entry in the current Intel manual runs to 28 pages. * * This instruction even it has its own Wikipedia entry. The Wikipedia entry * has been translated into 5 languages. I am not making this up! * * We could get funky here and identify ourselves as "GenuineLguest", but * instead we just use the real "cpuid" instruction. Then I pretty much turned * off feature bits until the Guest booted. (Don't say that: you'll damage * lguest sales!) Shut up, inner voice! (Hey, just pointing out that this is * hardly future proof.) No one's listening! They don't like you anyway, * parenthetic weirdo! * * Replacing the cpuid so we can turn features off is great for the kernel, but * anyone (including userspace) can just use the raw "cpuid" instruction and * the Host won't even notice since it isn't privileged. So we try not to get * too worked up about it. */ static void lguest_cpuid(unsigned int *ax, unsigned int *bx, unsigned int *cx, unsigned int *dx) { int function = *ax; native_cpuid(ax, bx, cx, dx); switch (function) { /* * CPUID 0 gives the highest legal CPUID number (and the ID string). * We futureproof our code a little by sticking to known CPUID values. */ case 0: if (*ax > 5) *ax = 5; break; /* * CPUID 1 is a basic feature request. * * CX: we only allow kernel to see SSE3, CMPXCHG16B and SSSE3 * DX: SSE, SSE2, FXSR, MMX, CMOV, CMPXCHG8B, TSC, FPU and PAE. */ case 1: *cx &= 0x00002201; *dx &= 0x07808151; /* * The Host can do a nice optimization if it knows that the * kernel mappings (addresses above 0xC0000000 or whatever * PAGE_OFFSET is set to) haven't changed. But Linux calls * flush_tlb_user() for both user and kernel mappings unless * the Page Global Enable (PGE) feature bit is set. */ *dx |= 0x00002000; /* * We also lie, and say we're family id 5. 6 or greater * leads to a rdmsr in early_init_intel which we can't handle. * Family ID is returned as bits 8-12 in ax. */ *ax &= 0xFFFFF0FF; *ax |= 0x00000500; break; /* * 0x80000000 returns the highest Extended Function, so we futureproof * like we do above by limiting it to known fields. */ case 0x80000000: if (*ax > 0x80000008) *ax = 0x80000008; break; /* * PAE systems can mark pages as non-executable. Linux calls this the * NX bit. Intel calls it XD (eXecute Disable), AMD EVP (Enhanced * Virus Protection). We just switch turn if off here, since we don't * support it. */ case 0x80000001: *dx &= ~(1 << 20); break; } }
void ffdecsa_init(void) { current = funcs_32int; #if defined(__i386__) || defined(__x86_64__) unsigned int eax, ebx, ecx, edx; unsigned int max_std_level, std_caps; #if defined(__i386__) x86_reg a, c; __asm__ volatile ( /* See if CPUID instruction is supported ... */ /* ... Get copies of EFLAGS into eax and ecx */ "pushfl\n\t" "pop %0\n\t" "mov %0, %1\n\t" /* ... Toggle the ID bit in one copy and store */ /* to the EFLAGS reg */ "xor $0x200000, %0\n\t" "push %0\n\t" "popfl\n\t" /* ... Get the (hopefully modified) EFLAGS */ "pushfl\n\t" "pop %0\n\t" : "=a" (a), "=c" (c) : : "cc" ); if (a != c) { #endif eax = ebx = ecx = edx = 0; native_cpuid(&eax, &ebx, &ecx, &edx); max_std_level = eax; if(max_std_level >= 1){ eax = 1; native_cpuid(&eax, &ebx, &ecx, &edx); std_caps = edx; #ifdef CONFIG_SSE2 if (std_caps & (1<<26)) { current = funcs_128sse2; tvhinfo(LS_CSA, "Using SSE2 128bit parallel descrambling"); return; } #endif #ifdef CONFIG_MMX if (std_caps & (1<<23)) { current = funcs_64mmx; tvhinfo(LS_CSA, "Using MMX 64bit parallel descrambling"); return; } #endif } #if defined(__i386__) } #endif #endif tvhinfo(LS_CSA, "Using 32bit parallel descrambling"); }
static bool __init xen_check_mwait(void) { #if defined(CONFIG_ACPI) && !defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) && \ !defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE) struct xen_platform_op op = { .cmd = XENPF_set_processor_pminfo, .u.set_pminfo.id = -1, .u.set_pminfo.type = XEN_PM_PDC, }; uint32_t buf[3]; unsigned int ax, bx, cx, dx; unsigned int mwait_mask; /* We need to determine whether it is OK to expose the MWAIT * capability to the kernel to harvest deeper than C3 states from ACPI * _CST using the processor_harvest_xen.c module. For this to work, we * need to gather the MWAIT_LEAF values (which the cstate.c code * checks against). The hypervisor won't expose the MWAIT flag because * it would break backwards compatibility; so we will find out directly * from the hardware and hypercall. */ if (!xen_initial_domain()) return false; ax = 1; cx = 0; native_cpuid(&ax, &bx, &cx, &dx); mwait_mask = (1 << (X86_FEATURE_EST % 32)) | (1 << (X86_FEATURE_MWAIT % 32)); if ((cx & mwait_mask) != mwait_mask) return false; /* We need to emulate the MWAIT_LEAF and for that we need both * ecx and edx. The hypercall provides only partial information. */ ax = CPUID_MWAIT_LEAF; bx = 0; cx = 0; dx = 0; native_cpuid(&ax, &bx, &cx, &dx); /* Ask the Hypervisor whether to clear ACPI_PDC_C_C2C3_FFH. If so, * don't expose MWAIT_LEAF and let ACPI pick the IOPORT version of C3. */ buf[0] = ACPI_PDC_REVISION_ID; buf[1] = 1; buf[2] = (ACPI_PDC_C_CAPABILITY_SMP | ACPI_PDC_EST_CAPABILITY_SWSMP); set_xen_guest_handle(op.u.set_pminfo.pdc, buf); if ((HYPERVISOR_dom0_op(&op) == 0) && (buf[2] & (ACPI_PDC_C_C1_FFH | ACPI_PDC_C_C2C3_FFH))) { cpuid_leaf5_ecx_val = cx; cpuid_leaf5_edx_val = dx; } return true; #else return false; #endif } static void __init xen_init_cpuid_mask(void) { unsigned int ax, bx, cx, dx; unsigned int xsave_mask; cpuid_leaf1_edx_mask = ~((1 << X86_FEATURE_MCE) | /* disable MCE */ (1 << X86_FEATURE_MCA) | /* disable MCA */ (1 << X86_FEATURE_MTRR) | /* disable MTRR */ (1 << X86_FEATURE_ACC)); /* thermal monitoring */ if (!xen_initial_domain()) cpuid_leaf1_edx_mask &= ~((1 << X86_FEATURE_APIC) | /* disable local APIC */ (1 << X86_FEATURE_ACPI)); /* disable ACPI */ ax = 1; cx = 0; xen_cpuid(&ax, &bx, &cx, &dx); xsave_mask = (1 << (X86_FEATURE_XSAVE % 32)) | (1 << (X86_FEATURE_OSXSAVE % 32)); /* Xen will set CR4.OSXSAVE if supported and not disabled by force */ if ((cx & xsave_mask) != xsave_mask) cpuid_leaf1_ecx_mask &= ~xsave_mask; /* disable XSAVE & OSXSAVE */ if (xen_check_mwait()) cpuid_leaf1_ecx_set_mask = (1 << (X86_FEATURE_MWAIT % 32)); }
static bool __init xen_check_mwait(void) { #if defined(CONFIG_ACPI) && !defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) && \ !defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE) struct xen_platform_op op = { .cmd = XENPF_set_processor_pminfo, .u.set_pminfo.id = -1, .u.set_pminfo.type = XEN_PM_PDC, }; uint32_t buf[3]; unsigned int ax, bx, cx, dx; unsigned int mwait_mask; /* */ if (!xen_initial_domain()) return false; ax = 1; cx = 0; native_cpuid(&ax, &bx, &cx, &dx); mwait_mask = (1 << (X86_FEATURE_EST % 32)) | (1 << (X86_FEATURE_MWAIT % 32)); if ((cx & mwait_mask) != mwait_mask) return false; /* */ ax = CPUID_MWAIT_LEAF; bx = 0; cx = 0; dx = 0; native_cpuid(&ax, &bx, &cx, &dx); /* */ buf[0] = ACPI_PDC_REVISION_ID; buf[1] = 1; buf[2] = (ACPI_PDC_C_CAPABILITY_SMP | ACPI_PDC_EST_CAPABILITY_SWSMP); set_xen_guest_handle(op.u.set_pminfo.pdc, buf); if ((HYPERVISOR_dom0_op(&op) == 0) && (buf[2] & (ACPI_PDC_C_C1_FFH | ACPI_PDC_C_C2C3_FFH))) { cpuid_leaf5_ecx_val = cx; cpuid_leaf5_edx_val = dx; } return true; #else return false; #endif } static void __init xen_init_cpuid_mask(void) { unsigned int ax, bx, cx, dx; unsigned int xsave_mask; cpuid_leaf1_edx_mask = ~((1 << X86_FEATURE_MCE) | /* */ (1 << X86_FEATURE_MCA) | /* */ (1 << X86_FEATURE_MTRR) | /* */ (1 << X86_FEATURE_ACC)); /* */ if (!xen_initial_domain()) cpuid_leaf1_edx_mask &= ~((1 << X86_FEATURE_APIC) | /* */ (1 << X86_FEATURE_ACPI)); /* */ ax = 1; cx = 0; xen_cpuid(&ax, &bx, &cx, &dx); xsave_mask = (1 << (X86_FEATURE_XSAVE % 32)) | (1 << (X86_FEATURE_OSXSAVE % 32)); /* */ if ((cx & xsave_mask) != xsave_mask) cpuid_leaf1_ecx_mask &= ~xsave_mask; /* */ if (xen_check_mwait()) cpuid_leaf1_ecx_set_mask = (1 << (X86_FEATURE_MWAIT % 32)); }