qemu-e2k/linux-user/e2k/target_cpu.h

97 lines
2.7 KiB
C

/*
* SPDX-License-Identifier: GPL-2.0-only
*/
#ifndef LINUX_USER_E2K_TARGET_CPU_H
#define LINUX_USER_E2K_TARGET_CPU_H
#include "user-mmap.h"
abi_long e2k_copy_from_user_crs(E2KCrs *crs, abi_ulong target_crs_addr);
abi_long e2k_copy_to_user_crs(abi_ulong target_crs_addr, E2KCrs *crs);
static inline void cpu_clone_regs_child(CPUE2KState *env, target_ulong newsp,
unsigned flags)
{
if (newsp) {
// FIXME: what size must be?
env->usd.size = 0x20000;
env->usd.base = env->sbr = newsp & ~0xf;
env->usd.read = 1;
env->usd.write = 1;
}
if (flags & CLONE_VM) {
E2KPsp pcs = { 0 };
E2KPsp ps = { 0 };
E2KCrs crs = { 0 };
uint64_t *ps_old, *ps_new;
size_t frame_size;
target_ulong pcsp = env->pcsp.base + env->pcsp.index;
target_ulong ps_base = env->psp.base + env->psp.index;
int i;
e2k_psp_new(&pcs, E2K_DEFAULT_PCS_SIZE, e2k_mmap(E2K_DEFAULT_PCS_SIZE), 0);
e2k_psp_new(&ps, E2K_DEFAULT_PS_SIZE, e2k_mmap(E2K_DEFAULT_PS_SIZE),
e2k_mmap(E2K_DEFAULT_PS_SIZE / 8));
// TODO: size checks and a way to report errors
// TODO: set a chain info to return to kernel
pcs.index += sizeof(E2KCrs);
if (e2k_copy_from_user_crs(&crs, pcsp)
|| e2k_copy_to_user_crs(pcs.base + pcs.index, &crs))
{
qemu_log("qemu-e2k internal error: failed to copy parent frame\n");
env->ip = 0;
return;
}
frame_size = crs.cr1.wbs * 32;
ps_base -= frame_size;
ps.index += frame_size;
ps_old = lock_user(VERIFY_READ, ps_base, frame_size, 1);
ps_new = lock_user(VERIFY_WRITE, ps.base, frame_size, 0);
for (i = 0; i < frame_size / 8; i++) {
uint64_t tmp;
__get_user(tmp, &ps_old[i]);
__put_user(tmp, &ps_new[i]);
}
unlock_user_struct(ps_new, ps.base, 1);
unlock_user_struct(ps_old, ps_base, 0);
env->ip = E2K_SYSRET_ADDR;
env->pcsp = pcs;
env->psp = ps;
env->wreg = env->regs;
env->wtag = env->tags;
env->wreg[0].lo = 0;
if (env->enable_tags) {
env->wtag[0] = 0;
}
}
}
static inline void cpu_clone_regs_parent(CPUE2KState *env, unsigned flags)
{
}
static inline void cpu_set_tls(CPUE2KState *env, target_ulong newtls)
{
env->greg[E2K_TLS_REG].lo = newtls;
}
static inline target_ulong cpu_get_tls(CPUE2KState *env)
{
return env->greg[E2K_TLS_REG].lo;
}
static inline abi_ulong get_sp_from_cpustate(CPUE2KState *env)
{
return env->usd.base;
}
#endif /* LINUX_USER_E2K_TARGET_CPU_H */