1 /*
2  * Copyright (c) 1992 OMRON Corporation.
3  * Copyright (c) 1982, 1986, 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * %sccs.include.redist.c%
7  *
8  * from: hp300/hp300/sys_machdep.c	7.11 (Berkeley) 12/27/92
9  *
10  *	@(#)sys_machdep.c	8.1 (Berkeley) 06/10/93
11  */
12 
13 #include <sys/param.h>
14 #include <sys/systm.h>
15 #include <sys/ioctl.h>
16 #include <sys/file.h>
17 #include <sys/time.h>
18 #include <sys/proc.h>
19 #include <sys/uio.h>
20 #include <sys/kernel.h>
21 #include <sys/mtio.h>
22 #include <sys/buf.h>
23 #include <sys/trace.h>
24 
25 #include <vm/vm.h>
26 
27 #ifdef TRACE
28 int	nvualarm;
29 
30 struct vtrace_args {
31 	int	request;
32 	int	value;
33 };
34 vtrace(p, uap, retval)
35 	struct proc *p;
36 	register struct vtrace_args *uap;
37 	int *retval;
38 {
39 	int vdoualarm();
40 
41 	switch (uap->request) {
42 
43 	case VTR_DISABLE:		/* disable a trace point */
44 	case VTR_ENABLE:		/* enable a trace point */
45 		if (uap->value < 0 || uap->value >= TR_NFLAGS)
46 			return (EINVAL);
47 		*retval = traceflags[uap->value];
48 		traceflags[uap->value] = uap->request;
49 		break;
50 
51 	case VTR_VALUE:		/* return a trace point setting */
52 		if (uap->value < 0 || uap->value >= TR_NFLAGS)
53 			return (EINVAL);
54 		*retval = traceflags[uap->value];
55 		break;
56 
57 	case VTR_UALARM:	/* set a real-time ualarm, less than 1 min */
58 		if (uap->value <= 0 || uap->value > 60 * hz || nvualarm > 5)
59 			return (EINVAL);
60 		nvualarm++;
61 		timeout(vdoualarm, (caddr_t)p->p_pid, uap->value);
62 		break;
63 
64 	case VTR_STAMP:
65 		trace(TR_STAMP, uap->value, p->p_pid);
66 		break;
67 	}
68 	return (0);
69 }
70 
71 vdoualarm(arg)
72 	int arg;
73 {
74 	register struct proc *p;
75 
76 	p = pfind(arg);
77 	if (p)
78 		psignal(p, 16);
79 	nvualarm--;
80 }
81 #endif
82 
83 #include <machine/cpu.h>
84 
85 /* XXX should be in an include file somewhere */
86 #define CC_PURGE	1
87 #define CC_FLUSH	2
88 #define CC_IPURGE	4
89 #define CC_EXTPURGE	0x80000000
90 /* XXX end should be */
91 
92 /*
93  * Note that what we do here for a 68040 is different than HP-UX.
94  *
95  * In 'pux they either act on a line (len == 16), a page (len == NBPG)
96  * or the whole cache (len == anything else).
97  *
98  * In BSD we attempt to be more optimal when acting on "odd" sizes.
99  * For lengths up to 1024 we do all affected lines, up to 2*NBPG we
100  * do pages, above that we do the entire cache.
101  */
102 /*ARGSUSED1*/
103 cachectl(req, addr, len)
104 	int req;
105 	caddr_t	addr;
106 	int len;
107 {
108 	int error = 0;
109 
110 #if defined(LUNA2)
111 	if (mmutype == MMU_68040) {
112 		register int inc;
113 		int pa = 0, doall = 0;
114 		caddr_t end;
115 
116 		if (addr == 0 ||
117 		    (req & ~CC_EXTPURGE) != CC_PURGE && len > 2*NBPG)
118 			doall = 1;
119 #ifdef HPUXCOMPAT
120 		if ((curproc->p_md.md_flags & MDP_HPUX) &&
121 		    len != 16 && len != NBPG)
122 			doall = 1;
123 #endif
124 		if (!doall) {
125 			end = addr + len;
126 			if (len <= 1024) {
127 				addr = (caddr_t)((int)addr & ~0xF);
128 				inc = 16;
129 			} else {
130 				addr = (caddr_t)((int)addr & ~PGOFSET);
131 				inc = NBPG;
132 			}
133 		}
134 		do {
135 			/*
136 			 * Convert to physical address if needed.
137 			 * If translation fails, we perform operation on
138 			 * entire cache (XXX is this a rational thing to do?)
139 			 */
140 			if (!doall &&
141 			    (pa == 0 || ((int)addr & PGOFSET) == 0)) {
142 				pa = pmap_extract(&curproc->p_vmspace->vm_pmap,
143 						  (vm_offset_t)addr);
144 				if (pa == 0)
145 					doall = 1;
146 			}
147 			switch (req) {
148 			case CC_EXTPURGE|CC_IPURGE:
149 			case CC_IPURGE:
150 				if (doall) {
151 					DCFA();
152 					ICPA();
153 				} else if (inc == 16) {
154 					DCFL(pa);
155 					ICPL(pa);
156 				} else if (inc == NBPG) {
157 					DCFP(pa);
158 					ICPP(pa);
159 				}
160 				break;
161 
162 			case CC_EXTPURGE|CC_PURGE:
163 			case CC_PURGE:
164 				if (doall)
165 					DCFA();	/* note: flush not purge */
166 				else if (inc == 16)
167 					DCPL(pa);
168 				else if (inc == NBPG)
169 					DCPP(pa);
170 				break;
171 
172 			case CC_EXTPURGE|CC_FLUSH:
173 			case CC_FLUSH:
174 				if (doall)
175 					DCFA();
176 				else if (inc == 16)
177 					DCFL(pa);
178 				else if (inc == NBPG)
179 					DCFP(pa);
180 				break;
181 
182 			default:
183 				error = EINVAL;
184 				break;
185 			}
186 			if (doall)
187 				break;
188 			pa += inc;
189 			addr += inc;
190 		} while (addr < end);
191 		return(error);
192 	}
193 #endif
194 	switch (req) {
195 	case CC_EXTPURGE|CC_PURGE:
196 	case CC_EXTPURGE|CC_FLUSH:
197 	case CC_PURGE:
198 	case CC_FLUSH:
199 #if defined(LUNA2)
200 		DCIU();
201 #endif
202 		break;
203 	case CC_EXTPURGE|CC_IPURGE:
204 #if defined(LUNA2)
205 		DCIU();
206 		/* fall into... */
207 #endif
208 	case CC_IPURGE:
209 		ICIA();
210 		break;
211 	default:
212 		error = EINVAL;
213 		break;
214 	}
215 	return(error);
216 }
217