From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wm1-x335.google.com (mail-wm1-x335.google.com [IPv6:2a00:1450:4864:20::335]) by sourceware.org (Postfix) with ESMTPS id 3CDEF384A00F for ; Tue, 15 Dec 2020 12:00:31 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 3CDEF384A00F Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=embecosm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=craig.blackmore@embecosm.com Received: by mail-wm1-x335.google.com with SMTP id n16so972375wmc.0 for ; Tue, 15 Dec 2020 04:00:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; h=subject:references:from:autocrypt:to:cc:message-id:date:user-agent :mime-version:in-reply-to:content-language; bh=xJ03uzOlH5ihduB51b7uUo5Z8brX03kVZGq1nI/0j9w=; b=Foxz8Ay604hl8VPJfxiFvcNs0BfpLEyp7bElP/njyCgtImVOytngoBlrmkTfd5WIG8 ay5/+f6hX28bUWX+PR7IQnbl8onADEHxzHprJlM8bKFRjT1Xo9r3G04n6GYDRdTNALfJ Gy2hrq1r6whT0uM7uaKoN0HwnwjMKD9qHoxNBLLGb2VpEcQ1s7/Nzl3+R0ldKi1/RAEG TWE9WWfMvLRf8r7etGpdgzkFPlu2NfmDcixMBmkPkpJEJlGQoKCVWgWbhkqaA48QYuuo XIbxgZgtYgLK1z/big4EnV5aEr4DVR6kWvqq+nKXy3NWfuw3aREEJbOEpwvwTuAdCc7L 9MPQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:references:from:autocrypt:to:cc :message-id:date:user-agent:mime-version:in-reply-to :content-language; bh=xJ03uzOlH5ihduB51b7uUo5Z8brX03kVZGq1nI/0j9w=; b=FTMm1H4N3p8RUoW4WADdzs6t+eZXLpMN+c2rqsuM7xtc4SDD4UpJ+a1owx8dC6nXwy dnRYTCFmYsmRyHb4y37+CHUuADhDpHi6zcnwIFQA03Wp0VhTZPyGvqvz3czoNYaSF6U6 IpiWUKty+KRX8Fsko6tjDJI/xwcJcV+zeaaJihw6SuQWEovZENSUxWnU0IPbh0gxU6Ld e729fp+sXFhkRWgLONZ99QmJPcjjpx9jnOsM5oLAxjSAcr2UsUC/fLE39/p8Ni9P+0oL oD8hl/YR43m7Ct/+XXeHVNFrTIKzmeUuvD7FrJFv7ka69QAnAwoMnw7+l0iUA0/8vsrA LnLQ== X-Gm-Message-State: AOAM530PYCuLRJMiWgp9vuM3yBwC2kax83YnsrOdtKLCPW2S/2eltbJ3 U52HW6qlKSz++SnsoiXp10PvNnsMbHBclocu X-Google-Smtp-Source: ABdhPJwEN8hNdyo0Pvu24pfXzzP+k9BA/+6Bmos16U3bYDYOJbI/sliJ0T+U4+mVwpaPNwv+x+X+Xg== X-Received: by 2002:a1c:65d4:: with SMTP id z203mr23418371wmb.65.1608033629398; Tue, 15 Dec 2020 04:00:29 -0800 (PST) Received: from [192.168.0.27] ([80.0.65.139]) by smtp.gmail.com with ESMTPSA id q15sm36556646wrw.75.2020.12.15.04.00.28 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 15 Dec 2020 04:00:28 -0800 (PST) Subject: Re: [PATCH] RISC-V: Add semihosting support References: <694d497b-bc07-a3ba-2643-a7336927e9a7@embecosm.com> From: Craig Blackmore Autocrypt: addr=craig.blackmore@embecosm.com; prefer-encrypt=mutual; keydata= xsBNBFdIF8oBCACwrsvc6YVfzJRT+ZoBfL9jEb8ITwNahDxCGSG6sIWrJ9UFeTwE8fnNhMpz RyFRm0OXruS5k/8YHJHrxKxFY9cgZ3CWNftXEjRqURUWGtN/ESiw0J7nVfhSGQTo3LBzpXZ1 0JHk4ZHKDJKYa+fhybCHOs19BfP3HydHoTlc5QTKMfom0X/xo7WDdwUYeZsjD9u8IzHk7gNw 05Abk1vqni+J7Fghjp4RI8W3IsjpKOfV3f02OyO/MTSraXNyejO4JRl0A8b3q1Lq+G6Z7o5n LVief5JpkRyzWQSawTIBKmRZa9EzAKZXd6IJdY/sZt7pTir5EP7MHq4a+AtKfKuDkrDDABEB AAHNLkNyYWlnIEJsYWNrbW9yZSA8Y3JhaWcuYmxhY2ttb3JlQGVtYmVjb3NtLmNvbT7CwHgE EwECACIFAldIF8oCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEGEeRQLLl5WtydMH /1nYd9jmOBaF8w5gGgjF5eOO5b/cdUegmO///VYj/5R7iF/zbB6KgF0Obo5h2gG9AIfsZG+T ybuTx7oU1DZYEIndw+YP9c9Yi5de5UzEHwbJiV57W0n+MP0Widgw7p6XJmUQ1XbHxdcWp7nY EJa8ASKLuuIhO8JFUXbQ8BcUiWbsA/JxgCzeid8iixGrzPWj6iFzoK2mX4GqP+24pXSDUamM TXmSQd2taYEsyUdJNiEkUC51ncRcMuThjdtfn6Ok+7lHjh3Zz8q0keJz5pnIp4EXdkAgKSjq U42PMrd3v1HoIFINTtr5F23OdkxoQzysu4GMO4pkw5pwz95Uckr08ojOwE0EV0gXygEIAKv/ luYHmCG/qefgzdbnegwMdG5753NJ+zGxFltFX6aaOPZ8go9Omf6zwjybUKv6Qx6AlDanwCl3 ewVQs+h9iW8uaQBRgeDmwAGMG/doBiFqs7X0jBf23exMiJezXlKb2ZlKzMAbzJ87408AzRaV sZdwEpXHVi2mRPoXtMrqL5iQEyG5hdx2ySj5164DIgVOs/ypFiaiFaDPkIcAQTzJrxsbt6pf iI9kT93DO9nRKVV0pPWztV8P5gKM8HY2rS0wQcfrqAU6T89Aa0VFw92J+w5d2spF8MUNPsvR NLm9ooCF3YME9STYHXrNH1U9fJUWpIC+b49UoWSWRD9nwl2h2i8AEQEAAcLAXwQYAQIACQUC V0gXygIbDAAKCRBhHkUCy5eVreLbB/sHPs1xu78uNV8O4UPTX7D5zBBS3nsrbDr+8stmXRap xbvo6kqKzIMAXuO3bYB/NyJ/tFzuFr9Tjd/2g56D2186bp01/kgxJ9CEl/m2T3lG3DlxIoLg pCExzTLTb8zH/7/6mdeJ17cdnrK+2QAKYctReVPAC67cq5KmUyU3bv5e1JzhV4ezz/i/O+Jv el112ZEsa54ya9KZOUHbgAR6hLnRWIa+8yQTtXqYRc3LxLRfS80Wn0Err1YvqFYzJsQMC8ND xAeEuqQ1gfk1b0jmv7tYljNqsHqzGVbuWz6hyzyLv5GjcdSDKpbw/797gRKQSY8Gty5ynfUH O4kKyuZPrE8P To: Kito Cheng Cc: Newlib Message-ID: Date: Tue, 15 Dec 2020 12:00:27 +0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.10.0 MIME-Version: 1.0 In-Reply-To: Content-Language: en-US X-Spam-Status: No, score=-13.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, HTML_MESSAGE, NICE_REPLY_A, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Content-Filtered-By: Mailman/MimeDel 2.1.29 X-BeenThere: newlib@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Newlib mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 15 Dec 2020 12:00:36 -0000 Hi Kito, Thanks for the test and review. On 09/12/2020 08:21, Kito Cheng wrote: > Hi Craig: > > I verified with GCC testsuite on qemu with Keith's semihosting patch, > And that's LGTM, only two minor review comment, see below: > >> +++ b/libgloss/riscv/semihost-sys_exit.c >> @@ -0,0 +1,19 @@ >> +#include >> +#include "semihost_syscall.h" >> + >> +#define ADP_Stopped_ApplicationExit 0x20026 >> + >> +/* Exit a program without cleaning up files. */ >> +void >> +_exit (int exit_status) >> +{ >> +#if __riscv_xlen =3D=3D 32 >> + syscall_errno (SEMIHOST_exit, (long *) ADP_Stopped_ApplicationExit)= ; > Could you use SEMIHOST_exit_extended here, so that we could have > return value on rv32. I can use SEMIHOST_exit_extended, but I will also need to add a check for= the SH_EXT_EXIT_EXTENDED feature. Can I follow up with this in a later patch?= >> +/* Return the fdentry for file or NULL if not found. */ >> + >> +struct fdentry * >> +__get_fdentry (int file) >> +{ >> + if (file<0 || file>RISCV_MAX_OPEN_FILES || fdtable[file].handle =3D= =3D -1) > Should be >=3D RISCV_MAX_OPEN_FILES here? Please see updated patch below which fixes this condition and adds a lice= nse as requested by Jeff Johnston. Best wishes, Craig --- libgloss/riscv/Makefile.in | 66 +++++++++++++++++- libgloss/riscv/machine/syscall.h | 25 +++++++ libgloss/riscv/semihost-sys_close.c | 28 ++++++++ libgloss/riscv/semihost-sys_exit.c | 23 ++++++ libgloss/riscv/semihost-sys_fdtable.c | 85 +++++++++++++++++++++++ libgloss/riscv/semihost-sys_fstat.c | 19 +++++ libgloss/riscv/semihost-sys_ftime.c | 16 +++++ libgloss/riscv/semihost-sys_isatty.c | 21 ++++++ libgloss/riscv/semihost-sys_link.c | 9 +++ libgloss/riscv/semihost-sys_lseek.c | 70 +++++++++++++++++++ libgloss/riscv/semihost-sys_open.c | 62 +++++++++++++++++ libgloss/riscv/semihost-sys_read.c | 32 +++++++++ libgloss/riscv/semihost-sys_sbrk.c | 26 +++++++ libgloss/riscv/semihost-sys_stat.c | 36 ++++++++++ libgloss/riscv/semihost-sys_stat_common.c | 36 ++++++++++ libgloss/riscv/semihost-sys_unlink.c | 15 ++++ libgloss/riscv/semihost-sys_write.c | 32 +++++++++ libgloss/riscv/semihost.specs | 10 +++ libgloss/riscv/semihost_fdtable.h | 21 ++++++ libgloss/riscv/semihost_stat.h | 14 ++++ libgloss/riscv/semihost_syscall.h | 47 +++++++++++++ 21 files changed, 692 insertions(+), 1 deletion(-) create mode 100644 libgloss/riscv/semihost-sys_close.c create mode 100644 libgloss/riscv/semihost-sys_exit.c create mode 100644 libgloss/riscv/semihost-sys_fdtable.c create mode 100644 libgloss/riscv/semihost-sys_fstat.c create mode 100644 libgloss/riscv/semihost-sys_ftime.c create mode 100644 libgloss/riscv/semihost-sys_isatty.c create mode 100644 libgloss/riscv/semihost-sys_link.c create mode 100644 libgloss/riscv/semihost-sys_lseek.c create mode 100644 libgloss/riscv/semihost-sys_open.c create mode 100644 libgloss/riscv/semihost-sys_read.c create mode 100644 libgloss/riscv/semihost-sys_sbrk.c create mode 100644 libgloss/riscv/semihost-sys_stat.c create mode 100644 libgloss/riscv/semihost-sys_stat_common.c create mode 100644 libgloss/riscv/semihost-sys_unlink.c create mode 100644 libgloss/riscv/semihost-sys_write.c create mode 100644 libgloss/riscv/semihost.specs create mode 100644 libgloss/riscv/semihost_fdtable.h create mode 100644 libgloss/riscv/semihost_stat.h create mode 100644 libgloss/riscv/semihost_syscall.h diff --git a/libgloss/riscv/Makefile.in b/libgloss/riscv/Makefile.in index 579dd9554..185b6e6d2 100644 --- a/libgloss/riscv/Makefile.in +++ b/libgloss/riscv/Makefile.in @@ -40,8 +40,38 @@ gloss_srcs =3D \ sys_wait.c \ sys_write.c=20 =20 +# libsemihost reuses some of the libgloss minimal implementations + +semihost_srcs =3D \ + nanosleep.c \ + sys_chdir.c \ + sys_chmod.c \ + sys_chown.c \ + sys_execve.c \ + sys_fork.c \ + sys_getcwd.c \ + sys_getpid.c \ + sys_kill.c \ + sys_utime.c \ + sys_wait.c \ + semihost-sys_close.c \ + semihost-sys_exit.c \ + semihost-sys_fdtable.c \ + semihost-sys_fstat.c \ + semihost-sys_ftime.c \ + semihost-sys_isatty.c \ + semihost-sys_link.c \ + semihost-sys_lseek.c \ + semihost-sys_open.c \ + semihost-sys_read.c \ + semihost-sys_sbrk.c \ + semihost-sys_stat.c \ + semihost-sys_stat_common.c \ + semihost-sys_unlink.c \ + semihost-sys_write.c + gloss_specs =3D \ - nano.specs sim.specs + nano.specs sim.specs semihost.specs =20 # Extra files =20 @@ -134,6 +164,17 @@ sim_objs +=3D $(sim_c_objs) deps +=3D $(sim_c_deps) junk +=3D $(sim_c_deps) $(sim_c_objs) =20 +semihost_c_srcs =3D $(filter %.c, $(semihost_srcs)) +semihost_c_objs =3D $(patsubst %.c, semihost-%.o, $(notdir $(semihost_c_= srcs))) +semihost_c_deps =3D $(patsubst %.c, semihost-%.d, $(notdir $(semihost_c_= srcs))) + +$(semihost_c_objs): semihost-%.o : %.c + $(COMPILE) -c -o $@ $< + +semihost_objs +=3D $(semihost_c_objs) +deps +=3D $(semihost_c_deps) +junk +=3D $(semihost_c_deps) $(semihost_c_objs) + #-----------------------------------------------------------------------= -- # Build Object Files from Assembly Source #-----------------------------------------------------------------------= -- @@ -159,6 +200,16 @@ sim_objs +=3D $(sim_asm_objs) deps +=3D $(sim_asm_deps) junk +=3D $(sim_asm_deps) $(sim_asm_objs) =20 +semihost_asm_objs =3D $(patsubst %.S, semihost-%.o, $(notdir $(gloss_asm= _srcs))) +semihost_asm_deps =3D $(patsubst %.S, semihost-%.d, $(notdir $(gloss_asm= _srcs))) + +$(semihost_asm_objs) : semihost-%.o : %.S + $(COMPILE) -c -DUSING_SEMIHOST_SPECS -o $@ $< + +semihost_objs +=3D $(semihost_asm_objs) +deps +=3D $(semihost_asm_deps) +junk +=3D $(semihost_asm_deps) $(semihost_asm_objs) + #-----------------------------------------------------------------------= -- # Build libgloss.a #-----------------------------------------------------------------------= -- @@ -187,6 +238,19 @@ junk +=3D $(sim_lib) =20 install_libs +=3D $(sim_lib) =20 +#-----------------------------------------------------------------------= -- +# Build libsemihost.a +#-----------------------------------------------------------------------= -- + +semihost_lib =3D libsemihost.a +$(semihost_lib) : $(semihost_objs) + $(AR) rcv $@ $^ + $(RANLIB) $@ + +junk +=3D $(semihost_lib) + +install_libs +=3D $(semihost_lib) + #-----------------------------------------------------------------------= -- # Build crt0.o #-----------------------------------------------------------------------= -- diff --git a/libgloss/riscv/machine/syscall.h b/libgloss/riscv/machine/sy= scall.h index 5cd15b848..88b9fdfda 100644 --- a/libgloss/riscv/machine/syscall.h +++ b/libgloss/riscv/machine/syscall.h @@ -54,4 +54,29 @@ #define SYS_time 1062 #define SYS_getmainvars 2011 =20 +/* Semihosting operations. */ +#define SEMIHOST_clock 0x10 +#define SEMIHOST_close 0x02 +#define SEMIHOST_elapsed 0x30 +#define SEMIHOST_errno 0x13 +#define SEMIHOST_exit 0x18 +#define SEMIHOST_exit_extended 0x20 +#define SEMIHOST_flen 0x0C +#define SEMIHOST_get_cmdline 0x15 +#define SEMIHOST_heapinfo 0x16 +#define SEMIHOST_iserror 0x08 +#define SEMIHOST_istty 0x09 +#define SEMIHOST_open 0x01 +#define SEMIHOST_read 0x06 +#define SEMIHOST_readc 0x07 +#define SEMIHOST_remove 0x0E +#define SEMIHOST_rename 0x0F +#define SEMIHOST_seek 0x0A +#define SEMIHOST_system 0x12 +#define SEMIHOST_tickfreq 0x31 +#define SEMIHOST_time 0x11 +#define SEMIHOST_tmpnam 0x0D +#define SEMIHOST_write 0x05 +#define SEMIHOST_writec 0x03 +#define SEMIHOST_write0 0x04 #endif diff --git a/libgloss/riscv/semihost-sys_close.c b/libgloss/riscv/semihos= t-sys_close.c new file mode 100644 index 000000000..47402340c --- /dev/null +++ b/libgloss/riscv/semihost-sys_close.c @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include "semihost_syscall.h" +#include "semihost_fdtable.h" + +/* Close a file. */ +int +_close (int file) +{ + long res; + struct fdentry *fd =3D__get_fdentry (file); + long data_block[1]; + + if (fd =3D=3D NULL) + return -1; + + data_block[0] =3D fd->handle; + res =3D syscall_errno (SEMIHOST_close, data_block); + + if (res !=3D 0) + return res; + + __remove_fdentry (file); + return 0; +} diff --git a/libgloss/riscv/semihost-sys_exit.c b/libgloss/riscv/semihost= -sys_exit.c new file mode 100644 index 000000000..626fb6aeb --- /dev/null +++ b/libgloss/riscv/semihost-sys_exit.c @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include "semihost_syscall.h" + +#define ADP_Stopped_ApplicationExit 0x20026 + +/* Exit a program without cleaning up files. */ +void +_exit (int exit_status) +{ +#if __riscv_xlen =3D=3D 32 + syscall_errno (SEMIHOST_exit, (long *) ADP_Stopped_ApplicationExit); +#else + /* The semihosting exit operation only allows 64-bit targets to report= the + exit code. */ + long data_block[] =3D {ADP_Stopped_ApplicationExit, exit_status}; + syscall_errno (SEMIHOST_exit, data_block); +#endif + while (1); +} diff --git a/libgloss/riscv/semihost-sys_fdtable.c b/libgloss/riscv/semih= ost-sys_fdtable.c new file mode 100644 index 000000000..152c92d15 --- /dev/null +++ b/libgloss/riscv/semihost-sys_fdtable.c @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include "semihost_fdtable.h" +#include +#include +#include + +#ifndef RISCV_MAX_OPEN_FILES +#define RISCV_MAX_OPEN_FILES 16 +#endif + +extern int errno; +extern int _open (const char *, int, ...); + +/* fdtable keeps track of the position of each file and is used to map s= tdin, + stdout and stderr to STDIN_FILENO, STDOUT_FILENO and STDERR_FILENO. = */ + +static struct fdentry fdtable[RISCV_MAX_OPEN_FILES]; + +/* Initialize fdtable. A handle of -1 denotes an empty entry. */ + +void __attribute__ ((constructor)) +init_semihosting () +{ + int handle; + + for (int i=3D0; i=3DRISCV_MAX_OPEN_FILES || fdtable[file].handle =3D= =3D -1) + { + errno =3D EBADF; + return NULL; + } + return &fdtable[file]; +} + +/* Remove entry from fdtable. */ + +void +__remove_fdentry (int file) +{ + fdtable[file].handle =3D -1; +} diff --git a/libgloss/riscv/semihost-sys_fstat.c b/libgloss/riscv/semihos= t-sys_fstat.c new file mode 100644 index 000000000..f57f0c07f --- /dev/null +++ b/libgloss/riscv/semihost-sys_fstat.c @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include +#include "semihost_stat.h" + +/* Status of an open file. The sys/stat.h header file required is + distributed in the include subdirectory for this C library. */ + +int +_fstat (int file, struct stat *st) +{ + /* Initialize st as not all fields will be set. */ + memset (st, 0, sizeof (*st)); + + return __stat_common (file, st); +} diff --git a/libgloss/riscv/semihost-sys_ftime.c b/libgloss/riscv/semihos= t-sys_ftime.c new file mode 100644 index 000000000..aeafc6ca2 --- /dev/null +++ b/libgloss/riscv/semihost-sys_ftime.c @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include +#include "semihost_syscall.h" + +/* Get the current time. */ +int +_ftime (struct timeb *tp) +{ + tp->time =3D syscall_errno (SEMIHOST_time, 0); + tp->millitm =3D 0; + return 0; +} diff --git a/libgloss/riscv/semihost-sys_isatty.c b/libgloss/riscv/semiho= st-sys_isatty.c new file mode 100644 index 000000000..02d8e39cb --- /dev/null +++ b/libgloss/riscv/semihost-sys_isatty.c @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include +#include "semihost_syscall.h" +#include "semihost_fdtable.h" + +int +_isatty (int file) +{ + struct fdentry *fd =3D__get_fdentry (file); + long data_block[1]; + + if (fd =3D=3D NULL) + return -1; + + data_block[0] =3D fd->handle; + return syscall_errno (SEMIHOST_istty, data_block); +} diff --git a/libgloss/riscv/semihost-sys_link.c b/libgloss/riscv/semihost= -sys_link.c new file mode 100644 index 000000000..717c5c81c --- /dev/null +++ b/libgloss/riscv/semihost-sys_link.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +/* Establish a new name for an existing file. */ +int _link (const char *old_name, const char *new_name) +{ + return -1; +} diff --git a/libgloss/riscv/semihost-sys_lseek.c b/libgloss/riscv/semihos= t-sys_lseek.c new file mode 100644 index 000000000..68fccf2ff --- /dev/null +++ b/libgloss/riscv/semihost-sys_lseek.c @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include +#include +#include +#include "semihost_syscall.h" +#include "semihost_fdtable.h" + +extern int errno; + +/* Set position in a file. */ +off_t +_lseek (int file, off_t offset, int dir) +{ + long data_block[2]; + long flen; + long res; + struct fdentry *fd; + off_t abs_pos; + + fd =3D__get_fdentry (file); + if (fd =3D=3D NULL) + { + errno =3D EBADF; + return -1; + } + + if (dir =3D=3D SEEK_CUR && offset =3D=3D 0) + return fd->pos; + + data_block[0] =3D fd->handle; + + switch (dir) + { + case SEEK_SET: + abs_pos =3D offset; + break; + case SEEK_CUR: + abs_pos =3D fd->pos + offset; + break; + case SEEK_END: + data_block[1] =3D 0; + flen =3D syscall_errno (SEMIHOST_flen, data_block); + if (flen =3D=3D -1) + return -1; + abs_pos =3D flen + offset; + break; + default: + errno =3D EINVAL; + return -1; + } + + if (abs_pos < 0) + { + errno =3D EINVAL; + return -1; + } + + data_block[1] =3D abs_pos; + res =3D syscall_errno (SEMIHOST_seek, data_block); + if (res =3D=3D 0) + { + fd->pos =3D abs_pos; + return abs_pos; + } + return res; +} diff --git a/libgloss/riscv/semihost-sys_open.c b/libgloss/riscv/semihost= -sys_open.c new file mode 100644 index 000000000..22f1d8206 --- /dev/null +++ b/libgloss/riscv/semihost-sys_open.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include "semihost_syscall.h" +#include "semihost_fdtable.h" +#include +#include +#include + +extern int errno; + +#define SEMIHOST_MODE_R 0 +#define SEMIHOST_MODE_RPLUS 2 +#define SEMIHOST_MODE_W 4 +#define SEMIHOST_MODE_WPLUS 6 +#define SEMIHOST_MODE_A 8 +#define SEMIHOST_MODE_APLUS 10 + +/* Open a file. */ +int +_open (const char *name, int flags, ...) +{ + int fh; + int mode; + long data_block[3]; + + /* Work out mode from flags. */ + if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) =3D=3D O_RDONLY) + mode =3D SEMIHOST_MODE_R; + else if ((flags & (O_WRONLY | O_CREAT | O_TRUNC)) + =3D=3D (O_WRONLY | O_CREAT | O_TRUNC)) + mode =3D SEMIHOST_MODE_W; + else if ((flags & (O_WRONLY | O_CREAT | O_APPEND)) + =3D=3D (O_WRONLY | O_CREAT | O_APPEND)) + mode =3D SEMIHOST_MODE_A; + else if ((flags & (O_RDWR | O_CREAT | O_TRUNC)) + =3D=3D (O_RDWR | O_CREAT | O_TRUNC)) + mode =3D SEMIHOST_MODE_WPLUS; + else if ((flags & (O_RDWR | O_CREAT | O_APPEND)) + =3D=3D (O_RDWR | O_CREAT | O_APPEND)) + mode =3D SEMIHOST_MODE_APLUS; + else if (flags & O_RDWR) + mode =3D SEMIHOST_MODE_RPLUS; + else + { + errno =3D EINVAL; + return -1; + } + + data_block[0] =3D (long) name; + data_block[1] =3D mode; + data_block[2] =3D strlen (name); + fh =3D syscall_errno (SEMIHOST_open, data_block); + /* Failed to open file. */ + if (fh =3D=3D -1) + return -1; + + /* Register the file in the fdtable. */ + return __add_fdentry (fh); +} diff --git a/libgloss/riscv/semihost-sys_read.c b/libgloss/riscv/semihost= -sys_read.c new file mode 100644 index 000000000..3164eed56 --- /dev/null +++ b/libgloss/riscv/semihost-sys_read.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include +#include +#include "semihost_syscall.h" +#include "semihost_fdtable.h" + +/* Read from a file. */ +ssize_t _read (int file, void *ptr, size_t len) +{ + struct fdentry *fd =3D__get_fdentry (file); + long data_block[3]; + long res; + + if (fd =3D=3D NULL) + return -1; + + data_block[0] =3D fd->handle; + data_block[1] =3D (long) ptr; + data_block[2] =3D len; + res =3D syscall_errno (SEMIHOST_read, data_block); + if (res >=3D 0) + { + ssize_t bytes_read =3D len - res; + fd->pos +=3D bytes_read; + return bytes_read; + } + return -1; +} diff --git a/libgloss/riscv/semihost-sys_sbrk.c b/libgloss/riscv/semihost= -sys_sbrk.c new file mode 100644 index 000000000..cbd035832 --- /dev/null +++ b/libgloss/riscv/semihost-sys_sbrk.c @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +/* Semihosting requires that sbrk be implemented without a syscall. */ +extern char _end[]; /* _end is set in the linker command f= ile. */ +char *heap_ptr; + +/* + * sbrk -- changes heap size size. Get nbytes more + * RAM. We just increment a pointer in what's + * left of memory on the board. + */ +char * +_sbrk (nbytes) + int nbytes; +{ + char *base; + + if (!heap_ptr) + heap_ptr =3D (char *)&_end; + base =3D heap_ptr; + heap_ptr +=3D nbytes; + + return base; +} diff --git a/libgloss/riscv/semihost-sys_stat.c b/libgloss/riscv/semihost= -sys_stat.c new file mode 100644 index 000000000..4015801b9 --- /dev/null +++ b/libgloss/riscv/semihost-sys_stat.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include +#include +#include "semihost_stat.h" + +/* Status of a file (by name). */ + +int +_stat (const char *name, struct stat *st) +{ + int file; + int res; + + /* Initialize st as not all fields will be set. */ + memset (st, 0, sizeof (*st)); + + /* Try to open file. */ + file =3D _open (name, O_RDONLY); + if (file =3D=3D -1) + /* _open should have already set errno. */ + return -1; + + /* File opened successfully, infer read permission for owner and assum= e it is + a regular file. */ + st->st_mode |=3D S_IREAD | S_IFREG; + + /* Fill in more info. */ + res =3D __stat_common (file, st); + + _close (file); + return res; +} diff --git a/libgloss/riscv/semihost-sys_stat_common.c b/libgloss/riscv/s= emihost-sys_stat_common.c new file mode 100644 index 000000000..b38eb0863 --- /dev/null +++ b/libgloss/riscv/semihost-sys_stat_common.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include "semihost_syscall.h" +#include +#include "semihost_fdtable.h" + +/* Used by _fstat and _stat to fill in some common details. */ + +int +__stat_common (int file, struct stat *st) +{ + int flen; + struct fdentry *fd =3D__get_fdentry (file); + long data_block[1]; + + if (fd =3D=3D NULL) + return -1; + + data_block[0] =3D fd->handle; + + /* Assume character device and default block size of 4096. */ + st->st_mode |=3D S_IFCHR; + st->st_blksize =3D 4096; + + /* Attempt to get length of file. */ + flen =3D syscall_errno (SEMIHOST_flen, data_block); + if (flen =3D=3D -1) + return -1; + + st->st_size =3D flen; + + return 0; +} diff --git a/libgloss/riscv/semihost-sys_unlink.c b/libgloss/riscv/semiho= st-sys_unlink.c new file mode 100644 index 000000000..1d2a6a0f9 --- /dev/null +++ b/libgloss/riscv/semihost-sys_unlink.c @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include "semihost_syscall.h" +#include + +/* Remove a file's directory entry. */ +int +_unlink (const char *name) +{ + long data_block[] =3D {(long) name, strlen (name)}; + return syscall_errno (SEMIHOST_remove, data_block); +} diff --git a/libgloss/riscv/semihost-sys_write.c b/libgloss/riscv/semihos= t-sys_write.c new file mode 100644 index 000000000..9aee6d30b --- /dev/null +++ b/libgloss/riscv/semihost-sys_write.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include +#include "semihost_syscall.h" +#include "semihost_fdtable.h" + +/* Write to a file. */ +ssize_t +_write (int file, const void *ptr, size_t len) +{ + struct fdentry *fd =3D__get_fdentry (file); + long data_block[3]; + long res; + + if (fd =3D=3D NULL) + return -1; + + data_block[0] =3D fd->handle; + data_block[1] =3D (long) ptr; + data_block[2] =3D len; + res =3D syscall_errno (SEMIHOST_write, data_block); + if (res >=3D 0) + { + ssize_t bytes_written =3D len - res; + fd->pos +=3D bytes_written; + return bytes_written; + } + return -1; +} diff --git a/libgloss/riscv/semihost.specs b/libgloss/riscv/semihost.spec= s new file mode 100644 index 000000000..1c86c67e4 --- /dev/null +++ b/libgloss/riscv/semihost.specs @@ -0,0 +1,10 @@ +# Spec file for semihosting syscalls. + +%rename lib semihost_lib +%rename link semihost_link + +*lib: +--start-group -lc -lsemihost --end-group + +*link: +%(semihost_link) %:replace-outfile(-lgloss -lsemihost) diff --git a/libgloss/riscv/semihost_fdtable.h b/libgloss/riscv/semihost_= fdtable.h new file mode 100644 index 000000000..f596a409a --- /dev/null +++ b/libgloss/riscv/semihost_fdtable.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include + +#ifndef RISCV_SEMIHOST_FDTABLE_H +#define RISCV_SEMIHOST_FDTABLE_H + +extern void __attribute__ ((constructor)) init_semihosting (); +extern int __add_fdentry (int); +extern struct fdentry * __get_fdentry (int); +extern void __remove_fdentry (int); + +struct fdentry +{ + int handle; + off_t pos; +}; + +#endif diff --git a/libgloss/riscv/semihost_stat.h b/libgloss/riscv/semihost_sta= t.h new file mode 100644 index 000000000..c040fe8e7 --- /dev/null +++ b/libgloss/riscv/semihost_stat.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include + +#ifndef RISCV_SEMIHOST_STAT_H +#define RISCV_SEMIHOST_STAT_H + +extern int __stat_common (int, struct stat *); +extern int _open (const char *, int, ...); +extern int _close (int); + +#endif diff --git a/libgloss/riscv/semihost_syscall.h b/libgloss/riscv/semihost_= syscall.h new file mode 100644 index 000000000..50e731b40 --- /dev/null +++ b/libgloss/riscv/semihost_syscall.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#ifndef _INTERNAL_SYSCALL_H +#define _INTERNAL_SYSCALL_H + +extern int errno; + +static inline long +__semihost_syscall (long id, long *data_block) +{ + register long a0 asm ("a0") =3D id; + register long a1 asm ("a1") =3D (long) data_block; + + /* RISC-V semihosting trap sequence. Must be uncompressed and must no= t + cross page boundary. */ + asm volatile ( + ".balign 16 \n" + ".option push \n" + ".option norvc \n" + "slli zero, zero, 0x1f \n" + "ebreak \n" + "srai zero, zero, 0x7 \n" + ".option pop \n" + : "+r"(a0) : "r"(a1) : "memory"); + + return a0; +} + +static inline long +__syscall_error () +{ + errno =3D __semihost_syscall (SEMIHOST_errno, 0); + return -1; +} + +static inline long +syscall_errno (long id, long *data_block) +{ + long res =3D __semihost_syscall (id, data_block); + if (res < 0) + return __syscall_error (); + return res; +} + +#endif --=20 2.17.1