[PowerPC64LE] Fix LE VSX/fpr interop

In the PCB struct, we need to match the VSX register file layout
correctly, as the VSRs shadow the FPRs.

In LE, we need to have a dword of padding before the fprs so they end up
on the correct side, as the struct may be manipulated by either the FP
routines or the VSX routines.

Additionally, when saving and restoring fprs, we need to explicitly target
the fpr union member so it gets offset correctly on LE.

Fixes weirdness with FP registers in VSX-using programs (A FPR that was
saved by the FP routines but restored by the VSX routines was becoming 0
due to being loaded to the wrong side of the VSR.)

Original patch by jhibbits.

Reviewed by:	jhibbits
Differential Revision:	https://reviews.freebsd.org/D27431
This commit is contained in:
Brandon Bergren 2020-12-03 01:39:59 +00:00
parent 3921dc1304
commit 3de50be851
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=368290
2 changed files with 12 additions and 2 deletions

View File

@ -37,6 +37,8 @@
#ifndef _MACHINE_PCB_H_
#define _MACHINE_PCB_H_
#include <sys/endian.h>
#include <machine/setjmp.h>
#ifndef _STANDALONE
@ -62,8 +64,16 @@ struct pcb {
#define PCB_CFSCR 0x40 /* Process had FSCR updated */
struct fpu {
union {
#if _BYTE_ORDER == _BIG_ENDIAN
double fpr;
uint32_t vsr[4];
#else
uint32_t vsr[4];
struct {
double padding;
double fpr;
};
#endif
} fpr[32];
double fpscr; /* FPSCR stored as double for easier access */
} pcb_fpu; /* Floating point processor */

View File

@ -79,7 +79,7 @@ save_fpu_int(struct thread *td)
#undef SFP
} else {
#define SFP(n) __asm ("stfd " #n ", 0(%0)" \
:: "b"(&pcb->pcb_fpu.fpr[n]));
:: "b"(&pcb->pcb_fpu.fpr[n].fpr));
SFP(0); SFP(1); SFP(2); SFP(3);
SFP(4); SFP(5); SFP(6); SFP(7);
SFP(8); SFP(9); SFP(10); SFP(11);
@ -164,7 +164,7 @@ enable_fpu(struct thread *td)
#undef LFP
} else {
#define LFP(n) __asm ("lfd " #n ", 0(%0)" \
:: "b"(&pcb->pcb_fpu.fpr[n]));
:: "b"(&pcb->pcb_fpu.fpr[n].fpr));
LFP(0); LFP(1); LFP(2); LFP(3);
LFP(4); LFP(5); LFP(6); LFP(7);
LFP(8); LFP(9); LFP(10); LFP(11);