185e7c9a4Smckusick /*
24975c9eaSbostic * Copyright (c) 1982, 1986, 1993
34975c9eaSbostic * The Regents of the University of California. All rights reserved.
485e7c9a4Smckusick *
585e7c9a4Smckusick * %sccs.include.redist.c%
685e7c9a4Smckusick *
7*2a74b1beShibler * @(#)sys_machdep.c 8.2 (Berkeley) 01/13/94
885e7c9a4Smckusick */
985e7c9a4Smckusick
104e6f2c04Sbostic #include <sys/param.h>
114e6f2c04Sbostic #include <sys/systm.h>
124e6f2c04Sbostic #include <sys/ioctl.h>
134e6f2c04Sbostic #include <sys/file.h>
144e6f2c04Sbostic #include <sys/time.h>
154e6f2c04Sbostic #include <sys/proc.h>
164e6f2c04Sbostic #include <sys/uio.h>
174e6f2c04Sbostic #include <sys/kernel.h>
184e6f2c04Sbostic #include <sys/mtio.h>
194e6f2c04Sbostic #include <sys/buf.h>
204e6f2c04Sbostic #include <sys/trace.h>
214e6f2c04Sbostic
224e6f2c04Sbostic #include <vm/vm.h>
2385e7c9a4Smckusick
2485e7c9a4Smckusick #ifdef TRACE
2585e7c9a4Smckusick int nvualarm;
2685e7c9a4Smckusick
27bf88622fStorek struct vtrace_args {
2885e7c9a4Smckusick int request;
2985e7c9a4Smckusick int value;
30bf88622fStorek };
31bf88622fStorek vtrace(p, uap, retval)
32bf88622fStorek struct proc *p;
33bf88622fStorek register struct vtrace_args *uap;
341af7d2d2Smckusick int *retval;
351af7d2d2Smckusick {
3685e7c9a4Smckusick int vdoualarm();
3785e7c9a4Smckusick
3885e7c9a4Smckusick switch (uap->request) {
3985e7c9a4Smckusick
4085e7c9a4Smckusick case VTR_DISABLE: /* disable a trace point */
4185e7c9a4Smckusick case VTR_ENABLE: /* enable a trace point */
4285e7c9a4Smckusick if (uap->value < 0 || uap->value >= TR_NFLAGS)
430e839d83Skarels return (EINVAL);
441af7d2d2Smckusick *retval = traceflags[uap->value];
4585e7c9a4Smckusick traceflags[uap->value] = uap->request;
4685e7c9a4Smckusick break;
4785e7c9a4Smckusick
4885e7c9a4Smckusick case VTR_VALUE: /* return a trace point setting */
4985e7c9a4Smckusick if (uap->value < 0 || uap->value >= TR_NFLAGS)
500e839d83Skarels return (EINVAL);
511af7d2d2Smckusick *retval = traceflags[uap->value];
5285e7c9a4Smckusick break;
5385e7c9a4Smckusick
5485e7c9a4Smckusick case VTR_UALARM: /* set a real-time ualarm, less than 1 min */
551af7d2d2Smckusick if (uap->value <= 0 || uap->value > 60 * hz || nvualarm > 5)
560e839d83Skarels return (EINVAL);
5785e7c9a4Smckusick nvualarm++;
581af7d2d2Smckusick timeout(vdoualarm, (caddr_t)p->p_pid, uap->value);
5985e7c9a4Smckusick break;
6085e7c9a4Smckusick
6185e7c9a4Smckusick case VTR_STAMP:
621af7d2d2Smckusick trace(TR_STAMP, uap->value, p->p_pid);
6385e7c9a4Smckusick break;
6485e7c9a4Smckusick }
650e839d83Skarels return (0);
6685e7c9a4Smckusick }
6785e7c9a4Smckusick
vdoualarm(arg)6885e7c9a4Smckusick vdoualarm(arg)
6985e7c9a4Smckusick int arg;
7085e7c9a4Smckusick {
7185e7c9a4Smckusick register struct proc *p;
7285e7c9a4Smckusick
7385e7c9a4Smckusick p = pfind(arg);
7485e7c9a4Smckusick if (p)
7585e7c9a4Smckusick psignal(p, 16);
7685e7c9a4Smckusick nvualarm--;
7785e7c9a4Smckusick }
7885e7c9a4Smckusick #endif
7953286c58Shibler
804e6f2c04Sbostic #include <machine/cpu.h>
8153286c58Shibler
8253286c58Shibler /* XXX should be in an include file somewhere */
8353286c58Shibler #define CC_PURGE 1
8453286c58Shibler #define CC_FLUSH 2
8553286c58Shibler #define CC_IPURGE 4
8653286c58Shibler #define CC_EXTPURGE 0x80000000
8753286c58Shibler /* XXX end should be */
8853286c58Shibler
8914b153a2Shibler /*
9014b153a2Shibler * Note that what we do here for a 68040 is different than HP-UX.
9114b153a2Shibler *
9214b153a2Shibler * In 'pux they either act on a line (len == 16), a page (len == NBPG)
9314b153a2Shibler * or the whole cache (len == anything else).
9414b153a2Shibler *
9514b153a2Shibler * In BSD we attempt to be more optimal when acting on "odd" sizes.
9614b153a2Shibler * For lengths up to 1024 we do all affected lines, up to 2*NBPG we
9714b153a2Shibler * do pages, above that we do the entire cache.
9814b153a2Shibler */
9953286c58Shibler /*ARGSUSED1*/
cachectl(req,addr,len)10053286c58Shibler cachectl(req, addr, len)
10153286c58Shibler int req;
10253286c58Shibler caddr_t addr;
10353286c58Shibler int len;
10453286c58Shibler {
10553286c58Shibler int error = 0;
10653286c58Shibler
10714b153a2Shibler #if defined(HP380)
10814b153a2Shibler if (mmutype == MMU_68040) {
109*2a74b1beShibler register int inc = 0;
11014b153a2Shibler int pa = 0, doall = 0;
11114b153a2Shibler caddr_t end;
11214b153a2Shibler
11314b153a2Shibler if (addr == 0 ||
11414b153a2Shibler (req & ~CC_EXTPURGE) != CC_PURGE && len > 2*NBPG)
11514b153a2Shibler doall = 1;
11614b153a2Shibler #ifdef HPUXCOMPAT
1176b3fa1f1Shibler if ((curproc->p_md.md_flags & MDP_HPUX) &&
1186b3fa1f1Shibler len != 16 && len != NBPG)
11914b153a2Shibler doall = 1;
12014b153a2Shibler #endif
12114b153a2Shibler if (!doall) {
12214b153a2Shibler end = addr + len;
12314b153a2Shibler if (len <= 1024) {
12414b153a2Shibler addr = (caddr_t)((int)addr & ~0xF);
12514b153a2Shibler inc = 16;
12614b153a2Shibler } else {
12714b153a2Shibler addr = (caddr_t)((int)addr & ~PGOFSET);
12814b153a2Shibler inc = NBPG;
12914b153a2Shibler }
13014b153a2Shibler }
13114b153a2Shibler do {
13214b153a2Shibler /*
13314b153a2Shibler * Convert to physical address if needed.
13414b153a2Shibler * If translation fails, we perform operation on
13514b153a2Shibler * entire cache (XXX is this a rational thing to do?)
13614b153a2Shibler */
13714b153a2Shibler if (!doall &&
13814b153a2Shibler (pa == 0 || ((int)addr & PGOFSET) == 0)) {
13914b153a2Shibler pa = pmap_extract(&curproc->p_vmspace->vm_pmap,
14014b153a2Shibler (vm_offset_t)addr);
14114b153a2Shibler if (pa == 0)
14214b153a2Shibler doall = 1;
14314b153a2Shibler }
14414b153a2Shibler switch (req) {
14514b153a2Shibler case CC_EXTPURGE|CC_IPURGE:
14614b153a2Shibler case CC_IPURGE:
14714b153a2Shibler if (doall) {
14814b153a2Shibler DCFA();
14914b153a2Shibler ICPA();
15014b153a2Shibler } else if (inc == 16) {
15114b153a2Shibler DCFL(pa);
15214b153a2Shibler ICPL(pa);
15314b153a2Shibler } else if (inc == NBPG) {
15414b153a2Shibler DCFP(pa);
15514b153a2Shibler ICPP(pa);
15614b153a2Shibler }
15714b153a2Shibler break;
15814b153a2Shibler
15914b153a2Shibler case CC_EXTPURGE|CC_PURGE:
16014b153a2Shibler case CC_PURGE:
16114b153a2Shibler if (doall)
16214b153a2Shibler DCFA(); /* note: flush not purge */
16314b153a2Shibler else if (inc == 16)
16414b153a2Shibler DCPL(pa);
16514b153a2Shibler else if (inc == NBPG)
16614b153a2Shibler DCPP(pa);
16714b153a2Shibler break;
16814b153a2Shibler
16914b153a2Shibler case CC_EXTPURGE|CC_FLUSH:
17014b153a2Shibler case CC_FLUSH:
17114b153a2Shibler if (doall)
17214b153a2Shibler DCFA();
17314b153a2Shibler else if (inc == 16)
17414b153a2Shibler DCFL(pa);
17514b153a2Shibler else if (inc == NBPG)
17614b153a2Shibler DCFP(pa);
17714b153a2Shibler break;
17814b153a2Shibler
17914b153a2Shibler default:
18014b153a2Shibler error = EINVAL;
18114b153a2Shibler break;
18214b153a2Shibler }
18314b153a2Shibler if (doall)
18414b153a2Shibler break;
18514b153a2Shibler pa += inc;
18614b153a2Shibler addr += inc;
18714b153a2Shibler } while (addr < end);
18814b153a2Shibler return(error);
18914b153a2Shibler }
19014b153a2Shibler #endif
19153286c58Shibler switch (req) {
19253286c58Shibler case CC_EXTPURGE|CC_PURGE:
19353286c58Shibler case CC_EXTPURGE|CC_FLUSH:
19453286c58Shibler #if defined(HP370)
19553286c58Shibler if (ectype == EC_PHYS)
19653286c58Shibler PCIA();
19753286c58Shibler /* fall into... */
19853286c58Shibler #endif
19953286c58Shibler case CC_PURGE:
20053286c58Shibler case CC_FLUSH:
20153286c58Shibler DCIU();
20253286c58Shibler break;
20353286c58Shibler case CC_EXTPURGE|CC_IPURGE:
20453286c58Shibler #if defined(HP370)
20553286c58Shibler if (ectype == EC_PHYS)
20653286c58Shibler PCIA();
20753286c58Shibler else
20853286c58Shibler #endif
20953286c58Shibler DCIU();
21053286c58Shibler /* fall into... */
21153286c58Shibler case CC_IPURGE:
21253286c58Shibler ICIA();
21353286c58Shibler break;
21453286c58Shibler default:
21553286c58Shibler error = EINVAL;
21653286c58Shibler break;
21753286c58Shibler }
21853286c58Shibler return(error);
21953286c58Shibler }
220