* Get the user state of the FPU into pcb->pcb_user_save without * dropping ownership (if possible). It returns the FPU ownership * status. */
| 866 | * status. |
| 867 | */ |
| 868 | int |
| 869 | fpugetregs(struct thread *td) |
| 870 | { |
| 871 | struct pcb *pcb; |
| 872 | uint64_t *xstate_bv, bit; |
| 873 | char *sa; |
| 874 | int max_ext_n, i, owned; |
| 875 | |
| 876 | pcb = td->td_pcb; |
| 877 | critical_enter(); |
| 878 | if ((pcb->pcb_flags & PCB_USERFPUINITDONE) == 0) { |
| 879 | bcopy(fpu_initialstate, get_pcb_user_save_pcb(pcb), |
| 880 | cpu_max_ext_state_size); |
| 881 | get_pcb_user_save_pcb(pcb)->sv_env.en_cw = |
| 882 | pcb->pcb_initial_fpucw; |
| 883 | fpuuserinited(td); |
| 884 | critical_exit(); |
| 885 | return (_MC_FPOWNED_PCB); |
| 886 | } |
| 887 | if (td == PCPU_GET(fpcurthread) && PCB_USER_FPU(pcb)) { |
| 888 | fpusave(get_pcb_user_save_pcb(pcb)); |
| 889 | owned = _MC_FPOWNED_FPU; |
| 890 | } else { |
| 891 | owned = _MC_FPOWNED_PCB; |
| 892 | } |
| 893 | if (use_xsave) { |
| 894 | /* |
| 895 | * Handle partially saved state. |
| 896 | */ |
| 897 | sa = (char *)get_pcb_user_save_pcb(pcb); |
| 898 | xstate_bv = (uint64_t *)(sa + sizeof(struct savefpu) + |
| 899 | offsetof(struct xstate_hdr, xstate_bv)); |
| 900 | max_ext_n = flsl(xsave_mask); |
| 901 | for (i = 0; i < max_ext_n; i++) { |
| 902 | bit = 1ULL << i; |
| 903 | if ((xsave_mask & bit) == 0 || (*xstate_bv & bit) != 0) |
| 904 | continue; |
| 905 | bcopy((char *)fpu_initialstate + |
| 906 | xsave_area_desc[i].offset, |
| 907 | sa + xsave_area_desc[i].offset, |
| 908 | xsave_area_desc[i].size); |
| 909 | *xstate_bv |= bit; |
| 910 | } |
| 911 | } |
| 912 | critical_exit(); |
| 913 | return (owned); |
| 914 | } |
| 915 | |
| 916 | void |
| 917 | fpuuserinited(struct thread *td) |
no test coverage detected