1 /* $NetBSD: sys_machdep.c,v 1.22 2021/02/28 21:34:34 tnn Exp $ */
2 
3 /*-
4  * Copyright (c) 2000 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Jason R. Thorpe.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
34  * All rights reserved.
35  *
36  * Author: Chris G. Demetriou
37  *
38  * Permission to use, copy, modify and distribute this software and
39  * its documentation is hereby granted, provided that both the copyright
40  * notice and this permission notice appear in all copies of the
41  * software, derivative works or modified versions, and any portions
42  * thereof, and that both notices appear in supporting documentation.
43  *
44  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
45  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
46  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
47  *
48  * Carnegie Mellon requests users of this software to return to
49  *
50  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
51  *  School of Computer Science
52  *  Carnegie Mellon University
53  *  Pittsburgh PA 15213-3890
54  *
55  * any improvements or extensions that they make and grant Carnegie the
56  * rights to redistribute these changes.
57  */
58 
59 #include <sys/cdefs.h>                            /* RCS ID & Copyright macro defns */
60 
61 __KERNEL_RCSID(0, "$NetBSD: sys_machdep.c,v 1.22 2021/02/28 21:34:34 tnn Exp $");
62 
63 #include <sys/param.h>
64 #include <sys/systm.h>
65 #include <sys/device.h>
66 #include <sys/proc.h>
67 #include <sys/cpu.h>
68 
69 #include <sys/mount.h>
70 #include <sys/syscallargs.h>
71 
72 #include <machine/fpu.h>
73 #include <machine/sysarch.h>
74 
75 #include <dev/pci/pcivar.h>
76 
77 u_int     alpha_bus_window_count[ALPHA_BUS_TYPE_MAX + 1];
78 
79 int       (*alpha_bus_get_window)(int, int,
80               struct alpha_bus_space_translation *);
81 
82 struct alpha_pci_chipset *alpha_pci_chipset;
83 
84 int
sys_sysarch(struct lwp * l,const struct sys_sysarch_args * uap,register_t * retval)85 sys_sysarch(struct lwp *l, const struct sys_sysarch_args *uap, register_t *retval)
86 {
87           /* {
88                     syscallarg(int) op;
89                     syscallarg(void *) parms;
90           } */
91           int error = 0;
92 
93           switch(SCARG(uap, op)) {
94           case ALPHA_FPGETMASK:
95                     *retval = FP_C_TO_NETBSD_MASK(l->l_md.md_flags);
96                     break;
97           case ALPHA_FPGETSTICKY:
98                     *retval = FP_C_TO_NETBSD_FLAG(l->l_md.md_flags);
99                     break;
100           case ALPHA_FPSETMASK:
101           case ALPHA_FPSETSTICKY:
102               {
103                     fp_except m;
104                     uint64_t md_flags;
105                     struct alpha_fp_except_args args;
106 
107                     error = copyin(SCARG(uap, parms), &args, sizeof args);
108                     if (error)
109                               return error;
110                     m = args.mask;
111                     md_flags = l->l_md.md_flags;
112                     switch (SCARG(uap, op)) {
113                     case ALPHA_FPSETMASK:
114                               *retval = FP_C_TO_NETBSD_MASK(md_flags);
115                               md_flags = SET_FP_C_MASK(md_flags, m);
116                               break;
117                     case ALPHA_FPSETSTICKY:
118                               *retval = FP_C_TO_NETBSD_FLAG(md_flags);
119                               md_flags = SET_FP_C_FLAG(md_flags, m);
120                               break;
121                     }
122                     alpha_write_fp_c(l, md_flags);
123                     break;
124               }
125           case ALPHA_GET_FP_C:
126               {
127                     struct alpha_fp_c_args args;
128 
129                     args.fp_c = alpha_read_fp_c(l);
130                     error = copyout(&args, SCARG(uap, parms), sizeof args);
131                     break;
132               }
133           case ALPHA_SET_FP_C:
134               {
135                     struct alpha_fp_c_args args;
136 
137                     error = copyin(SCARG(uap, parms), &args, sizeof args);
138                     if (error)
139                               return (error);
140                     if ((args.fp_c >> 63) != 0)
141                               args.fp_c |= IEEE_INHERIT;
142                     alpha_write_fp_c(l, args.fp_c);
143                     break;
144               }
145           case ALPHA_BUS_GET_WINDOW_COUNT:
146               {
147                     struct alpha_bus_get_window_count_args args;
148 
149                     error = copyin(SCARG(uap, parms), &args, sizeof(args));
150                     if (error)
151                               return (error);
152 
153                     if (args.type > ALPHA_BUS_TYPE_MAX)
154                               return (EINVAL);
155 
156                     if (alpha_bus_window_count[args.type] == 0)
157                               return (EOPNOTSUPP);
158 
159                     args.count = alpha_bus_window_count[args.type];
160                     error = copyout(&args, SCARG(uap, parms), sizeof(args));
161                     break;
162               }
163 
164           case ALPHA_BUS_GET_WINDOW:
165               {
166                     struct alpha_bus_space_translation abst;
167                     struct alpha_bus_get_window_args args;
168 
169                     error = copyin(SCARG(uap, parms), &args, sizeof(args));
170                     if (error)
171                               return (error);
172 
173                     if (args.type > ALPHA_BUS_TYPE_MAX)
174                               return (EINVAL);
175 
176                     if (alpha_bus_window_count[args.type] == 0)
177                               return (EOPNOTSUPP);
178 
179                     if (args.window >= alpha_bus_window_count[args.type])
180                               return (EINVAL);
181 
182                     error = (*alpha_bus_get_window)(args.type, args.window,
183                         &abst);
184                     if (error)
185                               return (error);
186 
187                     error = copyout(&abst, args.translation, sizeof(abst));
188                     break;
189               }
190 
191 #if NPCI > 0
192           case ALPHA_PCI_CONF_READWRITE:
193               {
194                     struct alpha_pci_conf_readwrite_args args;
195                     pcitag_t tag;
196 
197                     error = copyin(SCARG(uap, parms), &args, sizeof(args));
198                     if (error)
199                               return (error);
200 
201                     if (alpha_pci_chipset == NULL)
202                               return (EOPNOTSUPP);
203 
204                     if (args.bus > 0xff)                    /* XXX MAGIC NUMBER */
205                               return (EINVAL);
206                     if (args.device > pci_bus_maxdevs(alpha_pci_chipset, args.bus))
207                               return (EINVAL);
208                     if (args.function > 7)                  /* XXX MAGIC NUMBER */
209                               return (EINVAL);
210                     if (args.reg > 0xff)                    /* XXX MAGIC NUMBER */
211                               return (EINVAL);
212 
213                     tag = pci_make_tag(alpha_pci_chipset, args.bus, args.device,
214                         args.function);
215 
216                     if (args.write)
217                               pci_conf_write(alpha_pci_chipset, tag, args.reg,
218                                   args.val);
219                     else {
220                               args.val = pci_conf_read(alpha_pci_chipset, tag,
221                                   args.reg);
222                               error = copyout(&args, SCARG(uap, parms), sizeof(args));
223                     }
224                     break;
225               }
226 #endif
227 
228           default:
229                     error = EINVAL;
230                     break;
231           }
232 
233           return (error);
234 }
235 
236 int
cpu_lwp_setprivate(lwp_t * l,void * addr)237 cpu_lwp_setprivate(lwp_t *l, void *addr)
238 {
239           struct pcb *pcb;
240 
241           pcb = lwp_getpcb(l);
242           pcb->pcb_hw.apcb_unique = (unsigned long)addr;
243           if (l == curlwp)
244                     alpha_pal_wrunique(pcb->pcb_hw.apcb_unique);
245           return 0;
246 }
247