From: Andrew Jones <drjones@redhat.com>
To: kvmarm@lists.cs.columbia.edu, qemu-devel@nongnu.org,
ard.biesheuvel@linaro.org, christoffer.dall@linaro.org,
marc.zyngier@arm.com, peter.maydell@linaro.org
Cc: pbonzini@redhat.com, lersek@redhat.com, catalin.marinas@arm.com
Subject: Re: [RFC/WIP PATCH 6/6] memory: add clear_cache_to_poc
Date: Wed, 11 Mar 2015 20:21:15 +0100 [thread overview]
Message-ID: <20150311192115.GA16496@hawk.usersys.redhat.com> (raw)
In-Reply-To: <1425668018-3649-7-git-send-email-drjones@redhat.com>
On Fri, Mar 06, 2015 at 01:53:38PM -0500, Andrew Jones wrote:
> Add a function that flushes the cache to PoC. We need a new
> function because __builtin___clear_cache only flushes to
> PoU. Call this function each time an address in a memory
> region that has been flagged as having an incoherent cache
> is written. For starters we only implement it for ARM. Most
> other architectures don't need it anyway.
I started looking for my missing flushes, and see I have stupidity
in this patch. I'm not flushing in the right place at all... My
testing was just [un]lucky, making me think it was on the right
track. I'll send an update to this tomorrow after I remove my head
from a dark hole near my chair.
drew
>
> Signed-off-by: Andrew Jones <drjones@redhat.com>
> ---
> Currently only implemented for aarch64, doesn't completely work yet.
>
> exec.c | 16 ++++++++++------
> include/exec/exec-all.h | 41 +++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 51 insertions(+), 6 deletions(-)
>
> diff --git a/exec.c b/exec.c
> index c85321a38ba69..68268a5961ff5 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -2261,7 +2261,7 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
>
> #else
>
> -static void invalidate_and_set_dirty(hwaddr addr,
> +static void invalidate_and_set_dirty(MemoryRegion *mr, hwaddr addr,
> hwaddr length)
> {
> if (cpu_physical_memory_range_includes_clean(addr, length)) {
> @@ -2269,6 +2269,10 @@ static void invalidate_and_set_dirty(hwaddr addr,
> cpu_physical_memory_set_dirty_range_nocode(addr, length);
> }
> xen_modified_memory(addr, length);
> + if (memory_region_has_incoherent_cache(mr)) {
> + char *start = qemu_get_ram_ptr(addr);
> + clear_cache_to_poc(start, start + length);
> + }
> }
>
> static int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr)
> @@ -2348,7 +2352,7 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
> /* RAM case */
> ptr = qemu_get_ram_ptr(addr1);
> memcpy(ptr, buf, l);
> - invalidate_and_set_dirty(addr1, l);
> + invalidate_and_set_dirty(mr, addr1, l);
> }
> } else {
> if (!memory_access_is_direct(mr, is_write)) {
> @@ -2437,7 +2441,7 @@ static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as,
> switch (type) {
> case WRITE_DATA:
> memcpy(ptr, buf, l);
> - invalidate_and_set_dirty(addr1, l);
> + invalidate_and_set_dirty(mr, addr1, l);
> break;
> case FLUSH_CACHE:
> flush_icache_range((uintptr_t)ptr, (uintptr_t)ptr + l);
> @@ -2622,7 +2626,7 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len,
> mr = qemu_ram_addr_from_host(buffer, &addr1);
> assert(mr != NULL);
> if (is_write) {
> - invalidate_and_set_dirty(addr1, access_len);
> + invalidate_and_set_dirty(mr, addr1, access_len);
> }
> if (xen_enabled()) {
> xen_invalidate_map_cache_entry(buffer);
> @@ -2904,7 +2908,7 @@ static inline void stl_phys_internal(AddressSpace *as,
> stl_p(ptr, val);
> break;
> }
> - invalidate_and_set_dirty(addr1, 4);
> + invalidate_and_set_dirty(mr, addr1, 4);
> }
> }
>
> @@ -2967,7 +2971,7 @@ static inline void stw_phys_internal(AddressSpace *as,
> stw_p(ptr, val);
> break;
> }
> - invalidate_and_set_dirty(addr1, 2);
> + invalidate_and_set_dirty(mr, addr1, 2);
> }
> }
>
> diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
> index 8eb0db3910e86..9bf74e791f357 100644
> --- a/include/exec/exec-all.h
> +++ b/include/exec/exec-all.h
> @@ -106,6 +106,43 @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr,
> hwaddr paddr, int prot,
> int mmu_idx, target_ulong size);
> void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr);
> +#if defined(__aarch64__)
> +static inline void clear_cache_to_poc(char *begin, char *end)
> +{
> + /* Unfortunately __builtin___clear_cache only flushes
> + * to PoU, we need to implement this for PoC.
> + */
> + static unsigned long line_sz = 0;
> + unsigned long start, stop, addr;
> +
> + if (!line_sz) {
> + unsigned int ctr_el0;
> + asm volatile("mrs %0, ctr_el0" : "=&r" (ctr_el0));
> + line_sz = (1UL << ((ctr_el0 >> 16) & 0xf)) * sizeof(int);
> + }
> +
> + start = (unsigned long)begin & ~(line_sz - 1);
> + stop = ((unsigned long)(end + line_sz) & ~(line_sz - 1));
> +
> + for (addr = start; addr < stop; addr += line_sz) {
> + asm volatile("dc cvac, %0" : : "r" (addr));
> + }
> +
> + /* FIXME: Ideally, we'd also flush the icache now, just in
> + * case this is for an executable region. But, AArch64 can't
> + * flush it to PoC from userspace. We need a syscall.
> + */
> +}
> +#elif defined(__arm__)
> +static inline void clear_cache_to_poc(char *begin, char *end)
> +{
> +/* TODO */
> +}
> +#else
> +static inline void clear_cache_to_poc(char *begin, char *end)
> +{
> +}
> +#endif
> #else
> static inline void tlb_flush_page(CPUState *cpu, target_ulong addr)
> {
> @@ -114,6 +151,10 @@ static inline void tlb_flush_page(CPUState *cpu, target_ulong addr)
> static inline void tlb_flush(CPUState *cpu, int flush_global)
> {
> }
> +
> +void clear_cache_to_poc(char *begin, char *end)
> +{
> +}
> #endif
>
> #define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
> --
> 1.8.3.1
>
> _______________________________________________
> kvmarm mailing list
> kvmarm@lists.cs.columbia.edu
> https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
WARNING: multiple messages have this Message-ID (diff)
From: Andrew Jones <drjones@redhat.com>
To: kvmarm@lists.cs.columbia.edu, qemu-devel@nongnu.org,
ard.biesheuvel@linaro.org, christoffer.dall@linaro.org,
marc.zyngier@arm.com, peter.maydell@linaro.org
Cc: pbonzini@redhat.com, lersek@redhat.com, catalin.marinas@arm.com
Subject: Re: [Qemu-devel] [RFC/WIP PATCH 6/6] memory: add clear_cache_to_poc
Date: Wed, 11 Mar 2015 20:21:15 +0100 [thread overview]
Message-ID: <20150311192115.GA16496@hawk.usersys.redhat.com> (raw)
In-Reply-To: <1425668018-3649-7-git-send-email-drjones@redhat.com>
On Fri, Mar 06, 2015 at 01:53:38PM -0500, Andrew Jones wrote:
> Add a function that flushes the cache to PoC. We need a new
> function because __builtin___clear_cache only flushes to
> PoU. Call this function each time an address in a memory
> region that has been flagged as having an incoherent cache
> is written. For starters we only implement it for ARM. Most
> other architectures don't need it anyway.
I started looking for my missing flushes, and see I have stupidity
in this patch. I'm not flushing in the right place at all... My
testing was just [un]lucky, making me think it was on the right
track. I'll send an update to this tomorrow after I remove my head
from a dark hole near my chair.
drew
>
> Signed-off-by: Andrew Jones <drjones@redhat.com>
> ---
> Currently only implemented for aarch64, doesn't completely work yet.
>
> exec.c | 16 ++++++++++------
> include/exec/exec-all.h | 41 +++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 51 insertions(+), 6 deletions(-)
>
> diff --git a/exec.c b/exec.c
> index c85321a38ba69..68268a5961ff5 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -2261,7 +2261,7 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
>
> #else
>
> -static void invalidate_and_set_dirty(hwaddr addr,
> +static void invalidate_and_set_dirty(MemoryRegion *mr, hwaddr addr,
> hwaddr length)
> {
> if (cpu_physical_memory_range_includes_clean(addr, length)) {
> @@ -2269,6 +2269,10 @@ static void invalidate_and_set_dirty(hwaddr addr,
> cpu_physical_memory_set_dirty_range_nocode(addr, length);
> }
> xen_modified_memory(addr, length);
> + if (memory_region_has_incoherent_cache(mr)) {
> + char *start = qemu_get_ram_ptr(addr);
> + clear_cache_to_poc(start, start + length);
> + }
> }
>
> static int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr)
> @@ -2348,7 +2352,7 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
> /* RAM case */
> ptr = qemu_get_ram_ptr(addr1);
> memcpy(ptr, buf, l);
> - invalidate_and_set_dirty(addr1, l);
> + invalidate_and_set_dirty(mr, addr1, l);
> }
> } else {
> if (!memory_access_is_direct(mr, is_write)) {
> @@ -2437,7 +2441,7 @@ static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as,
> switch (type) {
> case WRITE_DATA:
> memcpy(ptr, buf, l);
> - invalidate_and_set_dirty(addr1, l);
> + invalidate_and_set_dirty(mr, addr1, l);
> break;
> case FLUSH_CACHE:
> flush_icache_range((uintptr_t)ptr, (uintptr_t)ptr + l);
> @@ -2622,7 +2626,7 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len,
> mr = qemu_ram_addr_from_host(buffer, &addr1);
> assert(mr != NULL);
> if (is_write) {
> - invalidate_and_set_dirty(addr1, access_len);
> + invalidate_and_set_dirty(mr, addr1, access_len);
> }
> if (xen_enabled()) {
> xen_invalidate_map_cache_entry(buffer);
> @@ -2904,7 +2908,7 @@ static inline void stl_phys_internal(AddressSpace *as,
> stl_p(ptr, val);
> break;
> }
> - invalidate_and_set_dirty(addr1, 4);
> + invalidate_and_set_dirty(mr, addr1, 4);
> }
> }
>
> @@ -2967,7 +2971,7 @@ static inline void stw_phys_internal(AddressSpace *as,
> stw_p(ptr, val);
> break;
> }
> - invalidate_and_set_dirty(addr1, 2);
> + invalidate_and_set_dirty(mr, addr1, 2);
> }
> }
>
> diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
> index 8eb0db3910e86..9bf74e791f357 100644
> --- a/include/exec/exec-all.h
> +++ b/include/exec/exec-all.h
> @@ -106,6 +106,43 @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr,
> hwaddr paddr, int prot,
> int mmu_idx, target_ulong size);
> void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr);
> +#if defined(__aarch64__)
> +static inline void clear_cache_to_poc(char *begin, char *end)
> +{
> + /* Unfortunately __builtin___clear_cache only flushes
> + * to PoU, we need to implement this for PoC.
> + */
> + static unsigned long line_sz = 0;
> + unsigned long start, stop, addr;
> +
> + if (!line_sz) {
> + unsigned int ctr_el0;
> + asm volatile("mrs %0, ctr_el0" : "=&r" (ctr_el0));
> + line_sz = (1UL << ((ctr_el0 >> 16) & 0xf)) * sizeof(int);
> + }
> +
> + start = (unsigned long)begin & ~(line_sz - 1);
> + stop = ((unsigned long)(end + line_sz) & ~(line_sz - 1));
> +
> + for (addr = start; addr < stop; addr += line_sz) {
> + asm volatile("dc cvac, %0" : : "r" (addr));
> + }
> +
> + /* FIXME: Ideally, we'd also flush the icache now, just in
> + * case this is for an executable region. But, AArch64 can't
> + * flush it to PoC from userspace. We need a syscall.
> + */
> +}
> +#elif defined(__arm__)
> +static inline void clear_cache_to_poc(char *begin, char *end)
> +{
> +/* TODO */
> +}
> +#else
> +static inline void clear_cache_to_poc(char *begin, char *end)
> +{
> +}
> +#endif
> #else
> static inline void tlb_flush_page(CPUState *cpu, target_ulong addr)
> {
> @@ -114,6 +151,10 @@ static inline void tlb_flush_page(CPUState *cpu, target_ulong addr)
> static inline void tlb_flush(CPUState *cpu, int flush_global)
> {
> }
> +
> +void clear_cache_to_poc(char *begin, char *end)
> +{
> +}
> #endif
>
> #define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
> --
> 1.8.3.1
>
> _______________________________________________
> kvmarm mailing list
> kvmarm@lists.cs.columbia.edu
> https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
next prev parent reply other threads:[~2015-03-11 19:15 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-03-06 18:49 the arm cache coherency cluster Andrew Jones
2015-03-06 18:49 ` [Qemu-devel] " Andrew Jones
2015-03-06 18:52 ` [RFC PATCH 0/6] flush/invalidate on entry/exit Andrew Jones
2015-03-06 18:52 ` [Qemu-devel] " Andrew Jones
2015-03-06 18:52 ` [RFC PATCH 1/6] kvm: promote KVM_MEMSLOT_INCOHERENT to uapi Andrew Jones
2015-03-06 18:52 ` [Qemu-devel] " Andrew Jones
2015-03-06 18:52 ` [RFC PATCH 2/6] KVM: Introduce incoherent cache maintenance API Andrew Jones
2015-03-06 18:52 ` [Qemu-devel] " Andrew Jones
2015-03-06 18:52 ` [RFC PATCH 3/6] KVM: ARM: change __coherent_cache_guest_page interface Andrew Jones
2015-03-06 18:52 ` [Qemu-devel] " Andrew Jones
2015-03-06 18:52 ` [RFC PATCH 4/6] KVM: ARM: extend __coherent_cache_guest_page Andrew Jones
2015-03-06 18:52 ` [Qemu-devel] " Andrew Jones
2015-03-06 18:52 ` [RFC PATCH 5/6] KVM: ARM: implement kvm_*_incoherent_memory_regions Andrew Jones
2015-03-06 18:52 ` [Qemu-devel] " Andrew Jones
2015-03-06 18:52 ` [RFC PATCH 6/6] KVM: ARM: no need for kvm_arch_flush_incoherent Andrew Jones
2015-03-06 18:52 ` [Qemu-devel] " Andrew Jones
2015-03-06 18:53 ` [RFC PATCH 0/6] support KVM_MEM_INCOHERENT Andrew Jones
2015-03-06 18:53 ` [Qemu-devel] " Andrew Jones
2015-03-06 18:53 ` [RFC PATCH 1/6] memory: add incoherent cache flag Andrew Jones
2015-03-06 18:53 ` [Qemu-devel] " Andrew Jones
2015-03-06 18:53 ` [RFC PATCH 2/6] HACK: linux header update Andrew Jones
2015-03-06 18:53 ` [Qemu-devel] " Andrew Jones
2015-03-06 18:53 ` [PATCH 3/6] kvm-all: put kvm_mem_flags to more work Andrew Jones
2015-03-06 18:53 ` [Qemu-devel] " Andrew Jones
2015-03-06 18:53 ` [RFC PATCH 4/6] kvm-all: set KVM_MEM_INCOHERENT Andrew Jones
2015-03-06 18:53 ` [Qemu-devel] " Andrew Jones
2015-03-06 18:53 ` [RFC PATCH 5/6] vga: flag vram as incoherent Andrew Jones
2015-03-06 18:53 ` [Qemu-devel] " Andrew Jones
2015-03-06 18:53 ` [RFC/WIP PATCH 6/6] memory: add clear_cache_to_poc Andrew Jones
2015-03-06 18:53 ` [Qemu-devel] " Andrew Jones
2015-03-11 19:21 ` Andrew Jones [this message]
2015-03-11 19:21 ` Andrew Jones
2015-03-18 19:00 ` the arm cache coherency cluster Andrew Jones
2015-03-18 19:00 ` [Qemu-devel] " Andrew Jones
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150311192115.GA16496@hawk.usersys.redhat.com \
--to=drjones@redhat.com \
--cc=ard.biesheuvel@linaro.org \
--cc=catalin.marinas@arm.com \
--cc=christoffer.dall@linaro.org \
--cc=kvmarm@lists.cs.columbia.edu \
--cc=lersek@redhat.com \
--cc=marc.zyngier@arm.com \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.