int cpuid_viridian_leaves(unsigned int leaf, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) { struct domain *d = current->domain; if ( !is_viridian_domain(d) ) return 0; leaf -= 0x40000000; if ( leaf > 6 ) return 0; *eax = *ebx = *ecx = *edx = 0; switch ( leaf ) { case 0: *eax = 0x40000006; /* Maximum leaf */ *ebx = 0x7263694d; /* Magic numbers */ *ecx = 0x666F736F; *edx = 0x76482074; break; case 1: *eax = 0x31237648; /* Version number */ break; case 2: /* Hypervisor information, but only if the guest has set its own version number. */ if ( d->arch.hvm_domain.viridian.guest_os_id.raw == 0 ) break; *eax = 1; /* Build number */ *ebx = (xen_major_version() << 16) | xen_minor_version(); *ecx = 0; /* SP */ *edx = 0; /* Service branch and number */ break; case 3: /* Which hypervisor MSRs are available to the guest */ *eax = (CPUID3A_MSR_APIC_ACCESS | CPUID3A_MSR_HYPERCALL | CPUID3A_MSR_VP_INDEX); break; case 4: /* Recommended hypercall usage. */ if ( (d->arch.hvm_domain.viridian.guest_os_id.raw == 0) || (d->arch.hvm_domain.viridian.guest_os_id.fields.os < 4) ) break; *eax = (CPUID4A_MSR_BASED_APIC | CPUID4A_RELAX_TIMER_INT); *ebx = 2047; /* long spin count */ break; } return 1; }
static ofdn_t ofd_xen_props(void *m, struct domain *d, ulong shared_info) { ofdn_t n; static const char path[] = "/xen"; static const char console[] = "/xen/console"; n = ofd_node_add(m, OFD_ROOT, path, sizeof (path)); if (n > 0) { char xen[256]; int xl; u64 val[2]; s32 dom_id; dom_id = d->domain_id; ofd_prop_add(m, n, "reg", &dom_id, sizeof (dom_id)); ofd_prop_add(m, n, "name", &path[1], sizeof (path) - 1); xl = snprintf(xen, sizeof (xen), "Xen-%d.%d%s", xen_major_version(), xen_minor_version(), xen_extra_version()); ASSERT(xl < sizeof (xen)); ofd_prop_add(m, n, "version", xen, xl + 1); /* convert xen pointer to guest physical */ val[0] = shared_info; val[1] = PAGE_SIZE; ofd_prop_add(m, n, "shared-info", val, sizeof (val)); /* reserve PAGE_SIZE @ addr shared info */ ofd_prop_add(m, n, "reserved", val, sizeof (val)); /* flags |= SIF_PROVILEDGED; */ ofd_prop_add(m, n, "privileged", NULL, 0); /* flags |= SIF_INITDOMAIN; */ ofd_prop_add(m, n, "initdomain", NULL, 0); /* tell dom0 that Xen depends on it to have power control */ if (!rtas_entry) ofd_prop_add(m, n, "power-control", NULL, 0); /* tell dom0 where granted pages go in the linear map */ val[0] = cpu_foreign_map_order(); val[1] = d->arch.foreign_mfn_count; ofd_prop_add(m, n, "foreign-map", val, sizeof (val)); n = ofd_node_add(m, n, console, sizeof (console)); if (n > 0) { val[0] = 0; ofd_prop_add(m, n, "interrupts", &val[0], sizeof (val[0])); } } return n; }
/* XXX could/should be common code */ static void print_xen_info(void) { char taint_str[TAINT_STRING_MAX_LEN]; printk("----[ Xen-%d.%d%s %s debug=%c %s ]----\n", xen_major_version(), xen_minor_version(), xen_extra_version(), #ifdef CONFIG_ARM_32 "arm32", #else "arm64", #endif debug_build() ? 'y' : 'n', print_tainted(taint_str)); }
/* XXX could/should be common code */ static void print_xen_info(void) { char taint_str[TAINT_STRING_MAX_LEN]; char debug = 'n'; #ifndef NDEBUG debug = 'y'; #endif printk("----[ Xen-%d.%d%s x86_64 debug=%c %s ]----\n", xen_major_version(), xen_minor_version(), xen_extra_version(), debug, print_tainted(taint_str)); }
/* Set up the single Xen-specific-info crash note. */ crash_xen_info_t *kexec_crash_save_info(void) { int cpu = smp_processor_id(); crash_xen_info_t info; crash_xen_info_t *out = (crash_xen_info_t *)ELFNOTE_DESC(xen_crash_note); BUG_ON(!cpu_test_and_set(cpu, crash_saved_cpus)); memset(&info, 0, sizeof(info)); info.xen_major_version = xen_major_version(); info.xen_minor_version = xen_minor_version(); info.xen_extra_version = __pa(xen_extra_version()); info.xen_changeset = __pa(xen_changeset()); info.xen_compiler = __pa(xen_compiler()); info.xen_compile_date = __pa(xen_compile_date()); info.xen_compile_time = __pa(xen_compile_time()); info.tainted = tainted; /* Copy from guaranteed-aligned local copy to possibly-unaligned dest. */ memcpy(out, &info, sizeof(info)); return out; }
void cpuid_viridian_leaves(const struct vcpu *v, uint32_t leaf, uint32_t subleaf, struct cpuid_leaf *res) { const struct domain *d = v->domain; ASSERT(is_viridian_domain(d)); ASSERT(leaf >= 0x40000000 && leaf < 0x40000100); leaf -= 0x40000000; switch ( leaf ) { case 0: res->a = 0x40000006; /* Maximum leaf */ res->b = 0x7263694d; /* Magic numbers */ res->c = 0x666F736F; res->d = 0x76482074; break; case 1: res->a = 0x31237648; /* Version number */ break; case 2: /* Hypervisor information, but only if the guest has set its own version number. */ if ( d->arch.hvm_domain.viridian.guest_os_id.raw == 0 ) break; res->a = 1; /* Build number */ res->b = (xen_major_version() << 16) | xen_minor_version(); res->c = 0; /* SP */ res->d = 0; /* Service branch and number */ break; case 3: /* Which hypervisor MSRs are available to the guest */ res->a = (CPUID3A_MSR_APIC_ACCESS | CPUID3A_MSR_HYPERCALL | CPUID3A_MSR_VP_INDEX); if ( !(viridian_feature_mask(d) & HVMPV_no_freq) ) res->a |= CPUID3A_MSR_FREQ; if ( viridian_feature_mask(d) & HVMPV_time_ref_count ) res->a |= CPUID3A_MSR_TIME_REF_COUNT; if ( viridian_feature_mask(d) & HVMPV_reference_tsc ) res->a |= CPUID3A_MSR_REFERENCE_TSC; break; case 4: /* Recommended hypercall usage. */ if ( (d->arch.hvm_domain.viridian.guest_os_id.raw == 0) || (d->arch.hvm_domain.viridian.guest_os_id.fields.os < 4) ) break; res->a = CPUID4A_RELAX_TIMER_INT; if ( viridian_feature_mask(d) & HVMPV_hcall_remote_tlb_flush ) res->a |= CPUID4A_HCALL_REMOTE_TLB_FLUSH; if ( !cpu_has_vmx_apic_reg_virt ) res->a |= CPUID4A_MSR_BASED_APIC; res->b = 2047; /* long spin count */ break; case 6: /* Detected and in use hardware features. */ if ( cpu_has_vmx_virtualize_apic_accesses ) res->a |= CPUID6A_APIC_OVERLAY; if ( cpu_has_vmx_msr_bitmap || (read_efer() & EFER_SVME) ) res->a |= CPUID6A_MSR_BITMAPS; if ( hap_enabled(d) ) res->a |= CPUID6A_NESTED_PAGING; break; } }
int cpuid_viridian_leaves(unsigned int leaf, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) { struct domain *d = current->domain; if ( !is_viridian_domain(d) ) return 0; leaf -= 0x40000000; if ( leaf > 6 ) return 0; *eax = *ebx = *ecx = *edx = 0; switch ( leaf ) { case 0: *eax = 0x40000006; /* Maximum leaf */ *ebx = 0x7263694d; /* Magic numbers */ *ecx = 0x666F736F; *edx = 0x76482074; break; case 1: *eax = 0x31237648; /* Version number */ break; case 2: /* Hypervisor information, but only if the guest has set its own version number. */ if ( d->arch.hvm_domain.viridian.guest_os_id.raw == 0 ) break; *eax = 1; /* Build number */ *ebx = (xen_major_version() << 16) | xen_minor_version(); *ecx = 0; /* SP */ *edx = 0; /* Service branch and number */ break; case 3: /* Which hypervisor MSRs are available to the guest */ *eax = (CPUID3A_MSR_APIC_ACCESS | CPUID3A_MSR_HYPERCALL | CPUID3A_MSR_VP_INDEX); break; case 4: /* Recommended hypercall usage. */ if ( (d->arch.hvm_domain.viridian.guest_os_id.raw == 0) || (d->arch.hvm_domain.viridian.guest_os_id.fields.os < 4) ) break; *eax = CPUID4A_RELAX_TIMER_INT; if ( !cpu_has_vmx_apic_reg_virt ) *eax |= CPUID4A_MSR_BASED_APIC; *ebx = 2047; /* long spin count */ break; case 6: /* Detected and in use hardware features. */ if ( cpu_has_vmx_virtualize_apic_accesses ) *eax |= CPUID6A_APIC_OVERLAY; if ( cpu_has_vmx_msr_bitmap || (read_efer() & EFER_SVME) ) *eax |= CPUID6A_MSR_BITMAPS; if ( hap_enabled(d) ) *eax |= CPUID6A_NESTED_PAGING; break; } return 1; }