]> rtime.felk.cvut.cz Git - jailhouse.git/commitdiff
arm: attribute virtual IDs to the cell cpus
authorJean-Philippe Brucker <jean-philippe.brucker@arm.com>
Wed, 9 Jul 2014 16:18:12 +0000 (17:18 +0100)
committerJan Kiszka <jan.kiszka@siemens.com>
Fri, 19 Dec 2014 10:04:07 +0000 (11:04 +0100)
To handle SMP guests, the cells need to be assigned virtual CPU IDs
through the VMPIDR register. For the moment, those IDs are simply
generated incrementally on each CPU.

This change will allow to use the same guest code in different cells.

Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
[Jan: add "arm_" prefix, uninline arm_cpu_virt2phys]
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
hypervisor/arch/arm/control.c
hypervisor/arch/arm/gic-v3.c
hypervisor/arch/arm/include/asm/cell.h
hypervisor/arch/arm/include/asm/percpu.h
hypervisor/arch/arm/include/asm/processor.h
hypervisor/arch/arm/include/asm/sysregs.h
hypervisor/arch/arm/setup.c

index 2bb1ae640f6b5fdae9ebaf81c487ccea8ca64aac..0d8b9ea7e66009d23ecb9b5eb187b4fb6909495d 100644 (file)
@@ -123,6 +123,9 @@ static void arch_reset_self(struct per_cpu *cpu_data)
        else
                reset_address = 0;
 
+       /* Set the new MPIDR */
+       arm_write_sysreg(VMPIDR_EL2, cpu_data->virt_id | MPIDR_MP_BIT);
+
        /* Restore an empty context */
        arch_reset_el1(regs);
 
@@ -264,25 +267,54 @@ void arch_handle_sgi(struct per_cpu *cpu_data, u32 irqn)
        }
 }
 
+unsigned int arm_cpu_virt2phys(struct cell *cell, unsigned int virt_id)
+{
+       unsigned int cpu;
+
+       for_each_cpu(cpu, cell->cpu_set) {
+               if (per_cpu(cpu)->virt_id == virt_id)
+                       return cpu;
+       }
+
+       return -1;
+}
+
 int arch_cell_create(struct cell *cell)
 {
        int err;
+       unsigned int cpu;
+       unsigned int virt_id = 0;
 
        err = arch_mmu_cell_init(cell);
        if (err)
                return err;
 
+       /*
+        * Generate a virtual CPU id according to the position of each CPU in
+        * the cell set
+        */
+       for_each_cpu(cpu, cell->cpu_set) {
+               per_cpu(cpu)->virt_id = virt_id;
+               virt_id++;
+       }
+       cell->arch.last_virt_id = virt_id - 1;
+
        return 0;
 }
 
 void arch_cell_destroy(struct cell *cell)
 {
        unsigned int cpu;
+       struct per_cpu *percpu;
 
        arch_mmu_cell_destroy(cell);
 
-       for_each_cpu(cpu, cell->cpu_set)
+       for_each_cpu(cpu, cell->cpu_set) {
+               percpu = per_cpu(cpu);
+               /* Re-assign the physical IDs for the root cell */
+               percpu->virt_id = percpu->cpu_id;
                arch_reset_cpu(cpu);
+       }
 }
 
 /* Note: only supports synchronous flushing as triggered by config_commit! */
index bb6ced3adf99d078fa09a5038088f76e3b3cf393..681bd066977b6ab4d77f12140c5041880ac45e89 100644 (file)
@@ -197,7 +197,7 @@ int gicv3_handle_sgir_write(struct per_cpu *cpu_data, u64 sgir)
 {
        struct sgi sgi;
        struct cell *cell = cpu_data->cell;
-       unsigned int cpu;
+       unsigned int cpu, virt_id;
        unsigned long this_cpu = cpu_data->cpu_id;
        unsigned long routing_mode = !!(sgir & ICC_SGIR_ROUTING_BIT);
        unsigned long targets = sgir & ICC_SGIR_TARGET_MASK;
@@ -212,7 +212,9 @@ int gicv3_handle_sgir_write(struct per_cpu *cpu_data, u64 sgir)
        sgi.id = SGI_INJECT;
 
        for_each_cpu_except(cpu, cell->cpu_set, this_cpu) {
-               if (routing_mode == 0 && !test_bit(cpu, &targets))
+               virt_id = arm_cpu_phys2virt(cpu);
+
+               if (routing_mode == 0 && !test_bit(virt_id, &targets))
                        continue;
                else if (routing_mode == 1 && cpu == this_cpu)
                        continue;
index e52e44e4fe78609dfdf980f20e6b4853ecd372cb..b45df16115cb83fca78347b9b83d41ebc9b851bf 100644 (file)
@@ -27,6 +27,8 @@ struct arch_cell {
 
        spinlock_t caches_lock;
        bool needs_flush;
+
+       unsigned int last_virt_id;
 };
 
 struct cell {
index 9d0c06fd627d055d137e2c793a9310abf2d77a77..64d0488df5d668f422181a9b544a6761c468ca16 100644 (file)
@@ -41,6 +41,7 @@ struct per_cpu {
        unsigned long linux_reg[NUM_ENTRY_REGS];
 
        unsigned int cpu_id;
+       unsigned int virt_id;
 
        /* Other CPUs can insert sgis into the pending array */
        spinlock_t gic_lock;
@@ -94,6 +95,13 @@ static inline struct registers *guest_regs(struct per_cpu *cpu_data)
                        - sizeof(struct registers));
 }
 
+static inline unsigned int arm_cpu_phys2virt(unsigned int cpu_id)
+{
+       return per_cpu(cpu_id)->virt_id;
+}
+
+unsigned int arm_cpu_virt2phys(struct cell *cell, unsigned int virt_id);
+
 /* Validate defines */
 #define CHECK_ASSUMPTION(assume)       ((void)sizeof(char[1 - 2*!(assume)]))
 
index e4d85370686ced5b794dc6d9488373158fd2dd21..1fa7a72aea6b0f2a41cbe0d3a1d7adda3d779b11 100644 (file)
@@ -41,6 +41,8 @@
                        | PSR_32_BIT)
 
 #define MPIDR_CPUID_MASK       0x00ffffff
+#define MPIDR_MP_BIT           (1 << 31)
+#define MPIDR_U_BIT            (1 << 30)
 
 #define PFR1_VIRT(pfr)         ((pfr) >> 12 & 0xf)
 
@@ -68,7 +70,6 @@
                        | SCTLR_UWXN_BIT | SCTLR_FI_BIT | SCTLR_EE_BIT  \
                        | SCTLR_TRE_BIT | SCTLR_AFE_BIT | SCTLR_TE_BIT)
 
-
 #define HCR_TRVM_BIT   (1 << 30)
 #define HCR_TVM_BIT    (1 << 26)
 #define HCR_HDC_BIT    (1 << 29)
index 47607561f84b2e807c16089a54a2d1d5aba51410..3cdd634bf73602d290f9e41ae3b05710cac9bd82 100644 (file)
@@ -40,6 +40,7 @@
 #define CSSIDR_EL1     SYSREG_32(1, c0, c0, 0)
 #define CLIDR_EL1      SYSREG_32(1, c0, c0, 1)
 #define CSSELR_EL1     SYSREG_32(2, c0, c0, 0)
+#define VMPIDR_EL2     SYSREG_32(4, c0, c0, 5)
 #define SCTLR_EL2      SYSREG_32(4, c1, c0, 0)
 #define ESR_EL2                SYSREG_32(4, c5, c2, 0)
 #define TPIDR_EL2      SYSREG_32(4, c13, c0, 2)
index 120d82f0547d41beb0d5906fc0ec20ab8c29a364..24ea1f8cb08417fcdc13de3eaeb343428a145702 100644 (file)
@@ -62,6 +62,7 @@ int arch_cpu_init(struct per_cpu *cpu_data)
        unsigned long hcr = HCR_VM_BIT | HCR_IMO_BIT | HCR_FMO_BIT;
 
        cpu_data->psci_mbox.entry = 0;
+       cpu_data->virt_id = cpu_data->cpu_id;
 
        /*
         * Copy the registers to restore from the linux stack here, because we