add riscv32 port

master
Ariadne Conill 2021-03-08 23:59:59 -07:00
parent 464f98a01b
commit 1ad20e03e5
8 changed files with 354 additions and 0 deletions

View File

@ -25,6 +25,7 @@ target to do it.
| mips64 | ✓ | | ✓ | |
| ppc | ✓ | ✓ | | |
| ppc64 | ✓ | ✓ | | |
| riscv32 | ✓ | | ✓ | ✓ |
| riscv64 | ✓ | | ✓ | ✓ |
| s390x | ✓ | | ✓ | |
| sh | ✓ | | ✓ | ✓ |

55
arch/riscv32/defs.h Normal file
View File

@ -0,0 +1,55 @@
#ifndef __ARCH_RISCV64_DEFS_H
#define __ARCH_RISCV64_DEFS_H
#define REG_SZ (4)
#define MCONTEXT_GREGS (160)
/* program counter is saved in x0 as well as x1, similar to mips */
#ifndef REG_PC
#define REG_PC (0)
#endif
#ifndef REG_RA
#define REG_RA (1)
#endif
#ifndef REG_SP
#define REG_SP (2)
#endif
#ifndef REG_S0
#define REG_S0 (8)
#endif
#define REG_S1 (9)
#ifndef REG_A0
#define REG_A0 (10)
#endif
#define REG_A1 (11)
#define REG_A2 (12)
#define REG_A3 (13)
#define REG_A4 (14)
#define REG_A5 (15)
#define REG_A6 (16)
#define REG_A7 (17)
#define REG_S2 (18)
#define REG_S3 (19)
#define REG_S4 (20)
#define REG_S5 (21)
#define REG_S6 (22)
#define REG_S7 (23)
#define REG_S8 (24)
#define REG_S9 (25)
#define REG_S10 (26)
#define REG_S11 (27)
#define PC_OFFSET REG_OFFSET(REG_PC)
#define FETCH_LINKPTR(dest) \
asm("mv %0, s1" : "=r" ((dest)))
#include "common-defs.h"
#endif

45
arch/riscv32/getcontext.S Normal file
View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#include "defs.h"
ALIAS(getcontext, libucontext_getcontext)
ALIAS(__getcontext, libucontext_getcontext)
FUNC(libucontext_getcontext)
sw ra, REG_OFFSET(REG_PC)(a0)
sw ra, REG_OFFSET(REG_RA)(a0)
sw sp, REG_OFFSET(REG_SP)(a0)
/* first saved register block */
sw s0, REG_OFFSET(REG_S0)(a0)
sw s1, REG_OFFSET(REG_S1)(a0)
/* return register block */
sw a0, REG_OFFSET(REG_A0)(a0)
sw a1, REG_OFFSET(REG_A1)(a0)
/* second saved register block */
sw s2, REG_OFFSET(REG_S2)(a0)
sw s3, REG_OFFSET(REG_S3)(a0)
sw s4, REG_OFFSET(REG_S4)(a0)
sw s5, REG_OFFSET(REG_S5)(a0)
sw s6, REG_OFFSET(REG_S6)(a0)
sw s7, REG_OFFSET(REG_S7)(a0)
sw s8, REG_OFFSET(REG_S8)(a0)
sw s9, REG_OFFSET(REG_S9)(a0)
sw s10, REG_OFFSET(REG_S10)(a0)
sw s11, REG_OFFSET(REG_S11)(a0)
/* done saving, return */
ret
END(libucontext_getcontext)

View File

@ -0,0 +1,48 @@
#ifndef LIBUCONTEXT_BITS_H
#define LIBUCONTEXT_BITS_H
typedef unsigned long libucontext_greg_t;
typedef unsigned long libucontext__riscv_mc_gp_state[32];
struct libucontext__riscv_mc_f_ext_state {
unsigned int __f[32];
unsigned int __fcsr;
};
struct libucontext__riscv_mc_d_ext_state {
unsigned long long __f[32];
unsigned int __fcsr;
};
struct libucontext__riscv_mc_q_ext_state {
unsigned long long __f[64] __attribute__((aligned(16)));
unsigned int __fcsr;
unsigned int __reserved[3];
};
union libucontext__riscv_mc_fp_state {
struct libucontext__riscv_mc_f_ext_state __f;
struct libucontext__riscv_mc_d_ext_state __d;
struct libucontext__riscv_mc_q_ext_state __q;
};
typedef struct libucontext_mcontext {
libucontext__riscv_mc_gp_state __gregs;
union libucontext__riscv_mc_fp_state __fpregs;
} libucontext_mcontext_t;
typedef struct {
void *ss_sp;
int ss_flags;
size_t ss_size;
} libucontext_stack_t;
typedef struct libucontext_ucontext {
unsigned long uc_flags;
struct libucontext_ucontext *uc_link;
libucontext_stack_t uc_stack;
unsigned char __pad[128];
libucontext_mcontext_t uc_mcontext;
} libucontext_ucontext_t;
#endif

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2018 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include "defs.h"
#include <libucontext/libucontext.h>
extern void libucontext_trampoline(void);
void
libucontext_makecontext(libucontext_ucontext_t *ucp, void (*func)(void), int argc, ...)
{
libucontext_greg_t *sp, *regp;
va_list va;
int i;
/* set up and align the stack. */
sp = (libucontext_greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
sp -= argc < 8 ? 0 : argc - 8;
sp = (libucontext_greg_t *) (((uintptr_t) sp & -16L));
/* set up the ucontext structure */
ucp->uc_mcontext.__gregs[REG_RA] = (libucontext_greg_t) libucontext_trampoline;
ucp->uc_mcontext.__gregs[REG_S0] = 0;
ucp->uc_mcontext.__gregs[REG_S1] = (libucontext_greg_t) ucp->uc_link;
ucp->uc_mcontext.__gregs[REG_SP] = (libucontext_greg_t) sp;
ucp->uc_mcontext.__gregs[REG_PC] = (libucontext_greg_t) func;
va_start(va, argc);
/* first 8 args go in $a0 through $a7. */
regp = &(ucp->uc_mcontext.__gregs[REG_A0]);
for (i = 0; (i < argc && i < 8); i++)
*regp++ = va_arg (va, libucontext_greg_t);
/* remainder overflows into stack */
for (; i < argc; i++)
*sp++ = va_arg (va, libucontext_greg_t);
va_end(va);
}
#ifdef EXPORT_UNPREFIXED
extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
#endif

56
arch/riscv32/setcontext.S Normal file
View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#include "defs.h"
ALIAS(setcontext, libucontext_setcontext)
ALIAS(__setcontext, libucontext_setcontext)
FUNC(libucontext_setcontext)
/* move $a0 to $t0 to avoid clobbering. */
mv t0, a0
lw t1, PC_OFFSET(t0)
lw ra, REG_OFFSET(REG_RA)(t0)
lw sp, REG_OFFSET(REG_SP)(t0)
/* first saved register block */
lw s0, REG_OFFSET(REG_S0)(t0)
lw s1, REG_OFFSET(REG_S1)(t0)
/* return register block */
lw a0, REG_OFFSET(REG_A0)(t0)
lw a1, REG_OFFSET(REG_A1)(t0)
/* argument register block */
lw a2, REG_OFFSET(REG_A2)(t0)
lw a3, REG_OFFSET(REG_A3)(t0)
lw a4, REG_OFFSET(REG_A4)(t0)
lw a5, REG_OFFSET(REG_A5)(t0)
lw a6, REG_OFFSET(REG_A6)(t0)
lw a7, REG_OFFSET(REG_A7)(t0)
/* second saved register block */
lw s2, REG_OFFSET(REG_S2)(t0)
lw s3, REG_OFFSET(REG_S3)(t0)
lw s4, REG_OFFSET(REG_S4)(t0)
lw s5, REG_OFFSET(REG_S5)(t0)
lw s6, REG_OFFSET(REG_S6)(t0)
lw s7, REG_OFFSET(REG_S7)(t0)
lw s8, REG_OFFSET(REG_S8)(t0)
lw s9, REG_OFFSET(REG_S9)(t0)
lw s10, REG_OFFSET(REG_S10)(t0)
lw s11, REG_OFFSET(REG_S11)(t0)
/* done restoring, jump to new pc in S1 */
jr t1
END(libucontext_setcontext)

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#include "defs.h"
ALIAS(swapcontext, libucontext_swapcontext)
ALIAS(__swapcontext, libucontext_swapcontext)
FUNC(libucontext_swapcontext)
/* move $a1 to $t0 to avoid clobbering. */
mv t0, a1
sw ra, REG_OFFSET(REG_PC)(a0)
sw ra, REG_OFFSET(REG_RA)(a0)
sw sp, REG_OFFSET(REG_SP)(a0)
/* first saved register block */
sw s0, REG_OFFSET(REG_S0)(a0)
sw s1, REG_OFFSET(REG_S1)(a0)
/* return register block */
sw a0, REG_OFFSET(REG_A0)(a0)
sw a1, REG_OFFSET(REG_A1)(a0)
/* second saved register block */
sw s2, REG_OFFSET(REG_S2)(a0)
sw s3, REG_OFFSET(REG_S3)(a0)
sw s4, REG_OFFSET(REG_S4)(a0)
sw s5, REG_OFFSET(REG_S5)(a0)
sw s6, REG_OFFSET(REG_S6)(a0)
sw s7, REG_OFFSET(REG_S7)(a0)
sw s8, REG_OFFSET(REG_S8)(a0)
sw s9, REG_OFFSET(REG_S9)(a0)
sw s10, REG_OFFSET(REG_S10)(a0)
sw s11, REG_OFFSET(REG_S11)(a0)
/* restore the other context from $t0. */
lw t1, REG_OFFSET(REG_PC)(t0)
lw ra, REG_OFFSET(REG_RA)(t0)
lw sp, REG_OFFSET(REG_SP)(t0)
/* first saved register block */
lw s0, REG_OFFSET(REG_S0)(t0)
lw s1, REG_OFFSET(REG_S1)(t0)
/* return register block */
lw a0, REG_OFFSET(REG_A0)(t0)
lw a1, REG_OFFSET(REG_A1)(t0)
/* argument register block */
lw a2, REG_OFFSET(REG_A2)(t0)
lw a3, REG_OFFSET(REG_A3)(t0)
lw a4, REG_OFFSET(REG_A4)(t0)
lw a5, REG_OFFSET(REG_A5)(t0)
lw a6, REG_OFFSET(REG_A6)(t0)
lw a7, REG_OFFSET(REG_A7)(t0)
/* second saved register block */
lw s2, REG_OFFSET(REG_S2)(t0)
lw s3, REG_OFFSET(REG_S3)(t0)
lw s4, REG_OFFSET(REG_S4)(t0)
lw s5, REG_OFFSET(REG_S5)(t0)
lw s6, REG_OFFSET(REG_S6)(t0)
lw s7, REG_OFFSET(REG_S7)(t0)
lw s8, REG_OFFSET(REG_S8)(t0)
lw s9, REG_OFFSET(REG_S9)(t0)
lw s10, REG_OFFSET(REG_S10)(t0)
lw s11, REG_OFFSET(REG_S11)(t0)
/* done swapping, jump to new PC in S1 */
jr t1
END(libucontext_swapcontext)

View File

@ -0,0 +1,3 @@
#include "defs.h"
#include <libucontext/libucontext.h>
#include "common-trampoline.c"