1 /*
2 * Copyright (c) 1982, 1986 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
6 * @(#)vm_machdep.c 7.10 (Berkeley) 12/16/90
7 */
8
9 #include "sys/param.h"
10 #include "sys/systm.h"
11 #include "sys/user.h"
12 #include "sys/proc.h"
13 #include "sys/cmap.h"
14 #include "sys/vm.h"
15 #include "sys/text.h"
16
17 #include "../include/pte.h"
18 #include "../include/mtpr.h"
19
20 /*
21 * Set a red zone in the kernel stack after the u. area.
22 */
setredzone(pte,vaddr)23 setredzone(pte, vaddr)
24 register struct pte *pte;
25 caddr_t vaddr;
26 {
27
28 pte += (sizeof (struct user) + NBPG - 1) / NBPG;
29 *(int *)pte &= ~PG_PROT;
30 *(int *)pte |= PG_URKR;
31 if (vaddr)
32 mtpr(TBIS, vaddr + sizeof (struct user));
33 }
34
35 /*
36 * Check for valid program size
37 * NB - Check data and data growth separately as they may overflow
38 * when summed together.
39 */
chksize(ts,ids,uds,ss)40 chksize(ts, ids, uds, ss)
41 unsigned ts, ids, uds, ss;
42 {
43 extern unsigned maxtsize;
44
45 if (ctob(ts) > maxtsize ||
46 ctob(ids) > u.u_rlimit[RLIMIT_DATA].rlim_cur ||
47 ctob(uds) > u.u_rlimit[RLIMIT_DATA].rlim_cur ||
48 ctob(ids + uds) > u.u_rlimit[RLIMIT_DATA].rlim_cur ||
49 ctob(ss) > u.u_rlimit[RLIMIT_STACK].rlim_cur) {
50 return (ENOMEM);
51 }
52 return (0);
53 }
54
55 /*ARGSUSED*/
newptes(pte,v,size)56 newptes(pte, v, size)
57 register struct pte *pte;
58 u_int v;
59 register int size;
60 {
61 register caddr_t a = ptob(v);
62
63 #ifdef lint
64 pte = pte;
65 #endif
66 if (size >= 8) {
67 mtpr(TBIA, 0);
68 return;
69 }
70 while (size > 0) {
71 mtpr(TBIS, a);
72 a += NBPG;
73 size--;
74 }
75 }
76
77 /*
78 * Change protection codes of text segment.
79 * Have to flush translation buffer since this
80 * affect virtual memory mapping of current process.
81 */
chgprot(addr,tprot)82 chgprot(addr, tprot)
83 caddr_t addr;
84 long tprot;
85 {
86 unsigned v;
87 int tp;
88 register struct pte *pte;
89 register struct cmap *c;
90
91 v = clbase(btop(addr));
92 if (!isatsv(u.u_procp, v))
93 return (EFAULT);
94 tp = vtotp(u.u_procp, v);
95 pte = tptopte(u.u_procp, tp);
96 if (pte->pg_fod == 0 && pte->pg_pfnum) {
97 c = &cmap[pgtocm(pte->pg_pfnum)];
98 if (c->c_blkno)
99 munhash(c->c_vp, (daddr_t)(u_long)c->c_blkno);
100 }
101 *(int *)pte &= ~PG_PROT;
102 *(int *)pte |= tprot;
103 distcl(pte);
104 tbiscl(v);
105 return (0);
106 }
107
settprot(tprot)108 settprot(tprot)
109 long tprot;
110 {
111 register int *ptaddr, i;
112
113 ptaddr = (int *)mfpr(P0BR);
114 for (i = 0; i < u.u_tsize; i++) {
115 ptaddr[i] &= ~PG_PROT;
116 ptaddr[i] |= tprot;
117 }
118 mtpr(TBIA, 0);
119 }
120
121 /*
122 * Rest are machine-dependent
123 */
124
getmemc(addr)125 getmemc(addr)
126 caddr_t addr;
127 {
128 register int c;
129 struct pte savemap;
130
131 savemap = mmap[0];
132 *(int *)mmap = PG_V | PG_KR | btop(addr);
133 mtpr(TBIS, vmmap);
134 c = *(char *)&vmmap[(int)addr & PGOFSET];
135 mmap[0] = savemap;
136 mtpr(TBIS, vmmap);
137 return (c & 0377);
138 }
139
putmemc(addr,val)140 putmemc(addr, val)
141 caddr_t addr;
142 {
143 struct pte savemap;
144
145 savemap = mmap[0];
146 *(int *)mmap = PG_V | PG_KW | btop(addr);
147 mtpr(TBIS, vmmap);
148 *(char *)&vmmap[(int)addr & PGOFSET] = val;
149 mmap[0] = savemap;
150 mtpr(TBIS, vmmap);
151 }
152
153 /*
154 * Move pages from one kernel virtual address to another.
155 * Both addresses are assumed to reside in the Sysmap,
156 * and size must be a multiple of CLSIZE.
157 */
pagemove(from,to,size)158 pagemove(from, to, size)
159 register caddr_t from, to;
160 int size;
161 {
162 register struct pte *fpte, *tpte;
163
164 if (size % CLBYTES)
165 panic("pagemove");
166 fpte = kvtopte(from);
167 tpte = kvtopte(to);
168 while (size > 0) {
169 *tpte++ = *fpte;
170 *(int *)fpte++ = 0;
171 mtpr(TBIS, from);
172 mtpr(TBIS, to);
173 from += NBPG;
174 to += NBPG;
175 size -= NBPG;
176 }
177 }
178