public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
From: Ed Robbins <edd.robbins@googlemail.com>
To: David Brown <david.brown@hesbynett.no>
Cc: Matthias Pfaller <leo@marco.de>, gcc-help@gcc.gnu.org
Subject: Re: arm-none-eabi, nested function trampolines and caching
Date: Tue, 5 Dec 2023 17:10:52 +0000	[thread overview]
Message-ID: <CALVXH_qZoed_MY1rxPdvnLcdxXgrWQQnpW-N3hB=451av3nm5Q@mail.gmail.com> (raw)
In-Reply-To: <a0b10199-a8da-4cb9-bbf9-9f68022af76a@hesbynett.no>

On Tue, 28 Nov 2023 at 18:00, David Brown <david.brown@hesbynett.no> wrote:
>
> On 28/11/2023 10:51, Ed Robbins via Gcc-help wrote:
> > On Tue, 28 Nov 2023 at 07:21, Matthias Pfaller <leo@marco.de> wrote:
> >>
> >> On 2023-11-27 16:16, Ed Robbins via Gcc-help wrote:
> >>> Hello,
> >>> I am using gcc-arm-none-eabi with a cortex M7 device, with caches
> >>> (data/instruction) enabled. Nested function calls result in a usage fault
> >>> because there is no clear cache call for this platform.
> >>>
>
> >> I have lots of code with nested functions. When switching to gcc-12 I got random
> >> crashes on my cortex-m7 targets. In order to get that working again I had to patch
> >> gcc/config/arm/arm.h:
> >>
>
>
> Can I ask (either or both of you) why you are using are using nested
> functions like this?  This is possibly the first time I have heard of
> anyone using them, certainly the first time in embedded development.
> Even when I programmed in Pascal, where nested functions are part of the
> language, I did not use them more than a couple of times.
>
> What benefit do you see in nested functions in C, compared to having
> separate functions?  Have you considered moving to C++ and using
> lambdas, which are more flexible, standard, and can be very much more
> efficient?
>
> This is, of course, straying from the topicality of this mailing list.
> But I am curious, and I doubt if I am the only one who is.
>
> David
>

In the simplest case you may want to do something like:

struct sometype* find_thing_with_value(struct list *things, uint32_t value) {
    bool match(void *thing) {
        return ((struct sometype*)thing)->field == value;
    }
    return (struct sometype*)list_find(things, &match);
}

In general though dependency inversion can be quite powerful. We use
nested functions that do not access local variables fairly frequently
in our codebase, mostly as a scoping mechanism. We would like to be
able to access locals, and are aware of the implications, but only
very recently decided to address the issue.

I think that rather than switch to C++ lambdas we would be more
inclined to move to clang blocks and stick with C. But there is no
impetus for either move: Nested functions are just fine for what we
need to do, and the syntax is very clean. We have thoughts about a HLL
shift but it wouldn't be to C++.

Security implications are not an issue for us because there is no way
for an outsider to communicate with the devices, let alone get a stack
overflow and code execution.

I think that it would be sensible if there was a -mflush_func option
for ARM targets, as for MIPS, which would resolve the caching issues
that require a patched gcc build in this case.

Thanks to Matthias for guidance. I have ended up implementing this a
bit differently, as in the patch below, as it's then totally
self-contained. I've tested by rebuilding the toolchain using the
script from [1] and it is working well.

Best regards,
Ed

[1] https://github.com/FreddieChopin/bleeding-edge-toolchain/tree/master

From 569177e29cdc777e84e5e8cf633ebef761e82f83 Mon Sep 17 00:00:00 2001
From: Ed Robbins <edd.robbins@gmail.com>
Date: Tue, 5 Dec 2023 16:56:36 +0000
Subject: [PATCH] Define CLEAR_INSN_CACHE in arm.h and implement for v7em
 targets

---
 gcc/config/arm/arm.h | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index f479540812a..666d98611bc 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -2518,4 +2518,37 @@ const char *arm_be8_option (int argc, const char **argv);
    representation for SHF_ARM_PURECODE in GCC.  */
 #define SECTION_ARM_PURECODE SECTION_MACH_DEP

+#ifndef CLEAR_INSN_CACHE
+/* When defined CLEAR_INSN_CACHE is called by __clear_cache in libgcc/libgcc2.c
+   It needs to always be _defined_, otherwise
maybe_emit_call_builtin___clear_cache
+   from gcc/builtins.cc will not generate a call to __clear_cache, however we
+   only want it _implemented_ for the multilib version of libgcc.a built for
+   v7em targets. */
+#ifdef __ARM_ARCH_7EM__
+#define CLEAR_INSN_CACHE(BEG, END) \
+ { \
+ const void *scb_base = (const void*)0xe000e000; \
+ const unsigned dccmvac_offset = 0x268; \
+ const unsigned icimvau_offset = 0x258; \
+ const unsigned cache_line_size = 32; \
+ void *addr = (void*)((unsigned)BEG & ~(cache_line_size - 1)); \
+ void *end = (void*)((unsigned)(END + cache_line_size - 1) &
~(cache_line_size - 1)); \
+ __asm__ __volatile__("dsb" : : : "memory"); \
+ while (addr < end) { \
+ *(unsigned**)(scb_base + dccmvac_offset) = addr; \
+ addr += cache_line_size; \
+ } \
+ __asm__ __volatile__("dsb; isb" : : : "memory"); \
+ addr = (void*)((unsigned)BEG & ~(cache_line_size - 1)); \
+ while (addr < end) { \
+ *(unsigned**)(scb_base + icimvau_offset) = addr; \
+ addr += cache_line_size; \
+ } \
+ __asm__ __volatile__("dsb; isb" : : : "memory"); \
+ }
+#else
+#define CLEAR_INSN_CACHE(BEG, END) ;
+#endif
+#endif
+
 #endif /* ! GCC_ARM_H */
-- 
2.34.1

  parent reply	other threads:[~2023-12-05 17:11 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-11-27 15:16 Ed Robbins
2023-11-27 17:23 ` David Brown
2023-11-27 18:30   ` Richard Earnshaw
2023-11-28  9:18   ` Ed Robbins
     [not found] ` <8342aeef-4eef-231b-bf45-416660954fdb@marco.de>
2023-11-28  9:51   ` Ed Robbins
2023-11-28 18:00     ` David Brown
2023-11-29  7:50       ` Matthias Pfaller
2023-11-29 11:52         ` David Brown
2023-11-29 12:33           ` Matthias Pfaller
2023-12-05 17:10       ` Ed Robbins [this message]
2023-12-05 18:40         ` Ed Robbins

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='CALVXH_qZoed_MY1rxPdvnLcdxXgrWQQnpW-N3hB=451av3nm5Q@mail.gmail.com' \
    --to=edd.robbins@googlemail.com \
    --cc=david.brown@hesbynett.no \
    --cc=edd.robbins@gmail.com \
    --cc=gcc-help@gcc.gnu.org \
    --cc=leo@marco.de \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).