This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 30a37690576 arch/mips: Add support for loadable ELF modules
30a37690576 is described below

commit 30a37690576456ebf5b94d3aa4efe1a6838c2705
Author: Lwazi Dube <[email protected]>
AuthorDate: Mon Aug 10 18:29:01 2026 -0400

    arch/mips: Add support for loadable ELF modules
    
    Implement architecture-specific ELF header definitions and relocation 
handling
    for the MIPS architecture to enable loadable modules.
    
    Fixes #19178.
    
    Changes include:
    - Add `arch/mips/include/elf.h` with MIPS ELF relocation types and
      architecture-specific ELF data structures (`arch_elfdata_s`).
    - Implement `libs/libc/machine/mips/arch_elf.c` containing `up_checkarch`,
      `up_relocate`, and `up_relocateadd` functions handling `R_MIPS_NONE`,
      `R_MIPS_32`, `R_MIPS_26`, `R_MIPS_HI16`, and `R_MIPS_LO16` relocations.
    - Integrate MIPS machine-specific C library support in
      `libs/libc/machine/mips/Make.defs`.
    - Update `LDMODULEFLAGS` in `arch/mips/src/mips32/Toolchain.defs` to 
include the
      little-endian (`-EL`) flag.
    - Update `up_coherent_dcache` for proper cache synchronization on JZ4780.
    
    Signed-off-by: Lwazi Dube <[email protected]>
---
 arch/mips/include/elf.h             |  62 +++++++++++
 arch/mips/src/jz4780/jz4780_cache.c |   2 +
 arch/mips/src/jz4780/jz4780_cache.h |   1 +
 arch/mips/src/mips32/Toolchain.defs |   2 +-
 libs/libc/machine/Make.defs         |   3 +
 libs/libc/machine/mips/Kconfig      |   5 +
 libs/libc/machine/mips/Make.defs    |  28 +++++
 libs/libc/machine/mips/arch_elf.c   | 212 ++++++++++++++++++++++++++++++++++++
 8 files changed, 314 insertions(+), 1 deletion(-)

diff --git a/arch/mips/include/elf.h b/arch/mips/include/elf.h
new file mode 100644
index 00000000000..ce1cc86dea6
--- /dev/null
+++ b/arch/mips/include/elf.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+ * arch/mips/include/elf.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_MIPS_INCLUDE_ELF_H
+#define __ARCH_MIPS_INCLUDE_ELF_H
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define R_MIPS_NONE          0
+#define R_MIPS_32            2
+#define R_MIPS_26            4
+#define R_MIPS_HI16          5
+#define R_MIPS_LO16          6
+
+#define MIPS_HI16_COUNT      10
+#define ARCH_ELFDATA         1
+
+/****************************************************************************
+ * Private Data Types
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+struct arch_elfdata_s
+{
+  struct hi_rel_s
+  {
+    Elf_Addr ahi;
+    Elf32_Addr *p;
+  }
+  hi[MIPS_HI16_COUNT];
+  int pos;
+
+  Elf_Addr ahi;         /* The newest ahi */
+};
+
+typedef struct arch_elfdata_s arch_elfdata_t;
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ARCH_MIPS_INCLUDE_ELF_H */
diff --git a/arch/mips/src/jz4780/jz4780_cache.c 
b/arch/mips/src/jz4780/jz4780_cache.c
index 3777118e933..96a78cd4bb0 100644
--- a/arch/mips/src/jz4780/jz4780_cache.c
+++ b/arch/mips/src/jz4780/jz4780_cache.c
@@ -437,6 +437,8 @@ void up_disable_dcache(void)
 
 void up_coherent_dcache(uintptr_t addr, size_t len)
 {
+  m32_dcache_clean(addr, len);
+  m32_clean_icache(addr, len);
 }
 
 #endif /* CONFIG_ARCH_DCACHE */
diff --git a/arch/mips/src/jz4780/jz4780_cache.h 
b/arch/mips/src/jz4780/jz4780_cache.h
index 21c8b234ea8..eeb5c35017b 100644
--- a/arch/mips/src/jz4780/jz4780_cache.h
+++ b/arch/mips/src/jz4780/jz4780_cache.h
@@ -66,6 +66,7 @@ void m32_size_cache(void);
 void m32_flush_dcache(void);
 void m32_flush_icache(void);
 void m32_clean_cache(uint32_t kva, size_t n);
+void m32_clean_icache(uint32_t kva, size_t n);
 void m32_sync_icache(uint32_t kva, size_t n);
 void m32_dcache_clean_invalidate(uint32_t kva, size_t n);
 void m32_dcache_invalidate(uint32_t kva, size_t n);
diff --git a/arch/mips/src/mips32/Toolchain.defs 
b/arch/mips/src/mips32/Toolchain.defs
index 67a8b28e6ca..5b09c374a1e 100644
--- a/arch/mips/src/mips32/Toolchain.defs
+++ b/arch/mips/src/mips32/Toolchain.defs
@@ -325,7 +325,7 @@ endif
 # Loadable module definitions
 
 CMODULEFLAGS = $(CFLAGS) -fvisibility=hidden
-LDMODULEFLAGS = -r -T $(call CONVERT_PATH,$(TOPDIR)/libs/libc/elf/gnu-elf.ld)
+LDMODULEFLAGS = -EL -r -T $(call 
CONVERT_PATH,$(TOPDIR)/libs/libc/elf/gnu-elf.ld)
 
 # ELF module definitions
 
diff --git a/libs/libc/machine/Make.defs b/libs/libc/machine/Make.defs
index fefcdff5c4e..73e34fecccb 100644
--- a/libs/libc/machine/Make.defs
+++ b/libs/libc/machine/Make.defs
@@ -32,6 +32,9 @@ endif
 ifeq ($(CONFIG_ARCH_ARM64),y)
 include $(TOPDIR)/libs/libc/machine/arm64/Make.defs
 endif
+ifeq ($(CONFIG_ARCH_MIPS),y)
+include $(TOPDIR)/libs/libc/machine/mips/Make.defs
+endif
 ifeq ($(CONFIG_ARCH_RISCV),y)
 include $(TOPDIR)/libs/libc/machine/risc-v/Make.defs
 endif
diff --git a/libs/libc/machine/mips/Kconfig b/libs/libc/machine/mips/Kconfig
new file mode 100644
index 00000000000..18c7905aed7
--- /dev/null
+++ b/libs/libc/machine/mips/Kconfig
@@ -0,0 +1,5 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
diff --git a/libs/libc/machine/mips/Make.defs b/libs/libc/machine/mips/Make.defs
new file mode 100644
index 00000000000..48efd78426d
--- /dev/null
+++ b/libs/libc/machine/mips/Make.defs
@@ -0,0 +1,28 @@
+############################################################################
+# libs/libc/machine/mips/Make.defs
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+ifeq ($(CONFIG_LIBC_ARCH_ELF),y)
+CSRCS += arch_elf.c
+endif
+
+DEPPATH += --dep-path machine/mips
+VPATH += :machine/mips
diff --git a/libs/libc/machine/mips/arch_elf.c 
b/libs/libc/machine/mips/arch_elf.c
new file mode 100644
index 00000000000..198dfdb9086
--- /dev/null
+++ b/libs/libc/machine/mips/arch_elf.c
@@ -0,0 +1,212 @@
+/****************************************************************************
+ * libs/libc/machine/mips/arch_elf.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <nuttx/debug.h>
+#include <assert.h>
+
+#include <nuttx/elf.h>
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_checkarch
+ *
+ * Description:
+ *   Given the ELF header in 'hdr', verify that the ELF file is appropriate
+ *   for the current, configured architecture.  Every architecture that uses
+ *   the ELF loader must provide this function.
+ *
+ * Input Parameters:
+ *   hdr - The ELF header read from the ELF file.
+ *
+ * Returned Value:
+ *   True if the architecture supports this ELF file.
+ *
+ ****************************************************************************/
+
+bool up_checkarch(const Elf32_Ehdr *ehdr)
+{
+  /* Make sure it's a MIPS executable */
+
+  if (ehdr->e_machine != EM_MIPS)
+    {
+      berr("ERROR: Not for MIPS: e_machine=%04x\n", ehdr->e_machine);
+      return false;
+    }
+
+  /* Make sure that 32-bit objects are supported */
+
+  if (ehdr->e_ident[EI_CLASS] != ELFCLASS32)
+    {
+      berr("ERROR: Need 32-bit objects: e_ident[EI_CLASS]=%02x\n",
+           ehdr->e_ident[EI_CLASS]);
+      return false;
+    }
+
+  /* Verify endian-ness */
+
+#ifdef CONFIG_ENDIAN_BIG
+  if (ehdr->e_ident[EI_DATA] != ELFDATA2MSB)
+#else
+  if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB)
+#endif
+    {
+      berr("ERROR: Wrong endian-ness: e_ident[EI_DATA]=%02x\n",
+           ehdr->e_ident[EI_DATA]);
+      return false;
+    }
+
+  /* Make sure the entry point address is properly aligned */
+
+  if ((ehdr->e_entry & 3) != 0)
+    {
+      berr("ERROR: Entry point is not properly aligned: %08" PRIx32 "\n",
+           ehdr->e_entry);
+      return false;
+    }
+
+  return true;
+}
+
+/****************************************************************************
+ * Name: up_relocate and up_relocateadd
+ *
+ * Description:
+ *   Perform an architecture-specific ELF relocation.  Every architecture
+ *   that uses the ELF loader must provide this function.
+ *
+ * Input Parameters:
+ *   rel       - The relocation type
+ *   sym       - The ELF symbol structure containing the fully resolved
+ *               value.  There are a few relocation types for a few
+ *               architectures that do not require symbol information.
+ *               For those, this value will be NULL.  Implementations of
+ *               these functions must be able to handle that case.
+ *   addr      - The address that requires the relocation.
+ *   arch_data - Pointer to architecture specific elf data container.
+ *
+ * Returned Value:
+ *   Zero (OK) if the relocation was successful.  Otherwise, a negated errno
+ *   value indicating the cause of the relocation failure.
+ *
+ ****************************************************************************/
+
+int up_relocate(const Elf_Rel *rel, const Elf_Sym *sym, uintptr_t addr,
+                void *arch_data)
+{
+  /* Variable names correspond to the MIPS ABI specification symbols
+   * (A, AHI, AHL, P, S) in lowercase.
+   */
+
+  Elf32_Addr *p = (Elf32_Addr *)addr;
+  Elf_Word r_type = ELF_R_TYPE(rel->r_info);
+  Elf_Addr s = (sym != NULL) ? sym->st_value : 0;
+  arch_elfdata_t *data = (arch_elfdata_t *)arch_data;
+
+  if ((sym == NULL && r_type != R_MIPS_NONE) || !data)
+    {
+      return -EINVAL;
+    }
+
+  switch (r_type)
+    {
+      case R_MIPS_NONE:
+        break;
+
+      case R_MIPS_32:
+        *p = s + *p;
+        break;
+
+      case R_MIPS_26:
+        {
+          Elf_Addr a = *p & 0x03ffffff;
+          Elf_Addr val = ((a << 2) | ((Elf_Addr)p & 0xf0000000)) + s;
+          val = (val >> 2) & 0x03ffffff;
+          *p &= 0xfc000000;
+          *p |= val;
+        }
+        break;
+
+      case R_MIPS_HI16:
+        if (data->pos >= MIPS_HI16_COUNT)
+          {
+            return -EINVAL;
+          }
+
+        data->ahi = *p;
+        data->hi[data->pos].ahi = *p;
+        data->hi[data->pos].p = p;
+
+        data->pos++;
+
+        break;
+
+      case R_MIPS_LO16:
+        {
+          int i;
+          int16_t a = *p;
+          Elf_Addr ahl = (data->ahi << 16) + a;
+          Elf32_Addr iword = *p & 0xffff0000;
+          iword |= (uint16_t)(ahl + s);
+          *p = iword;
+
+          for (i = 0; i < data->pos; i++)
+            {
+              ahl = (data->hi[i].ahi << 16) + a;
+
+              iword = *(data->hi[i].p) & 0xffff0000;
+              iword |= ((ahl + s) - (int16_t)(ahl + s)) >> 16;
+              *(data->hi[i].p) = iword;
+            }
+
+          data->pos = 0;
+        }
+        break;
+
+      default:
+        berr("ERROR: Unsupported relocation: %" PRIu32 "\n",
+             ELF_R_TYPE(rel->r_info));
+        return -EINVAL;
+    }
+
+  return OK;
+}
+
+int up_relocateadd(const Elf32_Rela *rela, const Elf32_Sym *sym,
+                   uintptr_t addr, void *arch_data)
+{
+  berr("Not implemented\n");
+  PANIC();
+  return -ENOSYS;
+}
+

Reply via email to