All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v5 0/2] Nios II generic board config and semihosting
@ 2019-02-13  3:45 Sandra Loosemore
  2019-02-13  3:45 ` [Qemu-devel] [PATCH v5 1/2] Add generic Nios II board Sandra Loosemore
  2019-02-13  3:46 ` [Qemu-devel] [PATCH v5 2/2] Add Nios II semihosting support Sandra Loosemore
  0 siblings, 2 replies; 11+ messages in thread
From: Sandra Loosemore @ 2019-02-13  3:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: marex

This is the fifth version of the patch series last posted here:

http://lists.nongnu.org/archive/html/qemu-devel/2018-08/msg01987.html

Since the previous version, I've updated the copyrights on the new
files, refreshed the patches against current trunk, and fixed bugs in
the implementations of lseek() and gettimeofday().

The original version of these patches was rejected because there was
no corresponding open-source BSP or I/O library support, making it
difficult to test the code.  I contributed those pieces to libgloss
last summer (commit fddc74d12bf7f765c04c3182a7237ecf23893d27), so that
should no longer be a blocking issue.

Sandra Loosemore (2):
  Add generic Nios II board.
  Add Nios II semihosting support.

 default-configs/nios2-softmmu.mak |   1 +
 hw/nios2/Makefile.objs            |   1 +
 hw/nios2/boot.c                   |   5 +-
 hw/nios2/generic_nommu.c          | 130 +++++++++++
 qemu-options.hx                   |   8 +-
 target/nios2/Makefile.objs        |   2 +-
 target/nios2/cpu.h                |   4 +-
 target/nios2/helper.c             |  11 +
 target/nios2/nios2-semi.c         | 446 ++++++++++++++++++++++++++++++++++++++
 9 files changed, 601 insertions(+), 7 deletions(-)
 create mode 100644 hw/nios2/generic_nommu.c
 create mode 100644 target/nios2/nios2-semi.c

-- 
2.8.1

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCH v5 1/2] Add generic Nios II board.
  2019-02-13  3:45 [Qemu-devel] [PATCH v5 0/2] Nios II generic board config and semihosting Sandra Loosemore
@ 2019-02-13  3:45 ` Sandra Loosemore
  2019-03-07 14:57   ` Peter Maydell
  2019-02-13  3:46 ` [Qemu-devel] [PATCH v5 2/2] Add Nios II semihosting support Sandra Loosemore
  1 sibling, 1 reply; 11+ messages in thread
From: Sandra Loosemore @ 2019-02-13  3:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: marex

This patch adds support for a generic MMU-less Nios II board that can
be used e.g. for bare-metal compiler testing.  Nios II booting is also
tweaked so that bare-metal binaries start executing in RAM starting at
0x00000000, rather than an alias at 0xc0000000, which allows features
such as unwinding to work when binaries are linked to start at the
beginning of the address space.

The generic_nommu.c parts are by Andrew Jenner, based on code by Marek
Vasut.

Originally by Marek Vasut and Andrew Jenner.

Signed-off-by: Sandra Loosemore <sandra@codesourcery.com>
Signed-off-by: Julian Brown <julian@codesourcery.com>
Signed-off-by: Andrew Jenner <andrew@codesourcery.com>
Signed-off-by: Marek Vasut <marex@denx.de>
---
 default-configs/nios2-softmmu.mak |   1 +
 hw/nios2/Makefile.objs            |   1 +
 hw/nios2/boot.c                   |   5 +-
 hw/nios2/generic_nommu.c          | 130 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 136 insertions(+), 1 deletion(-)
 create mode 100644 hw/nios2/generic_nommu.c

diff --git a/default-configs/nios2-softmmu.mak b/default-configs/nios2-softmmu.mak
index ab42d0f..95ed1c2 100644
--- a/default-configs/nios2-softmmu.mak
+++ b/default-configs/nios2-softmmu.mak
@@ -5,3 +5,4 @@ CONFIG_SERIAL=y
 CONFIG_PTIMER=y
 CONFIG_ALTERA_TIMER=y
 CONFIG_NIOS2_10M50=y
+CONFIG_NIOS2_GENERIC_NOMMU=y
diff --git a/hw/nios2/Makefile.objs b/hw/nios2/Makefile.objs
index 89a419a..3e01798 100644
--- a/hw/nios2/Makefile.objs
+++ b/hw/nios2/Makefile.objs
@@ -1,2 +1,3 @@
 obj-y = boot.o cpu_pic.o
 obj-$(CONFIG_NIOS2_10M50) += 10m50_devboard.o
+obj-$(CONFIG_NIOS2_GENERIC_NOMMU) += generic_nommu.o
diff --git a/hw/nios2/boot.c b/hw/nios2/boot.c
index 5f0ab2f..c697047 100644
--- a/hw/nios2/boot.c
+++ b/hw/nios2/boot.c
@@ -140,6 +140,7 @@ void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base,
         uint64_t entry, low, high;
         uint32_t base32;
         int big_endian = 0;
+        int kernel_space = 0;
 
 #ifdef TARGET_WORDS_BIGENDIAN
         big_endian = 1;
@@ -155,10 +156,12 @@ void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base,
                                    translate_kernel_address, NULL,
                                    &entry, NULL, NULL,
                                    big_endian, EM_ALTERA_NIOS2, 0, 0);
+            kernel_space = 1;
         }
 
         /* Always boot into physical ram. */
-        boot_info.bootstrap_pc = ddr_base + 0xc0000000 + (entry & 0x07ffffff);
+        boot_info.bootstrap_pc = ddr_base + (kernel_space ? 0xc0000000 : 0)
+                                 + (entry & 0x07ffffff);
 
         /* If it wasn't an ELF image, try an u-boot image. */
         if (kernel_size < 0) {
diff --git a/hw/nios2/generic_nommu.c b/hw/nios2/generic_nommu.c
new file mode 100644
index 0000000..502567f
--- /dev/null
+++ b/hw/nios2/generic_nommu.c
@@ -0,0 +1,130 @@
+/*
+ * Generic simulator target with no MMU
+ *
+ * Copyright (c) 2018-2019 Mentor Graphics
+ *
+ * Copyright (c) 2016 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on LabX device code
+ *
+ * Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "cpu.h"
+
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+#include "hw/char/serial.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "exec/memory.h"
+#include "exec/address-spaces.h"
+#include "qemu/config-file.h"
+
+#include "boot.h"
+
+#define BINARY_DEVICE_TREE_FILE    "generic-nommu.dtb"
+
+static void nios2_generic_nommu_init(MachineState *machine)
+{
+    Nios2CPU *cpu;
+    DeviceState *dev;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *phys_tcm = g_new(MemoryRegion, 1);
+    MemoryRegion *phys_tcm_alias = g_new(MemoryRegion, 1);
+    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
+    MemoryRegion *phys_ram_alias = g_new(MemoryRegion, 1);
+    ram_addr_t tcm_base = 0x0;
+    ram_addr_t tcm_size = 0x1000;    /* 1 kiB, but QEMU limit is 4 kiB */
+    ram_addr_t ram_base = 0x10000000;
+    ram_addr_t ram_size = 0x08000000;
+    qemu_irq *cpu_irq, irq[32];
+    int i;
+
+    /* Physical TCM (tb_ram_1k) with alias at 0xc0000000 */
+    memory_region_init_ram(phys_tcm, NULL, "nios2.tcm", tcm_size,
+                           &error_abort);
+    memory_region_init_alias(phys_tcm_alias, NULL, "nios2.tcm.alias",
+                             phys_tcm, 0, tcm_size);
+    memory_region_add_subregion(address_space_mem, tcm_base, phys_tcm);
+    memory_region_add_subregion(address_space_mem, 0xc0000000 + tcm_base,
+                                phys_tcm_alias);
+
+    /* Physical DRAM with alias at 0xc0000000 */
+    memory_region_init_ram(phys_ram, NULL, "nios2.ram", ram_size,
+                           &error_abort);
+    memory_region_init_alias(phys_ram_alias, NULL, "nios2.ram.alias",
+                             phys_ram, 0, ram_size);
+    memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
+    memory_region_add_subregion(address_space_mem, 0xc0000000 + ram_base,
+                                phys_ram_alias);
+
+    cpu = NIOS2_CPU(cpu_create(TYPE_NIOS2_CPU));
+
+    /* Remove MMU */
+    cpu->mmu_present = false;
+
+    /* Register: CPU interrupt controller (PIC) */
+    cpu_irq = nios2_cpu_pic_init(cpu);
+
+    /* Register: Internal Interrupt Controller (IIC) */
+    dev = qdev_create(NULL, "altera,iic");
+    object_property_add_const_link(OBJECT(dev), "cpu", OBJECT(cpu),
+                                   &error_abort);
+    qdev_init_nofail(dev);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, cpu_irq[0]);
+    for (i = 0; i < 32; i++) {
+        irq[i] = qdev_get_gpio_in(dev, i);
+    }
+
+    /* Register: Altera 16550 UART */
+    serial_mm_init(address_space_mem, 0xf8001600, 2, irq[1], 115200,
+                   serial_hd(0), DEVICE_NATIVE_ENDIAN);
+
+    /* Register: Timer sys_clk_timer  */
+    dev = qdev_create(NULL, "ALTR.timer");
+    qdev_prop_set_uint32(dev, "clock-frequency", 75 * 1000000);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xf8001440);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[0]);
+
+    /* Register: Timer sys_clk_timer_1  */
+    dev = qdev_create(NULL, "ALTR.timer");
+    qdev_prop_set_uint32(dev, "clock-frequency", 75 * 1000000);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xe0000880);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[5]);
+
+    /* Configure new exception vectors and reset CPU for it to take effect. */
+    cpu->reset_addr = 0xd0000000;
+    cpu->exception_addr = 0xc8000120;
+    cpu->fast_tlb_miss_addr = 0x7fff400;
+
+    nios2_load_kernel(cpu, ram_base, ram_size, machine->initrd_filename,
+                      BINARY_DEVICE_TREE_FILE, NULL);
+}
+
+static void nios2_generic_nommu_machine_init(struct MachineClass *mc)
+{
+    mc->desc = "Generic NOMMU Nios II design";
+    mc->init = nios2_generic_nommu_init;
+}
+
+DEFINE_MACHINE("nios2-generic-nommu", nios2_generic_nommu_machine_init);
-- 
2.8.1

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [PATCH v5 2/2] Add Nios II semihosting support.
  2019-02-13  3:45 [Qemu-devel] [PATCH v5 0/2] Nios II generic board config and semihosting Sandra Loosemore
  2019-02-13  3:45 ` [Qemu-devel] [PATCH v5 1/2] Add generic Nios II board Sandra Loosemore
@ 2019-02-13  3:46 ` Sandra Loosemore
  2019-03-07 14:58   ` Peter Maydell
  1 sibling, 1 reply; 11+ messages in thread
From: Sandra Loosemore @ 2019-02-13  3:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: marex

This patch adds support for libgloss semihosting to Nios II bare-metal
emulation.

Signed-off-by: Sandra Loosemore <sandra@codesourcery.com>
Signed-off-by: Julian Brown <julian@codesourcery.com>
---
 qemu-options.hx            |   8 +-
 target/nios2/Makefile.objs |   2 +-
 target/nios2/cpu.h         |   4 +-
 target/nios2/helper.c      |  11 ++
 target/nios2/nios2-semi.c  | 446 +++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 465 insertions(+), 6 deletions(-)
 create mode 100644 target/nios2/nios2-semi.c

diff --git a/qemu-options.hx b/qemu-options.hx
index 06ef1a7..5019ede 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3712,21 +3712,21 @@ ETEXI
 DEF("semihosting", 0, QEMU_OPTION_semihosting,
     "-semihosting    semihosting mode\n",
     QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA | QEMU_ARCH_LM32 |
-    QEMU_ARCH_MIPS)
+    QEMU_ARCH_MIPS | QEMU_ARCH_NIOS2)
 STEXI
 @item -semihosting
 @findex -semihosting
-Enable semihosting mode (ARM, M68K, Xtensa, MIPS only).
+Enable semihosting mode (ARM, M68K, Xtensa, MIPS, Nios II only).
 ETEXI
 DEF("semihosting-config", HAS_ARG, QEMU_OPTION_semihosting_config,
     "-semihosting-config [enable=on|off][,target=native|gdb|auto][,arg=str[,...]]\n" \
     "                semihosting configuration\n",
 QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA | QEMU_ARCH_LM32 |
-QEMU_ARCH_MIPS)
+QEMU_ARCH_MIPS | QEMU_ARCH_NIOS2)
 STEXI
 @item -semihosting-config [enable=on|off][,target=native|gdb|auto][,arg=str[,...]]
 @findex -semihosting-config
-Enable and configure semihosting (ARM, M68K, Xtensa, MIPS only).
+Enable and configure semihosting (ARM, M68K, Xtensa, MIPS, Nios II only).
 @table @option
 @item target=@code{native|gdb|auto}
 Defines where the semihosting calls will be addressed, to QEMU (@code{native})
diff --git a/target/nios2/Makefile.objs b/target/nios2/Makefile.objs
index 2a11c5c..010de0e 100644
--- a/target/nios2/Makefile.objs
+++ b/target/nios2/Makefile.objs
@@ -1,4 +1,4 @@
-obj-y += translate.o op_helper.o helper.o cpu.o mmu.o
+obj-y += translate.o op_helper.o helper.o cpu.o mmu.o nios2-semi.o
 obj-$(CONFIG_SOFTMMU) += monitor.o
 
 $(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target/nios2/cpu.h b/target/nios2/cpu.h
index 047f376..afd30d5 100644
--- a/target/nios2/cpu.h
+++ b/target/nios2/cpu.h
@@ -141,7 +141,7 @@ typedef struct Nios2CPUClass {
 #define R_PC         64
 
 /* Exceptions */
-#define EXCP_BREAK    -1
+#define EXCP_BREAK    0x1000
 #define EXCP_RESET    0
 #define EXCP_PRESET   1
 #define EXCP_IRQ      2
@@ -223,6 +223,8 @@ void nios2_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
 qemu_irq *nios2_cpu_pic_init(Nios2CPU *cpu);
 void nios2_check_interrupts(CPUNios2State *env);
 
+void do_nios2_semihosting(CPUNios2State *env);
+
 #define TARGET_PHYS_ADDR_SPACE_BITS 32
 #ifdef CONFIG_USER_ONLY
 # define TARGET_VIRT_ADDR_SPACE_BITS 31
diff --git a/target/nios2/helper.c b/target/nios2/helper.c
index a8b8ec6..ca3b087 100644
--- a/target/nios2/helper.c
+++ b/target/nios2/helper.c
@@ -25,6 +25,7 @@
 #include "exec/exec-all.h"
 #include "exec/log.h"
 #include "exec/helper-proto.h"
+#include "exec/semihost.h"
 
 #if defined(CONFIG_USER_ONLY)
 
@@ -169,6 +170,16 @@ void nios2_cpu_do_interrupt(CPUState *cs)
         break;
 
     case EXCP_BREAK:
+        qemu_log_mask(CPU_LOG_INT, "BREAK exception at pc=%x\n",
+                      env->regs[R_PC]);
+
+        if (semihosting_enabled()) {
+            qemu_log_mask(CPU_LOG_INT, "Entering semihosting\n");
+            env->regs[R_PC] += 4;
+            do_nios2_semihosting(env);
+            break;
+        }
+
         if ((env->regs[CR_STATUS] & CR_STATUS_EH) == 0) {
             env->regs[CR_BSTATUS] = env->regs[CR_STATUS];
             env->regs[R_BA] = env->regs[R_PC] + 4;
diff --git a/target/nios2/nios2-semi.c b/target/nios2/nios2-semi.c
new file mode 100644
index 0000000..9db518a
--- /dev/null
+++ b/target/nios2/nios2-semi.c
@@ -0,0 +1,446 @@
+/*
+ *  Nios II Semihosting syscall interface.
+ *  This code is derived from m68k-semi.c.
+ *
+ *  Copyright (c) 2017-2019 Mentor Graphics
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+
+#include "cpu.h"
+#if defined(CONFIG_USER_ONLY)
+#include "qemu.h"
+#else
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
+#include "exec/softmmu-semi.h"
+#endif
+#include "qemu/log.h"
+#include "sysemu/sysemu.h"
+
+#define HOSTED_EXIT  0
+#define HOSTED_INIT_SIM 1
+#define HOSTED_OPEN 2
+#define HOSTED_CLOSE 3
+#define HOSTED_READ 4
+#define HOSTED_WRITE 5
+#define HOSTED_LSEEK 6
+#define HOSTED_RENAME 7
+#define HOSTED_UNLINK 8
+#define HOSTED_STAT 9
+#define HOSTED_FSTAT 10
+#define HOSTED_GETTIMEOFDAY 11
+#define HOSTED_ISATTY 12
+#define HOSTED_SYSTEM 13
+
+typedef uint32_t gdb_mode_t;
+typedef uint32_t gdb_time_t;
+
+struct nios2_gdb_stat {
+  uint32_t    gdb_st_dev;     /* device */
+  uint32_t    gdb_st_ino;     /* inode */
+  gdb_mode_t  gdb_st_mode;    /* protection */
+  uint32_t    gdb_st_nlink;   /* number of hard links */
+  uint32_t    gdb_st_uid;     /* user ID of owner */
+  uint32_t    gdb_st_gid;     /* group ID of owner */
+  uint32_t    gdb_st_rdev;    /* device type (if inode device) */
+  uint64_t    gdb_st_size;    /* total size, in bytes */
+  uint64_t    gdb_st_blksize; /* blocksize for filesystem I/O */
+  uint64_t    gdb_st_blocks;  /* number of blocks allocated */
+  gdb_time_t  gdb_st_atime;   /* time of last access */
+  gdb_time_t  gdb_st_mtime;   /* time of last modification */
+  gdb_time_t  gdb_st_ctime;   /* time of last change */
+} QEMU_PACKED;
+
+struct gdb_timeval {
+  gdb_time_t tv_sec;  /* second */
+  uint64_t tv_usec;   /* microsecond */
+} QEMU_PACKED;
+
+#define GDB_O_RDONLY   0x0
+#define GDB_O_WRONLY   0x1
+#define GDB_O_RDWR     0x2
+#define GDB_O_APPEND   0x8
+#define GDB_O_CREAT  0x200
+#define GDB_O_TRUNC  0x400
+#define GDB_O_EXCL   0x800
+
+static int translate_openflags(int flags)
+{
+    int hf;
+
+    if (flags & GDB_O_WRONLY) {
+        hf = O_WRONLY;
+    } else if (flags & GDB_O_RDWR) {
+        hf = O_RDWR;
+    } else {
+        hf = O_RDONLY;
+    }
+
+    if (flags & GDB_O_APPEND) {
+        hf |= O_APPEND;
+    }
+    if (flags & GDB_O_CREAT) {
+        hf |= O_CREAT;
+    }
+    if (flags & GDB_O_TRUNC) {
+        hf |= O_TRUNC;
+    }
+    if (flags & GDB_O_EXCL) {
+        hf |= O_EXCL;
+    }
+
+    return hf;
+}
+
+static void translate_stat(CPUNios2State *env, target_ulong addr,
+                           struct stat *s)
+{
+    struct nios2_gdb_stat *p;
+
+    p = lock_user(VERIFY_WRITE, addr, sizeof(struct nios2_gdb_stat), 0);
+
+    if (!p) {
+        /* FIXME - should this return an error code? */
+        return;
+    }
+    p->gdb_st_dev = cpu_to_be32(s->st_dev);
+    p->gdb_st_ino = cpu_to_be32(s->st_ino);
+    p->gdb_st_mode = cpu_to_be32(s->st_mode);
+    p->gdb_st_nlink = cpu_to_be32(s->st_nlink);
+    p->gdb_st_uid = cpu_to_be32(s->st_uid);
+    p->gdb_st_gid = cpu_to_be32(s->st_gid);
+    p->gdb_st_rdev = cpu_to_be32(s->st_rdev);
+    p->gdb_st_size = cpu_to_be64(s->st_size);
+#ifdef _WIN32
+    /* Windows stat is missing some fields.  */
+    p->gdb_st_blksize = 0;
+    p->gdb_st_blocks = 0;
+#else
+    p->gdb_st_blksize = cpu_to_be64(s->st_blksize);
+    p->gdb_st_blocks = cpu_to_be64(s->st_blocks);
+#endif
+    p->gdb_st_atime = cpu_to_be32(s->st_atime);
+    p->gdb_st_mtime = cpu_to_be32(s->st_mtime);
+    p->gdb_st_ctime = cpu_to_be32(s->st_ctime);
+    unlock_user(p, addr, sizeof(struct nios2_gdb_stat));
+}
+
+static void nios2_semi_return_u32(CPUNios2State *env, uint32_t ret,
+                                  uint32_t err)
+{
+    target_ulong args = env->regs[R_ARG1];
+    if (put_user_u32(ret, args) ||
+        put_user_u32(err, args + 4)) {
+        /* The nios2 semihosting ABI does not provide any way to report this
+         * error to the guest, so the best we can do is log it in qemu.
+         * It is always a guest error not to pass us a valid argument block.
+         */
+        qemu_log_mask(LOG_GUEST_ERROR, "nios2-semihosting: return value "
+                      "discarded because argument block not writable\n");
+    }
+}
+
+static void nios2_semi_return_u64(CPUNios2State *env, uint64_t ret,
+                                  uint32_t err)
+{
+    target_ulong args = env->regs[R_ARG1];
+    if (put_user_u32(ret >> 32, args) ||
+        put_user_u32(ret, args + 4) ||
+        put_user_u32(err, args + 8)) {
+        /* No way to report this via nios2 semihosting ABI; just log it */
+        qemu_log_mask(LOG_GUEST_ERROR, "nios2-semihosting: return value "
+                      "discarded because argument block not writable\n");
+    }
+}
+
+static int nios2_semi_is_fseek;
+
+static void nios2_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
+{
+    Nios2CPU *cpu = NIOS2_CPU(cs);
+    CPUNios2State *env = &cpu->env;
+
+    if (nios2_semi_is_fseek) {
+        /* FIXME: We've already lost the high bits of the fseek
+           return value.  */
+        nios2_semi_return_u64(env, ret, err);
+        nios2_semi_is_fseek = 0;
+    } else {
+        nios2_semi_return_u32(env, ret, err);
+    }
+}
+
+/* Read the input value from the argument block; fail the semihosting
+ * call if the memory read fails.
+ */
+#define GET_ARG(n) do {                                 \
+    if (get_user_ual(arg ## n, args + (n) * 4)) {       \
+        result = -1;                                    \
+        errno = EFAULT;                                 \
+        goto failed;                                    \
+    }                                                   \
+} while (0)
+
+void do_nios2_semihosting(CPUNios2State *env)
+{
+    int nr;
+    uint32_t args;
+    target_ulong arg0, arg1, arg2, arg3;
+    void *p;
+    void *q;
+    uint32_t len;
+    uint32_t result;
+
+    nr = env->regs[R_ARG0];
+    args = env->regs[R_ARG1];
+    switch (nr) {
+    case HOSTED_EXIT:
+        gdb_exit(env, env->regs[R_ARG0]);
+        exit(env->regs[R_ARG0]);
+    case HOSTED_OPEN:
+        GET_ARG(0);
+        GET_ARG(1);
+        GET_ARG(2);
+        GET_ARG(3);
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(nios2_semi_cb, "open,%s,%x,%x", arg0, (int)arg1,
+                           arg2, arg3);
+            return;
+        } else {
+            p = lock_user_string(arg0);
+            if (!p) {
+                /* FIXME - check error code? */
+                result = -1;
+            } else {
+                result = open(p, translate_openflags(arg2), arg3);
+                unlock_user(p, arg0, 0);
+            }
+        }
+        break;
+    case HOSTED_CLOSE:
+        {
+            /* Ignore attempts to close stdin/out/err.  */
+            GET_ARG(0);
+            int fd = arg0;
+            if (fd > 2) {
+                if (use_gdb_syscalls()) {
+                    gdb_do_syscall(nios2_semi_cb, "close,%x", arg0);
+                    return;
+                } else {
+                    result = close(fd);
+                }
+            } else {
+                result = 0;
+            }
+            break;
+        }
+    case HOSTED_READ:
+        GET_ARG(0);
+        GET_ARG(1);
+        GET_ARG(2);
+        len = arg2;
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(nios2_semi_cb, "read,%x,%x,%x",
+                           arg0, arg1, len);
+            return;
+        } else {
+            p = lock_user(VERIFY_WRITE, arg1, len, 0);
+            if (!p) {
+                /* FIXME - check error code? */
+                result = -1;
+            } else {
+                result = read(arg0, p, len);
+                unlock_user(p, arg1, len);
+            }
+        }
+        break;
+    case HOSTED_WRITE:
+        GET_ARG(0);
+        GET_ARG(1);
+        GET_ARG(2);
+        len = arg2;
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(nios2_semi_cb, "write,%x,%x,%x",
+                           arg0, arg1, len);
+            return;
+        } else {
+            p = lock_user(VERIFY_READ, arg1, len, 1);
+            if (!p) {
+                /* FIXME - check error code? */
+                result = -1;
+            } else {
+                result = write(arg0, p, len);
+                unlock_user(p, arg0, 0);
+            }
+        }
+        break;
+    case HOSTED_LSEEK:
+        {
+            uint64_t off;
+            GET_ARG(0);
+            GET_ARG(1);
+            GET_ARG(2);
+            GET_ARG(3);
+            off = (uint32_t)arg2 | ((uint64_t)arg1 << 32);
+            if (use_gdb_syscalls()) {
+                nios2_semi_is_fseek = 1;
+                gdb_do_syscall(nios2_semi_cb, "lseek,%x,%lx,%x",
+                               arg0, off, arg3);
+            } else {
+                off = lseek(arg0, off, arg3);
+                nios2_semi_return_u64(env, off, errno);
+            }
+            return;
+        }
+    case HOSTED_RENAME:
+        GET_ARG(0);
+        GET_ARG(1);
+        GET_ARG(2);
+        GET_ARG(3);
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(nios2_semi_cb, "rename,%s,%s",
+                           arg0, (int)arg1, arg2, (int)arg3);
+            return;
+        } else {
+            p = lock_user_string(arg0);
+            q = lock_user_string(arg2);
+            if (!p || !q) {
+                /* FIXME - check error code? */
+                result = -1;
+            } else {
+                result = rename(p, q);
+            }
+            unlock_user(p, arg0, 0);
+            unlock_user(q, arg2, 0);
+        }
+        break;
+    case HOSTED_UNLINK:
+        GET_ARG(0);
+        GET_ARG(1);
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(nios2_semi_cb, "unlink,%s",
+                           arg0, (int)arg1);
+            return;
+        } else {
+            p = lock_user_string(arg0);
+            if (!p) {
+                /* FIXME - check error code? */
+                result = -1;
+            } else {
+                result = unlink(p);
+                unlock_user(p, arg0, 0);
+            }
+        }
+        break;
+    case HOSTED_STAT:
+        GET_ARG(0);
+        GET_ARG(1);
+        GET_ARG(2);
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(nios2_semi_cb, "stat,%s,%x",
+                           arg0, (int)arg1, arg2);
+            return;
+        } else {
+            struct stat s;
+            p = lock_user_string(arg0);
+            if (!p) {
+                /* FIXME - check error code? */
+                result = -1;
+            } else {
+                result = stat(p, &s);
+                unlock_user(p, arg0, 0);
+            }
+            if (result == 0) {
+                translate_stat(env, arg2, &s);
+            }
+        }
+        break;
+    case HOSTED_FSTAT:
+        GET_ARG(0);
+        GET_ARG(1);
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(nios2_semi_cb, "fstat,%x,%x",
+                           arg0, arg1);
+            return;
+        } else {
+            struct stat s;
+            result = fstat(arg0, &s);
+            if (result == 0) {
+                translate_stat(env, arg1, &s);
+            }
+        }
+        break;
+    case HOSTED_GETTIMEOFDAY:
+        /* Only the tv parameter is used.  tz is assumed NULL.  */
+        GET_ARG(0);
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(nios2_semi_cb, "gettimeofday,%x,%x",
+                           arg0, 0);
+            return;
+        } else {
+            qemu_timeval tv;
+            struct gdb_timeval *p;
+            result = qemu_gettimeofday(&tv);
+            if (result != 0) {
+                p = lock_user(VERIFY_WRITE, arg0, sizeof(struct gdb_timeval),
+                              0);
+                if (!p) {
+                    /* FIXME - check error code? */
+                    result = -1;
+                } else {
+                    p->tv_sec = cpu_to_be32(tv.tv_sec);
+                    p->tv_usec = cpu_to_be64(tv.tv_usec);
+                    unlock_user(p, arg0, sizeof(struct gdb_timeval));
+                }
+            }
+        }
+        break;
+    case HOSTED_ISATTY:
+        GET_ARG(0);
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(nios2_semi_cb, "isatty,%x", arg0);
+            return;
+        } else {
+            result = isatty(arg0);
+        }
+        break;
+    case HOSTED_SYSTEM:
+        GET_ARG(0);
+        GET_ARG(1);
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(nios2_semi_cb, "system,%s",
+                           arg0, (int)arg1);
+            return;
+        } else {
+            p = lock_user_string(arg0);
+            if (!p) {
+                /* FIXME - check error code? */
+                result = -1;
+            } else {
+                result = system(p);
+                unlock_user(p, arg0, 0);
+            }
+        }
+        break;
+    default:
+        cpu_abort(CPU(nios2_env_get_cpu(env)),
+                  "Unsupported semihosting syscall %d\n", nr);
+        result = 0;
+    }
+failed:
+    nios2_semi_return_u32(env, result, errno);
+}
-- 
2.8.1

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [Qemu-devel] [PATCH v5 1/2] Add generic Nios II board.
  2019-02-13  3:45 ` [Qemu-devel] [PATCH v5 1/2] Add generic Nios II board Sandra Loosemore
@ 2019-03-07 14:57   ` Peter Maydell
  2019-03-08 23:51     ` Sandra Loosemore
  0 siblings, 1 reply; 11+ messages in thread
From: Peter Maydell @ 2019-03-07 14:57 UTC (permalink / raw)
  To: Sandra Loosemore; +Cc: QEMU Developers, Marek Vasut

On Wed, 13 Feb 2019 at 04:04, Sandra Loosemore <sandra@codesourcery.com> wrote:
>
> This patch adds support for a generic MMU-less Nios II board that can
> be used e.g. for bare-metal compiler testing.  Nios II booting is also
> tweaked so that bare-metal binaries start executing in RAM starting at
> 0x00000000, rather than an alias at 0xc0000000, which allows features
> such as unwinding to work when binaries are linked to start at the
> beginning of the address space.

I should start this review by saying that I know nothing at all
about the Nios II architecture, so I'm just going on general
principles. Some of my comments might be confused or wrong as
a result...

> The generic_nommu.c parts are by Andrew Jenner, based on code by Marek
> Vasut.

> Originally by Marek Vasut and Andrew Jenner.
>
> Signed-off-by: Sandra Loosemore <sandra@codesourcery.com>
> Signed-off-by: Julian Brown <julian@codesourcery.com>
> Signed-off-by: Andrew Jenner <andrew@codesourcery.com>
> Signed-off-by: Marek Vasut <marex@denx.de>
> ---
>  default-configs/nios2-softmmu.mak |   1 +
>  hw/nios2/Makefile.objs            |   1 +
>  hw/nios2/boot.c                   |   5 +-
>  hw/nios2/generic_nommu.c          | 130 ++++++++++++++++++++++++++++++++++++++
>  4 files changed, 136 insertions(+), 1 deletion(-)
>  create mode 100644 hw/nios2/generic_nommu.c
>
> diff --git a/default-configs/nios2-softmmu.mak b/default-configs/nios2-softmmu.mak
> index ab42d0f..95ed1c2 100644
> --- a/default-configs/nios2-softmmu.mak
> +++ b/default-configs/nios2-softmmu.mak
> @@ -5,3 +5,4 @@ CONFIG_SERIAL=y
>  CONFIG_PTIMER=y
>  CONFIG_ALTERA_TIMER=y
>  CONFIG_NIOS2_10M50=y
> +CONFIG_NIOS2_GENERIC_NOMMU=y
> diff --git a/hw/nios2/Makefile.objs b/hw/nios2/Makefile.objs
> index 89a419a..3e01798 100644
> --- a/hw/nios2/Makefile.objs
> +++ b/hw/nios2/Makefile.objs
> @@ -1,2 +1,3 @@
>  obj-y = boot.o cpu_pic.o
>  obj-$(CONFIG_NIOS2_10M50) += 10m50_devboard.o
> +obj-$(CONFIG_NIOS2_GENERIC_NOMMU) += generic_nommu.o
> diff --git a/hw/nios2/boot.c b/hw/nios2/boot.c
> index 5f0ab2f..c697047 100644
> --- a/hw/nios2/boot.c
> +++ b/hw/nios2/boot.c
> @@ -140,6 +140,7 @@ void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base,
>          uint64_t entry, low, high;
>          uint32_t base32;
>          int big_endian = 0;
> +        int kernel_space = 0;
>
>  #ifdef TARGET_WORDS_BIGENDIAN
>          big_endian = 1;
> @@ -155,10 +156,12 @@ void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base,
>                                     translate_kernel_address, NULL,
>                                     &entry, NULL, NULL,
>                                     big_endian, EM_ALTERA_NIOS2, 0, 0);
> +            kernel_space = 1;
>          }
>
>          /* Always boot into physical ram. */
> -        boot_info.bootstrap_pc = ddr_base + 0xc0000000 + (entry & 0x07ffffff);
> +        boot_info.bootstrap_pc = ddr_base + (kernel_space ? 0xc0000000 : 0)
> +                                 + (entry & 0x07ffffff);

It's not clear to me what's going on here, or why an
entry address of 0xc000_0000 is special, but I don't
know anything about NiosII -- maybe it's clear if you do?

Why isn't the bootstrap_pc just always the entry address ?
Some comments on what is being done here and the use cases
being addressed might assist. I wasn't able to work out what
the remarks in the commit message meant, I'm afraid.

Looking at the code, I don't think that the second call to
load_elf() will return a different entry address to the first
one (ie translate_kernel_address() is not applied to &entry).
That means that kernel_space is only true if entry == 0xc0000000,
and
  (kernel_space ? 0xc0000000 : 0) + (entry & 0x07ffffff);
is almost the same thing as just 'entry'.

> +static void nios2_generic_nommu_init(MachineState *machine)
> +{
> +    Nios2CPU *cpu;
> +    DeviceState *dev;
> +    MemoryRegion *address_space_mem = get_system_memory();
> +    MemoryRegion *phys_tcm = g_new(MemoryRegion, 1);
> +    MemoryRegion *phys_tcm_alias = g_new(MemoryRegion, 1);
> +    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
> +    MemoryRegion *phys_ram_alias = g_new(MemoryRegion, 1);
> +    ram_addr_t tcm_base = 0x0;
> +    ram_addr_t tcm_size = 0x1000;    /* 1 kiB, but QEMU limit is 4 kiB */
> +    ram_addr_t ram_base = 0x10000000;
> +    ram_addr_t ram_size = 0x08000000;
> +    qemu_irq *cpu_irq, irq[32];
> +    int i;

The description says this is "generic", but it appears to
be almost identical to the existing 10M50 board model,
including having exactly the same devices at the same
apparently arbitrary addresses.

Could we instead add a machine parameter to the existing
board so you could say "-machine 10m50-ghrd,mmu=no"
(and drop the other changes -- it's not clear what they're
needed for) ?

If it really ought to be a separate board model, perhaps
it should be in the same source file and share the common
code.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Qemu-devel] [PATCH v5 2/2] Add Nios II semihosting support.
  2019-02-13  3:46 ` [Qemu-devel] [PATCH v5 2/2] Add Nios II semihosting support Sandra Loosemore
@ 2019-03-07 14:58   ` Peter Maydell
  2019-03-08  3:13     ` Sandra Loosemore
  0 siblings, 1 reply; 11+ messages in thread
From: Peter Maydell @ 2019-03-07 14:58 UTC (permalink / raw)
  To: Sandra Loosemore; +Cc: QEMU Developers, Marek Vasut

On Wed, 13 Feb 2019 at 04:02, Sandra Loosemore <sandra@codesourcery.com> wrote:
>
> This patch adds support for libgloss semihosting to Nios II bare-metal
> emulation.
>
> Signed-off-by: Sandra Loosemore <sandra@codesourcery.com>
> Signed-off-by: Julian Brown <julian@codesourcery.com>

Do you have a link to the spec that defines this semihosting
ABI, please ?

thanks
-- PMM

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Qemu-devel] [PATCH v5 2/2] Add Nios II semihosting support.
  2019-03-07 14:58   ` Peter Maydell
@ 2019-03-08  3:13     ` Sandra Loosemore
  2019-03-08 16:04       ` Peter Maydell
  0 siblings, 1 reply; 11+ messages in thread
From: Sandra Loosemore @ 2019-03-08  3:13 UTC (permalink / raw)
  To: Peter Maydell; +Cc: QEMU Developers, Marek Vasut

[-- Attachment #1: Type: text/plain, Size: 669 bytes --]

On 3/7/19 7:58 AM, Peter Maydell wrote:
> On Wed, 13 Feb 2019 at 04:02, Sandra Loosemore <sandra@codesourcery.com> wrote:
>>
>> This patch adds support for libgloss semihosting to Nios II bare-metal
>> emulation.
>>
>> Signed-off-by: Sandra Loosemore <sandra@codesourcery.com>
>> Signed-off-by: Julian Brown <julian@codesourcery.com>
> 
> Do you have a link to the spec that defines this semihosting
> ABI, please ?

Well, I just wrote some derived from the comments in the libgloss 
sources; see the attachment.  :-)

FWIW this is pretty much a direct copy of the m68k semihosting protocol, 
which CodeSourcery contributed ages ago to both libgloss and qemu.

-Sandra

[-- Attachment #2: nios2-semi.txt --]
[-- Type: text/plain, Size: 4776 bytes --]

Nios II Semihosting Protocol
----------------------------

The runtime (libgloss) indicates a semihosting request to the debug
agent by issuing a "break 1" instruction.  r4 and r5 are used to pass
parameters per the normal C ABI on nios2.

r4 contains a request code.  r5 is typically a pointer to a 4-word
parameter block, except for the exit operation where it is an
immediate integer value.

The result of the operation is returned in the first word of the
parameter block.  The second word is used to return an errno value,
encoded per the "Errno Values" section of the RSP documentation in the
GDB User Manual.

The supported r4 request codes are:

#define HOSTED_EXIT  0

  Terminate program execution; send a 'W' stop reply to GDB.

  r5 contains the exit code, as an immediate integer rather than indirectly
  in a parameter block.  This semihosting request isn't expected to return.

#define HOSTED_INIT_SIM 1

  Reserved/unimplemented.

#define HOSTED_OPEN 2

  Open file; 'Fopen' GDB fileio request.

  r5 points to a parameter block containing:
  [0] pointer to filename
  [1] filename length
  [2] open flags, encoded per the GDB RSP documentation
  [3] mode, encoded per the GDB RSP documentation

  Return values in parameter block:
  [0] file descriptor or -1 on error
  [1] errno, encoded per the GDB RSP documentation

#define HOSTED_CLOSE 3

  Close file; 'Fclose' GDB fileio request.

  r5 points to a parameter block containing:
  [0] file descriptor

  Return values in parameter block:
  [0] return status
  [1] errno, encoded per the GDB RSP documentation

#define HOSTED_READ 4

  Read from file; 'Fread' GDB fileio request.

  r5 points to a parameter block containing:
  [0] file descriptor
  [1] pointer to buffer
  [2] buffer size
  
  Return values in parameter block:
  [0] number of bytes read
  [1] errno, encoded per the GDB RSP documentation

#define HOSTED_WRITE 5

  Write to file; 'Fwrite' GDB fileio request.

  r5 points to a parameter block containing:
  [0] file descriptor
  [1] pointer to buffer
  [2] byte count
  
  Return values in parameter block:
  [0] number of bytes written
  [1] errno, encoded per the GDB RSP documentation

#define HOSTED_LSEEK 6

  File seek; 'Flseek' GDB fileio request.

  r5 points to a parameter block containing:
  [0] file descriptor
  [1] high word of 64-bit offset
  [2] low word of 64-bit offset
  [3] seek flag, encoded per the GDB RSP documentation

  Return values in parameter block:
  [0] high word of 64-bit result
  [1] low word of 64-bit result
  [2] errno, encoded per the GDB RSP documentation

#define HOSTED_RENAME 7

  File rename; 'Frename' GDB fileio request.

  r5 points to a parameter block containing:
  [0] oldname pointer
  [1] oldname length
  [2] newname pointer
  [3] newname length

  Return values in parameter block:
  [0] return status
  [1] errno, encoded per the GDB RSP documentation

#define HOSTED_UNLINK 8

  File unlink/delete; 'Funlink' GDB fileio request.

  r5 points to a parameter block containing:
  [0] filename pointer
  [1] filename length

  Return values in parameter block:
  [0] return status
  [1] errno, encoded per the GDB RSP documentation

#define HOSTED_STAT 9

  File information; 'Fstat' GDB fileio request.

  r5 points to a parameter block containing:
  [0] filename pointer
  [1] filename length
  [2] pointer to stat buf, using the structure definition in the GDB RSP
      documentation 

  Return values in parameter block:
  [0] return status
  [1] errno, encoded per the GDB RSP documentation

#define HOSTED_FSTAT 10

  File information; 'Ffstat' GDB fileio request.
  
  r5 points to a parameter block containing:
  [0] file descriptor
  [1] pointer to stat buf, using the structure definition in the GDB RSP
      documentation 

  Return values in parameter block:
  [0] return status
  [1] errno, encoded per the GDB RSP documentation

#define HOSTED_GETTIMEOFDAY 11

  Get current time; 'Fgettimeofday' GDB fileio request.

  r5 points to a parameter block containing:
  [0] timeval pointer, using the structure definition in the GDB RSP
      documentation

  Return values in parameter block:
  [0] return status
  [1] errno, encoded per the GDB RSP documentation

#define HOSTED_ISATTY 12

 Return true if the file descriptor is the GDB console; 'Fisatty' GDB fileio
 request.

  r5 points to a parameter block containing:
  [0] file descriptor

  Return values in parameter block:
  [0] return status
  [1] errno, encoded per the GDB RSP documentation

#define HOSTED_SYSTEM 13

  System call; 'Fsystem' GDB fileio request.

  r5 points to a parameter block containing:
  [0] command pointer
  [1] command length

  Return values in parameter block:
  [0] return status
  [1] errno, encoded per the GDB RSP documentation

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Qemu-devel] [PATCH v5 2/2] Add Nios II semihosting support.
  2019-03-08  3:13     ` Sandra Loosemore
@ 2019-03-08 16:04       ` Peter Maydell
  2019-03-08 17:01         ` Sandra Loosemore
  0 siblings, 1 reply; 11+ messages in thread
From: Peter Maydell @ 2019-03-08 16:04 UTC (permalink / raw)
  To: Sandra Loosemore; +Cc: QEMU Developers, Marek Vasut

On Fri, 8 Mar 2019 at 03:13, Sandra Loosemore <sandra@codesourcery.com> wrote:
>
> On 3/7/19 7:58 AM, Peter Maydell wrote:
> > On Wed, 13 Feb 2019 at 04:02, Sandra Loosemore <sandra@codesourcery.com> wrote:
> >>
> >> This patch adds support for libgloss semihosting to Nios II bare-metal
> >> emulation.
> >>
> >> Signed-off-by: Sandra Loosemore <sandra@codesourcery.com>
> >> Signed-off-by: Julian Brown <julian@codesourcery.com>
> >
> > Do you have a link to the spec that defines this semihosting
> > ABI, please ?
>
> Well, I just wrote some derived from the comments in the libgloss
> sources; see the attachment.  :-)

Thanks. So who "owns" this ABI (ie has the authority to change
it and should be the end documenting it)? How many projects or
bits of software are implementing either end of it?

If we decide that QEMU owns the spec we can put the documentation
into docs/specs/.

> FWIW this is pretty much a direct copy of the m68k semihosting protocol,
> which CodeSourcery contributed ages ago to both libgloss and qemu.

Yeah, and that seems to be undocumented too :-(  I'm not a huge
fan of "this is just some random thing that's private to QEMU
and libgloss".

thanks
-- PMM

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Qemu-devel] [PATCH v5 2/2] Add Nios II semihosting support.
  2019-03-08 16:04       ` Peter Maydell
@ 2019-03-08 17:01         ` Sandra Loosemore
  2019-03-08 18:21           ` Peter Maydell
  0 siblings, 1 reply; 11+ messages in thread
From: Sandra Loosemore @ 2019-03-08 17:01 UTC (permalink / raw)
  To: Peter Maydell; +Cc: QEMU Developers, Marek Vasut

On 3/8/19 9:04 AM, Peter Maydell wrote:
> On Fri, 8 Mar 2019 at 03:13, Sandra Loosemore <sandra@codesourcery.com> wrote:
>>
>> On 3/7/19 7:58 AM, Peter Maydell wrote:
>>> On Wed, 13 Feb 2019 at 04:02, Sandra Loosemore <sandra@codesourcery.com> wrote:
>>>>
>>>> This patch adds support for libgloss semihosting to Nios II bare-metal
>>>> emulation.
>>>>
>>>> Signed-off-by: Sandra Loosemore <sandra@codesourcery.com>
>>>> Signed-off-by: Julian Brown <julian@codesourcery.com>
>>>
>>> Do you have a link to the spec that defines this semihosting
>>> ABI, please ?
>>
>> Well, I just wrote some derived from the comments in the libgloss
>> sources; see the attachment.  :-)
> 
> Thanks. So who "owns" this ABI (ie has the authority to change
> it and should be the end documenting it)? How many projects or
> bits of software are implementing either end of it?

Going back in ancient history, I implemented the m68k version in 
libgloss in 2006 to support a hardware debug stub that CodeSourcery was 
also providing at that time.  We later moved the runtime side of it into 
target-agnostic code in an internal library, so when it came time to do 
a similar JTAG debug stub for bare-metal Nios II hardware testing in 
2012, we re-used our existing code for both library and debug stub. 
Later Altera implemented the same protocol in some proprietary 
simulators they provided to us, and more recently we wrote these patches 
to add it to QEMU.  We've shifted away from hardware testing and no 
longer use the original debug stub now.

> If we decide that QEMU owns the spec we can put the documentation
> into docs/specs/.

Making QEMU the "owner" of the ABI seems a little peculiar to me since 
it is only one client among several, and is a latecomer too.  I think 
libgloss would make a little more sense.  OTOH, I have no problem with 
making the documentation part of QEMU.

-Sandra

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Qemu-devel] [PATCH v5 2/2] Add Nios II semihosting support.
  2019-03-08 17:01         ` Sandra Loosemore
@ 2019-03-08 18:21           ` Peter Maydell
  0 siblings, 0 replies; 11+ messages in thread
From: Peter Maydell @ 2019-03-08 18:21 UTC (permalink / raw)
  To: Sandra Loosemore; +Cc: QEMU Developers, Marek Vasut

On Fri, 8 Mar 2019 at 17:01, Sandra Loosemore <sandra@codesourcery.com> wrote:
>
> On 3/8/19 9:04 AM, Peter Maydell wrote:
> > Thanks. So who "owns" this ABI (ie has the authority to change
> > it and should be the end documenting it)? How many projects or
> > bits of software are implementing either end of it?
>
> Going back in ancient history, I implemented the m68k version in
> libgloss in 2006 to support a hardware debug stub that CodeSourcery was
> also providing at that time.  We later moved the runtime side of it into
> target-agnostic code in an internal library, so when it came time to do
> a similar JTAG debug stub for bare-metal Nios II hardware testing in
> 2012, we re-used our existing code for both library and debug stub.
> Later Altera implemented the same protocol in some proprietary
> simulators they provided to us, and more recently we wrote these patches
> to add it to QEMU.  We've shifted away from hardware testing and no
> longer use the original debug stub now.
>
> > If we decide that QEMU owns the spec we can put the documentation
> > into docs/specs/.
>
> Making QEMU the "owner" of the ABI seems a little peculiar to me since
> it is only one client among several, and is a latecomer too.  I think
> libgloss would make a little more sense.  OTOH, I have no problem with
> making the documentation part of QEMU.

Thanks for the backstory. I agree that if QEMU is just one of
multiple implementations then it's not a great place to
hold the specification. Either libgloss, or I suppose in
theory Altera as the owner of the architecture could bless
the specification and host it...

-- PMM

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Qemu-devel] [PATCH v5 1/2] Add generic Nios II board.
  2019-03-07 14:57   ` Peter Maydell
@ 2019-03-08 23:51     ` Sandra Loosemore
  2019-03-09 14:27       ` Peter Maydell
  0 siblings, 1 reply; 11+ messages in thread
From: Sandra Loosemore @ 2019-03-08 23:51 UTC (permalink / raw)
  To: Peter Maydell; +Cc: QEMU Developers, Marek Vasut, Andrew Jenner

On 3/7/19 7:57 AM, Peter Maydell wrote:
>> diff --git a/hw/nios2/boot.c b/hw/nios2/boot.c
>> index 5f0ab2f..c697047 100644
>> --- a/hw/nios2/boot.c
>> +++ b/hw/nios2/boot.c
>> @@ -140,6 +140,7 @@ void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base,
>>           uint64_t entry, low, high;
>>           uint32_t base32;
>>           int big_endian = 0;
>> +        int kernel_space = 0;
>>
>>   #ifdef TARGET_WORDS_BIGENDIAN
>>           big_endian = 1;
>> @@ -155,10 +156,12 @@ void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base,
>>                                      translate_kernel_address, NULL,
>>                                      &entry, NULL, NULL,
>>                                      big_endian, EM_ALTERA_NIOS2, 0, 0);
>> +            kernel_space = 1;
>>           }
>>
>>           /* Always boot into physical ram. */
>> -        boot_info.bootstrap_pc = ddr_base + 0xc0000000 + (entry & 0x07ffffff);
>> +        boot_info.bootstrap_pc = ddr_base + (kernel_space ? 0xc0000000 : 0)
>> +                                 + (entry & 0x07ffffff);
> 
> It's not clear to me what's going on here, or why an
> entry address of 0xc000_0000 is special, but I don't
> know anything about NiosII -- maybe it's clear if you do?

The processor reference guide documents that the kernel is placed at 
virtual memory address 0xc0000000.

https://www.intel.com/content/www/us/en/programmable/documentation/iga1409256728501.html#iga1409332620358

The problem the patch to boot.c is trying to solve is that we found 
things like unwind info were screwed up when using -kernel to load 
executables with an entry address other than 0xc0000000.

> Why isn't the bootstrap_pc just always the entry address ?
> Some comments on what is being done here and the use cases
> being addressed might assist. I wasn't able to work out what
> the remarks in the commit message meant, I'm afraid.
> 
> Looking at the code, I don't think that the second call to
> load_elf() will return a different entry address to the first
> one (ie translate_kernel_address() is not applied to &entry).
> That means that kernel_space is only true if entry == 0xc0000000,
> and
>    (kernel_space ? 0xc0000000 : 0) + (entry & 0x07ffffff);
> is almost the same thing as just 'entry'.

It seems like these remarks are directed more at the existing code than 
the patch....  :-S  TBH, I don't know why it was done that way originally.

> 
>> +static void nios2_generic_nommu_init(MachineState *machine)
>> +{
>> +    Nios2CPU *cpu;
>> +    DeviceState *dev;
>> +    MemoryRegion *address_space_mem = get_system_memory();
>> +    MemoryRegion *phys_tcm = g_new(MemoryRegion, 1);
>> +    MemoryRegion *phys_tcm_alias = g_new(MemoryRegion, 1);
>> +    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
>> +    MemoryRegion *phys_ram_alias = g_new(MemoryRegion, 1);
>> +    ram_addr_t tcm_base = 0x0;
>> +    ram_addr_t tcm_size = 0x1000;    /* 1 kiB, but QEMU limit is 4 kiB */
>> +    ram_addr_t ram_base = 0x10000000;
>> +    ram_addr_t ram_size = 0x08000000;
>> +    qemu_irq *cpu_irq, irq[32];
>> +    int i;
> 
> The description says this is "generic", but it appears to
> be almost identical to the existing 10M50 board model,
> including having exactly the same devices at the same
> apparently arbitrary addresses.
> 
> Could we instead add a machine parameter to the existing
> board so you could say "-machine 10m50-ghrd,mmu=no"
> (and drop the other changes -- it's not clear what they're
> needed for) ?
> 
> If it really ought to be a separate board model, perhaps
> it should be in the same source file and share the common
> code.

I didn't write this code, but the intent was actually to allow 
executables linked for the 3c120 devboards we'd been using for hardware 
testing to run in this emulation; not to emulate a mmu-less 10m50 board. 
  The BSP that we contributed to libgloss locates the reset vector, etc 
appropriately for this emulation.

I can't comment on whether the peripherals copied from the 10m50 
emulation are actually necessary or useful for anything; we certainly 
don't intend to support manipulating them from the program being loaded, 
but maybe other parts of QEMU expect certain devices to be present (I've 
seen that on other targets like ARM).  Andrew, do you have any state on 
this left?

-Sandra

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Qemu-devel] [PATCH v5 1/2] Add generic Nios II board.
  2019-03-08 23:51     ` Sandra Loosemore
@ 2019-03-09 14:27       ` Peter Maydell
  0 siblings, 0 replies; 11+ messages in thread
From: Peter Maydell @ 2019-03-09 14:27 UTC (permalink / raw)
  To: Sandra Loosemore; +Cc: QEMU Developers, Marek Vasut, Andrew Jenner

On Fri, 8 Mar 2019 at 23:51, Sandra Loosemore <sandra@codesourcery.com> wrote:
>
> On 3/7/19 7:57 AM, Peter Maydell wrote:
> >> diff --git a/hw/nios2/boot.c b/hw/nios2/boot.c
> >> index 5f0ab2f..c697047 100644
> >> --- a/hw/nios2/boot.c
> >> +++ b/hw/nios2/boot.c
> >> @@ -140,6 +140,7 @@ void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base,
> >>           uint64_t entry, low, high;
> >>           uint32_t base32;
> >>           int big_endian = 0;
> >> +        int kernel_space = 0;
> >>
> >>   #ifdef TARGET_WORDS_BIGENDIAN
> >>           big_endian = 1;
> >> @@ -155,10 +156,12 @@ void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base,
> >>                                      translate_kernel_address, NULL,
> >>                                      &entry, NULL, NULL,
> >>                                      big_endian, EM_ALTERA_NIOS2, 0, 0);
> >> +            kernel_space = 1;
> >>           }
> >>
> >>           /* Always boot into physical ram. */
> >> -        boot_info.bootstrap_pc = ddr_base + 0xc0000000 + (entry & 0x07ffffff);
> >> +        boot_info.bootstrap_pc = ddr_base + (kernel_space ? 0xc0000000 : 0)
> >> +                                 + (entry & 0x07ffffff);
> >
> > It's not clear to me what's going on here, or why an
> > entry address of 0xc000_0000 is special, but I don't
> > know anything about NiosII -- maybe it's clear if you do?
>
> The processor reference guide documents that the kernel is placed at
> virtual memory address 0xc0000000.
>
> https://www.intel.com/content/www/us/en/programmable/documentation/iga1409256728501.html#iga1409332620358
>
> The problem the patch to boot.c is trying to solve is that we found
> things like unwind info were screwed up when using -kernel to load
> executables with an entry address other than 0xc0000000.

Ah, so this is one of those architectures like MIPS that
has multiple aliases of the same lump of physical RAM with
different properties. So an ELF file could be linked to
load in one of multiple aliases.

> > Why isn't the bootstrap_pc just always the entry address ?
> > Some comments on what is being done here and the use cases
> > being addressed might assist. I wasn't able to work out what
> > the remarks in the commit message meant, I'm afraid.
> >
> > Looking at the code, I don't think that the second call to
> > load_elf() will return a different entry address to the first
> > one (ie translate_kernel_address() is not applied to &entry).
> > That means that kernel_space is only true if entry == 0xc0000000,
> > and
> >    (kernel_space ? 0xc0000000 : 0) + (entry & 0x07ffffff);
> > is almost the same thing as just 'entry'.
>
> It seems like these remarks are directed more at the existing code than
> the patch....  :-S  TBH, I don't know why it was done that way originally.

Yeah, some of this is the fault of the original code, which is
doing weird things and not documenting why. But you're changing
this code, so you're currently the best expert we have at
what the architecture should do. So I'm trying to figure out
by asking you questions what the architecture does and what
the code is intended to do.

Right now my impression from reading the code and this patch is
that the existing code is doing something odd and possibly
wrong but which happens to work for whatever set of executables
it was being tested with, and then this patch is layering on a
workaround that fixes some other set of use cases -- but it would
be better if we could figure out what the real hardware does and
do that, which should then work in all the cases we're trying to
support (or we can say "no, these binaries are built wrongly and
they wouldn't load on the real hardware either"). If the real
hardware is doing something odd that's OK, but then we should
have a nice clear comment describing what the hardware does.

> > The description says this is "generic", but it appears to
> > be almost identical to the existing 10M50 board model,
> > including having exactly the same devices at the same
> > apparently arbitrary addresses.
> >
> > Could we instead add a machine parameter to the existing
> > board so you could say "-machine 10m50-ghrd,mmu=no"
> > (and drop the other changes -- it's not clear what they're
> > needed for) ?
> >
> > If it really ought to be a separate board model, perhaps
> > it should be in the same source file and share the common
> > code.
>
> I didn't write this code, but the intent was actually to allow
> executables linked for the 3c120 devboards we'd been using for hardware
> testing to run in this emulation; not to emulate a mmu-less 10m50 board.

That sounds like the right answer is "provide a model of a 3c120
board", not "provide something that is labelled generic but
is actually a 10m50 with no MMU" ?

thanks
-- PMM

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2019-03-09 14:27 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-13  3:45 [Qemu-devel] [PATCH v5 0/2] Nios II generic board config and semihosting Sandra Loosemore
2019-02-13  3:45 ` [Qemu-devel] [PATCH v5 1/2] Add generic Nios II board Sandra Loosemore
2019-03-07 14:57   ` Peter Maydell
2019-03-08 23:51     ` Sandra Loosemore
2019-03-09 14:27       ` Peter Maydell
2019-02-13  3:46 ` [Qemu-devel] [PATCH v5 2/2] Add Nios II semihosting support Sandra Loosemore
2019-03-07 14:58   ` Peter Maydell
2019-03-08  3:13     ` Sandra Loosemore
2019-03-08 16:04       ` Peter Maydell
2019-03-08 17:01         ` Sandra Loosemore
2019-03-08 18:21           ` Peter Maydell

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.