Skip to content

Commit

Permalink
Merge tag 'pull-loongarch-20231103' of https://gitlab.com/gaosong/qemu
Browse files Browse the repository at this point in the history
…into staging

pull-loongarch-20231103

# -----BEGIN PGP SIGNATURE-----
#
# iLMEAAEKAB0WIQS4/x2g0v3LLaCcbCxAov/yOSY+3wUCZUSQIgAKCRBAov/yOSY+
# 31aIBADj5FzdUxyFB813SouAiEiyMdI4bN98AunomAk3Kt8PF1XPoP8kPzcjxcMI
# kCW4eoHb12MVs9OclkqFY3VyaxtSD3YSG/h8W9YxaDyU+L/q89RS+J4r6CAZ8ylg
# J4uxs3Lv8nwPEvRb4zITAt8JQllLey1100j/uu4fU0Rx7vUcMA==
# =9RMx
# -----END PGP SIGNATURE-----
# gpg: Signature made Fri 03 Nov 2023 14:16:02 HKT
# gpg:                using RSA key B8FF1DA0D2FDCB2DA09C6C2C40A2FFF239263EDF
# gpg: Good signature from "Song Gao <m17746591750@163.com>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: B8FF 1DA0 D2FD CB2D A09C  6C2C 40A2 FFF2 3926 3EDF

* tag 'pull-loongarch-20231103' of https://gitlab.com/gaosong/qemu:
  linux-user/loongarch64: Add LASX sigcontext save/restore
  linux-user/loongarch64: Add LSX sigcontext save/restore
  linux-user/loongarch64: Use abi_{ulong,uint} types
  linux-user/loongarch64: setup_sigframe() set 'end' context size 0
  linux-user/loongarch64: Fix setup_extcontext alloc wrong fpu_context size
  linux-user/loongarch64: Use traps to track LSX/LASX usage
  target/loongarch: Support 4K page size
  target/loongarch: Implement query-cpu-model-expansion
  target/loongarch: Allow user enable/disable LSX/LASX features
  target/loongarch: Add cpu model 'max'

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
  • Loading branch information
stefanhaRH committed Nov 6, 2023
2 parents d762bf9 + f707773 commit 9477a89
Show file tree
Hide file tree
Showing 9 changed files with 318 additions and 52 deletions.
13 changes: 13 additions & 0 deletions linux-user/loongarch64/cpu_loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,19 @@ void cpu_loop(CPULoongArchState *env)
case EXCCODE_BCE:
force_sig_fault(TARGET_SIGSYS, TARGET_SI_KERNEL, env->pc);
break;

/*
* Begin with LSX and LASX disabled, then enable on the first trap.
* In this way we can tell if the unit is in use. This is used to
* choose the layout of any signal frame.
*/
case EXCCODE_SXD:
env->CSR_EUEN |= R_CSR_EUEN_SXE_MASK;
break;
case EXCCODE_ASXD:
env->CSR_EUEN |= R_CSR_EUEN_ASXE_MASK;
break;

case EXCP_ATOMIC:
cpu_exec_step_atomic(cs);
break;
Expand Down
189 changes: 156 additions & 33 deletions linux-user/loongarch64/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@
#define SC_USED_FP (1 << 0)

struct target_sigcontext {
uint64_t sc_pc;
uint64_t sc_regs[32];
uint32_t sc_flags;
uint64_t sc_extcontext[0] QEMU_ALIGNED(16);
abi_ulong sc_pc;
abi_ulong sc_regs[32];
abi_uint sc_flags;
abi_ulong sc_extcontext[0] QEMU_ALIGNED(16);
};

QEMU_BUILD_BUG_ON(sizeof(struct target_sigcontext) != sizeof_sigcontext);
Expand All @@ -33,19 +33,35 @@ QEMU_BUILD_BUG_ON(offsetof(struct target_sigcontext, sc_regs)
#define FPU_CTX_MAGIC 0x46505501
#define FPU_CTX_ALIGN 8
struct target_fpu_context {
uint64_t regs[32];
uint64_t fcc;
uint32_t fcsr;
abi_ulong regs[32];
abi_ulong fcc;
abi_uint fcsr;
} QEMU_ALIGNED(FPU_CTX_ALIGN);

QEMU_BUILD_BUG_ON(offsetof(struct target_fpu_context, regs)
!= offsetof_fpucontext_fr);

#define LSX_CTX_MAGIC 0x53580001
#define LSX_CTX_ALIGN 16
struct target_lsx_context {
abi_ulong regs[2 * 32];
abi_ulong fcc;
abi_uint fcsr;
} QEMU_ALIGNED(LSX_CTX_ALIGN);

#define LASX_CTX_MAGIC 0x41535801
#define LASX_CTX_ALIGN 32
struct target_lasx_context {
abi_ulong regs[4 * 32];
abi_ulong fcc;
abi_uint fcsr;
} QEMU_ALIGNED(LASX_CTX_ALIGN);

#define CONTEXT_INFO_ALIGN 16
struct target_sctx_info {
uint32_t magic;
uint32_t size;
uint64_t padding;
abi_uint magic;
abi_uint size;
abi_ulong padding;
} QEMU_ALIGNED(CONTEXT_INFO_ALIGN);

QEMU_BUILD_BUG_ON(sizeof(struct target_sctx_info) != sizeof_sctx_info);
Expand Down Expand Up @@ -81,9 +97,11 @@ struct ctx_layout {
};

struct extctx_layout {
unsigned int size;
unsigned long size;
unsigned int flags;
struct ctx_layout fpu;
struct ctx_layout lsx;
struct ctx_layout lasx;
struct ctx_layout end;
};

Expand All @@ -105,7 +123,8 @@ static abi_ptr extframe_alloc(struct extctx_layout *extctx,
return sp;
}

static abi_ptr setup_extcontext(struct extctx_layout *extctx, abi_ptr sp)
static abi_ptr setup_extcontext(CPULoongArchState *env,
struct extctx_layout *extctx, abi_ptr sp)
{
memset(extctx, 0, sizeof(struct extctx_layout));

Expand All @@ -114,8 +133,17 @@ static abi_ptr setup_extcontext(struct extctx_layout *extctx, abi_ptr sp)

/* For qemu, there is no lazy fp context switch, so fp always present. */
extctx->flags = SC_USED_FP;
sp = extframe_alloc(extctx, &extctx->fpu,
sizeof(struct target_rt_sigframe), FPU_CTX_ALIGN, sp);

if (FIELD_EX64(env->CSR_EUEN, CSR_EUEN, ASXE)) {
sp = extframe_alloc(extctx, &extctx->lasx,
sizeof(struct target_lasx_context), LASX_CTX_ALIGN, sp);
} else if (FIELD_EX64(env->CSR_EUEN, CSR_EUEN, SXE)) {
sp = extframe_alloc(extctx, &extctx->lsx,
sizeof(struct target_lsx_context), LSX_CTX_ALIGN, sp);
} else {
sp = extframe_alloc(extctx, &extctx->fpu,
sizeof(struct target_fpu_context), FPU_CTX_ALIGN, sp);
}

return sp;
}
Expand All @@ -125,7 +153,6 @@ static void setup_sigframe(CPULoongArchState *env,
struct extctx_layout *extctx)
{
struct target_sctx_info *info;
struct target_fpu_context *fpu_ctx;
int i;

__put_user(extctx->flags, &sc->sc_flags);
Expand All @@ -136,33 +163,71 @@ static void setup_sigframe(CPULoongArchState *env,
}

/*
* Set fpu context
* Set extension context
*/
info = extctx->fpu.haddr;
__put_user(FPU_CTX_MAGIC, &info->magic);
__put_user(extctx->fpu.size, &info->size);

fpu_ctx = (struct target_fpu_context *)(info + 1);
for (i = 0; i < 32; ++i) {
__put_user(env->fpr[i].vreg.D(0), &fpu_ctx->regs[i]);
if (FIELD_EX64(env->CSR_EUEN, CSR_EUEN, ASXE)) {
struct target_lasx_context *lasx_ctx;
info = extctx->lasx.haddr;

__put_user(LASX_CTX_MAGIC, &info->magic);
__put_user(extctx->lasx.size, &info->size);

lasx_ctx = (struct target_lasx_context *)(info + 1);

for (i = 0; i < 32; ++i) {
__put_user(env->fpr[i].vreg.UD(0), &lasx_ctx->regs[4 * i]);
__put_user(env->fpr[i].vreg.UD(1), &lasx_ctx->regs[4 * i + 1]);
__put_user(env->fpr[i].vreg.UD(2), &lasx_ctx->regs[4 * i + 2]);
__put_user(env->fpr[i].vreg.UD(3), &lasx_ctx->regs[4 * i + 3]);
}
__put_user(read_fcc(env), &lasx_ctx->fcc);
__put_user(env->fcsr0, &lasx_ctx->fcsr);
} else if (FIELD_EX64(env->CSR_EUEN, CSR_EUEN, SXE)) {
struct target_lsx_context *lsx_ctx;
info = extctx->lsx.haddr;

__put_user(LSX_CTX_MAGIC, &info->magic);
__put_user(extctx->lsx.size, &info->size);

lsx_ctx = (struct target_lsx_context *)(info + 1);

for (i = 0; i < 32; ++i) {
__put_user(env->fpr[i].vreg.UD(0), &lsx_ctx->regs[2 * i]);
__put_user(env->fpr[i].vreg.UD(1), &lsx_ctx->regs[2 * i + 1]);
}
__put_user(read_fcc(env), &lsx_ctx->fcc);
__put_user(env->fcsr0, &lsx_ctx->fcsr);
} else {
struct target_fpu_context *fpu_ctx;
info = extctx->fpu.haddr;

__put_user(FPU_CTX_MAGIC, &info->magic);
__put_user(extctx->fpu.size, &info->size);

fpu_ctx = (struct target_fpu_context *)(info + 1);

for (i = 0; i < 32; ++i) {
__put_user(env->fpr[i].vreg.UD(0), &fpu_ctx->regs[i]);
}
__put_user(read_fcc(env), &fpu_ctx->fcc);
__put_user(env->fcsr0, &fpu_ctx->fcsr);
}
__put_user(read_fcc(env), &fpu_ctx->fcc);
__put_user(env->fcsr0, &fpu_ctx->fcsr);

/*
* Set end context
*/
info = extctx->end.haddr;
__put_user(0, &info->magic);
__put_user(extctx->end.size, &info->size);
__put_user(0, &info->size);
}

static bool parse_extcontext(struct extctx_layout *extctx, abi_ptr frame)
{
memset(extctx, 0, sizeof(*extctx));

while (1) {
uint32_t magic, size;
abi_uint magic, size;

if (get_user_u32(magic, frame) || get_user_u32(size, frame + 4)) {
return false;
Expand All @@ -184,6 +249,24 @@ static bool parse_extcontext(struct extctx_layout *extctx, abi_ptr frame)
extctx->fpu.size = size;
extctx->size += size;
break;
case LSX_CTX_MAGIC:
if (size < (sizeof(struct target_sctx_info) +
sizeof(struct target_lsx_context))) {
return false;
}
extctx->lsx.gaddr = frame;
extctx->lsx.size = size;
extctx->size += size;
break;
case LASX_CTX_MAGIC:
if (size < (sizeof(struct target_sctx_info) +
sizeof(struct target_lasx_context))) {
return false;
}
extctx->lasx.gaddr = frame;
extctx->lasx.size = size;
extctx->size += size;
break;
default:
return false;
}
Expand All @@ -197,19 +280,45 @@ static void restore_sigframe(CPULoongArchState *env,
struct extctx_layout *extctx)
{
int i;
abi_ulong fcc;

__get_user(env->pc, &sc->sc_pc);
for (i = 1; i < 32; ++i) {
__get_user(env->gpr[i], &sc->sc_regs[i]);
}

if (extctx->fpu.haddr) {
if (extctx->lasx.haddr) {
struct target_lasx_context *lasx_ctx =
extctx->lasx.haddr + sizeof(struct target_sctx_info);

for (i = 0; i < 32; ++i) {
__get_user(env->fpr[i].vreg.UD(0), &lasx_ctx->regs[4 * i]);
__get_user(env->fpr[i].vreg.UD(1), &lasx_ctx->regs[4 * i + 1]);
__get_user(env->fpr[i].vreg.UD(2), &lasx_ctx->regs[4 * i + 2]);
__get_user(env->fpr[i].vreg.UD(3), &lasx_ctx->regs[4 * i + 3]);
}
__get_user(fcc, &lasx_ctx->fcc);
write_fcc(env, fcc);
__get_user(env->fcsr0, &lasx_ctx->fcsr);
restore_fp_status(env);
} else if (extctx->lsx.haddr) {
struct target_lsx_context *lsx_ctx =
extctx->lsx.haddr + sizeof(struct target_sctx_info);

for (i = 0; i < 32; ++i) {
__get_user(env->fpr[i].vreg.UD(0), &lsx_ctx->regs[2 * i]);
__get_user(env->fpr[i].vreg.UD(1), &lsx_ctx->regs[2 * i + 1]);
}
__get_user(fcc, &lsx_ctx->fcc);
write_fcc(env, fcc);
__get_user(env->fcsr0, &lsx_ctx->fcsr);
restore_fp_status(env);
} else if (extctx->fpu.haddr) {
struct target_fpu_context *fpu_ctx =
extctx->fpu.haddr + sizeof(struct target_sctx_info);
uint64_t fcc;

for (i = 0; i < 32; ++i) {
__get_user(env->fpr[i].vreg.D(0), &fpu_ctx->regs[i]);
__get_user(env->fpr[i].vreg.UD(0), &fpu_ctx->regs[i]);
}
__get_user(fcc, &fpu_ctx->fcc);
write_fcc(env, fcc);
Expand All @@ -229,7 +338,7 @@ static abi_ptr get_sigframe(struct target_sigaction *ka,

sp = target_sigsp(get_sp_from_cpustate(env), ka);
sp = ROUND_DOWN(sp, 16);
sp = setup_extcontext(extctx, sp);
sp = setup_extcontext(env, extctx, sp);
sp -= sizeof(struct target_rt_sigframe);

assert(QEMU_IS_ALIGNED(sp, 16));
Expand All @@ -255,8 +364,17 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
force_sigsegv(sig);
return;
}
extctx.fpu.haddr = (void *)frame + (extctx.fpu.gaddr - frame_addr);
extctx.end.haddr = (void *)frame + (extctx.end.gaddr - frame_addr);

if (FIELD_EX64(env->CSR_EUEN, CSR_EUEN, ASXE)) {
extctx.lasx.haddr = (void *)frame + (extctx.lasx.gaddr - frame_addr);
extctx.end.haddr = (void *)frame + (extctx.end.gaddr - frame_addr);
} else if (FIELD_EX64(env->CSR_EUEN, CSR_EUEN, SXE)) {
extctx.lsx.haddr = (void *)frame + (extctx.lsx.gaddr - frame_addr);
extctx.end.haddr = (void *)frame + (extctx.end.gaddr - frame_addr);
} else {
extctx.fpu.haddr = (void *)frame + (extctx.fpu.gaddr - frame_addr);
extctx.end.haddr = (void *)frame + (extctx.end.gaddr - frame_addr);
}

tswap_siginfo(&frame->rs_info, info);

Expand Down Expand Up @@ -299,7 +417,12 @@ long do_rt_sigreturn(CPULoongArchState *env)
if (!frame) {
goto badframe;
}
if (extctx.fpu.gaddr) {

if (extctx.lasx.gaddr) {
extctx.lasx.haddr = (void *)frame + (extctx.lasx.gaddr - frame_addr);
} else if (extctx.lsx.gaddr) {
extctx.lsx.haddr = (void *)frame + (extctx.lsx.gaddr - frame_addr);
} else if (extctx.fpu.gaddr) {
extctx.fpu.haddr = (void *)frame + (extctx.fpu.gaddr - frame_addr);
}

Expand Down
6 changes: 4 additions & 2 deletions qapi/machine-target.json
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,8 @@
'data': { 'model': 'CpuModelInfo' },
'if': { 'any': [ 'TARGET_S390X',
'TARGET_I386',
'TARGET_ARM' ] } }
'TARGET_ARM',
'TARGET_LOONGARCH64' ] } }

##
# @query-cpu-model-expansion:
Expand Down Expand Up @@ -275,7 +276,8 @@
'returns': 'CpuModelExpansionInfo',
'if': { 'any': [ 'TARGET_S390X',
'TARGET_I386',
'TARGET_ARM' ] } }
'TARGET_ARM',
'TARGET_LOONGARCH64' ] } }

##
# @CpuDefinitionInfo:
Expand Down
2 changes: 1 addition & 1 deletion target/loongarch/cpu-param.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@
#define TARGET_PHYS_ADDR_SPACE_BITS 48
#define TARGET_VIRT_ADDR_SPACE_BITS 48

#define TARGET_PAGE_BITS 14
#define TARGET_PAGE_BITS 12

#endif

0 comments on commit 9477a89

Please sign in to comment.