mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
xen: arm: implement cpuinfo
Use to: - Only context switch ThumbEE state if the processor implements it. In particular the ARMv8 FastModels do not. - Detect the generic timer, and therefore call identify_cpu before init_xen_time. Also improve the boot time messages a bit. I haven't added decoding for all of the CPUID words, it seems like overkill for the moment. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Tim Deegan <tim@xen.org> Cc: stefano.stabellini@citrix.com
This commit is contained in:
1 parent
75c3b4097c
commit
7269eeae75
10 files changed
+367
-47
No files matched your search
@@ -3,6 +3,7 @@ subdir-$(arm64) += arm64
|
||||
subdir-y += platforms
|
||||
|
||||
obj-y += early_printk.o
|
||||
obj-y += cpu.o
|
||||
obj-y += domain.o
|
||||
obj-y += domctl.o
|
||||
obj-y += sysctl.o
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <xen/config.h>
|
||||
#include <xen/init.h>
|
||||
#include <xen/lib.h>
|
||||
#include <xen/sched.h>
|
||||
|
||||
#include <asm/processor.h>
|
||||
|
||||
void __cpuinit identify_cpu(struct cpuinfo_arm *c)
|
||||
{
|
||||
c->midr.bits = READ_SYSREG32(MIDR_EL1);
|
||||
c->mpidr.bits = READ_SYSREG(MPIDR_EL1);
|
||||
|
||||
#ifdef CONFIG_ARM_64
|
||||
c->pfr64.bits[0] = READ_SYSREG64(ID_AA64PFR0_EL1);
|
||||
c->pfr64.bits[1] = READ_SYSREG64(ID_AA64PFR1_EL1);
|
||||
|
||||
c->dbg64.bits[0] = READ_SYSREG64(ID_AA64DFR0_EL1);
|
||||
c->dbg64.bits[1] = READ_SYSREG64(ID_AA64DFR1_EL1);
|
||||
|
||||
c->aux64.bits[0] = READ_SYSREG64(ID_AA64AFR0_EL1);
|
||||
c->aux64.bits[1] = READ_SYSREG64(ID_AA64AFR1_EL1);
|
||||
|
||||
c->mm64.bits[0] = READ_SYSREG64(ID_AA64MMFR0_EL1);
|
||||
c->mm64.bits[1] = READ_SYSREG64(ID_AA64MMFR1_EL1);
|
||||
|
||||
c->isa64.bits[0] = READ_SYSREG64(ID_AA64ISAR0_EL1);
|
||||
c->isa64.bits[1] = READ_SYSREG64(ID_AA64ISAR1_EL1);
|
||||
#endif
|
||||
|
||||
c->pfr32.bits[0] = READ_SYSREG32(ID_PFR0_EL1);
|
||||
c->pfr32.bits[1] = READ_SYSREG32(ID_PFR1_EL1);
|
||||
|
||||
c->dbg32.bits[0] = READ_SYSREG32(ID_DFR0_EL1);
|
||||
|
||||
c->aux32.bits[0] = READ_SYSREG32(ID_AFR0_EL1);
|
||||
|
||||
c->mm32.bits[0] = READ_SYSREG32(ID_MMFR0_EL1);
|
||||
c->mm32.bits[1] = READ_SYSREG32(ID_MMFR1_EL1);
|
||||
c->mm32.bits[2] = READ_SYSREG32(ID_MMFR2_EL1);
|
||||
c->mm32.bits[3] = READ_SYSREG32(ID_MMFR3_EL1);
|
||||
|
||||
c->isa32.bits[0] = READ_SYSREG32(ID_ISAR0_EL1);
|
||||
c->isa32.bits[1] = READ_SYSREG32(ID_ISAR1_EL1);
|
||||
c->isa32.bits[2] = READ_SYSREG32(ID_ISAR2_EL1);
|
||||
c->isa32.bits[3] = READ_SYSREG32(ID_ISAR3_EL1);
|
||||
c->isa32.bits[4] = READ_SYSREG32(ID_ISAR4_EL1);
|
||||
c->isa32.bits[5] = READ_SYSREG32(ID_ISAR5_EL1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-set-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
+31
-8
@@ -1,3 +1,14 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#include <xen/config.h>
|
||||
#include <xen/init.h>
|
||||
#include <xen/lib.h>
|
||||
@@ -13,6 +24,7 @@
|
||||
#include <asm/regs.h>
|
||||
#include <asm/p2m.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/cpufeature.h>
|
||||
|
||||
#include <asm/gic.h>
|
||||
#include "vtimer.h"
|
||||
@@ -58,11 +70,13 @@ static void ctxt_switch_from(struct vcpu *p)
|
||||
/* Arch timer */
|
||||
virt_timer_save(p);
|
||||
|
||||
#if defined(CONFIG_ARM_32)
|
||||
/* XXX only save these if ThumbEE e.g. ID_PFR0.THUMB_EE_SUPPORT */
|
||||
p->arch.teecr = READ_CP32(TEECR);
|
||||
p->arch.teehbr = READ_CP32(TEEHBR);
|
||||
if ( is_pv32_domain(p->domain) && cpu_has_thumbee )
|
||||
{
|
||||
p->arch.teecr = READ_SYSREG32(TEECR32_EL1);
|
||||
p->arch.teehbr = READ_SYSREG32(TEEHBR32_EL1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARM_32
|
||||
p->arch.joscr = READ_CP32(JOSCR);
|
||||
p->arch.jmcr = READ_CP32(JMCR);
|
||||
#endif
|
||||
@@ -121,6 +135,9 @@ static void ctxt_switch_to(struct vcpu *n)
|
||||
p2m_load_VTTBR(n->domain);
|
||||
isb();
|
||||
|
||||
WRITE_SYSREG32(n->domain->arch.vpidr, VPIDR_EL2);
|
||||
WRITE_SYSREG(n->domain->arch.vmpidr, VMPIDR_EL2);
|
||||
|
||||
/* VGIC */
|
||||
gic_restore_state(n);
|
||||
|
||||
@@ -169,11 +186,13 @@ static void ctxt_switch_to(struct vcpu *n)
|
||||
WRITE_SYSREG(n->arch.tpidrro_el0, TPIDRRO_EL0);
|
||||
WRITE_SYSREG(n->arch.tpidr_el1, TPIDR_EL1);
|
||||
|
||||
#if defined(CONFIG_ARM_32)
|
||||
/* XXX only restore these if ThumbEE e.g. ID_PFR0.THUMB_EE_SUPPORT */
|
||||
WRITE_CP32(n->arch.teecr, TEECR);
|
||||
WRITE_CP32(n->arch.teehbr, TEEHBR);
|
||||
if ( is_pv32_domain(n->domain) && cpu_has_thumbee )
|
||||
{
|
||||
WRITE_SYSREG32(n->arch.teecr, TEECR32_EL1);
|
||||
WRITE_SYSREG32(n->arch.teehbr, TEEHBR32_EL1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARM_32
|
||||
WRITE_CP32(n->arch.joscr, JOSCR);
|
||||
WRITE_CP32(n->arch.jmcr, JMCR);
|
||||
#endif
|
||||
@@ -447,6 +466,10 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags)
|
||||
if ( (d->shared_info = alloc_xenheap_pages(0, 0)) == NULL )
|
||||
goto fail;
|
||||
|
||||
/* Default the virtual ID to match the physical */
|
||||
d->arch.vpidr = boot_cpu_data.midr.bits;
|
||||
d->arch.vmpidr = boot_cpu_data.mpidr.bits;
|
||||
|
||||
clear_page(d->shared_info);
|
||||
share_xen_page_with_guest(
|
||||
virt_to_page(d->shared_info), d, XENSHARE_writable);
|
||||
|
||||
+81
-26
@@ -40,6 +40,9 @@
|
||||
#include <asm/vfp.h>
|
||||
#include <asm/early_printk.h>
|
||||
#include <asm/gic.h>
|
||||
#include <asm/cpufeature.h>
|
||||
|
||||
struct cpuinfo_arm __read_mostly boot_cpu_data;
|
||||
|
||||
static __used void init_done(void)
|
||||
{
|
||||
@@ -54,41 +57,93 @@ static void __init init_idle_domain(void)
|
||||
/* TODO: setup_idle_pagetable(); */
|
||||
}
|
||||
|
||||
static const char * __initdata processor_implementers[] = {
|
||||
['A'] = "ARM Limited",
|
||||
['D'] = "Digital Equipment Corp",
|
||||
['M'] = "Motorola, Freescale Semiconductor Inc.",
|
||||
['Q'] = "Qualcomm Inc.",
|
||||
['V'] = "Marvell Semiconductor Inc.",
|
||||
['i'] = "Intel Corporation",
|
||||
};
|
||||
|
||||
static void __init processor_id(void)
|
||||
{
|
||||
const char *implementer = "Unknown";
|
||||
struct cpuinfo_arm *c = &boot_cpu_data;
|
||||
|
||||
/* Setup the virtual ID to match the physical */
|
||||
WRITE_SYSREG32(READ_SYSREG32(MIDR_EL1), VPIDR_EL2);
|
||||
WRITE_SYSREG(READ_SYSREG(MPIDR_EL1), VMPIDR_EL2);
|
||||
identify_cpu(c);
|
||||
current_cpu_data = *c;
|
||||
|
||||
if ( c->midr.implementer < ARRAY_SIZE(processor_implementers) &&
|
||||
processor_implementers[c->midr.implementer] )
|
||||
implementer = processor_implementers[c->midr.implementer];
|
||||
|
||||
if ( c->midr.architecture != 0xf )
|
||||
printk("Huh, cpu architecture %x, expected 0xf (defined by cpuid)\n",
|
||||
c->midr.architecture);
|
||||
|
||||
printk("Processor: \"%s\", variant: 0x%x, part 0x%03x, rev 0x%x\n",
|
||||
implementer, c->midr.variant, c->midr.part_number, c->midr.revision);
|
||||
|
||||
#if defined(CONFIG_ARM_64)
|
||||
printk("64-bit Processor Features: %016"PRIx64" %016"PRIx64"\n",
|
||||
READ_SYSREG64(ID_AA64PFR0_EL1), READ_SYSREG64(ID_AA64PFR1_EL1));
|
||||
printk("64-bit Debug Features: %016"PRIx64" %016"PRIx64"\n",
|
||||
READ_SYSREG64(ID_AA64DFR0_EL1), READ_SYSREG64(ID_AA64DFR1_EL1));
|
||||
printk("64-bit Auxiliary Features: %016"PRIx64" %016"PRIx64"\n",
|
||||
READ_SYSREG64(ID_AA64AFR0_EL1), READ_SYSREG64(ID_AA64AFR1_EL1));
|
||||
printk("64-bit Memory Model Features: %016"PRIx64" %016"PRIx64"\n",
|
||||
READ_SYSREG64(ID_AA64MMFR0_EL1), READ_SYSREG64(ID_AA64MMFR1_EL1));
|
||||
printk("64-bit ISA Features: %016"PRIx64" %016"PRIx64"\n",
|
||||
READ_SYSREG64(ID_AA64ISAR0_EL1), READ_SYSREG64(ID_AA64ISAR1_EL1));
|
||||
printk("64-bit Execution:\n");
|
||||
printk(" Processor Features: %016"PRIx64" %016"PRIx64"\n",
|
||||
boot_cpu_data.pfr64.bits[0], boot_cpu_data.pfr64.bits[1]);
|
||||
printk(" Exception Levels: EL3:%s EL2:%s EL1:%s EL0:%s\n",
|
||||
cpu_has_el3_32 ? "64+32" : cpu_has_el3_64 ? "64" : "No",
|
||||
cpu_has_el2_32 ? "64+32" : cpu_has_el2_64 ? "64" : "No",
|
||||
cpu_has_el1_32 ? "64+32" : cpu_has_el1_64 ? "64" : "No",
|
||||
cpu_has_el0_32 ? "64+32" : cpu_has_el0_64 ? "64" : "No");
|
||||
printk(" Extensions:%s%s\n",
|
||||
cpu_has_fp ? " FloatingPoint" : "",
|
||||
cpu_has_simd ? " AdvancedSIMD" : "");
|
||||
|
||||
printk(" Debug Features: %016"PRIx64" %016"PRIx64"\n",
|
||||
boot_cpu_data.dbg64.bits[0], boot_cpu_data.dbg64.bits[1]);
|
||||
printk(" Auxiliary Features: %016"PRIx64" %016"PRIx64"\n",
|
||||
boot_cpu_data.aux64.bits[0], boot_cpu_data.aux64.bits[1]);
|
||||
printk(" Memory Model Features: %016"PRIx64" %016"PRIx64"\n",
|
||||
boot_cpu_data.mm64.bits[0], boot_cpu_data.mm64.bits[1]);
|
||||
printk(" ISA Features: %016"PRIx64" %016"PRIx64"\n",
|
||||
boot_cpu_data.isa64.bits[0], boot_cpu_data.isa64.bits[1]);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* On AArch64 these refer to the capabilities when running in
|
||||
* AArch32 mode.
|
||||
*/
|
||||
printk("32-bit Processor Features: %08x %08x\n",
|
||||
READ_SYSREG32(ID_PFR0_EL1), READ_SYSREG32(ID_PFR1_EL1));
|
||||
printk("32-bit Debug Features: %08x\n", READ_SYSREG32(ID_DFR0_EL1));
|
||||
printk("32-bit Auxiliary Features: %08x\n", READ_SYSREG32(ID_AFR0_EL1));
|
||||
printk("32-bit Memory Model Features: %08x %08x %08x %08x\n",
|
||||
READ_SYSREG32(ID_MMFR0_EL1), READ_SYSREG32(ID_MMFR1_EL1),
|
||||
READ_SYSREG32(ID_MMFR2_EL1), READ_SYSREG32(ID_MMFR3_EL1));
|
||||
printk("32-bit ISA Features: %08x %08x %08x %08x %08x %08x\n",
|
||||
READ_SYSREG32(ID_ISAR0_EL1), READ_SYSREG32(ID_ISAR1_EL1),
|
||||
READ_SYSREG32(ID_ISAR2_EL1), READ_SYSREG32(ID_ISAR3_EL1),
|
||||
READ_SYSREG32(ID_ISAR4_EL1), READ_SYSREG32(ID_ISAR5_EL1));
|
||||
if ( cpu_has_aarch32 )
|
||||
{
|
||||
printk("32-bit Execution:\n");
|
||||
printk(" Processor Features: %08"PRIx32":%08"PRIx32"\n",
|
||||
boot_cpu_data.pfr32.bits[0], boot_cpu_data.pfr32.bits[1]);
|
||||
printk(" Instruction Sets:%s%s%s%s%s\n",
|
||||
cpu_has_aarch32 ? " AArch32" : "",
|
||||
cpu_has_thumb ? " Thumb" : "",
|
||||
cpu_has_thumb2 ? " Thumb-2" : "",
|
||||
cpu_has_thumbee ? " ThumbEE" : "",
|
||||
cpu_has_jazelle ? " Jazelle" : "");
|
||||
printk(" Extensions:%s%s\n",
|
||||
cpu_has_gentimer ? " GenericTimer" : "",
|
||||
cpu_has_security ? " Security" : "");
|
||||
|
||||
printk(" Debug Features: %08"PRIx32"\n",
|
||||
boot_cpu_data.dbg32.bits[0]);
|
||||
printk(" Auxiliary Features: %08"PRIx32"\n",
|
||||
boot_cpu_data.aux32.bits[0]);
|
||||
printk(" Memory Model Features: "
|
||||
"%08"PRIx32" %08"PRIx32" %08"PRIx32" %08"PRIx32"\n",
|
||||
boot_cpu_data.mm32.bits[0], boot_cpu_data.mm32.bits[1],
|
||||
boot_cpu_data.mm32.bits[2], boot_cpu_data.mm32.bits[3]);
|
||||
printk(" ISA Features: %08x %08x %08x %08x %08x %08x\n",
|
||||
boot_cpu_data.isa32.bits[0], boot_cpu_data.isa32.bits[1],
|
||||
boot_cpu_data.isa32.bits[2], boot_cpu_data.isa32.bits[3],
|
||||
boot_cpu_data.isa32.bits[4], boot_cpu_data.isa32.bits[5]);
|
||||
}
|
||||
else
|
||||
{
|
||||
printk("32-bit Execution: Unsupported\n");
|
||||
}
|
||||
}
|
||||
|
||||
void __init discard_initial_modules(void)
|
||||
@@ -379,6 +434,8 @@ void __init start_xen(unsigned long boot_phys_offset,
|
||||
console_init_preirq();
|
||||
#endif
|
||||
|
||||
processor_id();
|
||||
|
||||
init_xen_time();
|
||||
|
||||
gic_init();
|
||||
@@ -400,8 +457,6 @@ void __init start_xen(unsigned long boot_phys_offset,
|
||||
*/
|
||||
WRITE_SYSREG32(0x80002558, VTCR_EL2); isb();
|
||||
|
||||
processor_id();
|
||||
|
||||
enable_vfp();
|
||||
|
||||
softirq_init();
|
||||
|
||||
@@ -38,6 +38,8 @@ EXPORT_SYMBOL(cpu_online_map);
|
||||
cpumask_t cpu_possible_map;
|
||||
EXPORT_SYMBOL(cpu_possible_map);
|
||||
|
||||
struct cpuinfo_arm cpu_data[NR_CPUS];
|
||||
|
||||
/* Fake one node for now. See also include/asm-arm/numa.h */
|
||||
nodemask_t __read_mostly node_online_map = { { [0] = 1UL } };
|
||||
|
||||
@@ -136,11 +138,16 @@ void __cpuinit start_secondary(unsigned long boot_phys_offset,
|
||||
unsigned long fdt_paddr,
|
||||
unsigned long cpuid)
|
||||
{
|
||||
struct cpuinfo_arm *c = cpu_data + cpuid;
|
||||
|
||||
memset(get_cpu_info(), 0, sizeof (struct cpu_info));
|
||||
|
||||
/* TODO: handle boards where CPUIDs are not contiguous */
|
||||
set_processor_id(cpuid);
|
||||
|
||||
*c = boot_cpu_data;
|
||||
identify_cpu(c);
|
||||
|
||||
/* Setup Hyp vector base */
|
||||
WRITE_SYSREG((vaddr_t)hyp_traps_vector, VBAR_EL2);
|
||||
|
||||
|
||||
+2
-3
@@ -31,6 +31,7 @@
|
||||
#include <asm/system.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/gic.h>
|
||||
#include <asm/cpufeature.h>
|
||||
|
||||
/*
|
||||
* Unfortunately the hypervisor timer interrupt appears to be buggy in
|
||||
@@ -90,10 +91,8 @@ static uint32_t calibrate_timer(void)
|
||||
int __init init_xen_time(void)
|
||||
{
|
||||
/* Check that this CPU supports the Generic Timer interface */
|
||||
#if defined(CONFIG_ARM_32)
|
||||
if ( (READ_CP32(ID_PFR1) & ID_PFR1_GT_MASK) != ID_PFR1_GT_v1 )
|
||||
if ( !cpu_has_gentimer )
|
||||
panic("CPU does not support the Generic Timer v1 interface.\n");
|
||||
#endif
|
||||
|
||||
cpu_khz = READ_SYSREG32(CNTFRQ_EL0) / 1000;
|
||||
boot_count = READ_SYSREG64(CNTPCT_EL0);
|
||||
|
||||
@@ -265,10 +265,14 @@
|
||||
#define ID_PFR0_EL1 ID_PFR0
|
||||
#define ID_PFR1_EL1 ID_PFR1
|
||||
#define IFSR32_EL2 IFSR
|
||||
#define MIDR_EL1 MIDR
|
||||
#define MPIDR_EL1 MPIDR
|
||||
#define PAR_EL1 PAR
|
||||
#define SCTLR_EL1 SCTLR
|
||||
#define SCTLR_EL2 HSCTLR
|
||||
#define TCR_EL1 TTBCR
|
||||
#define TEECR32_EL1 TEECR
|
||||
#define TEEHBR32_EL1 TEEHBR
|
||||
#define TPIDRRO_EL0 TPIDRURO
|
||||
#define TPIDR_EL0 TPIDRURW
|
||||
#define TPIDR_EL1 TPIDRPRW
|
||||
@@ -278,13 +282,10 @@
|
||||
#define TTBR1_EL1 TTBR1
|
||||
#define VBAR_EL1 VBAR
|
||||
#define VBAR_EL2 HVBAR
|
||||
#define VMPIDR_EL2 VMPIDR
|
||||
#define VPIDR_EL2 VPIDR
|
||||
#define VTCR_EL2 VTCR
|
||||
#define VTTBR_EL2 VTTBR
|
||||
#define MIDR_EL1 MIDR
|
||||
#define VPIDR_EL2 VPIDR
|
||||
#define MPIDR_EL1 MPIDR
|
||||
#define VMPIDR_EL2 VMPIDR
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
#ifndef __ASM_ARM_CPUFEATURE_H
|
||||
#define __ASM_ARM_CPUFEATURE_H
|
||||
|
||||
#ifdef CONFIG_ARM_64
|
||||
#define cpu_feature64(c, feat) ((c)->pfr64.feat)
|
||||
#define boot_cpu_feature64(feat) (boot_cpu_data.pfr64.feat)
|
||||
|
||||
#define cpu_has_el0_32 (boot_cpu_feature64(el0) == 2)
|
||||
#define cpu_has_el0_64 (boot_cpu_feature64(el0) >= 1)
|
||||
#define cpu_has_el1_32 (boot_cpu_feature64(el1) == 2)
|
||||
#define cpu_has_el1_64 (boot_cpu_feature64(el1) >= 1)
|
||||
#define cpu_has_el2_32 (boot_cpu_feature64(el2) == 2)
|
||||
#define cpu_has_el2_64 (boot_cpu_feature64(el2) >= 1)
|
||||
#define cpu_has_el3_32 (boot_cpu_feature64(el3) == 2)
|
||||
#define cpu_has_el3_64 (boot_cpu_feature64(el3) >= 1)
|
||||
#define cpu_has_fp (boot_cpu_feature64(fp) == 0)
|
||||
#define cpu_has_simd (boot_cpu_feature64(simd) == 0)
|
||||
#endif
|
||||
|
||||
#define cpu_feature32(c, feat) ((c)->pfr32.feat)
|
||||
#define boot_cpu_feature32(feat) (boot_cpu_data.pfr32.feat)
|
||||
|
||||
#define cpu_has_aarch32 (boot_cpu_feature32(arm) == 1)
|
||||
#define cpu_has_thumb (boot_cpu_feature32(thumb) >= 1)
|
||||
#define cpu_has_thumb2 (boot_cpu_feature32(thumb) >= 3)
|
||||
#define cpu_has_jazelle (boot_cpu_feature32(jazelle) >= 0)
|
||||
#define cpu_has_thumbee (boot_cpu_feature32(thumbee) == 1)
|
||||
|
||||
#define cpu_has_gentimer (boot_cpu_feature32(gentimer) == 1)
|
||||
#define cpu_has_security (boot_cpu_feature32(security) > 0)
|
||||
|
||||
#endif
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-set-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -57,6 +57,10 @@ struct arch_domain
|
||||
struct hvm_domain hvm_domain;
|
||||
xen_pfn_t *grant_table_gpfn;
|
||||
|
||||
/* Virtual CPUID */
|
||||
uint32_t vpidr;
|
||||
register_t vmpidr;
|
||||
|
||||
struct {
|
||||
/*
|
||||
* Covers access to other members of this struct _except_ for
|
||||
@@ -166,8 +170,12 @@ struct arch_vcpu
|
||||
register_t tpidr_el1;
|
||||
register_t tpidrro_el0;
|
||||
|
||||
uint32_t teecr, teehbr; /* ThumbEE, 32-bit guests only */
|
||||
#ifdef CONFIG_ARM_32
|
||||
uint32_t teecr, teehbr;
|
||||
/*
|
||||
* ARMv8 only supports a trivial implementation on Jazelle when in AArch32
|
||||
* mode and therefore has no extended control registers.
|
||||
*/
|
||||
uint32_t joscr, jmcr;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -91,6 +91,123 @@
|
||||
#define HSR_EC_DATA_ABORT_HYP 0x25
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <xen/types.h>
|
||||
|
||||
struct cpuinfo_arm {
|
||||
union {
|
||||
uint32_t bits;
|
||||
struct {
|
||||
unsigned long revision:4;
|
||||
unsigned long part_number:12;
|
||||
unsigned long architecture:4;
|
||||
unsigned long variant:4;
|
||||
unsigned long implementer:8;
|
||||
};
|
||||
} midr;
|
||||
union {
|
||||
register_t bits;
|
||||
struct {
|
||||
unsigned long aff0:8;
|
||||
unsigned long aff1:8;
|
||||
unsigned long aff2:8;
|
||||
unsigned long mt:1; /* Multi-thread, iff MP == 1 */
|
||||
unsigned long __res0:5;
|
||||
unsigned long up:1; /* UP system, iff MP == 1 */
|
||||
unsigned long mp:1; /* MP extensions */
|
||||
|
||||
#ifdef CONFIG_ARM_64
|
||||
unsigned long aff3:8;
|
||||
unsigned long __res1:24;
|
||||
#endif
|
||||
};
|
||||
} mpidr;
|
||||
|
||||
#ifdef CONFIG_ARM_64
|
||||
/* 64-bit CPUID registers. */
|
||||
union {
|
||||
uint64_t bits[2];
|
||||
struct {
|
||||
unsigned long el0:4;
|
||||
unsigned long el1:4;
|
||||
unsigned long el2:4;
|
||||
unsigned long el3:4;
|
||||
unsigned long fp:4; /* Floating Point */
|
||||
unsigned long simd:4; /* Advanced SIMD */
|
||||
unsigned long __res0:8;
|
||||
|
||||
unsigned long __res1;
|
||||
};
|
||||
} pfr64;
|
||||
|
||||
struct {
|
||||
uint64_t bits[2];
|
||||
} dbg64;
|
||||
|
||||
struct {
|
||||
uint64_t bits[2];
|
||||
} aux64;
|
||||
|
||||
struct {
|
||||
uint64_t bits[2];
|
||||
} mm64;
|
||||
|
||||
struct {
|
||||
uint64_t bits[2];
|
||||
} isa64;
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 32-bit CPUID registers. On ARMv8 these describe the properties
|
||||
* when running in 32-bit mode.
|
||||
*/
|
||||
union {
|
||||
uint32_t bits[2];
|
||||
struct {
|
||||
unsigned long arm:4;
|
||||
unsigned long thumb:4;
|
||||
unsigned long jazelle:4;
|
||||
unsigned long thumbee:4;
|
||||
unsigned long __res0:16;
|
||||
|
||||
unsigned long progmodel:4;
|
||||
unsigned long security:4;
|
||||
unsigned long mprofile:4;
|
||||
unsigned long virt:4;
|
||||
unsigned long gentimer:4;
|
||||
unsigned long __res1:12;
|
||||
};
|
||||
} pfr32;
|
||||
|
||||
struct {
|
||||
uint32_t bits[1];
|
||||
} dbg32;
|
||||
|
||||
struct {
|
||||
uint32_t bits[1];
|
||||
} aux32;
|
||||
|
||||
struct {
|
||||
uint32_t bits[4];
|
||||
} mm32;
|
||||
|
||||
struct {
|
||||
uint32_t bits[6];
|
||||
} isa32;
|
||||
};
|
||||
|
||||
/*
|
||||
* capabilities of CPUs
|
||||
*/
|
||||
|
||||
extern struct cpuinfo_arm boot_cpu_data;
|
||||
|
||||
extern void identify_cpu(struct cpuinfo_arm *);
|
||||
|
||||
extern struct cpuinfo_arm cpu_data[];
|
||||
#define current_cpu_data cpu_data[smp_processor_id()]
|
||||
|
||||
union hsr {
|
||||
uint32_t bits;
|
||||
struct {
|
||||
@@ -225,10 +342,6 @@ union hsr {
|
||||
#define CNTx_CTL_MASK (1u<<1) /* Mask IRQ */
|
||||
#define CNTx_CTL_PENDING (1u<<2) /* IRQ pending */
|
||||
|
||||
/* CPUID bits */
|
||||
#define ID_PFR1_GT_MASK 0x000F0000 /* Generic Timer interface support */
|
||||
#define ID_PFR1_GT_v1 0x00010000
|
||||
|
||||
#if defined(CONFIG_ARM_32)
|
||||
# include <asm/arm32/processor.h>
|
||||
#elif defined(CONFIG_ARM_64)
|
||||
@@ -260,6 +373,10 @@ void vcpu_regs_hyp_to_user(const struct vcpu *vcpu,
|
||||
void vcpu_regs_user_to_hyp(struct vcpu *vcpu,
|
||||
const struct vcpu_guest_core_regs *regs);
|
||||
|
||||
struct cpuinfo_x86 {
|
||||
uint32_t pfr32[2];
|
||||
};
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ASM_ARM_PROCESSOR_H */
|
||||
/*
|
||||
|
||||