An AArch64 hypervisor can host both AArch32 and AArch64 virtual machines
at the same time. If the inmate cell wants to run in AArch32 mode, the
assigned cpu must change to AArch32. Because AArch64 hypervisor and
AArch64 root cell are used, when the AArch32 inmate cell is destroyed,
cpu owned by inmate cell will be reassigned to AArch64 root cell, switch
the cpu back to AArch64.

The following is a summary of some of the points when supporting inmate
cell in AArch32 mode:
Define a macro "JAILHOUSE_CELL_AARCH32" to indicate AArch32 execution
state. Add a member variable cpu_mode to struct public_per_cpu, and
cpu_mode can use this macro to indicate whether the processor is AArch32
or AArch64 execution state.

AArch32 and AArch64 virtual machines use different ARM_PARKING_CODE.
0xd503207f and 0x17ffffff are used in AArch64 and 0xe320f003 and
0xeafffffd are used in AArch32. Add ARM_PARKING_CODE which is used by
AArch32 in arm64/include/asm/processor.h, and then select which one to
use by cpu_mode and cpu_mode and arm_cpu_reset().

When an exception occurs, the processor must execute handler code which
corresponds to the exception. When the exception is being taken at a
lower Exception level, the execution state of the next lower level
(AArch64 or AArch32) will be used. Fill exception handling functions for
Lower EL using AArch32 in hypervisor/arch/arm64/entry.S.

Changing to AArch32 happens after the command "jailhouse cell start 1"
is executed. In arch_cell_reset(), get the mode of cpu owned by inmate
cell from the member variable .flags which is defined in the configuration
file of inmate cell. If the inmate cell is AArch32, SPSR_EL2.M[4] will
be set to 0b1 which means AArch32 execution state, SPSR_EL2.M[3:0] will
be set to 0b0011 which means Supervisor, and HCR_EL2.RW will be set to
0b0 which means lower levels are all AArch32. If the inmate cell is
AArch64, make sure HCR_EL2.RW is 0 and the other registers are configured
according to the previous code.

Changing to AArch64 happens after the command "jailhouse cell destroy 1"
is executed. Since the cpu owned by inmate cell will be reassigned to
root cell, get the mode of cpu from .flags of the root cell configuration
file by arch_cell_destroy().

After Linux operating system boots up, execute the following commands to
use AArch32 virtual machine on the i.MX8DXL:
./jailhouse enable imx8dxl.cell
./jailhouse cell create imx8dxl-gic-demo-aarch32.cell
./jailhouse cell load 1 gic-demo.bin (32-bit)
./jailhouse cell start 1

Signed-off-by: Alice Guo <alice....@nxp.com>
---
 hypervisor/arch/arm-common/control.c          | 10 ++++++++--
 hypervisor/arch/arm64/control.c               | 13 +++++++++++++
 hypervisor/arch/arm64/entry.S                 |  8 ++++----
 hypervisor/arch/arm64/include/asm/processor.h |  4 +++-
 hypervisor/arch/arm64/include/asm/sysregs.h   |  2 ++
 hypervisor/include/jailhouse/percpu.h         |  2 ++
 include/jailhouse/cell-config.h               |  1 +
 7 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/hypervisor/arch/arm-common/control.c 
b/hypervisor/arch/arm-common/control.c
index 70793432..c0f9f229 100644
--- a/hypervisor/arch/arm-common/control.c
+++ b/hypervisor/arch/arm-common/control.c
@@ -32,7 +32,10 @@ void arm_cpu_park(void)
        enter_cpu_off(cpu_public);
        spin_unlock(&cpu_public->control_lock);
 
-       arm_cpu_reset(0);
+       if (cpu_public->cpu_mode == JAILHOUSE_CELL_AARCH32)
+               arm_cpu_reset(8);
+       else
+               arm_cpu_reset(0);
        arm_paging_vcpu_init(&parking_pt);
 }
 
@@ -169,6 +172,7 @@ void arch_cell_reset(struct cell *cell)
         * starts at cpu_reset_address, defined in the cell configuration.
         */
        public_per_cpu(first)->cpu_on_entry = cell->config->cpu_reset_address;
+       public_per_cpu(first)->cpu_mode = cell->config->flags & 
JAILHOUSE_CELL_AARCH32;
        for_each_cpu_except(cpu, cell->cpu_set, first)
                public_per_cpu(cpu)->cpu_on_entry = PSCI_INVALID_ADDRESS;
 
@@ -184,8 +188,10 @@ void arch_cell_destroy(struct cell *cell)
        arm_cell_dcaches_flush(cell, DCACHE_INVALIDATE);
 
        /* All CPUs are handed back to the root cell in suspended mode. */
-       for_each_cpu(cpu, cell->cpu_set)
+       for_each_cpu(cpu, cell->cpu_set) {
                public_per_cpu(cpu)->cpu_on_entry = PSCI_INVALID_ADDRESS;
+               public_per_cpu(cpu)->cpu_mode = root_cell.config->flags & 
JAILHOUSE_CELL_AARCH32;
+       }
 
        arm_paging_cell_destroy(cell);
 }
diff --git a/hypervisor/arch/arm64/control.c b/hypervisor/arch/arm64/control.c
index 6e1ffebf..661dcd77 100644
--- a/hypervisor/arch/arm64/control.c
+++ b/hypervisor/arch/arm64/control.c
@@ -20,6 +20,9 @@
 
 void arm_cpu_reset(unsigned long pc)
 {
+       unsigned int cpu_mode = this_cpu_data()->public.cpu_mode;
+       u64 hcr_el2;
+
        /* put the cpu in a reset state */
        /* AARCH64_TODO: handle big endian support */
        arm_write_sysreg(SPSR_EL2, RESET_PSR);
@@ -67,6 +70,16 @@ void arm_cpu_reset(unsigned long pc)
        /* AARCH64_TODO: handle PMU registers */
        /* AARCH64_TODO: handle debug registers */
        /* AARCH64_TODO: handle system registers for AArch32 state */
+       if (cpu_mode == JAILHOUSE_CELL_AARCH32) {
+               arm_write_sysreg(SPSR_EL2, PSR_32_BIT | PSR_MODE_SVC);
+               arm_read_sysreg(HCR_EL2, hcr_el2);
+               hcr_el2 &= ~HCR_RW_BIT;
+               arm_write_sysreg(HCR_EL2, hcr_el2);
+       } else {
+               arm_read_sysreg(HCR_EL2, hcr_el2);
+               hcr_el2 |= HCR_RW_BIT;
+               arm_write_sysreg(HCR_EL2, hcr_el2);
+       }
 
        arm_write_sysreg(ELR_EL2, pc);
 
diff --git a/hypervisor/arch/arm64/entry.S b/hypervisor/arch/arm64/entry.S
index 27e148c6..4789e933 100644
--- a/hypervisor/arch/arm64/entry.S
+++ b/hypervisor/arch/arm64/entry.S
@@ -401,8 +401,8 @@ hyp_vectors:
        ventry  .
        ventry  .
 
-       ventry  .
-       ventry  .
+       handle_vmexit arch_handle_trap
+       handle_vmexit irqchip_handle_irq
        ventry  .
        ventry  .
 
@@ -425,8 +425,8 @@ hyp_vectors_hardened:
        ventry  .
        ventry  .
 
-       ventry  .
-       ventry  .
+       handle_abort_fastpath
+       handle_vmexit irqchip_handle_irq
        ventry  .
        ventry  .
 
diff --git a/hypervisor/arch/arm64/include/asm/processor.h 
b/hypervisor/arch/arm64/include/asm/processor.h
index b52782b7..e7b048e0 100644
--- a/hypervisor/arch/arm64/include/asm/processor.h
+++ b/hypervisor/arch/arm64/include/asm/processor.h
@@ -34,7 +34,9 @@ union registers {
 
 #define ARM_PARKING_CODE               \
        0xd503207f, /* 1: wfi  */       \
-       0x17ffffff, /*    b 1b */
+       0x17ffffff, /*    b 1b */       \
+       0xe320f003, /* 2: wfi  */       \
+       0xeafffffd, /*    b 2b */
 
 #define dmb(domain)    asm volatile("dmb " #domain "\n" : : : "memory")
 #define dsb(domain)    asm volatile("dsb " #domain "\n" : : : "memory")
diff --git a/hypervisor/arch/arm64/include/asm/sysregs.h 
b/hypervisor/arch/arm64/include/asm/sysregs.h
index 0105b109..1d68ec54 100644
--- a/hypervisor/arch/arm64/include/asm/sysregs.h
+++ b/hypervisor/arch/arm64/include/asm/sysregs.h
@@ -15,11 +15,13 @@
 
 #define PSR_MODE_MASK  0xf
 #define PSR_MODE_EL0t  0x0
+#define PSR_MODE_SVC   0x3
 #define PSR_MODE_EL1t  0x4
 #define PSR_MODE_EL1h  0x5
 #define PSR_MODE_EL2t  0x8
 #define PSR_MODE_EL2h  0x9
 
+#define PSR_32_BIT     (1 << 4)
 #define PSR_F_BIT      (1 << 6)
 #define PSR_I_BIT      (1 << 7)
 #define PSR_A_BIT      (1 << 8)
diff --git a/hypervisor/include/jailhouse/percpu.h 
b/hypervisor/include/jailhouse/percpu.h
index 344ed65f..ece11bc9 100644
--- a/hypervisor/include/jailhouse/percpu.h
+++ b/hypervisor/include/jailhouse/percpu.h
@@ -59,6 +59,8 @@ struct public_per_cpu {
         *  host physical <-> guest physical memory mappings. */
        bool flush_vcpu_caches;
 
+       unsigned int cpu_mode;
+
        ARCH_PUBLIC_PERCPU_FIELDS;
 } __attribute__((aligned(PAGE_SIZE)));
 
diff --git a/include/jailhouse/cell-config.h b/include/jailhouse/cell-config.h
index 6df4a745..2a968dd5 100644
--- a/include/jailhouse/cell-config.h
+++ b/include/jailhouse/cell-config.h
@@ -56,6 +56,7 @@
 
 #define JAILHOUSE_CELL_PASSIVE_COMMREG 0x00000001
 #define JAILHOUSE_CELL_TEST_DEVICE     0x00000002
+#define JAILHOUSE_CELL_AARCH32         0x00000004
 
 /*
  * The flag JAILHOUSE_CELL_VIRTUAL_CONSOLE_PERMITTED allows inmates to invoke
-- 
2.17.1

-- 
You received this message because you are subscribed to the Google Groups 
"Jailhouse" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to jailhouse-dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/jailhouse-dev/20200811181641.7282-2-alice.guo%40nxp.com.

Reply via email to