BOOK.T
上传用户:datang2001
上传日期:2007-02-01
资源大小:53269k
文件大小:987k
源码类别:

操作系统开发

开发平台:

C/C++

  1. 13881                         }
  2. 13882                         cons->c_column = 0;
  3. 13883                         flush(cons);
  4. 13884                 }
  5. .Op 191 src/kernel/console.c
  6. 13885                 if (cons->c_rwords == buflen(cons->c_ramqueue)) flush(cons);
  7. 13886                 cons->c_ramqueue[cons->c_rwords++] = cons->c_attr | (c & BYTE);
  8. 13887                 cons->c_column++;                       /* next column */
  9. 13888                 return;
  10. 13889   }
  11. 13890 }
  12. 13893 /*===========================================================================*
  13. 13894  *                              scroll_screen                                *
  14. 13895  *===========================================================================*/
  15. 13896 PRIVATE void scroll_screen(cons, dir)
  16. 13897 register console_t *cons;       /* pointer to console struct */
  17. 13898 int dir;                        /* SCROLL_UP or SCROLL_DOWN */
  18. 13899 {
  19. 13900   unsigned new_line, new_org, chars;
  20. 13901
  21. 13902   flush(cons);
  22. 13903   chars = scr_size - scr_width;         /* one screen minus one line */
  23. 13904
  24. 13905   /* Scrolling the screen is a real nuisance due to the various incompatible
  25. 13906    * video cards.  This driver supports software scrolling (Hercules?),
  26. 13907    * hardware scrolling (mono and CGA cards) and hardware scrolling without
  27. 13908    * wrapping (EGA and VGA cards).  In the latter case we must make sure that
  28. 13909    *            c_start <= c_org && c_org + scr_size <= c_limit
  29. 13910    * holds, because EGA and VGA don't wrap around the end of video memory.
  30. 13911    */
  31. 13912   if (dir == SCROLL_UP) {
  32. 13913         /* Scroll one line up in 3 ways: soft, avoid wrap, use origin. */
  33. 13914         if (softscroll) {
  34. 13915                 vid_vid_copy(cons->c_start + scr_width, cons->c_start, chars);
  35. 13916         } else
  36. 13917         if (!wrap && cons->c_org + scr_size + scr_width >= cons->c_limit) {
  37. 13918                 vid_vid_copy(cons->c_org + scr_width, cons->c_start, chars);
  38. 13919                 cons->c_org = cons->c_start;
  39. 13920         } else {
  40. 13921                 cons->c_org = (cons->c_org + scr_width) & vid_mask;
  41. 13922         }
  42. 13923         new_line = (cons->c_org + chars) & vid_mask;
  43. 13924   } else {
  44. 13925         /* Scroll one line down in 3 ways: soft, avoid wrap, use origin. */
  45. 13926         if (softscroll) {
  46. 13927                 vid_vid_copy(cons->c_start, cons->c_start + scr_width, chars);
  47. 13928         } else
  48. 13929         if (!wrap && cons->c_org < cons->c_start + scr_width) {
  49. 13930                 new_org = cons->c_limit - scr_size;
  50. 13931                 vid_vid_copy(cons->c_org, new_org + scr_width, chars);
  51. 13932                 cons->c_org = new_org;
  52. 13933         } else {
  53. 13934                 cons->c_org = (cons->c_org - scr_width) & vid_mask;
  54. 13935         }
  55. 13936         new_line = cons->c_org;
  56. 13937   }
  57. 13938   /* Blank the new line at top or bottom. */
  58. 13939   blank_color = cons->c_blank;
  59. 13940   mem_vid_copy(BLANK_MEM, new_line, scr_width);
  60. 13941
  61. 13942   /* Set the new video origin. */
  62. 13943   if (cons == curcons) set_6845(VID_ORG, cons->c_org);
  63. 13944   flush(cons);
  64. .Ep 192 src/kernel/console.c
  65. 13945 }
  66. 13948 /*===========================================================================*
  67. 13949  *                              flush                                        *
  68. 13950  *===========================================================================*/
  69. 13951 PRIVATE void flush(cons)
  70. 13952 register console_t *cons;       /* pointer to console struct */
  71. 13953 {
  72. 13954 /* Send characters buffered in 'ramqueue' to screen memory, check the new
  73. 13955  * cursor position, compute the new hardware cursor position and set it.
  74. 13956  */
  75. 13957   unsigned cur;
  76. 13958   tty_t *tp = cons->c_tty;
  77. 13959
  78. 13960   /* Have the characters in 'ramqueue' transferred to the screen. */
  79. 13961   if (cons->c_rwords > 0) {
  80. 13962         mem_vid_copy(cons->c_ramqueue, cons->c_cur, cons->c_rwords);
  81. 13963         cons->c_rwords = 0;
  82. 13964
  83. 13965         /* TTY likes to know the current column and if echoing messed up. */
  84. 13966         tp->tty_position = cons->c_column;
  85. 13967         tp->tty_reprint = TRUE;
  86. 13968   }
  87. 13969
  88. 13970   /* Check and update the cursor position. */
  89. 13971   if (cons->c_column < 0) cons->c_column = 0;
  90. 13972   if (cons->c_column > scr_width) cons->c_column = scr_width;
  91. 13973   if (cons->c_row < 0) cons->c_row = 0;
  92. 13974   if (cons->c_row >= scr_lines) cons->c_row = scr_lines - 1;
  93. 13975   cur = cons->c_org + cons->c_row * scr_width + cons->c_column;
  94. 13976   if (cur != cons->c_cur) {
  95. 13977         if (cons == curcons) set_6845(CURSOR, cur);
  96. 13978         cons->c_cur = cur;
  97. 13979   }
  98. 13980 }
  99. 13983 /*===========================================================================*
  100. 13984  *                              parse_escape                                 *
  101. 13985  *===========================================================================*/
  102. 13986 PRIVATE void parse_escape(cons, c)
  103. 13987 register console_t *cons;       /* pointer to console struct */
  104. 13988 char c;                         /* next character in escape sequence */
  105. 13989 {
  106. 13990 /* The following ANSI escape sequences are currently supported.
  107. 13991  * If n and/or m are omitted, they default to 1. Omitted s defaults to 0.
  108. 13992  *   ESC [nA moves up n lines
  109. 13993  *   ESC [nB moves down n lines
  110. 13994  *   ESC [nC moves right n spaces
  111. 13995  *   ESC [nD moves left n spaces
  112. 13996  *   ESC [m;nH moves cursor to (m,n)
  113. 13997  *   ESC [sJ clears screen relative to cursor (0 to end, 1 from start, 2 all)
  114. 13998  *   ESC [sK clears line relative to cursor (0 to end, 1 from start, 2 all)
  115. 13999  *   ESC [nL inserts n lines at cursor
  116. 14000  *   ESC [nM deletes n lines at cursor
  117. 14001  *   ESC [nP deletes n chars at cursor
  118. 14002  *   ESC [n@ inserts n chars at cursor
  119. 14003  *   ESC [nm enables rendition n (0= normal, 1=bold, 4=underline, 5=blinking,
  120. 14004  *       7=reverse, 30..37 set foreground color, 40..47 set background color)
  121. .Op 193 src/kernel/console.c
  122. 14005  *   ESC M scrolls the screen backwards if the cursor is on the top line
  123. 14006  */
  124. 14007
  125. 14008   switch (cons->c_esc_state) {
  126. 14009     case 1:                     /* ESC seen */
  127. 14010         cons->c_esc_intro = '';
  128. 14011         cons->c_esc_parmp = cons->c_esc_parmv;
  129. 14012         cons->c_esc_parmv[0] = cons->c_esc_parmv[1] = 0;
  130. 14013         switch (c) {
  131. 14014             case '[':   /* Control Sequence Introducer */
  132. 14015                 cons->c_esc_intro = c;
  133. 14016                 cons->c_esc_state = 2;
  134. 14017                 break;
  135. 14018             case 'M':   /* Reverse Index */
  136. 14019                 do_escape(cons, c);
  137. 14020                 break;
  138. 14021             default:
  139. 14022                 cons->c_esc_state = 0;
  140. 14023         }
  141. 14024         break;
  142. 14025
  143. 14026     case 2:                     /* ESC [ seen */
  144. 14027         if (c >= '0' && c <= '9') {
  145. 14028                 if (cons->c_esc_parmp < bufend(cons->c_esc_parmv))
  146. 14029                         *cons->c_esc_parmp = *cons->c_esc_parmp * 10 + (c-'0');
  147. 14030         } else
  148. 14031         if (c == ';') {
  149. 14032                 if (++cons->c_esc_parmp < bufend(cons->c_esc_parmv))
  150. 14033                         *cons->c_esc_parmp = 0;
  151. 14034         } else {
  152. 14035                 do_escape(cons, c);
  153. 14036         }
  154. 14037         break;
  155. 14038   }
  156. 14039 }
  157. 14042 /*===========================================================================*
  158. 14043  *                              do_escape                                    *
  159. 14044  *===========================================================================*/
  160. 14045 PRIVATE void do_escape(cons, c)
  161. 14046 register console_t *cons;       /* pointer to console struct */
  162. 14047 char c;                         /* next character in escape sequence */
  163. 14048 {
  164. 14049   int value, n;
  165. 14050   unsigned src, dst, count;
  166. 14051
  167. 14052   /* Some of these things hack on screen RAM, so it had better be up to date */
  168. 14053   flush(cons);
  169. 14054
  170. 14055   if (cons->c_esc_intro == '') {
  171. 14056         /* Handle a sequence beginning with just ESC */
  172. 14057         switch (c) {
  173. 14058             case 'M':           /* Reverse Index */
  174. 14059                 if (cons->c_row == 0) {
  175. 14060                         scroll_screen(cons, SCROLL_DOWN);
  176. 14061                 } else {
  177. 14062                         cons->c_row--;
  178. 14063                 }
  179. 14064                 flush(cons);
  180. .Ep 194 src/kernel/console.c
  181. 14065                 break;
  182. 14066
  183. 14067             default: break;
  184. 14068         }
  185. 14069   } else
  186. 14070   if (cons->c_esc_intro == '[') {
  187. 14071         /* Handle a sequence beginning with ESC [ and parameters */
  188. 14072         value = cons->c_esc_parmv[0];
  189. 14073         switch (c) {
  190. 14074             case 'A':           /* ESC [nA moves up n lines */
  191. 14075                 n = (value == 0 ? 1 : value);
  192. 14076                 cons->c_row -= n;
  193. 14077                 flush(cons);
  194. 14078                 break;
  195. 14079
  196. 14080             case 'B':           /* ESC [nB moves down n lines */
  197. 14081                 n = (value == 0 ? 1 : value);
  198. 14082                 cons->c_row += n;
  199. 14083                 flush(cons);
  200. 14084                 break;
  201. 14085
  202. 14086             case 'C':           /* ESC [nC moves right n spaces */
  203. 14087                 n = (value == 0 ? 1 : value);
  204. 14088                 cons->c_column += n;
  205. 14089                 flush(cons);
  206. 14090                 break;
  207. 14091
  208. 14092             case 'D':           /* ESC [nD moves left n spaces */
  209. 14093                 n = (value == 0 ? 1 : value);
  210. 14094                 cons->c_column -= n;
  211. 14095                 flush(cons);
  212. 14096                 break;
  213. 14097
  214. 14098             case 'H':           /* ESC [m;nH" moves cursor to (m,n) */
  215. 14099                 cons->c_row = cons->c_esc_parmv[0] - 1;
  216. 14100                 cons->c_column = cons->c_esc_parmv[1] - 1;
  217. 14101                 flush(cons);
  218. 14102                 break;
  219. 14103
  220. 14104             case 'J':           /* ESC [sJ clears in display */
  221. 14105                 switch (value) {
  222. 14106                     case 0:     /* Clear from cursor to end of screen */
  223. 14107                         count = scr_size - (cons->c_cur - cons->c_org);
  224. 14108                         dst = cons->c_cur;
  225. 14109                         break;
  226. 14110                     case 1:     /* Clear from start of screen to cursor */
  227. 14111                         count = cons->c_cur - cons->c_org;
  228. 14112                         dst = cons->c_org;
  229. 14113                         break;
  230. 14114                     case 2:     /* Clear entire screen */
  231. 14115                         count = scr_size;
  232. 14116                         dst = cons->c_org;
  233. 14117                         break;
  234. 14118                     default:    /* Do nothing */
  235. 14119                         count = 0;
  236. 14120                         dst = cons->c_org;
  237. 14121                 }
  238. 14122                 blank_color = cons->c_blank;
  239. 14123                 mem_vid_copy(BLANK_MEM, dst, count);
  240. 14124                 break;
  241. .Op 195 src/kernel/console.c
  242. 14125
  243. 14126             case 'K':           /* ESC [sK clears line from cursor */
  244. 14127                 switch (value) {
  245. 14128                     case 0:     /* Clear from cursor to end of line */
  246. 14129                         count = scr_width - cons->c_column;
  247. 14130                         dst = cons->c_cur;
  248. 14131                         break;
  249. 14132                     case 1:     /* Clear from beginning of line to cursor */
  250. 14133                         count = cons->c_column;
  251. 14134                         dst = cons->c_cur - cons->c_column;
  252. 14135                         break;
  253. 14136                     case 2:     /* Clear entire line */
  254. 14137                         count = scr_width;
  255. 14138                         dst = cons->c_cur - cons->c_column;
  256. 14139                         break;
  257. 14140                     default:    /* Do nothing */
  258. 14141                         count = 0;
  259. 14142                         dst = cons->c_cur;
  260. 14143                 }
  261. 14144                 blank_color = cons->c_blank;
  262. 14145                 mem_vid_copy(BLANK_MEM, dst, count);
  263. 14146                 break;
  264. 14147
  265. 14148             case 'L':           /* ESC [nL inserts n lines at cursor */
  266. 14149                 n = value;
  267. 14150                 if (n < 1) n = 1;
  268. 14151                 if (n > (scr_lines - cons->c_row))
  269. 14152                         n = scr_lines - cons->c_row;
  270. 14153
  271. 14154                 src = cons->c_org + cons->c_row * scr_width;
  272. 14155                 dst = src + n * scr_width;
  273. 14156                 count = (scr_lines - cons->c_row - n) * scr_width;
  274. 14157                 vid_vid_copy(src, dst, count);
  275. 14158                 blank_color = cons->c_blank;
  276. 14159                 mem_vid_copy(BLANK_MEM, src, n * scr_width);
  277. 14160                 break;
  278. 14161
  279. 14162             case 'M':           /* ESC [nM deletes n lines at cursor */
  280. 14163                 n = value;
  281. 14164                 if (n < 1) n = 1;
  282. 14165                 if (n > (scr_lines - cons->c_row))
  283. 14166                         n = scr_lines - cons->c_row;
  284. 14167
  285. 14168                 dst = cons->c_org + cons->c_row * scr_width;
  286. 14169                 src = dst + n * scr_width;
  287. 14170                 count = (scr_lines - cons->c_row - n) * scr_width;
  288. 14171                 vid_vid_copy(src, dst, count);
  289. 14172                 blank_color = cons->c_blank;
  290. 14173                 mem_vid_copy(BLANK_MEM, dst + count, n * scr_width);
  291. 14174                 break;
  292. 14175
  293. 14176             case '@':           /* ESC [n@ inserts n chars at cursor */
  294. 14177                 n = value;
  295. 14178                 if (n < 1) n = 1;
  296. 14179                 if (n > (scr_width - cons->c_column))
  297. 14180                         n = scr_width - cons->c_column;
  298. 14181
  299. 14182                 src = cons->c_cur;
  300. 14183                 dst = src + n;
  301. 14184                 count = scr_width - cons->c_column - n;
  302. .Ep 196 src/kernel/console.c
  303. 14185                 vid_vid_copy(src, dst, count);
  304. 14186                 blank_color = cons->c_blank;
  305. 14187                 mem_vid_copy(BLANK_MEM, src, n);
  306. 14188                 break;
  307. 14189
  308. 14190             case 'P':           /* ESC [nP deletes n chars at cursor */
  309. 14191                 n = value;
  310. 14192                 if (n < 1) n = 1;
  311. 14193                 if (n > (scr_width - cons->c_column))
  312. 14194                         n = scr_width - cons->c_column;
  313. 14195
  314. 14196                 dst = cons->c_cur;
  315. 14197                 src = dst + n;
  316. 14198                 count = scr_width - cons->c_column - n;
  317. 14199                 vid_vid_copy(src, dst, count);
  318. 14200                 blank_color = cons->c_blank;
  319. 14201                 mem_vid_copy(BLANK_MEM, dst + count, n);
  320. 14202                 break;
  321. 14203
  322. 14204             case 'm':           /* ESC [nm enables rendition n */
  323. 14205                 switch (value) {
  324. 14206                     case 1:     /* BOLD  */
  325. 14207                         if (color) {
  326. 14208                                 /* Can't do bold, so use yellow */
  327. 14209                                 cons->c_attr = (cons->c_attr & 0xf0ff) | 0x0E00;
  328. 14210                         } else {
  329. 14211                                 /* Set intensity bit */
  330. 14212                                 cons->c_attr |= 0x0800;
  331. 14213                         }
  332. 14214                         break;
  333. 14215
  334. 14216                     case 4:     /* UNDERLINE */
  335. 14217                         if (color) {
  336. 14218                                 /* Use light green */
  337. 14219                                 cons->c_attr = (cons->c_attr & 0xf0ff) | 0x0A00;
  338. 14220                         } else {
  339. 14221                                 cons->c_attr = (cons->c_attr & 0x8900);
  340. 14222                         }
  341. 14223                         break;
  342. 14224
  343. 14225                     case 5:     /* BLINKING */
  344. 14226                         if (color) {
  345. 14227                                 /* Use magenta */
  346. 14228                                 cons->c_attr = (cons->c_attr & 0xf0ff) | 0x0500;
  347. 14229                         } else {
  348. 14230                                 /* Set the blink bit */
  349. 14231                                 cons->c_attr |= 0x8000;
  350. 14232                         }
  351. 14233                         break;
  352. 14234
  353. 14235                     case 7:     /* REVERSE */
  354. 14236                         if (color) {
  355. 14237                                 /* Swap fg and bg colors */
  356. 14238                                 cons->c_attr =
  357. 14239                                         ((cons->c_attr & 0xf000) >> 4) |
  358. 14240                                         ((cons->c_attr & 0x0f00) << 4);
  359. 14241                         } else
  360. 14242                         if ((cons->c_attr & 0x7000) == 0) {
  361. 14243                                 cons->c_attr = (cons->c_attr & 0x8800) | 0x7000;
  362. 14244                         } else {
  363. .Op 197 src/kernel/console.c
  364. 14245                                 cons->c_attr = (cons->c_attr & 0x8800) | 0x0700;
  365. 14246                         }
  366. 14247                         break;
  367. 14248
  368. 14249                     default:    /* COLOR */
  369. 14250                         if (30 <= value && value <= 37) {
  370. 14251                                 cons->c_attr =
  371. 14252                                         (cons->c_attr & 0xf0ff) |
  372. 14253                                         (ansi_colors[(value - 30)] << 8);
  373. 14254                                 cons->c_blank =
  374. 14255                                         (cons->c_blank & 0xf0ff) |
  375. 14256                                         (ansi_colors[(value - 30)] << 8);
  376. 14257                         } else
  377. 14258                         if (40 <= value && value <= 47) {
  378. 14259                                 cons->c_attr =
  379. 14260                                         (cons->c_attr & 0x0fff) |
  380. 14261                                         (ansi_colors[(value - 40)] << 12);
  381. 14262                                 cons->c_blank =
  382. 14263                                         (cons->c_blank & 0x0fff) |
  383. 14264                                         (ansi_colors[(value - 40)] << 12);
  384. 14265                         } else {
  385. 14266                                 cons->c_attr = cons->c_blank;
  386. 14267                         }
  387. 14268                         break;
  388. 14269                 }
  389. 14270                 break;
  390. 14271         }
  391. 14272   }
  392. 14273   cons->c_esc_state = 0;
  393. 14274 }
  394. 14277 /*===========================================================================*
  395. 14278  *                              set_6845                                     *
  396. 14279  *===========================================================================*/
  397. 14280 PRIVATE void set_6845(reg, val)
  398. 14281 int reg;                        /* which register pair to set */
  399. 14282 unsigned val;                   /* 16-bit value to set it to */
  400. 14283 {
  401. 14284 /* Set a register pair inside the 6845.
  402. 14285  * Registers 12-13 tell the 6845 where in video ram to start
  403. 14286  * Registers 14-15 tell the 6845 where to put the cursor
  404. 14287  */
  405. 14288   lock();                       /* try to stop h/w loading in-between value */
  406. 14289   out_byte(vid_port + INDEX, reg);              /* set the index register */
  407. 14290   out_byte(vid_port + DATA, (val>>8) & BYTE);   /* output high byte */
  408. 14291   out_byte(vid_port + INDEX, reg + 1);          /* again */
  409. 14292   out_byte(vid_port + DATA, val&BYTE);          /* output low byte */
  410. 14293   unlock();
  411. 14294 }
  412. 14297 /*===========================================================================*
  413. 14298  *                              beep                                         *
  414. 14299  *===========================================================================*/
  415. 14300 PRIVATE void beep()
  416. 14301 {
  417. 14302 /* Making a beeping sound on the speaker (output for CRTL-G).
  418. 14303  * This routine works by turning on the bits 0 and 1 in port B of the 8255
  419. 14304  * chip that drives the speaker.
  420. .Ep 198 src/kernel/console.c
  421. 14305  */
  422. 14306
  423. 14307   message mess;
  424. 14308
  425. 14309   if (beeping) return;
  426. 14310   out_byte(TIMER_MODE, 0xB6);   /* set up timer channel 2 (square wave) */
  427. 14311   out_byte(TIMER2, BEEP_FREQ & BYTE);   /* load low-order bits of frequency */
  428. 14312   out_byte(TIMER2, (BEEP_FREQ >> 8) & BYTE);    /* now high-order bits */
  429. 14313   lock();                       /* guard PORT_B from keyboard intr handler */
  430. 14314   out_byte(PORT_B, in_byte(PORT_B) | 3);        /* turn on beep bits */
  431. 14315   unlock();
  432. 14316   beeping = TRUE;
  433. 14317
  434. 14318   mess.m_type = SET_ALARM;
  435. 14319   mess.CLOCK_PROC_NR = TTY;
  436. 14320   mess.DELTA_TICKS = B_TIME;
  437. 14321   mess.FUNC_TO_CALL = (sighandler_t) stop_beep;
  438. 14322   sendrec(CLOCK, &mess);
  439. 14323 }
  440. 14326 /*===========================================================================*
  441. 14327  *                              stop_beep                                    *
  442. 14328  *===========================================================================*/
  443. 14329 PRIVATE void stop_beep()
  444. 14330 {
  445. 14331 /* Turn off the beeper by turning off bits 0 and 1 in PORT_B. */
  446. 14332
  447. 14333   lock();                       /* guard PORT_B from keyboard intr handler */
  448. 14334   out_byte(PORT_B, in_byte(PORT_B) & ~3);
  449. 14335   beeping = FALSE;
  450. 14336   unlock();
  451. 14337 }
  452. 14340 /*===========================================================================*
  453. 14341  *                              scr_init                                     *
  454. 14342  *===========================================================================*/
  455. 14343 PUBLIC void scr_init(tp)
  456. 14344 tty_t *tp;
  457. 14345 {
  458. 14346 /* Initialize the screen driver. */
  459. 14347   console_t *cons;
  460. 14348   phys_bytes vid_base;
  461. 14349   u16_t bios_crtbase;
  462. 14350   int line;
  463. 14351   unsigned page_size;
  464. 14352
  465. 14353   /* Associate console and TTY. */
  466. 14354   line = tp - &tty_table[0];
  467. 14355   if (line >= nr_cons) return;
  468. 14356   cons = &cons_table[line];
  469. 14357   cons->c_tty = tp;
  470. 14358   tp->tty_priv = cons;
  471. 14359
  472. 14360   /* Initialize the keyboard driver. */
  473. 14361   kb_init(tp);
  474. 14362
  475. 14363   /* Output functions. */
  476. 14364   tp->tty_devwrite = cons_write;
  477. .Op 199 src/kernel/console.c
  478. 14365   tp->tty_echo = cons_echo;
  479. 14366
  480. 14367   /* Get the BIOS parameters that tells the VDU I/O base register. */
  481. 14368   phys_copy(0x463L, vir2phys(&bios_crtbase), 2L);
  482. 14369
  483. 14370   vid_port = bios_crtbase;
  484. 14371
  485. 14372   if (color) {
  486. 14373         vid_base = COLOR_BASE;
  487. 14374         vid_size = COLOR_SIZE;
  488. 14375   } else {
  489. 14376         vid_base = MONO_BASE;
  490. 14377         vid_size = MONO_SIZE;
  491. 14378   }
  492. 14379   if (ega) vid_size = EGA_SIZE; /* for both EGA and VGA */
  493. 14380   wrap = !ega;
  494. 14381
  495. 14382   vid_seg = protected_mode ? VIDEO_SELECTOR : physb_to_hclick(vid_base);
  496. 14383   init_dataseg(&gdt[VIDEO_INDEX], vid_base, (phys_bytes) vid_size,
  497. 14384                                                         TASK_PRIVILEGE);
  498. 14385   vid_size >>= 1;               /* word count */
  499. 14386   vid_mask = vid_size - 1;
  500. 14387
  501. 14388   /* There can be as many consoles as video memory allows. */
  502. 14389   nr_cons = vid_size / scr_size;
  503. 14390   if (nr_cons > NR_CONS) nr_cons = NR_CONS;
  504. 14391   if (nr_cons > 1) wrap = 0;
  505. 14392   page_size = vid_size / nr_cons;
  506. 14393   cons->c_start = line * page_size;
  507. 14394   cons->c_limit = cons->c_start + page_size;
  508. 14395   cons->c_org = cons->c_start;
  509. 14396   cons->c_attr = cons->c_blank = BLANK_COLOR;
  510. 14397
  511. 14398   /* Clear the screen. */
  512. 14399   blank_color = BLANK_COLOR;
  513. 14400   mem_vid_copy(BLANK_MEM, cons->c_start, scr_size);
  514. 14401   select_console(0);
  515. 14402 }
  516. 14405 /*===========================================================================*
  517. 14406  *                              putk                                         *
  518. 14407  *===========================================================================*/
  519. 14408 PUBLIC void putk(c)
  520. 14409 int c;                          /* character to print */
  521. 14410 {
  522. 14411 /* This procedure is used by the version of printf() that is linked with
  523. 14412  * the kernel itself.  The one in the library sends a message to FS, which is
  524. 14413  * not what is needed for printing within the kernel.  This version just queues
  525. 14414  * the character and starts the output.
  526. 14415  */
  527. 14416
  528. 14417   if (c != 0) {
  529. 14418         if (c == 'n') putk('r');
  530. 14419         out_char(&cons_table[0], (int) c);
  531. 14420   } else {
  532. 14421         flush(&cons_table[0]);
  533. 14422   }
  534. 14423 }
  535. .Ep 200 src/kernel/console.c
  536. 14426 /*===========================================================================*
  537. 14427  *                              toggle_scroll                                *
  538. 14428  *===========================================================================*/
  539. 14429 PUBLIC void toggle_scroll()
  540. 14430 {
  541. 14431 /* Toggle between hardware and software scroll. */
  542. 14432
  543. 14433   cons_org0();
  544. 14434   softscroll = !softscroll;
  545. 14435   printf("%sware scrolling enabled.n", softscroll ? "Soft" : "Hard");
  546. 14436 }
  547. 14439 /*===========================================================================*
  548. 14440  *                              cons_stop                                    *
  549. 14441  *===========================================================================*/
  550. 14442 PUBLIC void cons_stop()
  551. 14443 {
  552. 14444 /* Prepare for halt or reboot. */
  553. 14445
  554. 14446   cons_org0();
  555. 14447   softscroll = 1;
  556. 14448   select_console(0);
  557. 14449   cons_table[0].c_attr = cons_table[0].c_blank = BLANK_COLOR;
  558. 14450 }
  559. 14453 /*===========================================================================*
  560. 14454  *                              cons_org0                                    *
  561. 14455  *===========================================================================*/
  562. 14456 PRIVATE void cons_org0()
  563. 14457 {
  564. 14458 /* Scroll video memory back to put the origin at 0. */
  565. 14459
  566. 14460   int cons_line;
  567. 14461   console_t *cons;
  568. 14462   unsigned n;
  569. 14463
  570. 14464   for (cons_line = 0; cons_line < nr_cons; cons_line++) {
  571. 14465         cons = &cons_table[cons_line];
  572. 14466         while (cons->c_org > cons->c_start) {
  573. 14467                 n = vid_size - scr_size;        /* amount of unused memory */
  574. 14468                 if (n > cons->c_org - cons->c_start)
  575. 14469                         n = cons->c_org - cons->c_start;
  576. 14470                 vid_vid_copy(cons->c_org, cons->c_org - n, scr_size);
  577. 14471                 cons->c_org -= n;
  578. 14472         }
  579. 14473         flush(cons);
  580. 14474   }
  581. 14475   select_console(current);
  582. 14476 }
  583. 14479 /*===========================================================================*
  584. 14480  *                              select_console                               *
  585. 14481  *===========================================================================*/
  586. 14482 PUBLIC void select_console(int cons_line)
  587. 14483 {
  588. 14484 /* Set the current console to console number 'cons_line'. */
  589. .Op 201 src/kernel/console.c
  590. 14485
  591. 14486   if (cons_line < 0 || cons_line >= nr_cons) return;
  592. 14487   current = cons_line;
  593. 14488   curcons = &cons_table[cons_line];
  594. 14489   set_6845(VID_ORG, curcons->c_org);
  595. 14490   set_6845(CURSOR, curcons->c_cur);
  596. 14491 }
  597. 14494 /*===========================================================================*
  598. 14495  *                              con_loadfont                                 *
  599. 14496  *===========================================================================*/
  600. 14497 PUBLIC int con_loadfont(user_phys)
  601. 14498 phys_bytes user_phys;
  602. 14499 {
  603. 14500 /* Load a font into the EGA or VGA adapter. */
  604. 14501
  605. 14502   static struct sequence seq1[7] = {
  606. 14503         { GA_SEQUENCER_INDEX, 0x00, 0x01 },
  607. 14504         { GA_SEQUENCER_INDEX, 0x02, 0x04 },
  608. 14505         { GA_SEQUENCER_INDEX, 0x04, 0x07 },
  609. 14506         { GA_SEQUENCER_INDEX, 0x00, 0x03 },
  610. 14507         { GA_GRAPHICS_INDEX, 0x04, 0x02 },
  611. 14508         { GA_GRAPHICS_INDEX, 0x05, 0x00 },
  612. 14509         { GA_GRAPHICS_INDEX, 0x06, 0x00 },
  613. 14510   };
  614. 14511   static struct sequence seq2[7] = {
  615. 14512         { GA_SEQUENCER_INDEX, 0x00, 0x01 },
  616. 14513         { GA_SEQUENCER_INDEX, 0x02, 0x03 },
  617. 14514         { GA_SEQUENCER_INDEX, 0x04, 0x03 },
  618. 14515         { GA_SEQUENCER_INDEX, 0x00, 0x03 },
  619. 14516         { GA_GRAPHICS_INDEX, 0x04, 0x00 },
  620. 14517         { GA_GRAPHICS_INDEX, 0x05, 0x10 },
  621. 14518         { GA_GRAPHICS_INDEX, 0x06,    0 },
  622. 14519   };
  623. 14520
  624. 14521   seq2[6].value= color ? 0x0E : 0x0A;
  625. 14522
  626. 14523   if (!ega) return(ENOTTY);
  627. 14524
  628. 14525   lock();
  629. 14526   ga_program(seq1);     /* bring font memory into view */
  630. 14527
  631. 14528   phys_copy(user_phys, (phys_bytes)GA_VIDEO_ADDRESS, (phys_bytes)GA_FONT_SIZE);
  632. 14529
  633. 14530   ga_program(seq2);     /* restore */
  634. 14531   unlock();
  635. 14532
  636. 14533   return(OK);
  637. 14534 }
  638. 14537 /*===========================================================================*
  639. 14538  *                              ga_program                                   *
  640. 14539  *===========================================================================*/
  641. 14540 PRIVATE void ga_program(seq)
  642. 14541 struct sequence *seq;
  643. 14542 {
  644. 14543 /* support function for con_loadfont */
  645. 14544
  646. .Ep 202 src/kernel/console.c
  647. 14545   int len= 7;
  648. 14546   do {
  649. 14547         out_byte(seq->index, seq->port);
  650. 14548         out_byte(seq->index+1, seq->value);
  651. 14549         seq++;
  652. 14550   } while (--len > 0);
  653. 14551 }
  654. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  655. src/kernel/dmp.c    
  656. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  657. 14600 /* This file contains some dumping routines for debugging. */
  658. 14601
  659. 14602 #include "kernel.h"
  660. 14603 #include <minix/com.h>
  661. 14604 #include "proc.h"
  662. 14605
  663. 14606 char *vargv;
  664. 14607
  665. 14608 FORWARD _PROTOTYPE(char *proc_name, (int proc_nr));
  666. 14609
  667. 14610 /*===========================================================================*
  668. 14611  *                              p_dmp                                        *
  669. 14612  *===========================================================================*/
  670. 14613 PUBLIC void p_dmp()
  671. 14614 {
  672. 14615 /* Proc table dump */
  673. 14616
  674. 14617   register struct proc *rp;
  675. 14618   static struct proc *oldrp = BEG_PROC_ADDR;
  676. 14619   int n = 0;
  677. 14620   phys_clicks text, data, size;
  678. 14621   int proc_nr;
  679. 14622
  680. 14623   printf("n--pid --pc- ---sp- flag -user --sys-- -text- -data- -size- -recv- commandn");
  681. 14624
  682. 14625   for (rp = oldrp; rp < END_PROC_ADDR; rp++) {
  683. 14626         proc_nr = proc_number(rp);
  684. 14627         if (rp->p_flags & P_SLOT_FREE) continue;
  685. 14628         if (++n > 20) break;
  686. 14629         text = rp->p_map[T].mem_phys;
  687. 14630         data = rp->p_map[D].mem_phys;
  688. 14631         size = rp->p_map[T].mem_len
  689. 14632                 + ((rp->p_map[S].mem_phys + rp->p_map[S].mem_len) - data);
  690. 14633         printf("%5d %5lx %6lx %2x %7U %7U %5uK %5uK %5uK ",
  691. 14634                proc_nr < 0 ? proc_nr : rp->p_pid,
  692. 14635                (unsigned long) rp->p_reg.pc,
  693. 14636                (unsigned long) rp->p_reg.sp,
  694. 14637                rp->p_flags,
  695. 14638                rp->user_time, rp->sys_time,
  696. 14639                click_to_round_k(text), click_to_round_k(data),
  697. 14640                click_to_round_k(size));
  698. 14641         if (rp->p_flags & RECEIVING) {
  699. 14642                 printf("%-7.7s", proc_name(rp->p_getfrom));
  700. 14643         } else
  701. 14644         if (rp->p_flags & SENDING) {
  702. .Op 203 src/kernel/dmp.c
  703. 14645                 printf("S:%-5.5s", proc_name(rp->p_sendto));
  704. 14646         } else
  705. 14647         if (rp->p_flags == 0) {
  706. 14648                 printf("       ");
  707. 14649         }
  708. 14650         printf("%sn", rp->p_name);
  709. 14651   }
  710. 14652   if (rp == END_PROC_ADDR) rp = BEG_PROC_ADDR; else printf("--more--r");
  711. 14653   oldrp = rp;
  712. 14654 }
  713. 14657 /*===========================================================================*
  714. 14658  *                              map_dmp                                      *
  715. 14659  *===========================================================================*/
  716. 14660 PUBLIC void map_dmp()
  717. 14661 {
  718. 14662   register struct proc *rp;
  719. 14663   static struct proc *oldrp = cproc_addr(HARDWARE);
  720. 14664   int n = 0;
  721. 14665   phys_clicks size;
  722. 14666
  723. 14667   printf("nPROC NAME-  -----TEXT-----  -----DATA-----  ----STACK-----  -SIZE-n");
  724. 14668   for (rp = oldrp; rp < END_PROC_ADDR; rp++) {
  725. 14669         if (rp->p_flags & P_SLOT_FREE) continue;
  726. 14670         if (++n > 20) break;
  727. 14671         size = rp->p_map[T].mem_len
  728. 14672                 + ((rp->p_map[S].mem_phys + rp->p_map[S].mem_len)
  729. 14673                                                 - rp->p_map[D].mem_phys);
  730. 14674         printf("%3d %-6.6s  %4x %4x %4x  %4x %4x %4x  %4x %4x %4x  %5uKn",
  731. 14675                proc_number(rp),
  732. 14676                rp->p_name,
  733. 14677                rp->p_map[T].mem_vir, rp->p_map[T].mem_phys, rp->p_map[T].mem_len,
  734. 14678                rp->p_map[D].mem_vir, rp->p_map[D].mem_phys, rp->p_map[D].mem_len,
  735. 14679                rp->p_map[S].mem_vir, rp->p_map[S].mem_phys, rp->p_map[S].mem_len,
  736. 14680                click_to_round_k(size));
  737. 14681   }
  738. 14682   if (rp == END_PROC_ADDR) rp = cproc_addr(HARDWARE); else printf("--more--r");
  739. 14683   oldrp = rp;
  740. 14684 }
  741. 14687 /*===========================================================================*
  742. 14688  *                              proc_name                                    *
  743. 14689  *===========================================================================*/
  744. 14690 PRIVATE char *proc_name(proc_nr)
  745. 14691 int proc_nr;
  746. 14692 {
  747. 14693   if (proc_nr == ANY) return "ANY";
  748. 14694   return proc_addr(proc_nr)->p_name;
  749. 14695 }
  750. .Ep 204 src/kernel/system.c
  751. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  752. src/kernel/system.c    
  753. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  754. 14700 /* This task handles the interface between file system and kernel as well as
  755. 14701  * between memory manager and kernel.  System services are obtained by sending
  756. 14702  * sys_task() a message specifying what is needed.  To make life easier for
  757. 14703  * MM and FS, a library is provided with routines whose names are of the
  758. 14704  * form sys_xxx, e.g. sys_xit sends the SYS_XIT message to sys_task.  The
  759. 14705  * message types and parameters are:
  760. 14706  *
  761. 14707  *   SYS_FORK    informs kernel that a process has forked
  762. 14708  *   SYS_NEWMAP  allows MM to set up a process memory map
  763. 14709  *   SYS_GETMAP  allows MM to get a process' memory map
  764. 14710  *   SYS_EXEC    sets program counter and stack pointer after EXEC
  765. 14711  *   SYS_XIT     informs kernel that a process has exited
  766. 14712  *   SYS_GETSP   caller wants to read out some process' stack pointer
  767. 14713  *   SYS_TIMES   caller wants to get accounting times for a process
  768. 14714  *   SYS_ABORT   MM or FS cannot go on; abort MINIX
  769. 14715  *   SYS_FRESH   start with a fresh process image during EXEC (68000 only)
  770. 14716  *   SYS_SENDSIG send a signal to a process (POSIX style)
  771. 14717  *   SYS_SIGRETURN complete POSIX-style signalling
  772. 14718  *   SYS_KILL    cause a signal to be sent via MM
  773. 14719  *   SYS_ENDSIG  finish up after SYS_KILL-type signal
  774. 14720  *   SYS_COPY    request a block of data to be copied between processes
  775. 14721  *   SYS_VCOPY   request a series of data blocks to be copied between procs
  776. 14722  *   SYS_GBOOT   copies the boot parameters to a process
  777. 14723  *   SYS_MEM     returns the next free chunk of physical memory
  778. 14724  *   SYS_UMAP    compute the physical address for a given virtual address
  779. 14725  *   SYS_TRACE   request a trace operation
  780. 14726  *
  781. 14727  * Message types and parameters:
  782. 14728  *
  783. 14729  *    m_type       PROC1     PROC2      PID     MEM_PTR
  784. 14730  * ------------------------------------------------------
  785. 14731  * | SYS_FORK   | parent  |  child  |   pid   |         |
  786. 14732  * |------------+---------+---------+---------+---------|
  787. 14733  * | SYS_NEWMAP | proc nr |         |         | map ptr |
  788. 14734  * |------------+---------+---------+---------+---------|
  789. 14735  * | SYS_EXEC   | proc nr | traced  | new sp  |         |
  790. 14736  * |------------+---------+---------+---------+---------|
  791. 14737  * | SYS_XIT    | parent  | exitee  |         |         |
  792. 14738  * |------------+---------+---------+---------+---------|
  793. 14739  * | SYS_GETSP  | proc nr |         |         |         |
  794. 14740  * |------------+---------+---------+---------+---------|
  795. 14741  * | SYS_TIMES  | proc nr |         | buf ptr |         |
  796. 14742  * |------------+---------+---------+---------+---------|
  797. 14743  * | SYS_ABORT  |         |         |         |         |
  798. 14744  * |------------+---------+---------+---------+---------|
  799. 14745  * | SYS_FRESH  | proc nr | data_cl |         |         |
  800. 14746  * |------------+---------+---------+---------+---------|
  801. 14747  * | SYS_GBOOT  | proc nr |         |         | bootptr |
  802. 14748  * |------------+---------+---------+---------+---------|
  803. 14749  * | SYS_GETMAP | proc nr |         |         | map ptr |
  804. 14750  * ------------------------------------------------------
  805. 14751  *
  806. 14752  *    m_type          m1_i1     m1_i2     m1_i3       m1_p1
  807. 14753  * ----------------+---------+---------+---------+--------------
  808. 14754  * | SYS_VCOPY     |  src p  |  dst p  | vec siz | vc addr     |
  809. .Op 205 src/kernel/system.c
  810. 14755  * |---------------+---------+---------+---------+-------------|
  811. 14756  * | SYS_SENDSIG   | proc nr |         |         | smp         |
  812. 14757  * |---------------+---------+---------+---------+-------------|
  813. 14758  * | SYS_SIGRETURN | proc nr |         |         | scp         |
  814. 14759  * |---------------+---------+---------+---------+-------------|
  815. 14760  * | SYS_ENDSIG    | proc nr |         |         |             |
  816. 14761  * -------------------------------------------------------------
  817. 14762  *
  818. 14763  *    m_type       m2_i1     m2_i2     m2_l1     m2_l2
  819. 14764  * ------------------------------------------------------
  820. 14765  * | SYS_TRACE  | proc_nr | request |  addr   |  data   |
  821. 14766  * ------------------------------------------------------
  822. 14767  *
  823. 14768  *
  824. 14769  *    m_type       m6_i1     m6_i2     m6_i3     m6_f1
  825. 14770  * ------------------------------------------------------
  826. 14771  * | SYS_KILL   | proc_nr  |  sig    |         |         |
  827. 14772  * ------------------------------------------------------
  828. 14773  *
  829. 14774  *
  830. 14775  *    m_type      m5_c1   m5_i1    m5_l1   m5_c2   m5_i2    m5_l2   m5_l3
  831. 14776  * --------------------------------------------------------------------------
  832. 14777  * | SYS_COPY   |src seg|src proc|src vir|dst seg|dst proc|dst vir| byte ct |
  833. 14778  * --------------------------------------------------------------------------
  834. 14779  * | SYS_UMAP   |  seg  |proc nr |vir adr|       |        |       | byte ct |
  835. 14780  * --------------------------------------------------------------------------
  836. 14781  *
  837. 14782  *
  838. 14783  *    m_type      m1_i1      m1_i2      m1_i3
  839. 14784  * |------------+----------+----------+----------
  840. 14785  * | SYS_MEM    | mem base | mem size | tot mem |
  841. 14786  * ----------------------------------------------
  842. 14787  *
  843. 14788  * In addition to the main sys_task() entry point, there are 5 other minor
  844. 14789  * entry points:
  845. 14790  *   cause_sig: take action to cause a signal to occur, sooner or later
  846. 14791  *   inform:    tell MM about pending signals
  847. 14792  *   numap:     umap D segment starting from process number instead of pointer
  848. 14793  *   umap:      compute the physical address for a given virtual address
  849. 14794  *   alloc_segments: allocate segments for 8088 or higher processor
  850. 14795  */
  851. 14796
  852. 14797 #include "kernel.h"
  853. 14798 #include <signal.h>
  854. 14799 #include <unistd.h>
  855. 14800 #include <sys/sigcontext.h>
  856. 14801 #include <sys/ptrace.h>
  857. 14802 #include <minix/boot.h>
  858. 14803 #include <minix/callnr.h>
  859. 14804 #include <minix/com.h>
  860. 14805 #include "proc.h"
  861. 14806 #include "protect.h"
  862. 14807
  863. 14808 /* PSW masks. */
  864. 14809 #define IF_MASK 0x00000200
  865. 14810 #define IOPL_MASK 0x003000
  866. 14811
  867. 14812 PRIVATE message m;
  868. 14813
  869. 14814 FORWARD _PROTOTYPE( int do_abort, (message *m_ptr) );
  870. .Ep 206 src/kernel/system.c
  871. 14815 FORWARD _PROTOTYPE( int do_copy, (message *m_ptr) );
  872. 14816 FORWARD _PROTOTYPE( int do_exec, (message *m_ptr) );
  873. 14817 FORWARD _PROTOTYPE( int do_fork, (message *m_ptr) );
  874. 14818 FORWARD _PROTOTYPE( int do_gboot, (message *m_ptr) );
  875. 14819 FORWARD _PROTOTYPE( int do_getsp, (message *m_ptr) );
  876. 14820 FORWARD _PROTOTYPE( int do_kill, (message *m_ptr) );
  877. 14821 FORWARD _PROTOTYPE( int do_mem, (message *m_ptr) );
  878. 14822 FORWARD _PROTOTYPE( int do_newmap, (message *m_ptr) );
  879. 14823 FORWARD _PROTOTYPE( int do_sendsig, (message *m_ptr) );
  880. 14824 FORWARD _PROTOTYPE( int do_sigreturn, (message *m_ptr) );
  881. 14825 FORWARD _PROTOTYPE( int do_endsig, (message *m_ptr) );
  882. 14826 FORWARD _PROTOTYPE( int do_times, (message *m_ptr) );
  883. 14827 FORWARD _PROTOTYPE( int do_trace, (message *m_ptr) );
  884. 14828 FORWARD _PROTOTYPE( int do_umap, (message *m_ptr) );
  885. 14829 FORWARD _PROTOTYPE( int do_xit, (message *m_ptr) );
  886. 14830 FORWARD _PROTOTYPE( int do_vcopy, (message *m_ptr) );
  887. 14831 FORWARD _PROTOTYPE( int do_getmap, (message *m_ptr) );
  888. 14832
  889. 14833
  890. 14834 /*===========================================================================*
  891. 14835  *                              sys_task                                     *
  892. 14836  *===========================================================================*/
  893. 14837 PUBLIC void sys_task()
  894. 14838 {
  895. 14839 /* Main entry point of sys_task.  Get the message and dispatch on type. */
  896. 14840
  897. 14841   register int r;
  898. 14842
  899. 14843   while (TRUE) {
  900. 14844         receive(ANY, &m);
  901. 14845
  902. 14846         switch (m.m_type) {     /* which system call */
  903. 14847             case SYS_FORK:      r = do_fork(&m);        break;
  904. 14848             case SYS_NEWMAP:    r = do_newmap(&m);      break;
  905. 14849             case SYS_GETMAP:    r = do_getmap(&m);      break;
  906. 14850             case SYS_EXEC:      r = do_exec(&m);        break;
  907. 14851             case SYS_XIT:       r = do_xit(&m);         break;
  908. 14852             case SYS_GETSP:     r = do_getsp(&m);       break;
  909. 14853             case SYS_TIMES:     r = do_times(&m);       break;
  910. 14854             case SYS_ABORT:     r = do_abort(&m);       break;
  911. 14855             case SYS_SENDSIG:   r = do_sendsig(&m);     break;
  912. 14856             case SYS_SIGRETURN: r = do_sigreturn(&m);   break;
  913. 14857             case SYS_KILL:      r = do_kill(&m);        break;
  914. 14858             case SYS_ENDSIG:    r = do_endsig(&m);      break;
  915. 14859             case SYS_COPY:      r = do_copy(&m);        break;
  916. 14860             case SYS_VCOPY:     r = do_vcopy(&m);       break;
  917. 14861             case SYS_GBOOT:     r = do_gboot(&m);       break;
  918. 14862             case SYS_MEM:       r = do_mem(&m);         break;
  919. 14863             case SYS_UMAP:      r = do_umap(&m);        break;
  920. 14864             case SYS_TRACE:     r = do_trace(&m);       break;
  921. 14865             default:            r = E_BAD_FCN;
  922. 14866         }
  923. 14867
  924. 14868         m.m_type = r;           /* 'r' reports status of call */
  925. 14869         send(m.m_source, &m);   /* send reply to caller */
  926. 14870   }
  927. 14871 }
  928. 14874 /*===========================================================================*
  929. .Op 207 src/kernel/system.c
  930. 14875  *                              do_fork                                      *
  931. 14876  *===========================================================================*/
  932. 14877 PRIVATE int do_fork(m_ptr)
  933. 14878 register message *m_ptr;        /* pointer to request message */
  934. 14879 {
  935. 14880 /* Handle sys_fork().  m_ptr->PROC1 has forked.  The child is m_ptr->PROC2. */
  936. 14881
  937. 14882   reg_t old_ldt_sel;
  938. 14883   register struct proc *rpc;
  939. 14884   struct proc *rpp;
  940. 14885
  941. 14886   if (!isoksusern(m_ptr->PROC1) || !isoksusern(m_ptr->PROC2))
  942. 14887         return(E_BAD_PROC);
  943. 14888   rpp = proc_addr(m_ptr->PROC1);
  944. 14889   rpc = proc_addr(m_ptr->PROC2);
  945. 14890
  946. 14891   /* Copy parent 'proc' struct to child. */
  947. 14892   old_ldt_sel = rpc->p_ldt_sel; /* stop this being obliterated by copy */
  948. 14893
  949. 14894   *rpc = *rpp;                  /* copy 'proc' struct */
  950. 14895
  951. 14896   rpc->p_ldt_sel = old_ldt_sel;
  952. 14897   rpc->p_nr = m_ptr->PROC2;     /* this was obliterated by copy */
  953. 14898
  954. 14899   rpc->p_flags |= NO_MAP;       /* inhibit the process from running */
  955. 14900
  956. 14901   rpc->p_flags &= ~(PENDING | SIG_PENDING | P_STOP);
  957. 14902
  958. 14903   /* Only 1 in group should have PENDING, child does not inherit trace status*/
  959. 14904   sigemptyset(&rpc->p_pending);
  960. 14905   rpc->p_pendcount = 0;
  961. 14906   rpc->p_pid = m_ptr->PID;      /* install child's pid */
  962. 14907   rpc->p_reg.retreg = 0;        /* child sees pid = 0 to know it is child */
  963. 14908
  964. 14909   rpc->user_time = 0;           /* set all the accounting times to 0 */
  965. 14910   rpc->sys_time = 0;
  966. 14911   rpc->child_utime = 0;
  967. 14912   rpc->child_stime = 0;
  968. 14913
  969. 14914   return(OK);
  970. 14915 }
  971. 14918 /*===========================================================================*
  972. 14919  *                              do_newmap                                    *
  973. 14920  *===========================================================================*/
  974. 14921 PRIVATE int do_newmap(m_ptr)
  975. 14922 message *m_ptr;                 /* pointer to request message */
  976. 14923 {
  977. 14924 /* Handle sys_newmap().  Fetch the memory map from MM. */
  978. 14925
  979. 14926   register struct proc *rp;
  980. 14927   phys_bytes src_phys;
  981. 14928   int caller;                   /* whose space has the new map (usually MM) */
  982. 14929   int k;                        /* process whose map is to be loaded */
  983. 14930   int old_flags;                /* value of flags before modification */
  984. 14931   struct mem_map *map_ptr;      /* virtual address of map inside caller (MM) */
  985. 14932
  986. 14933   /* Extract message parameters and copy new memory map from MM. */
  987. 14934   caller = m_ptr->m_source;
  988. .Ep 208 src/kernel/system.c
  989. 14935   k = m_ptr->PROC1;
  990. 14936   map_ptr = (struct mem_map *) m_ptr->MEM_PTR;
  991. 14937   if (!isokprocn(k)) return(E_BAD_PROC);
  992. 14938   rp = proc_addr(k);            /* ptr to entry of user getting new map */
  993. 14939
  994. 14940   /* Copy the map from MM. */
  995. 14941   src_phys = umap(proc_addr(caller), D, (vir_bytes) map_ptr, sizeof(rp->p_map));
  996. 14942   if (src_phys == 0) panic("bad call to sys_newmap", NO_NUM);
  997. 14943   phys_copy(src_phys, vir2phys(rp->p_map), (phys_bytes) sizeof(rp->p_map));
  998. 14944
  999. 14945   alloc_segments(rp);
  1000. 14946   old_flags = rp->p_flags;      /* save the previous value of the flags */
  1001. 14947   rp->p_flags &= ~NO_MAP;
  1002. 14948   if (old_flags != 0 && rp->p_flags == 0) lock_ready(rp);
  1003. 14949
  1004. 14950   return(OK);
  1005. 14951 }
  1006. 14954 /*===========================================================================*
  1007. 14955  *                              do_getmap                                    *
  1008. 14956  *===========================================================================*/
  1009. 14957 PRIVATE int do_getmap(m_ptr)
  1010. 14958 message *m_ptr;                 /* pointer to request message */
  1011. 14959 {
  1012. 14960 /* Handle sys_getmap().  Report the memory map to MM. */
  1013. 14961
  1014. 14962   register struct proc *rp;
  1015. 14963   phys_bytes dst_phys;
  1016. 14964   int caller;                   /* where the map has to be stored */
  1017. 14965   int k;                        /* process whose map is to be loaded */
  1018. 14966   struct mem_map *map_ptr;      /* virtual address of map inside caller (MM) */
  1019. 14967
  1020. 14968   /* Extract message parameters and copy new memory map to MM. */
  1021. 14969   caller = m_ptr->m_source;
  1022. 14970   k = m_ptr->PROC1;
  1023. 14971   map_ptr = (struct mem_map *) m_ptr->MEM_PTR;
  1024. 14972
  1025. 14973   if (!isokprocn(k))
  1026. 14974         panic("do_getmap got bad proc: ", m_ptr->PROC1);
  1027. 14975
  1028. 14976   rp = proc_addr(k);            /* ptr to entry of the map */
  1029. 14977
  1030. 14978   /* Copy the map to MM. */
  1031. 14979   dst_phys = umap(proc_addr(caller), D, (vir_bytes) map_ptr, sizeof(rp->p_map));
  1032. 14980   if (dst_phys == 0) panic("bad call to sys_getmap", NO_NUM);
  1033. 14981   phys_copy(vir2phys(rp->p_map), dst_phys, sizeof(rp->p_map));
  1034. 14982
  1035. 14983   return(OK);
  1036. 14984 }
  1037. 14987 /*===========================================================================*
  1038. 14988  *                              do_exec                                      *
  1039. 14989  *===========================================================================*/
  1040. 14990 PRIVATE int do_exec(m_ptr)
  1041. 14991 register message *m_ptr;        /* pointer to request message */
  1042. 14992 {
  1043. 14993 /* Handle sys_exec().  A process has done a successful EXEC. Patch it up. */
  1044. 14994
  1045. .Op 209 src/kernel/system.c
  1046. 14995   register struct proc *rp;
  1047. 14996   reg_t sp;                     /* new sp */
  1048. 14997   phys_bytes phys_name;
  1049. 14998   char *np;
  1050. 14999 #define NLEN (sizeof(rp->p_name)-1)
  1051. 15000
  1052. 15001   if (!isoksusern(m_ptr->PROC1)) return E_BAD_PROC;
  1053. 15002   /* PROC2 field is used as flag to indicate process is being traced */
  1054. 15003   if (m_ptr->PROC2) cause_sig(m_ptr->PROC1, SIGTRAP);
  1055. 15004   sp = (reg_t) m_ptr->STACK_PTR;
  1056. 15005   rp = proc_addr(m_ptr->PROC1);
  1057. 15006   rp->p_reg.sp = sp;            /* set the stack pointer */
  1058. 15007   rp->p_reg.pc = (reg_t) m_ptr->IP_PTR; /* set pc */
  1059. 15008   rp->p_alarm = 0;              /* reset alarm timer */
  1060. 15009   rp->p_flags &= ~RECEIVING;    /* MM does not reply to EXEC call */
  1061. 15010   if (rp->p_flags == 0) lock_ready(rp);
  1062. 15011
  1063. 15012   /* Save command name for debugging, ps(1) output, etc. */
  1064. 15013   phys_name = numap(m_ptr->m_source, (vir_bytes) m_ptr->NAME_PTR,
  1065. 15014                                                         (vir_bytes) NLEN);
  1066. 15015   if (phys_name != 0) {
  1067. 15016         phys_copy(phys_name, vir2phys(rp->p_name), (phys_bytes) NLEN);
  1068. 15017         for (np = rp->p_name; (*np & BYTE) >= ' '; np++) {}
  1069. 15018         *np = 0;
  1070. 15019   }
  1071. 15020   return(OK);
  1072. 15021 }
  1073. 15024 /*===========================================================================*
  1074. 15025  *                              do_xit                                       *
  1075. 15026  *===========================================================================*/
  1076. 15027 PRIVATE int do_xit(m_ptr)
  1077. 15028 message *m_ptr;                 /* pointer to request message */
  1078. 15029 {
  1079. 15030 /* Handle sys_xit().  A process has exited. */
  1080. 15031
  1081. 15032   register struct proc *rp, *rc;
  1082. 15033   struct proc *np, *xp;
  1083. 15034   int parent;                   /* number of exiting proc's parent */
  1084. 15035   int proc_nr;                  /* number of process doing the exit */
  1085. 15036   phys_clicks base, size;
  1086. 15037
  1087. 15038   parent = m_ptr->PROC1;        /* slot number of parent process */
  1088. 15039   proc_nr = m_ptr->PROC2;       /* slot number of exiting process */
  1089. 15040   if (!isoksusern(parent) || !isoksusern(proc_nr)) return(E_BAD_PROC);
  1090. 15041   rp = proc_addr(parent);
  1091. 15042   rc = proc_addr(proc_nr);
  1092. 15043   lock();
  1093. 15044   rp->child_utime += rc->user_time + rc->child_utime;   /* accum child times */
  1094. 15045   rp->child_stime += rc->sys_time + rc->child_stime;
  1095. 15046   unlock();
  1096. 15047   rc->p_alarm = 0;              /* turn off alarm timer */
  1097. 15048   if (rc->p_flags == 0) lock_unready(rc);
  1098. 15049
  1099. 15050   strcpy(rc->p_name, "<noname>");       /* process no longer has a name */
  1100. 15051
  1101. 15052   /* If the process being terminated happens to be queued trying to send a
  1102. 15053    * message (i.e., the process was killed by a signal, rather than it doing an
  1103. 15054    * EXIT), then it must be removed from the message queues.
  1104. .Ep 210 src/kernel/system.c
  1105. 15055    */
  1106. 15056   if (rc->p_flags & SENDING) {
  1107. 15057         /* Check all proc slots to see if the exiting process is queued. */
  1108. 15058         for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) {
  1109. 15059                 if (rp->p_callerq == NIL_PROC) continue;
  1110. 15060                 if (rp->p_callerq == rc) {
  1111. 15061                         /* Exiting process is on front of this queue. */
  1112. 15062                         rp->p_callerq = rc->p_sendlink;
  1113. 15063                         break;
  1114. 15064                 } else {
  1115. 15065                         /* See if exiting process is in middle of queue. */
  1116. 15066                         np = rp->p_callerq;
  1117. 15067                         while ( ( xp = np->p_sendlink) != NIL_PROC)
  1118. 15068                                 if (xp == rc) {
  1119. 15069                                         np->p_sendlink = xp->p_sendlink;
  1120. 15070                                         break;
  1121. 15071                                 } else {
  1122. 15072                                         np = xp;
  1123. 15073                                 }
  1124. 15074                 }
  1125. 15075         }
  1126. 15076   }
  1127. 15077
  1128. 15078   if (rc->p_flags & PENDING) --sig_procs;
  1129. 15079   sigemptyset(&rc->p_pending);
  1130. 15080   rc->p_pendcount = 0;
  1131. 15081   rc->p_flags = P_SLOT_FREE;
  1132. 15082   return(OK);
  1133. 15083 }
  1134. 15086 /*===========================================================================*
  1135. 15087  *                              do_getsp                                     *
  1136. 15088  *===========================================================================*/
  1137. 15089 PRIVATE int do_getsp(m_ptr)
  1138. 15090 register message *m_ptr;        /* pointer to request message */
  1139. 15091 {
  1140. 15092 /* Handle sys_getsp().  MM wants to know what sp is. */
  1141. 15093
  1142. 15094   register struct proc *rp;
  1143. 15095
  1144. 15096   if (!isoksusern(m_ptr->PROC1)) return(E_BAD_PROC);
  1145. 15097   rp = proc_addr(m_ptr->PROC1);
  1146. 15098   m_ptr->STACK_PTR = (char *) rp->p_reg.sp;     /* return sp here (bad type) */
  1147. 15099   return(OK);
  1148. 15100 }
  1149. 15103 /*===========================================================================*
  1150. 15104  *                              do_times                                     *
  1151. 15105  *===========================================================================*/
  1152. 15106 PRIVATE int do_times(m_ptr)
  1153. 15107 register message *m_ptr;        /* pointer to request message */
  1154. 15108 {
  1155. 15109 /* Handle sys_times().  Retrieve the accounting information. */
  1156. 15110
  1157. 15111   register struct proc *rp;
  1158. 15112
  1159. 15113   if (!isoksusern(m_ptr->PROC1)) return E_BAD_PROC;
  1160. 15114   rp = proc_addr(m_ptr->PROC1);
  1161. .Op 211 src/kernel/system.c
  1162. 15115
  1163. 15116   /* Insert the times needed by the TIMES system call in the message. */
  1164. 15117   lock();                       /* halt the volatile time counters in rp */
  1165. 15118   m_ptr->USER_TIME   = rp->user_time;
  1166. 15119   m_ptr->SYSTEM_TIME = rp->sys_time;
  1167. 15120   unlock();
  1168. 15121   m_ptr->CHILD_UTIME = rp->child_utime;
  1169. 15122   m_ptr->CHILD_STIME = rp->child_stime;
  1170. 15123   m_ptr->BOOT_TICKS  = get_uptime();
  1171. 15124   return(OK);
  1172. 15125 }
  1173. 15128 /*===========================================================================*
  1174. 15129  *                              do_abort                                     *
  1175. 15130  *===========================================================================*/
  1176. 15131 PRIVATE int do_abort(m_ptr)
  1177. 15132 message *m_ptr;                 /* pointer to request message */
  1178. 15133 {
  1179. 15134 /* Handle sys_abort.  MINIX is unable to continue.  Terminate operation. */
  1180. 15135   char monitor_code[64];
  1181. 15136   phys_bytes src_phys;
  1182. 15137
  1183. 15138   if (m_ptr->m1_i1 == RBT_MONITOR) {
  1184. 15139         /* The monitor is to run user specified instructions. */
  1185. 15140         src_phys = numap(m_ptr->m_source, (vir_bytes) m_ptr->m1_p1,
  1186. 15141                                         (vir_bytes) sizeof(monitor_code));
  1187. 15142         if (src_phys == 0) panic("bad monitor code from", m_ptr->m_source);
  1188. 15143         phys_copy(src_phys, vir2phys(monitor_code),
  1189. 15144                                         (phys_bytes) sizeof(monitor_code));
  1190. 15145         reboot_code = vir2phys(monitor_code);
  1191. 15146   }
  1192. 15147   wreboot(m_ptr->m1_i1);
  1193. 15148   return(OK);                   /* pro-forma (really EDISASTER) */
  1194. 15149 }
  1195. 15154 /*===========================================================================*
  1196. 15155  *                            do_sendsig                                     *
  1197. 15156  *===========================================================================*/
  1198. 15157 PRIVATE int do_sendsig(m_ptr)
  1199. 15158 message *m_ptr;                 /* pointer to request message */
  1200. 15159 {
  1201. 15160 /* Handle sys_sendsig, POSIX-style signal */
  1202. 15161
  1203. 15162   struct sigmsg smsg;
  1204. 15163   register struct proc *rp;
  1205. 15164   phys_bytes src_phys, dst_phys;
  1206. 15165   struct sigcontext sc, *scp;
  1207. 15166   struct sigframe fr, *frp;
  1208. 15167
  1209. 15168   if (!isokusern(m_ptr->PROC1)) return(E_BAD_PROC);
  1210. 15169   rp = proc_addr(m_ptr->PROC1);
  1211. 15170
  1212. 15171   /* Get the sigmsg structure into our address space.  */
  1213. 15172   src_phys = umap(proc_addr(MM_PROC_NR), D, (vir_bytes) m_ptr->SIG_CTXT_PTR,
  1214. 15173                   (vir_bytes) sizeof(struct sigmsg));
  1215. 15174   if (src_phys == 0)
  1216. .Ep 212 src/kernel/system.c
  1217. 15175         panic("do_sendsig can't signal: bad sigmsg address from MM", NO_NUM);
  1218. 15176   phys_copy(src_phys, vir2phys(&smsg), (phys_bytes) sizeof(struct sigmsg));
  1219. 15177
  1220. 15178   /* Compute the usr stack pointer value where sigcontext will be stored. */
  1221. 15179   scp = (struct sigcontext *) smsg.sm_stkptr - 1;
  1222. 15180
  1223. 15181   /* Copy the registers to the sigcontext structure. */
  1224. 15182   memcpy(&sc.sc_regs, &rp->p_reg, sizeof(struct sigregs));
  1225. 15183
  1226. 15184   /* Finish the sigcontext initialization. */
  1227. 15185   sc.sc_flags = SC_SIGCONTEXT;
  1228. 15186
  1229. 15187   sc.sc_mask = smsg.sm_mask;
  1230. 15188
  1231. 15189   /* Copy the sigcontext structure to the user's stack. */
  1232. 15190   dst_phys = umap(rp, D, (vir_bytes) scp,
  1233. 15191                   (vir_bytes) sizeof(struct sigcontext));
  1234. 15192   if (dst_phys == 0) return(EFAULT);
  1235. 15193   phys_copy(vir2phys(&sc), dst_phys, (phys_bytes) sizeof(struct sigcontext));
  1236. 15194
  1237. 15195   /* Initialize the sigframe structure. */
  1238. 15196   frp = (struct sigframe *) scp - 1;
  1239. 15197   fr.sf_scpcopy = scp;
  1240. 15198   fr.sf_retadr2= (void (*)()) rp->p_reg.pc;
  1241. 15199   fr.sf_fp = rp->p_reg.fp;
  1242. 15200   rp->p_reg.fp = (reg_t) &frp->sf_fp;
  1243. 15201   fr.sf_scp = scp;
  1244. 15202   fr.sf_code = 0;       /* XXX - should be used for type of FP exception */
  1245. 15203   fr.sf_signo = smsg.sm_signo;
  1246. 15204   fr.sf_retadr = (void (*)()) smsg.sm_sigreturn;
  1247. 15205
  1248. 15206   /* Copy the sigframe structure to the user's stack. */
  1249. 15207   dst_phys = umap(rp, D, (vir_bytes) frp, (vir_bytes) sizeof(struct sigframe));
  1250. 15208   if (dst_phys == 0) return(EFAULT);
  1251. 15209   phys_copy(vir2phys(&fr), dst_phys, (phys_bytes) sizeof(struct sigframe));
  1252. 15210
  1253. 15211   /* Reset user registers to execute the signal handler. */
  1254. 15212   rp->p_reg.sp = (reg_t) frp;
  1255. 15213   rp->p_reg.pc = (reg_t) smsg.sm_sighandler;
  1256. 15214
  1257. 15215   return(OK);
  1258. 15216 }
  1259. 15218 /*===========================================================================*
  1260. 15219  *                            do_sigreturn                                   *
  1261. 15220  *===========================================================================*/
  1262. 15221 PRIVATE int do_sigreturn(m_ptr)
  1263. 15222 register message *m_ptr;
  1264. 15223 {
  1265. 15224 /* POSIX style signals require sys_sigreturn to put things in order before the
  1266. 15225  * signalled process can resume execution
  1267. 15226  */
  1268. 15227
  1269. 15228   struct sigcontext sc;
  1270. 15229   register struct proc *rp;
  1271. 15230   phys_bytes src_phys;
  1272. 15231
  1273. 15232   if (!isokusern(m_ptr->PROC1)) return(E_BAD_PROC);
  1274. 15233   rp = proc_addr(m_ptr->PROC1);
  1275. 15234
  1276. .Op 213 src/kernel/system.c
  1277. 15235   /* Copy in the sigcontext structure. */
  1278. 15236   src_phys = umap(rp, D, (vir_bytes) m_ptr->SIG_CTXT_PTR,
  1279. 15237                   (vir_bytes) sizeof(struct sigcontext));
  1280. 15238   if (src_phys == 0) return(EFAULT);
  1281. 15239   phys_copy(src_phys, vir2phys(&sc), (phys_bytes) sizeof(struct sigcontext));
  1282. 15240
  1283. 15241   /* Make sure that this is not just a jmp_buf. */
  1284. 15242   if ((sc.sc_flags & SC_SIGCONTEXT) == 0) return(EINVAL);
  1285. 15243
  1286. 15244   /* Fix up only certain key registers if the compiler doesn't use
  1287. 15245    * register variables within functions containing setjmp.
  1288. 15246    */
  1289. 15247   if (sc.sc_flags & SC_NOREGLOCALS) {
  1290. 15248         rp->p_reg.retreg = sc.sc_retreg;
  1291. 15249         rp->p_reg.fp = sc.sc_fp;
  1292. 15250         rp->p_reg.pc = sc.sc_pc;
  1293. 15251         rp->p_reg.sp = sc.sc_sp;
  1294. 15252         return (OK);
  1295. 15253   }
  1296. 15254   sc.sc_psw  = rp->p_reg.psw;
  1297. 15255
  1298. 15256 #if (CHIP == INTEL)
  1299. 15257   /* Don't panic kernel if user gave bad selectors. */
  1300. 15258   sc.sc_cs = rp->p_reg.cs;
  1301. 15259   sc.sc_ds = rp->p_reg.ds;
  1302. 15260   sc.sc_es = rp->p_reg.es;
  1303. 15261 #if _WORD_SIZE == 4
  1304. 15262   sc.sc_fs = rp->p_reg.fs;
  1305. 15263   sc.sc_gs = rp->p_reg.gs;
  1306. 15264 #endif
  1307. 15265 #endif
  1308. 15266
  1309. 15267   /* Restore the registers. */
  1310. 15268   memcpy(&rp->p_reg, (char *)&sc.sc_regs, sizeof(struct sigregs));
  1311. 15269
  1312. 15270   return(OK);
  1313. 15271 }
  1314. 15273 /*===========================================================================*
  1315. 15274  *                              do_kill                                      *
  1316. 15275  *===========================================================================*/
  1317. 15276 PRIVATE int do_kill(m_ptr)
  1318. 15277 register message *m_ptr;        /* pointer to request message */
  1319. 15278 {
  1320. 15279 /* Handle sys_kill(). Cause a signal to be sent to a process via MM.
  1321. 15280  * Note that this has nothing to do with the kill (2) system call, this
  1322. 15281  * is how the FS (and possibly other servers) get access to cause_sig to
  1323. 15282  * send a KSIG message to MM
  1324. 15283  */
  1325. 15284
  1326. 15285   if (!isokusern(m_ptr->PR)) return(E_BAD_PROC);
  1327. 15286   cause_sig(m_ptr->PR, m_ptr->SIGNUM);
  1328. 15287   return(OK);
  1329. 15288 }
  1330. 15291 /*===========================================================================*
  1331. 15292  *                            do_endsig                                      *
  1332. 15293  *===========================================================================*/
  1333. 15294 PRIVATE int do_endsig(m_ptr)
  1334. .Ep 214 src/kernel/system.c
  1335. 15295 register message *m_ptr;        /* pointer to request message */
  1336. 15296 {
  1337. 15297 /* Finish up after a KSIG-type signal, caused by a SYS_KILL message or a call
  1338. 15298  * to cause_sig by a task
  1339. 15299  */
  1340. 15300
  1341. 15301   register struct proc *rp;
  1342. 15302
  1343. 15303   if (!isokusern(m_ptr->PROC1)) return(E_BAD_PROC);
  1344. 15304   rp = proc_addr(m_ptr->PROC1);
  1345. 15305
  1346. 15306   /* MM has finished one KSIG. */
  1347. 15307   if (rp->p_pendcount != 0 && --rp->p_pendcount == 0
  1348. 15308       && (rp->p_flags &= ~SIG_PENDING) == 0)
  1349. 15309         lock_ready(rp);
  1350. 15310   return(OK);
  1351. 15311 }
  1352. 15313 /*===========================================================================*
  1353. 15314  *                              do_copy                                      *
  1354. 15315  *===========================================================================*/
  1355. 15316 PRIVATE int do_copy(m_ptr)
  1356. 15317 register message *m_ptr;        /* pointer to request message */
  1357. 15318 {
  1358. 15319 /* Handle sys_copy().  Copy data for MM or FS. */
  1359. 15320
  1360. 15321   int src_proc, dst_proc, src_space, dst_space;
  1361. 15322   vir_bytes src_vir, dst_vir;
  1362. 15323   phys_bytes src_phys, dst_phys, bytes;
  1363. 15324
  1364. 15325   /* Dismember the command message. */
  1365. 15326   src_proc = m_ptr->SRC_PROC_NR;
  1366. 15327   dst_proc = m_ptr->DST_PROC_NR;
  1367. 15328   src_space = m_ptr->SRC_SPACE;
  1368. 15329   dst_space = m_ptr->DST_SPACE;
  1369. 15330   src_vir = (vir_bytes) m_ptr->SRC_BUFFER;
  1370. 15331   dst_vir = (vir_bytes) m_ptr->DST_BUFFER;
  1371. 15332   bytes = (phys_bytes) m_ptr->COPY_BYTES;
  1372. 15333
  1373. 15334   /* Compute the source and destination addresses and do the copy. */
  1374. 15335   if (src_proc == ABS)
  1375. 15336         src_phys = (phys_bytes) m_ptr->SRC_BUFFER;
  1376. 15337   else {
  1377. 15338         if (bytes != (vir_bytes) bytes)
  1378. 15339                 /* This would happen for 64K segments and 16-bit vir_bytes.
  1379. 15340                  * It would happen a lot for do_fork except MM uses ABS
  1380. 15341                  * copies for that case.
  1381. 15342                  */
  1382. 15343                 panic("overflow in count in do_copy", NO_NUM);
  1383. 15344
  1384. 15345         src_phys = umap(proc_addr(src_proc), src_space, src_vir,
  1385. 15346                         (vir_bytes) bytes);
  1386. 15347         }
  1387. 15348
  1388. 15349   if (dst_proc == ABS)
  1389. 15350         dst_phys = (phys_bytes) m_ptr->DST_BUFFER;
  1390. 15351   else
  1391. 15352         dst_phys = umap(proc_addr(dst_proc), dst_space, dst_vir,
  1392. 15353                         (vir_bytes) bytes);
  1393. 15354
  1394. .Op 215 src/kernel/system.c
  1395. 15355   if (src_phys == 0 || dst_phys == 0) return(EFAULT);
  1396. 15356   phys_copy(src_phys, dst_phys, bytes);
  1397. 15357   return(OK);
  1398. 15358 }
  1399. 15361 /*===========================================================================*
  1400. 15362  *                              do_vcopy                                     *
  1401. 15363  *===========================================================================*/
  1402. 15364 PRIVATE int do_vcopy(m_ptr)
  1403. 15365 register message *m_ptr;        /* pointer to request message */
  1404. 15366 {
  1405. 15367 /* Handle sys_vcopy(). Copy multiple blocks of memory */
  1406. 15368
  1407. 15369   int src_proc, dst_proc, vect_s, i;
  1408. 15370   vir_bytes src_vir, dst_vir, vect_addr;
  1409. 15371   phys_bytes src_phys, dst_phys, bytes;
  1410. 15372   cpvec_t cpvec_table[CPVEC_NR];
  1411. 15373
  1412. 15374   /* Dismember the command message. */
  1413. 15375   src_proc = m_ptr->m1_i1;
  1414. 15376   dst_proc = m_ptr->m1_i2;
  1415. 15377   vect_s = m_ptr->m1_i3;
  1416. 15378   vect_addr = (vir_bytes)m_ptr->m1_p1;
  1417. 15379
  1418. 15380   if (vect_s > CPVEC_NR) return EDOM;
  1419. 15381
  1420. 15382   src_phys= numap (m_ptr->m_source, vect_addr, vect_s * sizeof(cpvec_t));
  1421. 15383   if (!src_phys) return EFAULT;
  1422. 15384   phys_copy(src_phys, vir2phys(cpvec_table),
  1423. 15385                                 (phys_bytes) (vect_s * sizeof(cpvec_t)));
  1424. 15386
  1425. 15387   for (i = 0; i < vect_s; i++) {
  1426. 15388         src_vir= cpvec_table[i].cpv_src;
  1427. 15389         dst_vir= cpvec_table[i].cpv_dst;
  1428. 15390         bytes= cpvec_table[i].cpv_size;
  1429. 15391         src_phys = numap(src_proc,src_vir,(vir_bytes)bytes);
  1430. 15392         dst_phys = numap(dst_proc,dst_vir,(vir_bytes)bytes);
  1431. 15393         if (src_phys == 0 || dst_phys == 0) return(EFAULT);
  1432. 15394         phys_copy(src_phys, dst_phys, bytes);
  1433. 15395   }
  1434. 15396   return(OK);
  1435. 15397 }
  1436. 15400 /*==========================================================================*
  1437. 15401  *                              do_gboot                                    *
  1438. 15402  *==========================================================================*/
  1439. 15403 PUBLIC struct bparam_s boot_parameters;
  1440. 15404
  1441. 15405 PRIVATE int do_gboot(m_ptr)
  1442. 15406 message *m_ptr;                 /* pointer to request message */
  1443. 15407 {
  1444. 15408 /* Copy the boot parameters.  Normally only called during fs init. */
  1445. 15409
  1446. 15410   phys_bytes dst_phys;
  1447. 15411
  1448. 15412   dst_phys = umap(proc_addr(m_ptr->PROC1), D, (vir_bytes) m_ptr->MEM_PTR,
  1449. 15413                                 (vir_bytes) sizeof(boot_parameters));
  1450. 15414   if (dst_phys == 0) panic("bad call to SYS_GBOOT", NO_NUM);
  1451. .Ep 216 src/kernel/system.c
  1452. 15415   phys_copy(vir2phys(&boot_parameters), dst_phys,
  1453. 15416                                 (phys_bytes) sizeof(boot_parameters));
  1454. 15417   return(OK);
  1455. 15418 }
  1456. 15421 /*===========================================================================*
  1457. 15422  *                              do_mem                                       *
  1458. 15423  *===========================================================================*/
  1459. 15424 PRIVATE int do_mem(m_ptr)
  1460. 15425 register message *m_ptr;        /* pointer to request message */
  1461. 15426 {
  1462. 15427 /* Return the base and size of the next chunk of memory. */
  1463. 15428
  1464. 15429   struct memory *memp;
  1465. 15430
  1466. 15431   for (memp = mem; memp < &mem[NR_MEMS]; ++memp) {
  1467. 15432         m_ptr->m1_i1 = memp->base;
  1468. 15433         m_ptr->m1_i2 = memp->size;
  1469. 15434         m_ptr->m1_i3 = tot_mem_size;
  1470. 15435         memp->size = 0;
  1471. 15436         if (m_ptr->m1_i2 != 0) break;           /* found a chunk */
  1472. 15437   }
  1473. 15438   return(OK);
  1474. 15439 }
  1475. 15442 /*==========================================================================*
  1476. 15443  *                              do_umap                                     *
  1477. 15444  *==========================================================================*/
  1478. 15445 PRIVATE int do_umap(m_ptr)
  1479. 15446 register message *m_ptr;        /* pointer to request message */
  1480. 15447 {
  1481. 15448 /* Same as umap(), for non-kernel processes. */
  1482. 15449
  1483. 15450   m_ptr->SRC_BUFFER = umap(proc_addr((int) m_ptr->SRC_PROC_NR),
  1484. 15451                            (int) m_ptr->SRC_SPACE,
  1485. 15452                            (vir_bytes) m_ptr->SRC_BUFFER,
  1486. 15453                            (vir_bytes) m_ptr->COPY_BYTES);
  1487. 15454   return(OK);
  1488. 15455 }
  1489. 15458 /*==========================================================================*
  1490. 15459  *                              do_trace                                    *
  1491. 15460  *==========================================================================*/
  1492. 15461 #define TR_PROCNR       (m_ptr->m2_i1)
  1493. 15462 #define TR_REQUEST      (m_ptr->m2_i2)
  1494. 15463 #define TR_ADDR         ((vir_bytes) m_ptr->m2_l1)
  1495. 15464 #define TR_DATA         (m_ptr->m2_l2)
  1496. 15465 #define TR_VLSIZE       ((vir_bytes) sizeof(long))
  1497. 15466
  1498. 15467 PRIVATE int do_trace(m_ptr)
  1499. 15468 register message *m_ptr;
  1500. 15469 {
  1501. 15470 /* Handle the debugging commands supported by the ptrace system call
  1502. 15471  * The commands are:
  1503. 15472  * T_STOP       stop the process
  1504. 15473  * T_OK         enable tracing by parent for this process
  1505. 15474  * T_GETINS     return value from instruction space
  1506. .Op 217 src/kernel/system.c
  1507. 15475  * T_GETDATA    return value from data space
  1508. 15476  * T_GETUSER    return value from user process table
  1509. 15477  * T_SETINS     set value from instruction space
  1510. 15478  * T_SETDATA    set value from data space
  1511. 15479  * T_SETUSER    set value in user process table
  1512. 15480  * T_RESUME     resume execution
  1513. 15481  * T_EXIT       exit
  1514. 15482  * T_STEP       set trace bit
  1515. 15483  *
  1516. 15484  * The T_OK and T_EXIT commands are handled completely by the memory manager,
  1517. 15485  * all others come here.
  1518. 15486  */
  1519. 15487
  1520. 15488   register struct proc *rp;
  1521. 15489   phys_bytes src, dst;
  1522. 15490   int i;
  1523. 15491
  1524. 15492   rp = proc_addr(TR_PROCNR);
  1525. 15493   if (rp->p_flags & P_SLOT_FREE) return(EIO);
  1526. 15494   switch (TR_REQUEST) {
  1527. 15495   case T_STOP:                  /* stop process */
  1528. 15496         if (rp->p_flags == 0) lock_unready(rp);
  1529. 15497         rp->p_flags |= P_STOP;
  1530. 15498         rp->p_reg.psw &= ~TRACEBIT;     /* clear trace bit */
  1531. 15499         return(OK);
  1532. 15500
  1533. 15501   case T_GETINS:                /* return value from instruction space */
  1534. 15502         if (rp->p_map[T].mem_len != 0) {
  1535. 15503                 if ((src = umap(rp, T, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
  1536. 15504                 phys_copy(src, vir2phys(&TR_DATA), (phys_bytes) sizeof(long));
  1537. 15505                 break;
  1538. 15506         }
  1539. 15507         /* Text space is actually data space - fall through. */
  1540. 15508
  1541. 15509   case T_GETDATA:               /* return value from data space */
  1542. 15510         if ((src = umap(rp, D, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
  1543. 15511         phys_copy(src, vir2phys(&TR_DATA), (phys_bytes) sizeof(long));
  1544. 15512         break;
  1545. 15513
  1546. 15514   case T_GETUSER:               /* return value from process table */
  1547. 15515         if ((TR_ADDR & (sizeof(long) - 1)) != 0 ||
  1548. 15516             TR_ADDR > sizeof(struct proc) - sizeof(long))
  1549. 15517                 return(EIO);
  1550. 15518         TR_DATA = *(long *) ((char *) rp + (int) TR_ADDR);
  1551. 15519         break;
  1552. 15520
  1553. 15521   case T_SETINS:                /* set value in instruction space */
  1554. 15522         if (rp->p_map[T].mem_len != 0) {
  1555. 15523                 if ((dst = umap(rp, T, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
  1556. 15524                 phys_copy(vir2phys(&TR_DATA), dst, (phys_bytes) sizeof(long));
  1557. 15525                 TR_DATA = 0;
  1558. 15526                 break;
  1559. 15527         }
  1560. 15528         /* Text space is actually data space - fall through. */
  1561. 15529
  1562. 15530   case T_SETDATA:                       /* set value in data space */
  1563. 15531         if ((dst = umap(rp, D, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
  1564. 15532         phys_copy(vir2phys(&TR_DATA), dst, (phys_bytes) sizeof(long));
  1565. 15533         TR_DATA = 0;
  1566. 15534         break;
  1567. .Ep 218 src/kernel/system.c
  1568. 15535
  1569. 15536   case T_SETUSER:                       /* set value in process table */
  1570. 15537         if ((TR_ADDR & (sizeof(reg_t) - 1)) != 0 ||
  1571. 15538              TR_ADDR > sizeof(struct stackframe_s) - sizeof(reg_t))
  1572. 15539                 return(EIO);
  1573. 15540         i = (int) TR_ADDR;
  1574. 15541 #if (CHIP == INTEL)
  1575. 15542         /* Altering segment registers might crash the kernel when it
  1576. 15543          * tries to load them prior to restarting a process, so do
  1577. 15544          * not allow it.
  1578. 15545          */
  1579. 15546         if (i == (int) &((struct proc *) 0)->p_reg.cs ||
  1580. 15547             i == (int) &((struct proc *) 0)->p_reg.ds ||
  1581. 15548             i == (int) &((struct proc *) 0)->p_reg.es ||
  1582. 15549 #if _WORD_SIZE == 4
  1583. 15550             i == (int) &((struct proc *) 0)->p_reg.gs ||
  1584. 15551             i == (int) &((struct proc *) 0)->p_reg.fs ||
  1585. 15552 #endif
  1586. 15553             i == (int) &((struct proc *) 0)->p_reg.ss)
  1587. 15554                 return(EIO);
  1588. 15555 #endif
  1589. 15556         if (i == (int) &((struct proc *) 0)->p_reg.psw)
  1590. 15557                 /* only selected bits are changeable */
  1591. 15558                 SETPSW(rp, TR_DATA);
  1592. 15559         else
  1593. 15560                 *(reg_t *) ((char *) &rp->p_reg + i) = (reg_t) TR_DATA;
  1594. 15561         TR_DATA = 0;
  1595. 15562         break;
  1596. 15563
  1597. 15564   case T_RESUME:                /* resume execution */
  1598. 15565         rp->p_flags &= ~P_STOP;
  1599. 15566         if (rp->p_flags == 0) lock_ready(rp);
  1600. 15567         TR_DATA = 0;
  1601. 15568         break;
  1602. 15569
  1603. 15570   case T_STEP:                  /* set trace bit */
  1604. 15571         rp->p_reg.psw |= TRACEBIT;
  1605. 15572         rp->p_flags &= ~P_STOP;
  1606. 15573         if (rp->p_flags == 0) lock_ready(rp);
  1607. 15574         TR_DATA = 0;
  1608. 15575         break;
  1609. 15576
  1610. 15577   default:
  1611. 15578         return(EIO);
  1612. 15579   }
  1613. 15580   return(OK);
  1614. 15581 }
  1615. 15583 /*===========================================================================*
  1616. 15584  *                              cause_sig                                    *
  1617. 15585  *===========================================================================*/
  1618. 15586 PUBLIC void cause_sig(proc_nr, sig_nr)
  1619. 15587 int proc_nr;                    /* process to be signalled */
  1620. 15588 int sig_nr;                     /* signal to be sent, 1 to _NSIG */
  1621. 15589 {
  1622. 15590 /* A task wants to send a signal to a process.   Examples of such tasks are:
  1623. 15591  *   TTY wanting to cause SIGINT upon getting a DEL
  1624. 15592  *   CLOCK wanting to cause SIGALRM when timer expires
  1625. 15593  * FS also uses this to send a signal, via the SYS_KILL message.
  1626. 15594  * Signals are handled by sending a message to MM.  The tasks don't dare do
  1627. .Op 219 src/kernel/system.c
  1628. 15595  * that directly, for fear of what would happen if MM were busy.  Instead they
  1629. 15596  * call cause_sig, which sets bits in p_pending, and then carefully checks to
  1630. 15597  * see if MM is free.  If so, a message is sent to it.  If not, when it becomes
  1631. 15598  * free, a message is sent.  The process being signaled is blocked while MM
  1632. 15599  * has not seen or finished with all signals for it.  These signals are
  1633. 15600  * counted in p_pendcount, and the SIG_PENDING flag is kept nonzero while
  1634. 15601  * there are some.  It is not sufficient to ready the process when MM is
  1635. 15602  * informed, because MM can block waiting for FS to do a core dump.
  1636. 15603  */
  1637. 15604
  1638. 15605   register struct proc *rp, *mmp;
  1639. 15606
  1640. 15607   rp = proc_addr(proc_nr);
  1641. 15608   if (sigismember(&rp->p_pending, sig_nr))
  1642. 15609         return;                 /* this signal already pending */
  1643. 15610   sigaddset(&rp->p_pending, sig_nr);
  1644. 15611   ++rp->p_pendcount;            /* count new signal pending */
  1645. 15612   if (rp->p_flags & PENDING)
  1646. 15613         return;                 /* another signal already pending */
  1647. 15614   if (rp->p_flags == 0) lock_unready(rp);
  1648. 15615   rp->p_flags |= PENDING | SIG_PENDING;
  1649. 15616   ++sig_procs;                  /* count new process pending */
  1650. 15617
  1651. 15618   mmp = proc_addr(MM_PROC_NR);
  1652. 15619   if ( ((mmp->p_flags & RECEIVING) == 0) || mmp->p_getfrom != ANY) return;
  1653. 15620   inform();
  1654. 15621 }
  1655. 15624 /*===========================================================================*
  1656. 15625  *                              inform                                       *
  1657. 15626  *===========================================================================*/
  1658. 15627 PUBLIC void inform()
  1659. 15628 {
  1660. 15629 /* When a signal is detected by the kernel (e.g., DEL), or generated by a task
  1661. 15630  * (e.g. clock task for SIGALRM), cause_sig() is called to set a bit in the
  1662. 15631  * p_pending field of the process to signal.  Then inform() is called to see
  1663. 15632  * if MM is idle and can be told about it.  Whenever MM blocks, a check is
  1664. 15633  * made to see if 'sig_procs' is nonzero; if so, inform() is called.
  1665. 15634  */
  1666. 15635
  1667. 15636   register struct proc *rp;
  1668. 15637
  1669. 15638   /* MM is waiting for new input.  Find a process with pending signals. */
  1670. 15639   for (rp = BEG_SERV_ADDR; rp < END_PROC_ADDR; rp++)
  1671. 15640         if (rp->p_flags & PENDING) {
  1672. 15641                 m.m_type = KSIG;
  1673. 15642                 m.SIG_PROC = proc_number(rp);
  1674. 15643                 m.SIG_MAP = rp->p_pending;
  1675. 15644                 sig_procs--;
  1676. 15645                 if (lock_mini_send(proc_addr(HARDWARE), MM_PROC_NR, &m) != OK)
  1677. 15646                         panic("can't inform MM", NO_NUM);
  1678. 15647                 sigemptyset(&rp->p_pending); /* the ball is now in MM's court */
  1679. 15648                 rp->p_flags &= ~PENDING;/* remains inhibited by SIG_PENDING */
  1680. 15649                 lock_pick_proc();       /* avoid delay in scheduling MM */
  1681. 15650                 return;
  1682. 15651         }
  1683. 15652 }
  1684. .Ep 220 src/kernel/system.c
  1685. 15655 /*===========================================================================*
  1686. 15656  *                              umap                                         *
  1687. 15657  *===========================================================================*/
  1688. 15658 PUBLIC phys_bytes umap(rp, seg, vir_addr, bytes)
  1689. 15659 register struct proc *rp;       /* pointer to proc table entry for process */
  1690. 15660 int seg;                        /* T, D, or S segment */
  1691. 15661 vir_bytes vir_addr;             /* virtual address in bytes within the seg */
  1692. 15662 vir_bytes bytes;                /* # of bytes to be copied */
  1693. 15663 {
  1694. 15664 /* Calculate the physical memory address for a given virtual address. */
  1695. 15665
  1696. 15666   vir_clicks vc;                /* the virtual address in clicks */
  1697. 15667   phys_bytes pa;                /* intermediate variables as phys_bytes */
  1698. 15668   phys_bytes seg_base;
  1699. 15669
  1700. 15670   /* If 'seg' is D it could really be S and vice versa.  T really means T.
  1701. 15671    * If the virtual address falls in the gap,  it causes a problem. On the
  1702. 15672    * 8088 it is probably a legal stack reference, since "stackfaults" are
  1703. 15673    * not detected by the hardware.  On 8088s, the gap is called S and
  1704. 15674    * accepted, but on other machines it is called D and rejected.
  1705. 15675    * The Atari ST behaves like the 8088 in this respect.
  1706. 15676    */
  1707. 15677
  1708. 15678   if (bytes <= 0) return( (phys_bytes) 0);
  1709. 15679   vc = (vir_addr + bytes - 1) >> CLICK_SHIFT;   /* last click of data */
  1710. 15680
  1711. 15681   if (seg != T)
  1712. 15682         seg = (vc < rp->p_map[D].mem_vir + rp->p_map[D].mem_len ? D : S);
  1713. 15683
  1714. 15684   if((vir_addr>>CLICK_SHIFT) >= rp->p_map[seg].mem_vir+ rp->p_map[seg].mem_len)
  1715. 15685         return( (phys_bytes) 0 );
  1716. 15686   seg_base = (phys_bytes) rp->p_map[seg].mem_phys;
  1717. 15687   seg_base = seg_base << CLICK_SHIFT;   /* segment origin in bytes */
  1718. 15688   pa = (phys_bytes) vir_addr;
  1719. 15689   pa -= rp->p_map[seg].mem_vir << CLICK_SHIFT;
  1720. 15690   return(seg_base + pa);
  1721. 15691 }
  1722. 15694 /*==========================================================================*
  1723. 15695  *                              numap                                       *
  1724. 15696  *==========================================================================*/
  1725. 15697 PUBLIC phys_bytes numap(proc_nr, vir_addr, bytes)
  1726. 15698 int proc_nr;                    /* process number to be mapped */
  1727. 15699 vir_bytes vir_addr;             /* virtual address in bytes within D seg */
  1728. 15700 vir_bytes bytes;                /* # of bytes required in segment  */
  1729. 15701 {
  1730. 15702 /* Do umap() starting from a process number instead of a pointer.  This
  1731. 15703  * function is used by device drivers, so they need not know about the
  1732. 15704  * process table.  To save time, there is no 'seg' parameter. The segment
  1733. 15705  * is always D.
  1734. 15706  */
  1735. 15707
  1736. 15708   return(umap(proc_addr(proc_nr), D, vir_addr, bytes));
  1737. 15709 }
  1738. 15711 #if (CHIP == INTEL)
  1739. 15712 /*==========================================================================*
  1740. 15713  *                              alloc_segments                              *
  1741. 15714  *==========================================================================*/
  1742. .Op 221 src/kernel/system.c
  1743. 15715 PUBLIC void alloc_segments(rp)
  1744. 15716 register struct proc *rp;
  1745. 15717 {
  1746. 15718 /* This is called only by do_newmap, but is broken out as a separate function
  1747. 15719  * because so much is hardware-dependent.
  1748. 15720  */
  1749. 15721
  1750. 15722   phys_bytes code_bytes;
  1751. 15723   phys_bytes data_bytes;
  1752. 15724   int privilege;
  1753. 15725
  1754. 15726   if (protected_mode) {
  1755. 15727         data_bytes = (phys_bytes) (rp->p_map[S].mem_vir + rp->p_map[S].mem_len)
  1756. 15728                      << CLICK_SHIFT;
  1757. 15729         if (rp->p_map[T].mem_len == 0)
  1758. 15730                 code_bytes = data_bytes;        /* common I&D, poor protect */
  1759. 15731         else
  1760. 15732                 code_bytes = (phys_bytes) rp->p_map[T].mem_len << CLICK_SHIFT;
  1761. 15733         privilege = istaskp(rp) ? TASK_PRIVILEGE : USER_PRIVILEGE;
  1762. 15734         init_codeseg(&rp->p_ldt[CS_LDT_INDEX],
  1763. 15735                      (phys_bytes) rp->p_map[T].mem_phys << CLICK_SHIFT,
  1764. 15736                      code_bytes, privilege);
  1765. 15737         init_dataseg(&rp->p_ldt[DS_LDT_INDEX],
  1766. 15738                      (phys_bytes) rp->p_map[D].mem_phys << CLICK_SHIFT,
  1767. 15739                      data_bytes, privilege);
  1768. 15740         rp->p_reg.cs = (CS_LDT_INDEX * DESC_SIZE) | TI | privilege;
  1769. 15741 #if _WORD_SIZE == 4
  1770. 15742         rp->p_reg.gs =
  1771. 15743         rp->p_reg.fs =
  1772. 15744 #endif
  1773. 15745         rp->p_reg.ss =
  1774. 15746         rp->p_reg.es =
  1775. 15747         rp->p_reg.ds = (DS_LDT_INDEX*DESC_SIZE) | TI | privilege;
  1776. 15748   } else {
  1777. 15749         rp->p_reg.cs = click_to_hclick(rp->p_map[T].mem_phys);
  1778. 15750         rp->p_reg.ss =
  1779. 15751         rp->p_reg.es =
  1780. 15752         rp->p_reg.ds = click_to_hclick(rp->p_map[D].mem_phys);
  1781. 15753   }
  1782. 15754 }
  1783. 15755 #endif /* (CHIP == INTEL) */
  1784. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1785. src/mm/mm.h    
  1786. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1787. 15800 /* This is the master header for mm.  It includes some other files
  1788. 15801  * and defines the principal constants.
  1789. 15802  */
  1790. 15803 #define _POSIX_SOURCE      1    /* tell headers to include POSIX stuff */
  1791. 15804 #define _MINIX             1    /* tell headers to include MINIX stuff */
  1792. 15805 #define _SYSTEM            1    /* tell headers that this is the kernel */
  1793. 15806
  1794. 15807 /* The following are so basic, all the *.c files get them automatically. */
  1795. 15808 #include <minix/config.h>       /* MUST be first */
  1796. 15809 #include <ansi.h>               /* MUST be second */
  1797. .Ep 222 src/mm/mm.h
  1798. 15810 #include <sys/types.h>
  1799. 15811 #include <minix/const.h>
  1800. 15812 #include <minix/type.h>
  1801. 15813
  1802. 15814 #include <fcntl.h>
  1803. 15815 #include <unistd.h>
  1804. 15816 #include <minix/syslib.h>
  1805. 15817
  1806. 15818 #include <limits.h>
  1807. 15819 #include <errno.h>
  1808. 15820
  1809. 15821 #include "const.h"
  1810. 15822 #include "type.h"
  1811. 15823 #include "proto.h"
  1812. 15824 #include "glo.h"
  1813. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1814. src/mm/const.h    
  1815. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1816. 15900 /* Constants used by the Memory Manager. */
  1817. 15901
  1818. 15902 #define NO_MEM ((phys_clicks) 0)  /* returned by alloc_mem() with mem is up */
  1819. 15903
  1820. 15904 #if (CHIP == INTEL && _WORD_SIZE == 2)
  1821. 15905 /* These definitions are used in size_ok and are not needed for 386.
  1822. 15906  * The 386 segment granularity is 1 for segments smaller than 1M and 4096
  1823. 15907  * above that.  
  1824. 15908  */
  1825. 15909 #define PAGE_SIZE         16    /* how many bytes in a page (s.b.HCLICK_SIZE)*/
  1826. 15910 #define MAX_PAGES       4096    /* how many pages in the virtual addr space */
  1827. 15911 #endif
  1828. 15912
  1829. 15913 #define printf        printk
  1830. 15914
  1831. 15915 #define INIT_PID           1    /* init's process id number */
  1832. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1833. src/mm/type.h    
  1834. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1835. 16000 /* If there were any type definitions local to the Memory Manager, they would
  1836. 16001  * be here.  This file is included only for symmetry with the kernel and File
  1837. 16002  * System, which do have some local type definitions.
  1838. 16003  */
  1839. 16004
  1840. .Op 223 src/mm/proto.h
  1841. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1842. src/mm/proto.h    
  1843. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1844. 16100 /* Function prototypes. */
  1845. 16101
  1846. 16102 struct mproc;           /* need types outside of parameter list --kub */
  1847. 16103 struct stat;
  1848. 16104
  1849. 16105 /* alloc.c */
  1850. 16106 _PROTOTYPE( phys_clicks alloc_mem, (phys_clicks clicks)                 );
  1851. 16107 _PROTOTYPE( void free_mem, (phys_clicks base, phys_clicks clicks)       );
  1852. 16108 _PROTOTYPE( phys_clicks max_hole, (void)                                );
  1853. 16109 _PROTOTYPE( void mem_init, (phys_clicks *total, phys_clicks *free)      );
  1854. 16110 _PROTOTYPE( phys_clicks mem_left, (void)                                );
  1855. 16111 _PROTOTYPE( int do_brk3, (void)                                         );
  1856. 16112
  1857. 16113 /* break.c */
  1858. 16114 _PROTOTYPE( int adjust, (struct mproc *rmp,
  1859. 16115                         vir_clicks data_clicks, vir_bytes sp)           );
  1860. 16116 _PROTOTYPE( int do_brk, (void)                                          );
  1861. 16117 _PROTOTYPE( int size_ok, (int file_type, vir_clicks tc, vir_clicks dc,
  1862. 16118                         vir_clicks sc, vir_clicks dvir, vir_clicks s_vir) );
  1863. 16119
  1864. 16120 /* exec.c */
  1865. 16121 _PROTOTYPE( int do_exec, (void)                                         );
  1866. 16122 _PROTOTYPE( struct mproc *find_share, (struct mproc *mp_ign, Ino_t ino,
  1867. 16123                         Dev_t dev, time_t ctime)                        );
  1868. 16124
  1869. 16125 /* forkexit.c */
  1870. 16126 _PROTOTYPE( int do_fork, (void)                                         );
  1871. 16127 _PROTOTYPE( int do_mm_exit, (void)                                      );
  1872. 16128 _PROTOTYPE( int do_waitpid, (void)                                      );
  1873. 16129 _PROTOTYPE( void mm_exit, (struct mproc *rmp, int exit_status)          );
  1874. 16130
  1875. 16131 /* getset.c */
  1876. 16132 _PROTOTYPE( int do_getset, (void)                                       );
  1877. 16133
  1878. 16134 /* main.c */
  1879. 16135 _PROTOTYPE( void main, (void)                                           );
  1880. 16136
  1881. 16137 #if (MACHINE == MACINTOSH)
  1882. 16138 _PROTOTYPE( phys_clicks start_click, (void)                             );
  1883. 16139 #endif
  1884. 16140
  1885. 16141 _PROTOTYPE( void reply, (int proc_nr, int result, int res2, char *respt));
  1886. 16142
  1887. 16143 /* putk.c */
  1888. 16144 _PROTOTYPE( void putk, (int c)                                          );
  1889. 16145
  1890. 16146 /* signal.c */
  1891. 16147 _PROTOTYPE( int do_alarm, (void)                                        );
  1892. 16148 _PROTOTYPE( int do_kill, (void)                                         );
  1893. 16149 _PROTOTYPE( int do_ksig, (void)                                         );
  1894. 16150 _PROTOTYPE( int do_pause, (void)                                        );
  1895. 16151 _PROTOTYPE( int set_alarm, (int proc_nr, int sec)                       );
  1896. 16152 _PROTOTYPE( int check_sig, (pid_t proc_id, int signo)                   );
  1897. 16153 _PROTOTYPE( void sig_proc, (struct mproc *rmp, int sig_nr)              );
  1898. 16154 _PROTOTYPE( int do_sigaction, (void)                                    );
  1899. .Ep 224 src/mm/proto.h
  1900. 16155 _PROTOTYPE( int do_sigpending, (void)                                   );
  1901. 16156 _PROTOTYPE( int do_sigprocmask, (void)                                  );
  1902. 16157 _PROTOTYPE( int do_sigreturn, (void)                                    );
  1903. 16158 _PROTOTYPE( int do_sigsuspend, (void)                                   );
  1904. 16159 _PROTOTYPE( int do_reboot, (void)                                       );
  1905. 16160
  1906. 16161 /* trace.c */
  1907. 16162 _PROTOTYPE( int do_trace, (void)                                        );
  1908. 16163 _PROTOTYPE( void stop_proc, (struct mproc *rmp, int sig_nr)             );
  1909. 16164
  1910. 16165 /* utility.c */
  1911. 16166 _PROTOTYPE( int allowed, (char *name_buf, struct stat *s_buf, int mask) );
  1912. 16167 _PROTOTYPE( int no_sys, (void)                                          );
  1913. 16168 _PROTOTYPE( void panic, (char *format, int num)                         );
  1914. 16169 _PROTOTYPE( void tell_fs, (int what, int p1, int p2, int p3)            );
  1915. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1916. src/mm/glo.h    
  1917. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1918. 16200 /* EXTERN should be extern except in table.c */
  1919. 16201 #ifdef _TABLE
  1920. 16202 #undef EXTERN
  1921. 16203 #define EXTERN
  1922. 16204 #endif
  1923. 16205
  1924. 16206 /* Global variables. */
  1925. 16207 EXTERN struct mproc *mp;        /* ptr to 'mproc' slot of current process */
  1926. 16208 EXTERN int dont_reply;          /* normally 0; set to 1 to inhibit reply */
  1927. 16209 EXTERN int procs_in_use;        /* how many processes are marked as IN_USE */
  1928. 16210
  1929. 16211 /* The parameters of the call are kept here. */
  1930. 16212 EXTERN message mm_in;           /* the incoming message itself is kept here. */
  1931. 16213 EXTERN message mm_out;          /* the reply message is built up here. */
  1932. 16214 EXTERN int who;                 /* caller's proc number */
  1933. 16215 EXTERN int mm_call;             /* system call number */
  1934. 16216
  1935. 16217 /* The following variables are used for returning results to the caller. */
  1936. 16218 EXTERN int err_code;            /* temporary storage for error number */
  1937. 16219 EXTERN int result2;             /* secondary result */
  1938. 16220 EXTERN char *res_ptr;           /* result, if pointer */
  1939. 16221
  1940. 16222 extern _PROTOTYPE (int (*call_vec[]), (void) ); /* system call handlers */
  1941. 16223 extern char core_name[];        /* file name where core images are produced */
  1942. 16224 EXTERN sigset_t core_sset;      /* which signals cause core images */
  1943. .Op 225 src/mm/mproc.h
  1944. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1945. src/mm/mproc.h    
  1946. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1947. 16300 /* This table has one slot per process.  It contains all the memory management
  1948. 16301  * information for each process.  Among other things, it defines the text, data
  1949. 16302  * and stack segments, uids and gids, and various flags.  The kernel and file
  1950. 16303  * systems have tables that are also indexed by process, with the contents
  1951. 16304  * of corresponding slots referring to the same process in all three.
  1952. 16305  */
  1953. 16306
  1954. 16307 EXTERN struct mproc {
  1955. 16308   struct mem_map mp_seg[NR_SEGS];/* points to text, data, stack */
  1956. 16309   char mp_exitstatus;           /* storage for status when process exits */
  1957. 16310   char mp_sigstatus;            /* storage for signal # for killed procs */
  1958. 16311   pid_t mp_pid;                 /* process id */
  1959. 16312   pid_t mp_procgrp;             /* pid of process group (used for signals) */
  1960. 16313   pid_t mp_wpid;                /* pid this process is waiting for */
  1961. 16314   int mp_parent;                /* index of parent process */
  1962. 16315
  1963. 16316   /* Real and effective uids and gids. */
  1964. 16317   uid_t mp_realuid;             /* process' real uid */
  1965. 16318   uid_t mp_effuid;              /* process' effective uid */
  1966. 16319   gid_t mp_realgid;             /* process' real gid */
  1967. 16320   gid_t mp_effgid;              /* process' effective gid */
  1968. 16321
  1969. 16322   /* File identification for sharing. */
  1970. 16323   ino_t mp_ino;                 /* inode number of file */
  1971. 16324   dev_t mp_dev;                 /* device number of file system */
  1972. 16325   time_t mp_ctime;              /* inode changed time */
  1973. 16326
  1974. 16327   /* Signal handling information. */
  1975. 16328   sigset_t mp_ignore;           /* 1 means ignore the signal, 0 means don't */
  1976. 16329   sigset_t mp_catch;            /* 1 means catch the signal, 0 means don't */
  1977. 16330   sigset_t mp_sigmask;          /* signals to be blocked */
  1978. 16331   sigset_t mp_sigmask2;         /* saved copy of mp_sigmask */
  1979. 16332   sigset_t mp_sigpending;       /* signals being blocked */
  1980. 16333   struct sigaction mp_sigact[_NSIG + 1]; /* as in sigaction(2) */
  1981. 16334   vir_bytes mp_sigreturn;       /* address of C library __sigreturn function */
  1982. 16335
  1983. 16336   /* Backwards compatibility for signals. */
  1984. 16337   sighandler_t mp_func;         /* all sigs vectored to a single user fcn */
  1985. 16338
  1986. 16339   unsigned mp_flags;            /* flag bits */
  1987. 16340   vir_bytes mp_procargs;        /* ptr to proc's initial stack arguments */
  1988. 16341 } mproc[NR_PROCS];
  1989. 16342
  1990. 16343 /* Flag values */
  1991. 16344 #define IN_USE           001    /* set when 'mproc' slot in use */
  1992. 16345 #define WAITING          002    /* set by WAIT system call */
  1993. 16346 #define HANGING          004    /* set by EXIT system call */
  1994. 16347 #define PAUSED           010    /* set by PAUSE system call */
  1995. 16348 #define ALARM_ON         020    /* set when SIGALRM timer started */
  1996. 16349 #define SEPARATE         040    /* set if file is separate I & D space */
  1997. 16350 #define TRACED          0100    /* set if process is to be traced */
  1998. 16351 #define STOPPED         0200    /* set if process stopped for tracing */
  1999. 16352 #define SIGSUSPENDED    0400    /* set by SIGSUSPEND system call */
  2000. 16353
  2001. 16354 #define NIL_MPROC ((struct mproc *) 0)
  2002. .Ep 226 src/mm/param.h
  2003. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2004. src/mm/param.h    
  2005. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2006. 16400 /* The following names are synonyms for the variables in the input message. */
  2007. 16401 #define addr            mm_in.m1_p1
  2008. 16402 #define exec_name       mm_in.m1_p1
  2009. 16403 #define exec_len        mm_in.m1_i1
  2010. 16404 #define func            mm_in.m6_f1
  2011. 16405 #define grpid           (gid_t) mm_in.m1_i1
  2012. 16406 #define namelen         mm_in.m1_i1
  2013. 16407 #define pid             mm_in.m1_i1
  2014. 16408 #define seconds         mm_in.m1_i1
  2015. 16409 #define sig             mm_in.m6_i1
  2016. 16410 #define stack_bytes     mm_in.m1_i2
  2017. 16411 #define stack_ptr       mm_in.m1_p2
  2018. 16412 #define status          mm_in.m1_i1
  2019. 16413 #define usr_id          (uid_t) mm_in.m1_i1
  2020. 16414 #define request         mm_in.m2_i2
  2021. 16415 #define taddr           mm_in.m2_l1
  2022. 16416 #define data            mm_in.m2_l2
  2023. 16417 #define sig_nr          mm_in.m1_i2
  2024. 16418 #define sig_nsa         mm_in.m1_p1
  2025. 16419 #define sig_osa         mm_in.m1_p2
  2026. 16420 #define sig_ret         mm_in.m1_p3
  2027. 16421 #define sig_set         mm_in.m2_l1
  2028. 16422 #define sig_how         mm_in.m2_i1
  2029. 16423 #define sig_flags       mm_in.m2_i2
  2030. 16424 #define sig_context     mm_in.m2_p1
  2031. 16425 #ifdef _SIGMESSAGE
  2032. 16426 #define sig_msg         mm_in.m1_i1
  2033. 16427 #endif
  2034. 16428 #define reboot_flag     mm_in.m1_i1
  2035. 16429 #define reboot_code     mm_in.m1_p1
  2036. 16430 #define reboot_size     mm_in.m1_i2
  2037. 16431
  2038. 16432 /* The following names are synonyms for the variables in the output message. */
  2039. 16433 #define reply_type      mm_out.m_type
  2040. 16434 #define reply_i1        mm_out.m2_i1
  2041. 16435 #define reply_p1        mm_out.m2_p1
  2042. 16436 #define ret_mask        mm_out.m2_l1    
  2043. 16437
  2044. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2045. src/mm/table.c    
  2046. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2047. 16500 /* This file contains the table used to map system call numbers onto the
  2048. 16501  * routines that perform them.
  2049. 16502  */
  2050. 16503
  2051. 16504 #define _TABLE
  2052. 16505
  2053. 16506 #include "mm.h"
  2054. 16507 #include <minix/callnr.h>
  2055. 16508 #include <signal.h>
  2056. 16509 #include "mproc.h"
  2057. .Op 227 src/mm/table.c
  2058. 16510 #include "param.h"
  2059. 16511
  2060. 16512 /* Miscellaneous */
  2061. 16513 char core_name[] = "core";      /* file name where core images are produced */
  2062. 16514
  2063. 16515 _PROTOTYPE (int (*call_vec[NCALLS]), (void) ) = {
  2064. 16516         no_sys,         /*  0 = unused  */
  2065. 16517         do_mm_exit,     /*  1 = exit    */
  2066. 16518         do_fork,        /*  2 = fork    */
  2067. 16519         no_sys,         /*  3 = read    */
  2068. 16520         no_sys,         /*  4 = write   */
  2069. 16521         no_sys,         /*  5 = open    */
  2070. 16522         no_sys,         /*  6 = close   */
  2071. 16523         do_waitpid,     /*  7 = wait    */
  2072. 16524         no_sys,         /*  8 = creat   */
  2073. 16525         no_sys,         /*  9 = link    */
  2074. 16526         no_sys,         /* 10 = unlink  */
  2075. 16527         do_waitpid,     /* 11 = waitpid */
  2076. 16528         no_sys,         /* 12 = chdir   */
  2077. 16529         no_sys,         /* 13 = time    */
  2078. 16530         no_sys,         /* 14 = mknod   */
  2079. 16531         no_sys,         /* 15 = chmod   */
  2080. 16532         no_sys,         /* 16 = chown   */
  2081. 16533         do_brk,         /* 17 = break   */
  2082. 16534         no_sys,         /* 18 = stat    */
  2083. 16535         no_sys,         /* 19 = lseek   */
  2084. 16536         do_getset,      /* 20 = getpid  */
  2085. 16537         no_sys,         /* 21 = mount   */
  2086. 16538         no_sys,         /* 22 = umount  */
  2087. 16539         do_getset,      /* 23 = setuid  */
  2088. 16540         do_getset,      /* 24 = getuid  */
  2089. 16541         no_sys,         /* 25 = stime   */
  2090. 16542         do_trace,       /* 26 = ptrace  */
  2091. 16543         do_alarm,       /* 27 = alarm   */
  2092. 16544         no_sys,         /* 28 = fstat   */
  2093. 16545         do_pause,       /* 29 = pause   */
  2094. 16546         no_sys,         /* 30 = utime   */
  2095. 16547         no_sys,         /* 31 = (stty)  */
  2096. 16548         no_sys,         /* 32 = (gtty)  */
  2097. 16549         no_sys,         /* 33 = access  */
  2098. 16550         no_sys,         /* 34 = (nice)  */
  2099. 16551         no_sys,         /* 35 = (ftime) */
  2100. 16552         no_sys,         /* 36 = sync    */
  2101. 16553         do_kill,        /* 37 = kill    */
  2102. 16554         no_sys,         /* 38 = rename  */
  2103. 16555         no_sys,         /* 39 = mkdir   */
  2104. 16556         no_sys,         /* 40 = rmdir   */
  2105. 16557         no_sys,         /* 41 = dup     */
  2106. 16558         no_sys,         /* 42 = pipe    */
  2107. 16559         no_sys,         /* 43 = times   */
  2108. 16560         no_sys,         /* 44 = (prof)  */
  2109. 16561         no_sys,         /* 45 = unused  */
  2110. 16562         do_getset,      /* 46 = setgid  */
  2111. 16563         do_getset,      /* 47 = getgid  */
  2112. 16564         no_sys,         /* 48 = (signal)*/
  2113. 16565         no_sys,         /* 49 = unused  */
  2114. 16566         no_sys,         /* 50 = unused  */
  2115. 16567         no_sys,         /* 51 = (acct)  */
  2116. 16568         no_sys,         /* 52 = (phys)  */
  2117. 16569         no_sys,         /* 53 = (lock)  */
  2118. .Ep 228 src/mm/table.c
  2119. 16570         no_sys,         /* 54 = ioctl   */
  2120. 16571         no_sys,         /* 55 = fcntl   */
  2121. 16572         no_sys,         /* 56 = (mpx)   */
  2122. 16573         no_sys,         /* 57 = unused  */
  2123. 16574         no_sys,         /* 58 = unused  */
  2124. 16575         do_exec,        /* 59 = execve  */
  2125. 16576         no_sys,         /* 60 = umask   */
  2126. 16577         no_sys,         /* 61 = chroot  */
  2127. 16578         do_getset,      /* 62 = setsid  */
  2128. 16579         do_getset,      /* 63 = getpgrp */
  2129. 16580
  2130. 16581         do_ksig,        /* 64 = KSIG: signals originating in the kernel */
  2131. 16582         no_sys,         /* 65 = UNPAUSE */
  2132. 16583         no_sys,         /* 66 = unused  */
  2133. 16584         no_sys,         /* 67 = REVIVE  */
  2134. 16585         no_sys,         /* 68 = TASK_REPLY  */
  2135. 16586         no_sys,         /* 69 = unused  */
  2136. 16587         no_sys,         /* 70 = unused  */
  2137. 16588         do_sigaction,   /* 71 = sigaction   */
  2138. 16589         do_sigsuspend,  /* 72 = sigsuspend  */
  2139. 16590         do_sigpending,  /* 73 = sigpending  */
  2140. 16591         do_sigprocmask, /* 74 = sigprocmask */
  2141. 16592         do_sigreturn,   /* 75 = sigreturn   */
  2142. 16593         do_reboot,      /* 76 = reboot  */
  2143. 16594 };
  2144. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2145. src/mm/main.c    
  2146. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2147. 16600 /* This file contains the main program of the memory manager and some related
  2148. 16601  * procedures.  When MINIX starts up, the kernel runs for a little while,
  2149. 16602  * initializing itself and its tasks, and then it runs MM and FS.  Both MM
  2150. 16603  * and FS initialize themselves as far as they can.  FS then makes a call to
  2151. 16604  * MM, because MM has to wait for FS to acquire a RAM disk.  MM asks the
  2152. 16605  * kernel for all free memory and starts serving requests.
  2153. 16606  *
  2154. 16607  * The entry points into this file are:
  2155. 16608  *   main:      starts MM running
  2156. 16609  *   reply:     reply to a process making an MM system call
  2157. 16610  */
  2158. 16611
  2159. 16612 #include "mm.h"
  2160. 16613 #include <minix/callnr.h>
  2161. 16614 #include <minix/com.h>
  2162. 16615 #include <signal.h>
  2163. 16616 #include <fcntl.h>
  2164. 16617 #include <sys/ioctl.h>
  2165. 16618 #include "mproc.h"
  2166. 16619 #include "param.h"
  2167. 16620
  2168. 16621 FORWARD _PROTOTYPE( void get_work, (void)                               );
  2169. 16622 FORWARD _PROTOTYPE( void mm_init, (void)                                );
  2170. 16623
  2171. 16624 /*===========================================================================*
  2172. .Op 229 src/mm/main.c
  2173. 16625  *                              main                                         *
  2174. 16626  *===========================================================================*/
  2175. 16627 PUBLIC void main()
  2176. 16628 {
  2177. 16629 /* Main routine of the memory manager. */
  2178. 16630
  2179. 16631   int error;
  2180. 16632
  2181. 16633   mm_init();                    /* initialize memory manager tables */
  2182. 16634
  2183. 16635   /* This is MM's main loop-  get work and do it, forever and forever. */
  2184. 16636   while (TRUE) {
  2185. 16637         /* Wait for message. */
  2186. 16638         get_work();             /* wait for an MM system call */
  2187. 16639         mp = &mproc[who];
  2188. 16640
  2189. 16641         /* Set some flags. */
  2190. 16642         error = OK;
  2191. 16643         dont_reply = FALSE;
  2192. 16644         err_code = -999;
  2193. 16645
  2194. 16646         /* If the call number is valid, perform the call. */
  2195. 16647         if (mm_call < 0 || mm_call >= NCALLS)
  2196. 16648                 error = EBADCALL;
  2197. 16649         else
  2198. 16650                 error = (*call_vec[mm_call])();
  2199. 16651
  2200. 16652         /* Send the results back to the user to indicate completion. */
  2201. 16653         if (dont_reply) continue;       /* no reply for EXIT and WAIT */
  2202. 16654         if (mm_call == EXEC && error == OK) continue;
  2203. 16655         reply(who, error, result2, res_ptr);
  2204. 16656   }
  2205. 16657 }
  2206. 16660 /*===========================================================================*
  2207. 16661  *                              get_work                                     *
  2208. 16662  *===========================================================================*/
  2209. 16663 PRIVATE void get_work()
  2210. 16664 {
  2211. 16665 /* Wait for the next message and extract useful information from it. */
  2212. 16666
  2213. 16667   if (receive(ANY, &mm_in) != OK) panic("MM receive error", NO_NUM);
  2214. 16668   who = mm_in.m_source;         /* who sent the message */
  2215. 16669   mm_call = mm_in.m_type;       /* system call number */
  2216. 16670 }
  2217. 16673 /*===========================================================================*
  2218. 16674  *                              reply                                        *
  2219. 16675  *===========================================================================*/
  2220. 16676 PUBLIC void reply(proc_nr, result, res2, respt)
  2221. 16677 int proc_nr;                    /* process to reply to */
  2222. 16678 int result;                     /* result of the call (usually OK or error #)*/
  2223. 16679 int res2;                       /* secondary result */
  2224. 16680 char *respt;                    /* result if pointer */
  2225. 16681 {
  2226. 16682 /* Send a reply to a user process. */
  2227. 16683
  2228. 16684   register struct mproc *proc_ptr;
  2229. .Ep 230 src/mm/main.c
  2230. 16685
  2231. 16686   proc_ptr = &mproc[proc_nr];
  2232. 16687   /* 
  2233. 16688    * To make MM robust, check to see if destination is still alive.  This
  2234. 16689    * validy check must be skipped if the caller is a task.
  2235. 16690    */
  2236. 16691   if ((who >=0) && ((proc_ptr->mp_flags&IN_USE) == 0 || 
  2237. 16692         (proc_ptr->mp_flags&HANGING))) return;
  2238. 16693
  2239. 16694   reply_type = result;
  2240. 16695   reply_i1 = res2;
  2241. 16696   reply_p1 = respt;
  2242. 16697   if (send(proc_nr, &mm_out) != OK) panic("MM can't reply", NO_NUM);
  2243. 16698 }
  2244. 16701 /*===========================================================================*
  2245. 16702  *                              mm_init                                      *
  2246. 16703  *===========================================================================*/
  2247. 16704 PRIVATE void mm_init()
  2248. 16705 {
  2249. 16706 /* Initialize the memory manager. */
  2250. 16707
  2251. 16708   static char core_sigs[] = {
  2252. 16709         SIGQUIT, SIGILL, SIGTRAP, SIGABRT,
  2253. 16710         SIGEMT, SIGFPE, SIGUSR1, SIGSEGV,
  2254. 16711         SIGUSR2, 0 };
  2255. 16712   register int proc_nr;
  2256. 16713   register struct mproc *rmp;
  2257. 16714   register char *sig_ptr;
  2258. 16715   phys_clicks ram_clicks, total_clicks, minix_clicks, free_clicks, dummy;
  2259. 16716   message mess;
  2260. 16717   struct mem_map kernel_map[NR_SEGS];
  2261. 16718   int mem;
  2262. 16719
  2263. 16720   /* Build the set of signals which cause core dumps. Do it the Posix
  2264. 16721    * way, so no knowledge of bit positions is needed.
  2265. 16722    */
  2266. 16723   sigemptyset(&core_sset);
  2267. 16724   for (sig_ptr = core_sigs; *sig_ptr != 0; sig_ptr++)
  2268. 16725         sigaddset(&core_sset, *sig_ptr);
  2269. 16726
  2270. 16727   /* Get the memory map of the kernel to see how much memory it uses,
  2271. 16728    * including the gap between address 0 and the start of the kernel.
  2272. 16729    */
  2273. 16730   sys_getmap(SYSTASK, kernel_map);
  2274. 16731   minix_clicks = kernel_map[S].mem_phys + kernel_map[S].mem_len;
  2275. 16732
  2276. 16733   /* Initialize MM's tables. */
  2277. 16734   for (proc_nr = 0; proc_nr <= INIT_PROC_NR; proc_nr++) {
  2278. 16735         rmp = &mproc[proc_nr];
  2279. 16736         rmp->mp_flags |= IN_USE;
  2280. 16737         sys_getmap(proc_nr, rmp->mp_seg);
  2281. 16738         if (rmp->mp_seg[T].mem_len != 0) rmp->mp_flags |= SEPARATE;
  2282. 16739         minix_clicks += (rmp->mp_seg[S].mem_phys + rmp->mp_seg[S].mem_len)
  2283. 16740                                 - rmp->mp_seg[T].mem_phys;
  2284. 16741   }
  2285. 16742   mproc[INIT_PROC_NR].mp_pid = INIT_PID;
  2286. 16743   sigemptyset(&mproc[INIT_PROC_NR].mp_ignore);
  2287. 16744   sigemptyset(&mproc[INIT_PROC_NR].mp_catch);
  2288. .Op 231 src/mm/main.c
  2289. 16745   procs_in_use = LOW_USER + 1;
  2290. 16746
  2291. 16747   /* Wait for FS to send a message telling the RAM disk size then go "on-line".
  2292. 16748    */
  2293. 16749   if (receive(FS_PROC_NR, &mess) != OK)
  2294. 16750         panic("MM can't obtain RAM disk size from FS", NO_NUM);
  2295. 16751
  2296. 16752   ram_clicks = mess.m1_i1;
  2297. 16753
  2298. 16754   /* Initialize tables to all physical mem. */
  2299. 16755   mem_init(&total_clicks, &free_clicks);
  2300. 16756
  2301. 16757   /* Print memory information. */
  2302. 16758   printf("nMemory size =%5dK   ", click_to_round_k(total_clicks));
  2303. 16759   printf("MINIX =%4dK   ", click_to_round_k(minix_clicks));
  2304. 16760   printf("RAM disk =%5dK   ", click_to_round_k(ram_clicks));
  2305. 16761   printf("Available =%5dKnn", click_to_round_k(free_clicks));
  2306. 16762
  2307. 16763   /* Tell FS to continue. */
  2308. 16764   if (send(FS_PROC_NR, &mess) != OK)
  2309. 16765         panic("MM can't sync up with FS", NO_NUM);
  2310. 16766
  2311. 16767   /* Tell the memory task where my process table is for the sake of ps(1). */
  2312. 16768   if ((mem = open("/dev/mem", O_RDWR)) != -1) {
  2313. 16769         ioctl(mem, MIOCSPSINFO, (void *) mproc);
  2314. 16770         close(mem);
  2315. 16771   }
  2316. 16772 }
  2317. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2318. src/mm/forkexit.c    
  2319. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2320. 16800 /* This file deals with creating processes (via FORK) and deleting them (via
  2321. 16801  * EXIT/WAIT).  When a process forks, a new slot in the 'mproc' table is
  2322. 16802  * allocated for it, and a copy of the parent's core image is made for the
  2323. 16803  * child.  Then the kernel and file system are informed.  A process is removed
  2324. 16804  * from the 'mproc' table when two events have occurred: (1) it has exited or
  2325. 16805  * been killed by a signal, and (2) the parent has done a WAIT.  If the process
  2326. 16806  * exits first, it continues to occupy a slot until the parent does a WAIT.
  2327. 16807  *
  2328. 16808  * The entry points into this file are:
  2329. 16809  *   do_fork:    perform the FORK system call
  2330. 16810  *   do_mm_exit: perform the EXIT system call (by calling mm_exit())
  2331. 16811  *   mm_exit:    actually do the exiting
  2332. 16812  *   do_wait:    perform the WAITPID or WAIT system call
  2333. 16813  */
  2334. 16814
  2335. 16815
  2336. 16816 #include "mm.h"
  2337. 16817 #include <sys/wait.h>
  2338. 16818 #include <minix/callnr.h>
  2339. 16819 #include <signal.h>
  2340. 16820 #include "mproc.h"
  2341. 16821 #include "param.h"
  2342. 16822
  2343. 16823 #define LAST_FEW            2   /* last few slots reserved for superuser */
  2344. 16824
  2345. .Ep 232 src/mm/forkexit.c
  2346. 16825 PRIVATE pid_t next_pid = INIT_PID+1;    /* next pid to be assigned */
  2347. 16826
  2348. 16827 FORWARD _PROTOTYPE (void cleanup, (register struct mproc *child) );
  2349. 16828
  2350. 16829 /*===========================================================================*
  2351. 16830  *                              do_fork                                      *
  2352. 16831  *===========================================================================*/
  2353. 16832 PUBLIC int do_fork()
  2354. 16833 {
  2355. 16834 /* The process pointed to by 'mp' has forked.  Create a child process. */
  2356. 16835
  2357. 16836   register struct mproc *rmp;   /* pointer to parent */
  2358. 16837   register struct mproc *rmc;   /* pointer to child */
  2359. 16838   int i, child_nr, t;
  2360. 16839   phys_clicks prog_clicks, child_base = 0;
  2361. 16840   phys_bytes prog_bytes, parent_abs, child_abs; /* Intel only */
  2362. 16841
  2363. 16842  /* If tables might fill up during FORK, don't even start since recovery half
  2364. 16843   * way through is such a nuisance.
  2365. 16844   */
  2366. 16845   rmp = mp;
  2367. 16846   if (procs_in_use == NR_PROCS) return(EAGAIN);
  2368. 16847   if (procs_in_use >= NR_PROCS-LAST_FEW && rmp->mp_effuid != 0)return(EAGAIN);
  2369. 16848
  2370. 16849   /* Determine how much memory to allocate.  Only the data and stack need to
  2371. 16850    * be copied, because the text segment is either shared or of zero length.
  2372. 16851    */
  2373. 16852   prog_clicks = (phys_clicks) rmp->mp_seg[S].mem_len;
  2374. 16853   prog_clicks += (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir);
  2375. 16854   prog_bytes = (phys_bytes) prog_clicks << CLICK_SHIFT;
  2376. 16855   if ( (child_base = alloc_mem(prog_clicks)) == NO_MEM) return(EAGAIN);
  2377. 16856
  2378. 16857   /* Create a copy of the parent's core image for the child. */
  2379. 16858   child_abs = (phys_bytes) child_base << CLICK_SHIFT;
  2380. 16859   parent_abs = (phys_bytes) rmp->mp_seg[D].mem_phys << CLICK_SHIFT;
  2381. 16860   i = sys_copy(ABS, 0, parent_abs, ABS, 0, child_abs, prog_bytes);
  2382. 16861   if (i < 0) panic("do_fork can't copy", i);
  2383. 16862
  2384. 16863   /* Find a slot in 'mproc' for the child process.  A slot must exist. */
  2385. 16864   for (rmc = &mproc[0]; rmc < &mproc[NR_PROCS]; rmc++)
  2386. 16865         if ( (rmc->mp_flags & IN_USE) == 0) break;
  2387. 16866
  2388. 16867   /* Set up the child and its memory map; copy its 'mproc' slot from parent. */
  2389. 16868   child_nr = (int)(rmc - mproc);        /* slot number of the child */
  2390. 16869   procs_in_use++;
  2391. 16870   *rmc = *rmp;                  /* copy parent's process slot to child's */
  2392. 16871
  2393. 16872   rmc->mp_parent = who;         /* record child's parent */
  2394. 16873   rmc->mp_flags &= ~TRACED;     /* child does not inherit trace status */
  2395. 16874   /* A separate I&D child keeps the parents text segment.  The data and stack
  2396. 16875    * segments must refer to the new copy.
  2397. 16876    */
  2398. 16877   if (!(rmc->mp_flags & SEPARATE)) rmc->mp_seg[T].mem_phys = child_base;
  2399. 16878   rmc->mp_seg[D].mem_phys = child_base;
  2400. 16879   rmc->mp_seg[S].mem_phys = rmc->mp_seg[D].mem_phys + 
  2401. 16880                         (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir);
  2402. 16881   rmc->mp_exitstatus = 0;
  2403. 16882   rmc->mp_sigstatus = 0;
  2404. 16883
  2405. 16884   /* Find a free pid for the child and put it in the table. */
  2406. .Op 233 src/mm/forkexit.c
  2407. 16885   do {
  2408. 16886         t = 0;                  /* 't' = 0 means pid still free */
  2409. 16887         next_pid = (next_pid < 30000 ? next_pid + 1 : INIT_PID + 1);
  2410. 16888         for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++)
  2411. 16889                 if (rmp->mp_pid == next_pid || rmp->mp_procgrp == next_pid) {
  2412. 16890                         t = 1;
  2413. 16891                         break;
  2414. 16892                 }
  2415. 16893         rmc->mp_pid = next_pid; /* assign pid to child */
  2416. 16894   } while (t);
  2417. 16895
  2418. 16896   /* Tell kernel and file system about the (now successful) FORK. */
  2419. 16897   sys_fork(who, child_nr, rmc->mp_pid, child_base); /* child_base is 68K only*/
  2420. 16898   tell_fs(FORK, who, child_nr, rmc->mp_pid);
  2421. 16899
  2422. 16900   /* Report child's memory map to kernel. */
  2423. 16901   sys_newmap(child_nr, rmc->mp_seg);
  2424. 16902
  2425. 16903   /* Reply to child to wake it up. */
  2426. 16904   reply(child_nr, 0, 0, NIL_PTR);
  2427. 16905   return(next_pid);              /* child's pid */
  2428. 16906 }
  2429. 16909 /*===========================================================================*
  2430. 16910  *                              do_mm_exit                                   *
  2431. 16911  *===========================================================================*/
  2432. 16912 PUBLIC int do_mm_exit()
  2433. 16913 {
  2434. 16914 /* Perform the exit(status) system call. The real work is done by mm_exit(),
  2435. 16915  * which is also called when a process is killed by a signal.
  2436. 16916  */
  2437. 16917
  2438. 16918   mm_exit(mp, status);
  2439. 16919   dont_reply = TRUE;            /* don't reply to newly terminated process */
  2440. 16920   return(OK);                   /* pro forma return code */
  2441. 16921 }
  2442. 16924 /*===========================================================================*
  2443. 16925  *                              mm_exit                                      *
  2444. 16926  *===========================================================================*/
  2445. 16927 PUBLIC void mm_exit(rmp, exit_status)
  2446. 16928 register struct mproc *rmp;     /* pointer to the process to be terminated */
  2447. 16929 int exit_status;                /* the process' exit status (for parent) */
  2448. 16930 {
  2449. 16931 /* A process is done.  Release most of the process' possessions.  If its
  2450. 16932  * parent is waiting, release the rest, else hang.
  2451. 16933  */
  2452. 16934
  2453. 16935   register int proc_nr;
  2454. 16936   int parent_waiting, right_child;
  2455. 16937   pid_t pidarg, procgrp;
  2456. 16938   phys_clicks base, size, s;            /* base and size used on 68000 only */
  2457. 16939
  2458. 16940   proc_nr = (int) (rmp - mproc);        /* get process slot number */
  2459. 16941
  2460. 16942   /* Remember a session leader's process group. */
  2461. 16943   procgrp = (rmp->mp_pid == mp->mp_procgrp) ? mp->mp_procgrp : 0;
  2462. 16944
  2463. .Ep 234 src/mm/forkexit.c
  2464. 16945   /* If the exited process has a timer pending, kill it. */
  2465. 16946   if (rmp->mp_flags & ALARM_ON) set_alarm(proc_nr, (unsigned) 0);
  2466. 16947
  2467. 16948   /* Tell the kernel and FS that the process is no longer runnable. */
  2468. 16949   tell_fs(EXIT, proc_nr, 0, 0);  /* file system can free the proc slot */
  2469. 16950   sys_xit(rmp->mp_parent, proc_nr, &base, &size);
  2470. 16951
  2471. 16952   /* Release the memory occupied by the child. */
  2472. 16953   if (find_share(rmp, rmp->mp_ino, rmp->mp_dev, rmp->mp_ctime) == NULL) {
  2473. 16954         /* No other process shares the text segment, so free it. */
  2474. 16955         free_mem(rmp->mp_seg[T].mem_phys, rmp->mp_seg[T].mem_len);
  2475. 16956   }
  2476. 16957   /* Free the data and stack segments. */
  2477. 16958   free_mem(rmp->mp_seg[D].mem_phys,
  2478. 16959       rmp->mp_seg[S].mem_vir + rmp->mp_seg[S].mem_len - rmp->mp_seg[D].mem_vir);
  2479. 16960
  2480. 16961   /* The process slot can only be freed if the parent has done a WAIT. */
  2481. 16962   rmp->mp_exitstatus = (char) exit_status;
  2482. 16963   pidarg = mproc[rmp->mp_parent].mp_wpid;       /* who's being waited for? */
  2483. 16964   parent_waiting = mproc[rmp->mp_parent].mp_flags & WAITING;
  2484. 16965   if (pidarg == -1 || pidarg == rmp->mp_pid || -pidarg == rmp->mp_procgrp)
  2485. 16966         right_child = TRUE;             /* child meets one of the 3 tests */
  2486. 16967   else
  2487. 16968         right_child = FALSE;            /* child fails all 3 tests */
  2488. 16969   if (parent_waiting && right_child)
  2489. 16970         cleanup(rmp);                   /* tell parent and release child slot */
  2490. 16971   else
  2491. 16972         rmp->mp_flags |= HANGING;       /* parent not waiting, suspend child */
  2492. 16973
  2493. 16974   /* If the process has children, disinherit them.  INIT is the new parent. */
  2494. 16975   for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {
  2495. 16976         if (rmp->mp_flags & IN_USE && rmp->mp_parent == proc_nr) {
  2496. 16977                 /* 'rmp' now points to a child to be disinherited. */
  2497. 16978                 rmp->mp_parent = INIT_PROC_NR;
  2498. 16979                 parent_waiting = mproc[INIT_PROC_NR].mp_flags & WAITING;
  2499. 16980                 if (parent_waiting && (rmp->mp_flags & HANGING)) cleanup(rmp);
  2500. 16981         }
  2501. 16982   }
  2502. 16983
  2503. 16984   /* Send a hangup to the process' process group if it was a session leader. */
  2504. 16985   if (procgrp != 0) check_sig(-procgrp, SIGHUP);
  2505. 16986 }
  2506. 16989 /*===========================================================================*
  2507. 16990  *                              do_waitpid                                   *
  2508. 16991  *===========================================================================*/
  2509. 16992 PUBLIC int do_waitpid()
  2510. 16993 {
  2511. 16994 /* A process wants to wait for a child to terminate. If one is already waiting,
  2512. 16995  * go clean it up and let this WAIT call terminate.  Otherwise, really wait.
  2513. 16996  * Both WAIT and WAITPID are handled by this code.
  2514. 16997  */
  2515. 16998
  2516. 16999   register struct mproc *rp;
  2517. 17000   int pidarg, options, children, res2;
  2518. 17001
  2519. 17002   /* A process calling WAIT never gets a reply in the usual way via the
  2520. 17003    * reply() in the main loop (unless WNOHANG is set or no qualifying child
  2521. 17004    * exists).  If a child has already exited, the routine cleanup() sends 
  2522. .Op 235 src/mm/forkexit.c
  2523. 17005    * the reply to awaken the caller.
  2524. 17006    */
  2525. 17007
  2526. 17008   /* Set internal variables, depending on whether this is WAIT or WAITPID. */
  2527. 17009   pidarg  = (mm_call == WAIT ? -1 : pid);       /* first param of waitpid */
  2528. 17010   options = (mm_call == WAIT ?  0 : sig_nr);    /* third param of waitpid */
  2529. 17011   if (pidarg == 0) pidarg = -mp->mp_procgrp;    /* pidarg < 0 ==> proc grp */
  2530. 17012
  2531. 17013   /* Is there a child waiting to be collected? At this point, pidarg != 0:
  2532. 17014    *    pidarg  >  0 means pidarg is pid of a specific process to wait for
  2533. 17015    *    pidarg == -1 means wait for any child
  2534. 17016    *    pidarg  < -1 means wait for any child whose process group = -pidarg
  2535. 17017    */
  2536. 17018   children = 0;
  2537. 17019   for (rp = &mproc[0]; rp < &mproc[NR_PROCS]; rp++) {
  2538. 17020         if ( (rp->mp_flags & IN_USE) && rp->mp_parent == who) {
  2539. 17021                 /* The value of pidarg determines which children qualify. */
  2540. 17022                 if (pidarg  > 0 && pidarg != rp->mp_pid) continue;
  2541. 17023                 if (pidarg < -1 && -pidarg != rp->mp_procgrp) continue;
  2542. 17024
  2543. 17025                 children++;             /* this child is acceptable */
  2544. 17026                 if (rp->mp_flags & HANGING) {
  2545. 17027                         /* This child meets the pid test and has exited. */
  2546. 17028                         cleanup(rp);    /* this child has already exited */
  2547. 17029                         dont_reply = TRUE;
  2548. 17030                         return(OK);
  2549. 17031                 }
  2550. 17032                 if ((rp->mp_flags & STOPPED) && rp->mp_sigstatus) {
  2551. 17033                         /* This child meets the pid test and is being traced.*/
  2552. 17034                         res2 =  0177 | (rp->mp_sigstatus << 8);
  2553. 17035                         reply(who, rp->mp_pid, res2, NIL_PTR);
  2554. 17036                         dont_reply = TRUE;
  2555. 17037                         rp->mp_sigstatus = 0;
  2556. 17038                         return(OK);
  2557. 17039                 }
  2558. 17040         }
  2559. 17041   }
  2560. 17042
  2561. 17043   /* No qualifying child has exited.  Wait for one, unless none exists. */
  2562. 17044   if (children > 0) {
  2563. 17045         /* At least 1 child meets the pid test exists, but has not exited. */
  2564. 17046         if (options & WNOHANG) return(0);    /* parent does not want to wait */
  2565. 17047         mp->mp_flags |= WAITING;             /* parent wants to wait */
  2566. 17048         mp->mp_wpid = (pid_t) pidarg;        /* save pid for later */
  2567. 17049         dont_reply = TRUE;                   /* do not reply now though */
  2568. 17050         return(OK);                          /* yes - wait for one to exit */
  2569. 17051   } else {
  2570. 17052         /* No child even meets the pid test.  Return error immediately. */
  2571. 17053         return(ECHILD);                      /* no - parent has no children */
  2572. 17054   }
  2573. 17055 }
  2574. 17058 /*===========================================================================*
  2575. 17059  *                              cleanup                                      *
  2576. 17060  *===========================================================================*/
  2577. 17061 PRIVATE void cleanup(child)
  2578. 17062 register struct mproc *child;   /* tells which process is exiting */
  2579. 17063 {
  2580. 17064 /* Finish off the exit of a process.  The process has exited or been killed
  2581. .Ep 236 src/mm/forkexit.c
  2582. 17065  * by a signal, and its parent is waiting.
  2583. 17066  */
  2584. 17067
  2585. 17068   int exitstatus;
  2586. 17069
  2587. 17070   /* Wake up the parent. */
  2588. 17071   exitstatus = (child->mp_exitstatus << 8) | (child->mp_sigstatus & 0377);
  2589. 17072   reply(child->mp_parent, child->mp_pid, exitstatus, NIL_PTR);
  2590. 17073   mproc[child->mp_parent].mp_flags &= ~WAITING; /* parent no longer waiting */
  2591. 17074
  2592. 17075   /* Release the process table entry. */
  2593. 17076   child->mp_flags = 0;
  2594. 17077   procs_in_use--;
  2595. 17078 }
  2596. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2597. src/mm/exec.c    
  2598. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2599. 17100 /* This file handles the EXEC system call.  It performs the work as follows:
  2600. 17101  *    - see if the permissions allow the file to be executed
  2601. 17102  *    - read the header and extract the sizes
  2602. 17103  *    - fetch the initial args and environment from the user space
  2603. 17104  *    - allocate the memory for the new process
  2604. 17105  *    - copy the initial stack from MM to the process
  2605. 17106  *    - read in the text and data segments and copy to the process
  2606. 17107  *    - take care of setuid and setgid bits
  2607. 17108  *    - fix up 'mproc' table
  2608. 17109  *    - tell kernel about EXEC
  2609. 17110  *    - save offset to initial argc (for ps)
  2610. 17111  *
  2611. 17112  * The entry points into this file are:
  2612. 17113  *   do_exec:    perform the EXEC system call
  2613. 17114  *   find_share: find a process whose text segment can be shared
  2614. 17115  */
  2615. 17116
  2616. 17117 #include "mm.h"
  2617. 17118 #include <sys/stat.h>
  2618. 17119 #include <minix/callnr.h>
  2619. 17120 #include <a.out.h>
  2620. 17121 #include <signal.h>
  2621. 17122 #include <string.h>
  2622. 17123 #include "mproc.h"
  2623. 17124 #include "param.h"
  2624. 17125
  2625. 17126 FORWARD _PROTOTYPE( void load_seg, (int fd, int seg, vir_bytes seg_bytes) );
  2626. 17127 FORWARD _PROTOTYPE( int new_mem, (struct mproc *sh_mp, vir_bytes text_bytes,
  2627. 17128                 vir_bytes data_bytes, vir_bytes bss_bytes,
  2628. 17129                 vir_bytes stk_bytes, phys_bytes tot_bytes)              );
  2629. 17130 FORWARD _PROTOTYPE( void patch_ptr, (char stack [ARG_MAX ], vir_bytes base) );
  2630. 17131 FORWARD _PROTOTYPE( int read_header, (int fd, int *ft, vir_bytes *text_bytes,
  2631. 17132                 vir_bytes *data_bytes, vir_bytes *bss_bytes,
  2632. 17133                 phys_bytes *tot_bytes, long *sym_bytes, vir_clicks sc,
  2633. 17134                 vir_bytes *pc)                                          );
  2634. 17135
  2635. 17136
  2636. 17137 /*===========================================================================*
  2637. 17138  *                              do_exec                                      *
  2638. 17139  *===========================================================================*/
  2639. .Op 237 src/mm/exec.c
  2640. 17140 PUBLIC int do_exec()
  2641. 17141 {
  2642. 17142 /* Perform the execve(name, argv, envp) call.  The user library builds a
  2643. 17143  * complete stack image, including pointers, args, environ, etc.  The stack
  2644. 17144  * is copied to a buffer inside MM, and then to the new core image.
  2645. 17145  */
  2646. 17146
  2647. 17147   register struct mproc *rmp;
  2648. 17148   struct mproc *sh_mp;
  2649. 17149   int m, r, fd, ft, sn;
  2650. 17150   static char mbuf[ARG_MAX];    /* buffer for stack and zeroes */
  2651. 17151   static char name_buf[PATH_MAX]; /* the name of the file to exec */
  2652. 17152   char *new_sp, *basename;
  2653. 17153   vir_bytes src, dst, text_bytes, data_bytes, bss_bytes, stk_bytes, vsp;
  2654. 17154   phys_bytes tot_bytes;         /* total space for program, including gap */
  2655. 17155   long sym_bytes;
  2656. 17156   vir_clicks sc;
  2657. 17157   struct stat s_buf;
  2658. 17158   vir_bytes pc;
  2659. 17159
  2660. 17160   /* Do some validity checks. */
  2661. 17161   rmp = mp;
  2662. 17162   stk_bytes = (vir_bytes) stack_bytes;
  2663. 17163   if (stk_bytes > ARG_MAX) return(ENOMEM);      /* stack too big */
  2664. 17164   if (exec_len <= 0 || exec_len > PATH_MAX) return(EINVAL);
  2665. 17165
  2666. 17166   /* Get the exec file name and see if the file is executable. */
  2667. 17167   src = (vir_bytes) exec_name;
  2668. 17168   dst = (vir_bytes) name_buf;
  2669. 17169   r = sys_copy(who, D, (phys_bytes) src,
  2670. 17170                 MM_PROC_NR, D, (phys_bytes) dst, (phys_bytes) exec_len);
  2671. 17171   if (r != OK) return(r);       /* file name not in user data segment */
  2672. 17172   tell_fs(CHDIR, who, FALSE, 0);        /* switch to the user's FS environ. */
  2673. 17173   fd = allowed(name_buf, &s_buf, X_BIT);        /* is file executable? */
  2674. 17174   if (fd < 0) return(fd);       /* file was not executable */
  2675. 17175
  2676. 17176   /* Read the file header and extract the segment sizes. */
  2677. 17177   sc = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
  2678. 17178   m = read_header(fd, &ft, &text_bytes, &data_bytes, &bss_bytes, 
  2679. 17179                                         &tot_bytes, &sym_bytes, sc, &pc);
  2680. 17180   if (m < 0) {
  2681. 17181         close(fd);              /* something wrong with header */
  2682. 17182         return(ENOEXEC);
  2683. 17183   }
  2684. 17184
  2685. 17185   /* Fetch the stack from the user before destroying the old core image. */
  2686. 17186   src = (vir_bytes) stack_ptr;
  2687. 17187   dst = (vir_bytes) mbuf;
  2688. 17188   r = sys_copy(who, D, (phys_bytes) src,
  2689. 17189                         MM_PROC_NR, D, (phys_bytes) dst, (phys_bytes)stk_bytes);
  2690. 17190   if (r != OK) {
  2691. 17191         close(fd);              /* can't fetch stack (e.g. bad virtual addr) */
  2692. 17192         return(EACCES);
  2693. 17193   }
  2694. 17194
  2695. 17195   /* Can the process' text be shared with that of one already running? */
  2696. 17196   sh_mp = find_share(rmp, s_buf.st_ino, s_buf.st_dev, s_buf.st_ctime);
  2697. 17197
  2698. 17198   /* Allocate new memory and release old memory.  Fix map and tell kernel. */
  2699. 17199   r = new_mem(sh_mp, text_bytes, data_bytes, bss_bytes, stk_bytes, tot_bytes);
  2700. .Ep 238 src/mm/exec.c
  2701. 17200   if (r != OK) {
  2702. 17201         close(fd);              /* insufficient core or program too big */
  2703. 17202         return(r);
  2704. 17203   }
  2705. 17204
  2706. 17205   /* Save file identification to allow it to be shared. */
  2707. 17206   rmp->mp_ino = s_buf.st_ino;
  2708. 17207   rmp->mp_dev = s_buf.st_dev;
  2709. 17208   rmp->mp_ctime = s_buf.st_ctime;
  2710. 17209
  2711. 17210   /* Patch up stack and copy it from MM to new core image. */
  2712. 17211   vsp = (vir_bytes) rmp->mp_seg[S].mem_vir << CLICK_SHIFT;
  2713. 17212   vsp += (vir_bytes) rmp->mp_seg[S].mem_len << CLICK_SHIFT;
  2714. 17213   vsp -= stk_bytes;
  2715. 17214   patch_ptr(mbuf, vsp);
  2716. 17215   src = (vir_bytes) mbuf;
  2717. 17216   r = sys_copy(MM_PROC_NR, D, (phys_bytes) src,
  2718. 17217                         who, D, (phys_bytes) vsp, (phys_bytes)stk_bytes);
  2719. 17218   if (r != OK) panic("do_exec stack copy err", NO_NUM);
  2720. 17219
  2721. 17220   /* Read in text and data segments. */
  2722. 17221   if (sh_mp != NULL) {
  2723. 17222         lseek(fd, (off_t) text_bytes, SEEK_CUR);  /* shared: skip text */
  2724. 17223   } else {
  2725. 17224         load_seg(fd, T, text_bytes);
  2726. 17225   }
  2727. 17226   load_seg(fd, D, data_bytes);
  2728. 17227
  2729. 17228
  2730. 17229   close(fd);                    /* don't need exec file any more */
  2731. 17230
  2732. 17231   /* Take care of setuid/setgid bits. */
  2733. 17232   if ((rmp->mp_flags & TRACED) == 0) { /* suppress if tracing */
  2734. 17233         if (s_buf.st_mode & I_SET_UID_BIT) {