fork: fpregs: return error code.
Change-Id: I6ff150a39cd8952adad9b21d0c9f8514126ef957
This commit is contained in:
committed by
Masamichi Takagi
parent
de0e07f29e
commit
58f4593478
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user