From: Peng Fan <peng....@nxp.com>

If early_loader set to 1, it means jailhouse hypervisor booted
by an bootloader before Linux, so when "jailhouse enable [x].cell",
we need to bypass some operations.

Signed-off-by: Peng Fan <peng....@nxp.com>
---
 driver/main.c | 89 +++++++++++++++++++++++++++++++++--------------------------
 1 file changed, 50 insertions(+), 39 deletions(-)

diff --git a/driver/main.c b/driver/main.c
index ec302639..28c65f90 100644
--- a/driver/main.c
+++ b/driver/main.c
@@ -103,6 +103,7 @@ static int error_code;
 static struct jailhouse_virt_console* volatile console_page;
 static bool console_available;
 static struct resource *hypervisor_mem_res;
+static u32 early_loader = 0;
 
 static typeof(ioremap_page_range) *ioremap_page_range_sym;
 #ifdef CONFIG_X86
@@ -363,6 +364,7 @@ static int jailhouse_cmd_enable(struct jailhouse_system 
__user *arg)
        unsigned int clock_gates;
        const char *fw_name;
        long max_cpus;
+       int cpu;
        int err;
 
        fw_name = jailhouse_get_fw_name();
@@ -474,46 +476,46 @@ static int jailhouse_cmd_enable(struct jailhouse_system 
__user *arg)
                (hypervisor_mem + header->console_page);
        last_console.valid = false;
 
-       /* Copy hypervisor's binary image at beginning of the memory region
-        * and clear the rest to zero. */
-       memcpy(hypervisor_mem, hypervisor->data, hypervisor->size);
-       memset(hypervisor_mem + hypervisor->size, 0,
-              hv_mem->size - hypervisor->size);
-
        header = (struct jailhouse_header *)hypervisor_mem;
-       header->max_cpus = max_cpus;
+       /* Copy system configuration to its target address in hypervisor memory
+        * region. */
+       config = (struct jailhouse_system *)
+               (hypervisor_mem + hv_core_and_percpu_size);
+       if (!early_loader) {
+               /* Copy hypervisor's binary image at beginning of the memory 
region
+                * and clear the rest to zero. */
+               memcpy(hypervisor_mem, hypervisor->data, hypervisor->size);
+               memset(hypervisor_mem + hypervisor->size, 0,
+                      hv_mem->size - hypervisor->size);
+               header->max_cpus = max_cpus;
 
 #if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
-       header->arm_linux_hyp_vectors = virt_to_phys(*__hyp_stub_vectors_sym);
+               header->arm_linux_hyp_vectors = 
virt_to_phys(*__hyp_stub_vectors_sym);
 #if LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0)
-       header->arm_linux_hyp_abi = HYP_STUB_ABI_LEGACY;
+               header->arm_linux_hyp_abi = HYP_STUB_ABI_LEGACY;
 #else
-       header->arm_linux_hyp_abi = HYP_STUB_ABI_OPCODE;
+               header->arm_linux_hyp_abi = HYP_STUB_ABI_OPCODE;
 #endif
 #endif
+               /*
+                * ARMv8 requires to clean D-cache and invalidate I-cache for 
memory
+                * containing new instructions. On x86 this is a NOP. On ARMv7 
the
+                * firmware does its own cache maintenance, so it is an
+                * extraneous (but harmless) flush.
+                */
+               flush_icache_range((unsigned long)hypervisor_mem,
+                                  (unsigned long)(hypervisor_mem + 
header->core_size));
+
+               if (copy_from_user(config, arg, config_size)) {
+                       err = -EFAULT;
+                       goto error_unmap;
+               }
+       }
 
        err = jailhouse_sysfs_core_init(jailhouse_dev, header->core_size);
        if (err)
                goto error_unmap;
 
-       /*
-        * ARMv8 requires to clean D-cache and invalidate I-cache for memory
-        * containing new instructions. On x86 this is a NOP. On ARMv7 the
-        * firmware does its own cache maintenance, so it is an
-        * extraneous (but harmless) flush.
-        */
-       flush_icache_range((unsigned long)hypervisor_mem,
-                          (unsigned long)(hypervisor_mem + header->core_size));
-
-       /* Copy system configuration to its target address in hypervisor memory
-        * region. */
-       config = (struct jailhouse_system *)
-               (hypervisor_mem + hv_core_and_percpu_size);
-       if (copy_from_user(config, arg, config_size)) {
-               err = -EFAULT;
-               goto error_unmap;
-       }
-
        if (config->debug_console.clock_reg) {
                clock_reg = ioremap(config->debug_console.clock_reg,
                                    sizeof(clock_gates));
@@ -548,7 +550,8 @@ static int jailhouse_cmd_enable(struct jailhouse_system 
__user *arg)
                }
                /* The hypervisor has no notion of address spaces, so we need
                 * to enforce conversion. */
-               header->debug_console_base = (void * __force)console;
+               if (!early_loader)
+                       header->debug_console_base = (void * __force)console;
        }
 #endif
 
@@ -570,17 +573,24 @@ static int jailhouse_cmd_enable(struct jailhouse_system 
__user *arg)
 
        preempt_disable();
 
-       header->online_cpus = num_online_cpus();
+       if (!early_loader) {
+               header->online_cpus = num_online_cpus();
 
-       /*
-        * Cannot use wait=true here because all CPUs have to enter the
-        * hypervisor to start the handover while on_each_cpu holds the calling
-        * CPU back.
-        */
-       atomic_set(&call_done, 0);
-       on_each_cpu(enter_hypervisor, header, 0);
-       while (atomic_read(&call_done) != num_online_cpus())
-               cpu_relax();
+               /*
+                * Cannot use wait=true here because all CPUs have to enter the
+                * hypervisor to start the handover while on_each_cpu holds the 
calling
+                * CPU back.
+                */
+               atomic_set(&call_done, 0);
+               on_each_cpu(enter_hypervisor, header, 0);
+               while (atomic_read(&call_done) != num_online_cpus())
+                       cpu_relax();
+       } else {
+               for_each_cpu(cpu, &root_cell->cpus_assigned) {
+                       if (!cpu_online(cpu))
+                               cpumask_clear_cpu(cpu, 
&root_cell->cpus_assigned);
+               }
+       }
 
        preempt_enable();
 
@@ -964,5 +974,6 @@ static void __exit jailhouse_exit(void)
        root_device_unregister(jailhouse_dev);
 }
 
+module_param(early_loader, uint, S_IRUGO);
 module_init(jailhouse_init);
 module_exit(jailhouse_exit);
-- 
2.16.4

-- 
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/20200807030632.28259-11-peng.fan%40nxp.com.

Reply via email to