Emania

E3

May 20th, 2015
382
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.83 KB | None | 0 0
  1. /*
  2.  * Execution Context
  3.  *
  4.  * Copyright (C) 2009-2011 Udo Steinberg <[email protected]>
  5.  * Economic rights: Technische Universitaet Dresden (Germany)
  6.  *
  7.  * This file is part of the NOVA microhypervisor.
  8.  *
  9.  * NOVA is free software: you can redistribute it and/or modify it
  10.  * under the terms of the GNU General Public License version 2 as
  11.  * published by the Free Software Foundation.
  12.  *
  13.  * NOVA is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16.  * GNU General Public License version 2 for more details.
  17.  */
  18.  
  19. #include "bits.h"
  20. #include "ec.h"
  21. #include "assert.h"
  22. #include "cpu.h"
  23. #include "ptab.h"
  24.  
  25. #include "multiboot.h"
  26. #include "elf.h"
  27.  
  28. Ec * Ec::current;
  29.  
  30. // used for idle() and root_invoke()
  31. Ec::Ec (void (*f)(), mword mbi) : cont (f)
  32. {
  33.     regs.eax = mbi;
  34.     regs.cs  = SEL_USER_CODE;
  35.     regs.ds  = SEL_USER_DATA;
  36.     regs.es  = SEL_USER_DATA;
  37.     regs.ss  = SEL_USER_DATA;
  38.     regs.efl = 0x200;           // IF = 1
  39. }
  40.  
  41. // only used by syscall create thread (EC+SC)
  42. Ec::Ec (mword eip)
  43. {
  44.     cont = ret_user_iret;
  45.     regs.cs  = SEL_USER_CODE;
  46.     regs.ds  = SEL_USER_DATA;
  47.     regs.es  = SEL_USER_DATA;
  48.     regs.ss  = SEL_USER_DATA;
  49.     regs.efl = 0x200;           // IF = 1
  50.     regs.eip = eip;
  51. }
  52.  
  53. void Ec::ret_user_sysexit()
  54. {
  55.     asm volatile ("lea %0, %%esp;"
  56.                   "popa;"
  57.                   "sti;"
  58.                   "sysexit"
  59.                   : : "m" (current->regs) : "memory");
  60.  
  61.     UNREACHED;
  62. }
  63.  
  64. void Ec::ret_user_iret()
  65. {
  66.     asm volatile ("lea %0, %%esp;"
  67.                   "popa;"
  68.                   "pop %%gs;"
  69.                   "pop %%fs;"
  70.                   "pop %%es;"
  71.                   "pop %%ds;"
  72.                   "add $8, %%esp;"
  73.                   "iret"
  74.                   : : "m" (current->regs) : "memory");
  75.  
  76.     UNREACHED;
  77. }
  78.  
  79. void Ec::idle()
  80. {
  81.     for (;;)
  82.  
  83.     UNREACHED;
  84. }
  85.  
  86. void Ec::root_invoke()
  87.  {
  88.     //panic ("root_invoke\n");
  89.     printf("Running root_invoke()\n");
  90.     // TODO
  91.     // - current->regs.eax holds pointer to Multiboot info (see multiboot.h)
  92.     // - get mbi remapped, find single Multiboot_module
  93.     // - get module descriptor mapped, print physical addr and size, check
  94.     //   if its size is correct (should be equal to filesize of user.nova)
  95.     // - get module remapped (its an elf binary, see elf.h for details)
  96.     // - sanity check and decode elf binary
  97.     // - finally start user module via sys_user_iret()
  98.     // find multi boot info
  99.     Multiboot * multiboot = static_cast<Multiboot *>(Ptab::remap (current->regs.eax));
  100.  
  101.     if (!(multiboot->flags & 8) || (multiboot->mods_count != 1)){
  102.         panic ("Panika, horii\n");
  103.         }
  104.  
  105.     Multiboot_module module = *static_cast<Multiboot_module *>(Ptab::remap (multiboot->mods_addr));
  106.          printf("module.mod_start is %x and module.mod_end is %x\n", module.mod_start, module.mod_end);
  107.  
  108.          char *cmd_line = static_cast<char *>(Ptab::remap (module.cmdline));
  109.     printf ("cmd_line is %s\n",cmd_line);
  110.  
  111.  
  112.     Eh *elf = static_cast<Eh *>(Ptab::remap (module.mod_start));
  113.  
  114.     int headers = elf->ph_count;                //number of program headers
  115.     current->regs.eip = elf->entry;     //set regs.eip to correct entry point
  116.         int offset1 = elf->ph_offset;
  117.  
  118.  
  119.          //program header
  120.     Ph *ph = static_cast<Ph *>(Ptab::remap (module.mod_start + offset1));        //first header
  121.  
  122.         int i;
  123.         printf("# of Headers %d\n", headers);
  124.     for(i = 0; i < headers; i++){
  125.  
  126.         if (ph->type == Ph::PT_LOAD) {  //from slides page 13.
  127.             printf("---------\n");
  128.                         printf("HEADER %d\n", i);
  129.            
  130.             unsigned attr;
  131.                         if(Ph::PF_W & ph->flags){
  132.                                 attr=7;
  133.                         } else{
  134.                                 attr=5;
  135.                         }
  136.  
  137.                         //if file size is different from memory size
  138.                         if (ph->f_size != ph->m_size){panic ("file size is different from memory size\n");}
  139.  
  140.                         //if virtual address remainder is different from offset remainder
  141.                         if(ph->v_addr % PAGE_SIZE != ph->f_offs % PAGE_SIZE){panic ("virtual address remainder is different from offset remainder\n");}
  142.  
  143.                         printf("ph: v_addr %d, p_addr %d, f_size %d, m_size %d, f_offs %d\n", ph->v_addr, ph->p_addr, ph->f_size, ph->m_size, ph->f_offs);
  144.  
  145.                         int offset2 = ph->f_offs;
  146.             mword phys = align_dn (offset2 + module.mod_start, PAGE_SIZE);
  147.             mword virt = align_dn (ph->v_addr, PAGE_SIZE);       //where to map
  148.             mword size = align_up (ph->f_size, PAGE_SIZE);
  149.  
  150.                         int j;
  151.                         int pages = (size%PAGE_SIZE == 0) ? (size/PAGE_SIZE) : (size/PAGE_SIZE + 1);
  152.  
  153.  
  154.             for(j = 0; j < pages; j++) {
  155.                 Ptab::insert_mapping (virt, phys, attr);
  156.                 virt += PAGE_SIZE;
  157.                 phys += PAGE_SIZE;
  158.             }
  159.         //printf("After alligning:  v_addr %d, p_addr %d, f_size %d, m_size %d, f_offs %d\n", ph->v_addr, ph->p_addr, ph->f_size, ph->m_size, ph->f_offs);
  160.         }
  161.     ph++;
  162.     }
  163.     printf("ret_user_iret()\n");
  164.     ret_user_iret();
  165.  
  166.      FAIL;
  167.  }
  168.  
  169. void Ec::handle_tss()
  170. {
  171.     panic ("Task gate invoked\n");
  172. }
  173.  
  174. void Ec::syscall_handler (uint8 number)
  175. {
  176.     Sys_regs * r = current->sys_regs();
  177.  
  178.     switch (number) {
  179.  
  180.     case 0: // nop
  181.         printf ("syscall %d - nop\n", number);
  182.         break;
  183.  
  184.     case 1: // add
  185.         printf ("syscall %d - add : %lu + %lu\n", number, r->esi, r->edi);
  186.         r->esi += r->edi;
  187.         break;
  188.  
  189.     case 2: // ptab
  190.         printf ("syscall %d - ptab : to be implemented\n", number);
  191.         // TODO
  192.         // - implement functionality in ptab.h and ptab.cc
  193.         // - make Ptab::dump() available though syscall
  194.         // Ptab::dump();
  195.         break;
  196.  
  197.     default:
  198.         printf ("syscall %d - unknown\n", number);
  199.         break;
  200.     };
  201.  
  202.     ret_user_sysexit();
  203.  
  204.     UNREACHED;
  205. }
  206.  
  207. bool Ec::handle_exc_ts (Exc_regs *r)
  208. {
  209.     if (r->user())
  210.         return false;
  211.  
  212.     // SYSENTER with EFLAGS.NT=1 and IRET faulted
  213.     r->efl &= ~0x4000; // nested task eflag
  214.  
  215.     return true;
  216. }
  217.  
  218. void Ec::handle_exc (Exc_regs *r)
  219. {
  220.     if (r->vec == Cpu::EXC_TS && handle_exc_ts (r))
  221.         return;
  222.  
  223.     if (r->vec == Cpu::EXC_GP)
  224.         panic ("%s GP (EIP=%#lx CR2=%#lx)\n", r->eip < LINK_ADDR ? "User" : "Kernel", r->eip, r->cr2);
  225.  
  226.     if (r->vec == Cpu::EXC_PF)
  227.         panic ("%s PF (EIP=%#lx CR2=%#lx)\n", r->eip < LINK_ADDR ? "User" : "Kernel", r->eip, r->cr2);
  228.  
  229.     panic ("%s EXC %#lx (EIP=%#lx CR2=%#lx)\n", r->eip < LINK_ADDR ? "User" : "Kernel", r->vec, r->eip, r->cr2);
  230.  
  231.     UNREACHED;
  232. }
Advertisement
Add Comment
Please, Sign In to add comment