Advertisement
Guest User

Untitled

a guest
Nov 18th, 2017
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 13.53 KB | None | 0 0
  1. /* See COPYRIGHT for copyright information. */
  2.  
  3. #include <inc/x86.h>
  4. #include <inc/error.h>
  5. #include <inc/string.h>
  6. #include <inc/assert.h>
  7.  
  8. #include <kern/env.h>
  9. #include <kern/pmap.h>
  10. #include <kern/trap.h>
  11. #include <kern/syscall.h>
  12. #include <kern/console.h>
  13. #include <kern/sched.h>
  14.  
  15. // Print a string to the system console.
  16. // The string is exactly 'len' characters long.
  17. // Destroys the environment on memory errors.
  18. static void
  19. sys_cputs(const char *s, size_t len)
  20. {
  21.     // Check that the user has permission to read memory [s, s+len).
  22.     // Destroy the environment if not.
  23.  
  24.     // LAB 3: Your code here.
  25.     user_mem_assert(curenv,(void *)s,len, PTE_U); // kontrola pamate, ci moze user citat z pamate s, s+len
  26.     // Print the string supplied by the user.
  27.     cprintf("%.*s", len, s);
  28. }
  29.  
  30. // Read a character from the system console without blocking.
  31. // Returns the character, or 0 if there is no input waiting.
  32. static int
  33. sys_cgetc(void)
  34. {
  35.     return cons_getc();
  36. }
  37.  
  38. // Returns the current environment's envid.
  39. static envid_t
  40. sys_getenvid(void)
  41. {
  42.     return curenv->env_id;
  43. }
  44.  
  45. // Destroy a given environment (possibly the currently running environment).
  46. //
  47. // Returns 0 on success, < 0 on error.  Errors are:
  48. //  -E_BAD_ENV if environment envid doesn't currently exist,
  49. //      or the caller doesn't have permission to change envid.
  50. static int
  51. sys_env_destroy(envid_t envid)
  52. {
  53.     int r;
  54.     struct Env *e;
  55.  
  56.     if ((r = envid2env(envid, &e, 1)) < 0)
  57.         return r;
  58.     if (e == curenv)
  59.         cprintf("[%08x] exiting gracefully\n", curenv->env_id);
  60.     else
  61.         cprintf("[%08x] destroying %08x\n", curenv->env_id, e->env_id);
  62.     env_destroy(e);
  63.     return 0;
  64. }
  65.  
  66. // Deschedule current environment and pick a different one to run.
  67. static void
  68. sys_yield(void)
  69. {
  70.     sched_yield();
  71. }
  72.  
  73. // Allocate a new environment.
  74. // Returns envid of new environment, or < 0 on error.  Errors are:
  75. //  -E_NO_FREE_ENV if no free environment is available.
  76. //  -E_NO_MEM on memory exhaustion.
  77. static envid_t
  78. sys_exofork(void)
  79. {
  80.     // Create the new environment with env_alloc(), from kern/env.c.
  81.     // It should be left as env_alloc created it, except that
  82.     // status is set to ENV_NOT_RUNNABLE, and the register set is copied
  83.     // from the current environment -- but tweaked so sys_exofork
  84.     // will appear to return 0.
  85.  
  86.     // LAB 4: Your code here.
  87.     struct Env *e;
  88.     if(env_alloc(&e, curenv->env_id) < 0){
  89.         return -E_NO_FREE_ENV;
  90.     }
  91.  
  92.     e->env_status = ENV_NOT_RUNNABLE;
  93.     e->env_tf = curenv->env_tf;
  94.     e->env_tf.tf_regs.reg_eax = 0;
  95.  
  96.     return e->env_id;
  97.     //panic("sys_exofork not implemented");
  98. }
  99.  
  100. // Set envid's env_status to status, which must be ENV_RUNNABLE
  101. // or ENV_NOT_RUNNABLE.
  102. //
  103. // Returns 0 on success, < 0 on error.  Errors are:
  104. //  -E_BAD_ENV if environment envid doesn't currently exist,
  105. //      or the caller doesn't have permission to change envid.
  106. //  -E_INVAL if status is not a valid status for an environment.
  107. static int
  108. sys_env_set_status(envid_t envid, int status)
  109. {
  110.     // Hint: Use the 'envid2env' function from kern/env.c to translate an
  111.     // envid to a struct Env.
  112.     // You should set envid2env's third argument to 1, which will
  113.     // check whether the current environment has permission to set
  114.     // envid's status.
  115.  
  116.     // LAB 4: Your code here.
  117.     struct Env *e;
  118.  
  119.     if(envid2env(envid, &e, 1) < 0){            //if environment envid doesn't currently exist or the caller doesn't have permission to change envid.
  120.         return -E_BAD_ENV;
  121.     }
  122.  
  123.     if(status != ENV_RUNNABLE && status != ENV_NOT_RUNNABLE){       //if status is not a valid status for an environment
  124.         return -E_INVAL;
  125.     }
  126.  
  127.     e->env_status = status;
  128.     return 0;
  129.     //panic("sys_env_set_status not implemented");
  130. }
  131.  
  132. // Set the page fault upcall for 'envid' by modifying the corresponding struct
  133. // Env's 'env_pgfault_upcall' field.  When 'envid' causes a page fault, the
  134. // kernel will push a fault record onto the exception stack, then branch to
  135. // 'func'.
  136. //
  137. // Returns 0 on success, < 0 on error.  Errors are:
  138. //  -E_BAD_ENV if environment envid doesn't currently exist,
  139. //      or the caller doesn't have permission to change envid.
  140. static int
  141. sys_env_set_pgfault_upcall(envid_t envid, void *func)
  142. {
  143.     // LAB 4: Your code here.
  144.     //int ret;
  145.     struct Env * env;
  146.  
  147.   //
  148.     if (envid2env(envid, &env, 1) )
  149.         return -E_BAD_ENV;
  150.     env->env_pgfault_upcall = func;
  151.     return 0;
  152.     //panic("sys_env_set_pgfault_upcall not implemented");
  153. }
  154.  
  155. // Allocate a page of memory and map it at 'va' with permission
  156. // 'perm' in the address space of 'envid'.
  157. // The page's contents are set to 0.
  158. // If a page is already mapped at 'va', that page is unmapped as a
  159. // side effect.
  160. //
  161. // perm -- PTE_U | PTE_P must be set, PTE_AVAIL | PTE_W may or may not be set,
  162. //         but no other bits may be set.  See PTE_SYSCALL in inc/mmu.h.
  163. //
  164. // Return 0 on success, < 0 on error.  Errors are:
  165. //  -E_BAD_ENV if environment envid doesn't currently exist,
  166. //      or the caller doesn't have permission to change envid.Fs
  167. //  -E_INVAL if va >= UTOP, or va is not page-aligned.
  168. //  -E_INVAL if perm is inappropriate (see above).
  169. //  -E_NO_MEM if there's no memory to allocate the new page,
  170. //      or to allocate any necessary page tables.
  171. static int
  172. sys_page_alloc(envid_t envid, void *va, int perm)
  173. {
  174.     // Hint: This function is a wrapper around page_alloc() and
  175.     //   page_insert() from kern/pmap.c.
  176.     //   Most of the new code you write should be to check the
  177.     //   parameters for correctness.
  178.     //   If page_insert() fails, remember to free the page you
  179.     //   allocated!
  180.  
  181.     // LAB 4: Your code here.
  182.     struct Env *e;
  183.  
  184.     int ret = envid2env(envid, &e, 1);
  185.  
  186.     if (ret) return ret;
  187.     if (va >= (void*)UTOP) return -E_INVAL;
  188.  
  189.     if((perm & PTE_U & PTE_P) && ((perm | PTE_SYSCALL) != PTE_SYSCALL) )
  190.         return(-E_INVAL);
  191.  
  192.     struct PageInfo *pg = page_alloc(1);
  193.     if (!pg)
  194.         return -E_NO_MEM;
  195.  
  196.     //pg->pp_ref++;
  197.     ret = page_insert(e->env_pgdir, pg, va, perm);
  198.  
  199.     if (ret)
  200.     {
  201.         page_free(pg);
  202.         return ret;
  203.     }
  204.     return 0;
  205.     //panic("sys_page_alloc not implemented");
  206. }
  207.  
  208. // Map the page of memory at 'srcva' in srcenvid's address space
  209. // at 'dstva' in envid's address space with permission 'perm'.
  210. // Perm has the same restrictions as in sys_page_alloc, except
  211. // that it also must not grant write access to a read-only
  212. // page.
  213. //
  214. // Return 0 on success, < 0 on error.  Errors are:
  215. //  -E_BAD_ENV if srcenvid and/or envid doesn't currently exist,
  216. //      or the caller doesn't have permission to change one of them.
  217. //  -E_INVAL if srcva >= UTOP or srcva is not page-aligned,
  218. //      or dstva >= UTOP or dstva is not page-aligned.
  219. //  -E_INVAL is srcva is not mapped in srcenvid's address space.
  220. //  -E_INVAL if perm is inappropriate (see sys_page_alloc).
  221. //  -E_INVAL if (perm & PTE_W), but srcva is read-only in srcenvid's
  222. //      address space.
  223. //  -E_NO_MEM if there's no memory to allocate any necessary page tables.
  224. static int
  225. sys_page_map(envid_t srcenvid, void *srcva,
  226.          envid_t envid, void *dstva, int perm)
  227. {
  228.  
  229.     // Hint: This function is a wrapper around page_lookup() and
  230.     //   page_insert() from kern/pmap.c.
  231.     //   Again, most of the new code you write should be to check the
  232.     //   parameters for correctness.
  233.     //   Use the third argument to page_lookup() to
  234.     //   check the current permissions on the page.
  235.  
  236.     // LAB 4: Your code here.
  237.    
  238.     struct Env *src;
  239.     struct Env *dest;
  240.     if(envid2env(srcenvid,&src,true) || envid2env(envid,&dest,true))
  241.         return(-E_BAD_ENV);
  242.     if(((uintptr_t)srcva >= UTOP) || PGOFF(srcva) || (((uintptr_t)dstva >= UTOP)) || PGOFF(dstva))
  243.         return (-E_INVAL);
  244.     pte_t *pp;
  245.     struct PageInfo *p=page_lookup(src->env_pgdir,srcva,&pp);
  246.     if(p == NULL)
  247.         return(-E_INVAL);
  248.    
  249.     if((perm & PTE_U & PTE_P) && ((perm | PTE_SYSCALL) != PTE_SYSCALL) )
  250.         return(-E_INVAL);
  251.  
  252.     if((!(*pp & PTE_W)) && (perm & PTE_W))
  253.         return (-E_INVAL);
  254.  
  255.     if(page_insert(dest->env_pgdir,p,dstva,perm))
  256.         return(-E_NO_MEM);
  257.     return 0;
  258.  
  259.     //panic("sys_page_map not implemented");
  260. }
  261.  
  262. // Unmap the page of memory at 'va' in the address space of 'envid'.
  263. // If no page is mapped, the function silently succeeds.
  264. //
  265. // Return 0 on success, < 0 on error.  Errors are:
  266. //  -E_BAD_ENV if environment envid doesn't currently exist,
  267. //      or the caller doesn't have permission to change envid.
  268. //  -E_INVAL if va >= UTOP, or va is not page-aligned.
  269. static int
  270. sys_page_unmap(envid_t envid, void *va)
  271. {
  272.     // Hint: This function is a wrapper around page_remove().
  273.  
  274.     // LAB 4: Your code here.
  275.     if (va>=(void*)UTOP || ROUNDDOWN(va,PGSIZE)!=va) //ak virtualna adresa je väcsia alebo rovna od UTOP alebo nie je zarovnana stranka tak vrati error
  276.         return -E_INVAL;
  277.     struct Env *e;
  278.     if ((int)envid2env(envid, &e, 1))
  279.         return -E_BAD_ENV;  //ak enviroment neexistuje alebo nemá oprávnenie tak vráti error
  280.     page_remove(e->env_pgdir, va);  //vymaĹľe stránku
  281.     return 0;
  282.     //panic("sys_page_unmap not implemented");
  283. }
  284.  
  285. // Try to send 'value' to the target env 'envid'.
  286. // If srcva < UTOP, then also send page currently mapped at 'srcva',
  287. // so that receiver gets a duplicate mapping of the same page.
  288. //
  289. // The send fails with a return value of -E_IPC_NOT_RECV if the
  290. // target is not blocked, waiting for an IPC.
  291. //
  292. // The send also can fail for the other reasons listed below.
  293. //
  294. // Otherwise, the send succeeds, and the target's ipc fields are
  295. // updated as follows:
  296. //    env_ipc_recving is set to 0 to block future sends;
  297. //    env_ipc_from is set to the sending envid;
  298. //    env_ipc_value is set to the 'value' parameter;
  299. //    env_ipc_perm is set to 'perm' if a page was transferred, 0 otherwise.
  300. // The target environment is marked runnable again, returning 0
  301. // from the paused sys_ipc_recv system call.  (Hint: does the
  302. // sys_ipc_recv function ever actually return?)
  303. //
  304. // If the sender wants to send a page but the receiver isn't asking for one,
  305. // then no page mapping is transferred, but no error occurs.
  306. // The ipc only happens when no errors occur.
  307. //
  308. // Returns 0 on success, < 0 on error.
  309. // Errors are:
  310. //  -E_BAD_ENV if environment envid doesn't currently exist.
  311. //      (No need to check permissions.)
  312. //  -E_IPC_NOT_RECV if envid is not currently blocked in sys_ipc_recv,
  313. //      or another environment managed to send first.
  314. //  -E_INVAL if srcva < UTOP but srcva is not page-aligned.
  315. //  -E_INVAL if srcva < UTOP and perm is inappropriate
  316. //      (see sys_page_alloc).
  317. //  -E_INVAL if srcva < UTOP but srcva is not mapped in the caller's
  318. //      address space.
  319. //  -E_INVAL if (perm & PTE_W), but srcva is read-only in the
  320. //      current environment's address space.
  321. //  -E_NO_MEM if there's not enough memory to map srcva in envid's
  322. //      address space.
  323. static int
  324. sys_ipc_try_send(envid_t envid, uint32_t value, void *srcva, unsigned perm)
  325. {
  326.     // LAB 4: Your code here.
  327.     struct Env *env;
  328.     if (envid2env (envid, &env, 0) < 0) {  
  329.         return -E_BAD_ENV; //error 1
  330.     }
  331.  
  332.     if (!env->env_ipc_recving) {
  333.         return -E_IPC_NOT_RECV; //error 2
  334.     }
  335.  
  336.     if (srcva < (void *)UTOP)
  337.     {
  338.    
  339.         pte_t* pte;
  340.         struct PageInfo* page = page_lookup(curenv->env_pgdir, srcva, &pte);
  341.  
  342.         if(!page) {
  343.             return -E_INVAL;
  344.         }
  345.        
  346.         if((perm & PTE_W) && !(*pte & PTE_W)) {
  347.             return -E_INVAL;  
  348.         }
  349.  
  350.         if(env->env_ipc_dstva < (void *) UTOP) {
  351.  
  352.             if(page_insert(env->env_pgdir, page, env->env_ipc_dstva, perm)) {  
  353.                 return -E_NO_MEM;
  354.             }
  355.         }
  356.         env->env_ipc_perm = perm;  
  357.     }
  358.     else
  359.     {
  360.         env->env_ipc_perm = 0;
  361.     }
  362.    
  363.    
  364.     env->env_ipc_recving = 0;
  365.     env->env_ipc_from = curenv->env_id;
  366.     env->env_ipc_value = value;
  367.     env->env_status = ENV_RUNNABLE;
  368.     env->env_tf.tf_regs.reg_eax = 0;
  369.  
  370.     return 0;
  371. }
  372.  
  373. // Block until a value is ready.  Record that you want to receive
  374. // using the env_ipc_recving and env_ipc_dstva fields of struct Env,
  375. // mark yourself not runnable, and then give up the CPU.
  376. //
  377. // If 'dstva' is < UTOP, then you are willing to receive a page of data.
  378. // 'dstva' is the virtual address at which the sent page should be mapped.
  379. //
  380. // This function only returns on error, but the system call will eventually
  381. // return 0 on success.
  382. // Return < 0 on error.  Errors are:
  383. //  -E_INVAL if dstva < UTOP but dstva is not page-aligned.
  384. static int
  385. sys_ipc_recv(void *dstva)
  386. {
  387.     // LAB 4: Your code here.
  388.     if(((size_t)dstva < UTOP) && ((size_t)dstva % PGSIZE != 0))
  389.         return -E_INVAL;
  390.  
  391.     curenv->env_ipc_recving = true; // in struct Env - inc/env.h
  392.     curenv->env_ipc_dstva = dstva;
  393.     curenv->env_status = ENV_NOT_RUNNABLE;
  394.     sched_yield();
  395.    
  396.     return 0;
  397. }
  398.  
  399. // Dispatches to the correct kernel function, passing the arguments.
  400. int32_t
  401. syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5)
  402. {
  403.     // Call the function corresponding to the 'syscallno' parameter.
  404.     // Return any appropriate return value.
  405.     // LAB 3: Your code here.
  406.  
  407.     switch (syscallno) { //presmerovanie systemoveho volania na handler
  408.         case SYS_cputs:
  409.             sys_cputs((char *)a1,(size_t)a2);
  410.             return 0;
  411.         case SYS_cgetc:
  412.             return(sys_cgetc());
  413.         case SYS_env_destroy:
  414.             return(sys_env_destroy((envid_t)a1));
  415.         case SYS_getenvid:
  416.             return(sys_getenvid());
  417.         case SYS_yield:
  418.             sys_yield();
  419.             return(0);
  420.         case SYS_exofork:
  421.             return sys_exofork();
  422.         case SYS_page_alloc:
  423.             return sys_page_alloc(a1, (void*)a2, a3);
  424.         case SYS_page_map:
  425.             return sys_page_map(a1, (void*)a2, a3, (void*)a4, a5);
  426.         case SYS_page_unmap:
  427.             return sys_page_unmap(a1, (void*)a2);
  428.         case SYS_env_set_status:
  429.             return sys_env_set_status(a1, a2);
  430.         case SYS_env_set_pgfault_upcall:
  431.             return sys_env_set_pgfault_upcall(a1, (void*)a2);
  432.         case SYS_ipc_recv:
  433.             return sys_ipc_recv((void*)a1);
  434.         case SYS_ipc_try_send:
  435.             return sys_ipc_try_send(a1, a2, (void*)a3, a4);
  436.     default:
  437.         return -E_INVAL;
  438.     }
  439. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement