]> rtime.felk.cvut.cz Git - jailhouse.git/commitdiff
driver: sync I-cache, D-cache and memory
authorDmitry Voytik <dmitry.voytik@huawei.com>
Fri, 17 Jun 2016 12:37:29 +0000 (14:37 +0200)
committerJan Kiszka <jan.kiszka@siemens.com>
Sun, 26 Jun 2016 07:16:27 +0000 (09:16 +0200)
Syncronize I-cache with D-cache after loading the hypervisor
image or a cell image. This must be done in arm64 according to
ARMv8 ARM spec. See page 1712, D3.4.6 "Non-cacheable accesses
and instruction caches".

This patch fixes coherency problems observed on real HW targets.
On x86 this operation is a NOP.

Signed-off-by: Dmitry Voytik <dmitry.voytik@huawei.com>
Signed-off-by: Antonios Motakis <antonios.motakis@huawei.com>
[antonios.motakis@huawei.com: edited comments]

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
driver/cell.c
driver/main.c

index dc1b3c8a1e5584fffafc04c852f17a39fd8ab3ca..05ac7b22ff55c043c177918b813d42b9aff48f1d 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <asm/cacheflush.h>
 
 #include "cell.h"
 #include "main.h"
@@ -323,6 +324,14 @@ static int load_image(struct cell *cell,
                           (void __user *)(unsigned long)image.source_address,
                           image.size))
                err = -EFAULT;
+       /*
+        * 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)(image_mem + page_offs),
+                          (unsigned long)(image_mem + page_offs) + image.size);
 
        vunmap(image_mem);
 
index ec184af32072b84a9280ea304cb79c0f7f3c6c2d..13154e61fbf1168dda2c7174f863f9694b247790 100644 (file)
@@ -257,6 +257,15 @@ static int jailhouse_cmd_enable(struct jailhouse_system __user *arg)
        header = (struct jailhouse_header *)hypervisor_mem;
        header->max_cpus = max_cpus;
 
+       /*
+        * 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));
+
        config = (struct jailhouse_system *)
                (hypervisor_mem + hv_core_and_percpu_size);
        if (copy_from_user(config, arg, config_size)) {