fork: fpregs: return error code.

Change-Id: I6ff150a39cd8952adad9b21d0c9f8514126ef957
This commit is contained in:
TOIDA,Suguru
2019-08-20 12:15:45 +09:00
committed by Masamichi Takagi
parent de0e07f29e
commit 58f4593478
5 changed files with 56 additions and 30 deletions

View File

@@ -1,4 +1,4 @@
/* cpu.c COPYRIGHT FUJITSU LIMITED 2015-2018 */ /* cpu.c COPYRIGHT FUJITSU LIMITED 2015-2019 */
#include <ihk/cpu.h> #include <ihk/cpu.h>
#include <ihk/mm.h> #include <ihk/mm.h>
#include <types.h> #include <types.h>
@@ -1240,7 +1240,6 @@ err:
} }
static int check_and_allocate_fp_regs(struct thread *thread); static int check_and_allocate_fp_regs(struct thread *thread);
void save_fp_regs(struct thread *thread);
void arch_clone_thread(struct thread *othread, unsigned long pc, void arch_clone_thread(struct thread *othread, unsigned long pc,
unsigned long sp, struct thread *nthread) unsigned long sp, struct thread *nthread)
@@ -1481,8 +1480,7 @@ check_and_allocate_fp_regs(struct thread *thread)
if (!thread->fp_regs) { if (!thread->fp_regs) {
kprintf("error: allocating fp_regs pages\n"); kprintf("error: allocating fp_regs pages\n");
result = 1; result = -ENOMEM;
panic("panic: error allocating fp_regs pages");
goto out; goto out;
} }
@@ -1491,37 +1489,51 @@ check_and_allocate_fp_regs(struct thread *thread)
#ifdef CONFIG_ARM64_SVE #ifdef CONFIG_ARM64_SVE
if (likely(elf_hwcap & HWCAP_SVE)) { if (likely(elf_hwcap & HWCAP_SVE)) {
sve_alloc(thread); result = sve_alloc(thread);
} }
#endif /* CONFIG_ARM64_SVE */ #endif /* CONFIG_ARM64_SVE */
out: out:
if (result) {
release_fp_regs(thread);
}
return result; return result;
} }
/*@ /*@
@ requires \valid(thread); @ requires \valid(thread);
@*/ @*/
void int
save_fp_regs(struct thread *thread) save_fp_regs(struct thread *thread)
{ {
int ret = 0;
if (thread == &cpu_local_var(idle)) { if (thread == &cpu_local_var(idle)) {
return; goto out;
} }
if (likely(elf_hwcap & (HWCAP_FP | HWCAP_ASIMD))) { if (likely(elf_hwcap & (HWCAP_FP | HWCAP_ASIMD))) {
if (check_and_allocate_fp_regs(thread) != 0) { ret = check_and_allocate_fp_regs(thread);
// alloc error. if (ret) {
return; goto out;
} }
thread_fpsimd_save(thread); thread_fpsimd_save(thread);
} }
out:
return ret;
} }
void copy_fp_regs(struct thread *from, struct thread *to) int copy_fp_regs(struct thread *from, struct thread *to)
{ {
if ((from->fp_regs != NULL) && (check_and_allocate_fp_regs(to) == 0)) { int ret = 0;
memcpy(to->fp_regs, from->fp_regs, sizeof(fp_regs_struct));
if (from->fp_regs != NULL) {
ret = check_and_allocate_fp_regs(to);
if (!ret) {
memcpy(to->fp_regs,
from->fp_regs,
sizeof(fp_regs_struct));
}
} }
return ret;
} }
void clear_fp_regs(void) void clear_fp_regs(void)

View File

@@ -119,17 +119,19 @@ void sve_free(struct thread *thread)
} }
} }
void sve_alloc(struct thread *thread) int sve_alloc(struct thread *thread)
{ {
if (thread->ctx.thread->sve_state) { if (thread->ctx.thread->sve_state) {
return; return 0;
} }
thread->ctx.thread->sve_state = thread->ctx.thread->sve_state =
kmalloc(sve_state_size(thread), IHK_MC_AP_NOWAIT); kmalloc(sve_state_size(thread), IHK_MC_AP_NOWAIT);
BUG_ON(!thread->ctx.thread->sve_state); if (thread->ctx.thread->sve_state == NULL) {
return -ENOMEM;
}
memset(thread->ctx.thread->sve_state, 0, sve_state_size(thread)); memset(thread->ctx.thread->sve_state, 0, sve_state_size(thread));
return 0;
} }
static int get_nr_threads(struct process *proc) static int get_nr_threads(struct process *proc)

View File

@@ -42,7 +42,7 @@ extern void thread_sve_to_fpsimd(struct thread *thread, fp_regs_struct *fp_regs)
extern size_t sve_state_size(struct thread const *thread); extern size_t sve_state_size(struct thread const *thread);
extern void sve_free(struct thread *thread); extern void sve_free(struct thread *thread);
extern void sve_alloc(struct thread *thread); extern int sve_alloc(struct thread *thread);
extern void sve_save_state(void *state, unsigned int *pfpsr); extern void sve_save_state(void *state, unsigned int *pfpsr);
extern void sve_load_state(void const *state, unsigned int const *pfpsr, unsigned long vq_minus_1); extern void sve_load_state(void const *state, unsigned int const *pfpsr, unsigned long vq_minus_1);
extern unsigned int sve_get_vl(void); extern unsigned int sve_get_vl(void);

View File

@@ -1,4 +1,4 @@
/* cpu.c COPYRIGHT FUJITSU LIMITED 2018 */ /* cpu.c COPYRIGHT FUJITSU LIMITED 2018-2019 */
/** /**
* \file cpu.c * \file cpu.c
* License details are found in the file LICENSE. * License details are found in the file LICENSE.
@@ -1709,7 +1709,7 @@ check_and_allocate_fp_regs(struct thread *thread)
if (!thread->fp_regs) { if (!thread->fp_regs) {
kprintf("error: allocating fp_regs pages\n"); kprintf("error: allocating fp_regs pages\n");
result = 1; result = -ENOMEM;
goto out; goto out;
} }
@@ -1722,12 +1722,14 @@ out:
/*@ /*@
@ requires \valid(thread); @ requires \valid(thread);
@*/ @*/
void int
save_fp_regs(struct thread *thread) save_fp_regs(struct thread *thread)
{ {
if (check_and_allocate_fp_regs(thread) != 0) { int ret = 0;
// alloc error
return; ret = check_and_allocate_fp_regs(thread);
if (ret) {
goto out;
} }
if (xsave_available) { if (xsave_available) {
@@ -1742,13 +1744,23 @@ save_fp_regs(struct thread *thread)
dkprintf("fp_regs for TID %d saved\n", thread->tid); dkprintf("fp_regs for TID %d saved\n", thread->tid);
} }
out:
return ret;
} }
void copy_fp_regs(struct thread *from, struct thread *to) int copy_fp_regs(struct thread *from, struct thread *to)
{ {
if ((from->fp_regs != NULL) && (check_and_allocate_fp_regs(to) == 0)) { int ret = 0;
memcpy(to->fp_regs, from->fp_regs, sizeof(fp_regs_struct));
if (from->fp_regs != NULL) {
ret = check_and_allocate_fp_regs(to);
if (!ret) {
memcpy(to->fp_regs,
from->fp_regs,
sizeof(fp_regs_struct));
}
} }
return ret;
} }
/*@ /*@

View File

@@ -9,7 +9,7 @@
/* /*
* HISTORY * HISTORY
*/ */
/* process.h COPYRIGHT FUJITSU LIMITED 2015-2018 */ /* process.h COPYRIGHT FUJITSU LIMITED 2015-2019 */
#ifndef HEADER_PROCESS_H #ifndef HEADER_PROCESS_H
#define HEADER_PROCESS_H #define HEADER_PROCESS_H
@@ -914,8 +914,8 @@ extern void check_sig_pending(void);
void clear_single_step(struct thread *thread); void clear_single_step(struct thread *thread);
void release_fp_regs(struct thread *proc); void release_fp_regs(struct thread *proc);
void save_fp_regs(struct thread *proc); int save_fp_regs(struct thread *proc);
void copy_fp_regs(struct thread *from, struct thread *to); int copy_fp_regs(struct thread *from, struct thread *to);
void restore_fp_regs(struct thread *proc); void restore_fp_regs(struct thread *proc);
void clear_fp_regs(void); void clear_fp_regs(void);