]> Zhao Yanbai Git Server - minix.git/commitdiff
IOPL, VM, and serial debug output (disabled).
authorPhilip Homburg <philip@cs.vu.nl>
Fri, 30 Sep 2005 12:54:59 +0000 (12:54 +0000)
committerPhilip Homburg <philip@cs.vu.nl>
Fri, 30 Sep 2005 12:54:59 +0000 (12:54 +0000)
13 files changed:
kernel/glo.h
kernel/klib386.s
kernel/proc.h
kernel/proto.h
kernel/system.c
kernel/system.h
kernel/system/Makefile
kernel/system/do_exit.c
kernel/system/do_iopenable.c [new file with mode: 0644]
kernel/system/do_vm.c [new file with mode: 0644]
kernel/system/do_vm_setbuf.c [new file with mode: 0644]
kernel/table.c
kernel/utility.c

index bbc3e8383c1ae4ab48195988143fc252f484a736..e37b7a4d4eea6782fa2601a3c3f0721a018e5f8e 100755 (executable)
@@ -44,6 +44,12 @@ EXTERN int irq_use;                          /* map of all in-use irq's */
 /* Miscellaneous. */
 EXTERN reg_t mon_ss, mon_sp;           /* boot monitor stack */
 EXTERN int mon_return;                 /* true if we can return to monitor */
+EXTERN int do_serial_debug;
+
+/* VM */
+EXTERN phys_bytes vm_base;
+EXTERN phys_bytes vm_size;
+EXTERN phys_bytes vm_mem_high;
 
 /* Variables that are initialized elsewhere are just extern here. */
 extern struct boot_image image[];      /* system image processes */
index e258e664478aa92de42d0c2583ca64bfff092a2d..d8c90a11b26ff83df312ff066884812a8ca2ca9c 100755 (executable)
@@ -33,6 +33,9 @@
 .define        _level0         ! call a function at level 0
 .define        _read_tsc       ! read the cycle counter (Pentium and up)
 .define        _read_cpu_flags ! read the cpu flags
+.define        _read_cr0       ! read cr0
+.define        _write_cr0      ! write a value in cr0
+.define        _write_cr3      ! write a value in cr3 (root of the page table)
 
 ! The routines only guarantee to preserve the registers the C compiler
 ! expects to be preserved (ebx, esi, edi, ebp, esp, segment registers, and
@@ -572,3 +575,41 @@ _read_cpu_flags:
        popf
        ret
 
+
+!*===========================================================================*
+!*                           read_cr0                                       *
+!*===========================================================================*
+! PUBLIC unsigned long read_cr0(void);
+_read_cr0:
+       push    ebp
+       mov     ebp, esp
+       mov     eax, cr0
+       pop     ebp
+       ret
+
+!*===========================================================================*
+!*                           write_cr0                                      *
+!*===========================================================================*
+! PUBLIC void write_cr0(unsigned long value);
+_write_cr0:
+       push    ebp
+       mov     ebp, esp
+       mov     eax, 8(ebp)
+       mov     cr0, eax
+       jmp     0f              ! A jump is required for some flags
+0:
+       pop     ebp
+       ret
+
+!*===========================================================================*
+!*                           write_cr3                                      *
+!*===========================================================================*
+! PUBLIC void write_cr3(unsigned long value);
+_write_cr3:
+       push    ebp
+       mov     ebp, esp
+       mov     eax, 8(ebp)
+       mov     cr3, eax
+       pop     ebp
+       ret
+
index 5e4a1f07e03e9e9c58c95dc4d4fe784fc1b75661..7f6a3278032b3afbdbd59ef387b939c6421260ff 100755 (executable)
@@ -30,6 +30,8 @@ struct proc {
   struct priv *p_priv;         /* system privileges structure */
   char p_rts_flags;            /* SENDING, RECEIVING, etc. */
 
+  char p_misc_flags;           /* Flags that do suspend the process */
+
   char p_priority;             /* current scheduling priority */
   char p_max_priority;         /* maximum scheduling priority */
   char p_ticks_left;           /* number of scheduling ticks left */
@@ -66,6 +68,9 @@ struct proc {
 #define P_STOP         0x40    /* set when process is being traced */
 #define NO_PRIV                0x80    /* keep forked system process from running */
 
+/* Misc flags */
+#define MF_VM          0x01    /* Process uses VM */
+
 /* Scheduling priorities for p_priority. Values must start at zero (highest
  * priority) and increment.  Priorities of the processes in the boot image 
  * can be set in table.c. IDLE must have a queue for itself, to prevent low 
index f2530549d769897c63d8648dd2b54fc291ec5376..1d69a95196dd1b32c266f5ee64d8b3272604a499 100755 (executable)
@@ -82,6 +82,9 @@ _PROTOTYPE( void reset, (void)                                                );
 _PROTOTYPE( void level0, (void (*func)(void))                          );
 _PROTOTYPE( void monitor, (void)                                       );
 _PROTOTYPE( void read_tsc, (unsigned long *high, unsigned long *low)   );
+_PROTOTYPE( unsigned long read_cr0, (void)                             );
+_PROTOTYPE( void write_cr0, (unsigned long value)                      );
+_PROTOTYPE( void write_cr3, (unsigned long value)                      );
 _PROTOTYPE( unsigned long read_cpu_flags, (void)                       );
 
 /* mpx*.s */
@@ -142,6 +145,9 @@ _PROTOTYPE( void phys2seg, (u16_t *seg, vir_bytes *off, phys_bytes phys));
 _PROTOTYPE( void enable_iop, (struct proc *pp)                         );
 _PROTOTYPE( void alloc_segments, (struct proc *rp)                     );
 
+/* system/do_vm.c */
+_PROTOTYPE( void vm_map_default, (struct proc *pp)                     );
+
 #endif /* (CHIP == INTEL) */
 
 #if (CHIP == M68000)
index 5019dd94ea36e88d086499be9369a2d94580363c..59f79b4a0931d8d4353d4cd37753ccf98998c956 100755 (executable)
@@ -75,7 +75,8 @@ PUBLIC void sys_task()
       caller_ptr = proc_addr(m.m_source);      
 
       /* See if the caller made a valid request and try to handle it. */
-      if (! (priv(caller_ptr)->s_call_mask & (1<<call_nr))) {
+      if (! (priv(caller_ptr)->s_call_mask & (1<<call_nr)) &&
+         m.m_type != SYS_IOPENABLE ) {
          kprintf("SYSTEM: request %d from %d denied.\n", call_nr,m.m_source);
          result = ECALLDENIED;                 /* illegal message type */
       } else if (call_nr >= NR_SYS_CALLS) {            /* check call number */
@@ -152,6 +153,8 @@ PRIVATE void initialize(void)
   map(SYS_NEWMAP, do_newmap);          /* set up a process memory map */
   map(SYS_SEGCTL, do_segctl);          /* add segment and get selector */
   map(SYS_MEMSET, do_memset);          /* write char to memory area */
+  map(SYS_VM_SETBUF, do_vm_setbuf);    /* PM passes buffer for page tables */
+  map(SYS_VM_MAP, do_vm_map);          /* Map/unmap physical (device) memory */
 
   /* Copying. */
   map(SYS_UMAP, do_umap);              /* map virtual to physical address */
@@ -167,6 +170,7 @@ PRIVATE void initialize(void)
   /* System control. */
   map(SYS_ABORT, do_abort);            /* abort MINIX */
   map(SYS_GETINFO, do_getinfo);        /* request system information */ 
+  map(SYS_IOPENABLE, do_iopenable);    /* Enable I/O */
 }
 
 /*===========================================================================*
index 64dcad14500cc3e223924adaf0b295b6bc0110fa..c2a25035dd43b972d2b57b9ead13026646c49a2a 100644 (file)
@@ -92,6 +92,9 @@ _PROTOTYPE( int do_memset, (message *m_ptr) );
 #define do_memset do_unused
 #endif
 
+_PROTOTYPE( int do_vm_setbuf, (message *m_ptr) );
+_PROTOTYPE( int do_vm_map, (message *m_ptr) );
+
 _PROTOTYPE( int do_abort, (message *m_ptr) );
 #if ! USE_ABORT
 #define do_abort do_unused
@@ -169,5 +172,7 @@ _PROTOTYPE( int do_setalarm, (message *m_ptr) );
 #define do_setalarm do_unused
 #endif
 
+_PROTOTYPE( int do_iopenable, (message *m_ptr) );      
+
 #endif /* SYSTEM_H */
 
index f852ae6667ddc1e5580b7e1cfbb96ae78bac8c72..8d18fbefadb542cffa6a6f19e635b1087b31b211 100644 (file)
@@ -44,6 +44,9 @@ OBJECTS       = \
        $(SYSTEM)(do_sigreturn.o) \
        $(SYSTEM)(do_abort.o) \
        $(SYSTEM)(do_getinfo.o) \
+       $(SYSTEM)(do_iopenable.o) \
+       $(SYSTEM)(do_vm.o) \
+       $(SYSTEM)(do_vm_setbuf.o) \
 
 $(SYSTEM):     $(OBJECTS)
        aal cr $@ *.o
@@ -138,3 +141,13 @@ $(SYSTEM)(do_privctl.o):   do_privctl.c
 
 $(SYSTEM)(do_segctl.o):        do_segctl.c
        $(CC) do_segctl.c
+
+$(SYSTEM)(do_iopenable.o):     do_iopenable.c
+       $(CC) do_iopenable.c
+
+$(SYSTEM)(do_vm.o):    do_vm.o
+do_vm.o:       do_vm.c
+       $(CC) do_vm.c
+
+$(SYSTEM)(do_vm_setbuf.o):     do_vm_setbuf.c
+       $(CC) do_vm_setbuf.c
index c76ecfa9a188f45e82317c2dfaeeafd8f9a81a3b..982bd66264eb839f430f14bc2884484ce21a4d9e 100644 (file)
@@ -84,6 +84,10 @@ register struct proc *rc;            /* slot of process to clean up */
       }
   }
 
+  /* Clean up virtual memory */
+  if (rc->p_misc_flags & MF_VM)
+       vm_map_default(rc);
+
   /* Now it is safe to release the process table slot. If this is a system 
    * process, also release its privilege structure.  Further cleanup is not
    * needed at this point. All important fields are reinitialized when the 
diff --git a/kernel/system/do_iopenable.c b/kernel/system/do_iopenable.c
new file mode 100644 (file)
index 0000000..71b33ca
--- /dev/null
@@ -0,0 +1,33 @@
+/* The system call implemented in this file:
+ *   m_type:   SYS_IOPENABLE
+ *
+ * The parameters for this system call are:
+ *    m2_i2:   PROC_NR         (process to give I/O Protection Level bits)
+ *
+ * Author:
+ *    Jorrit N. Herder <jnherder@cs.vu.nl>
+ */
+
+#include "../kernel.h"
+#include "../system.h"
+
+/*===========================================================================*
+ *                             do_iopenable                                 *
+ *===========================================================================*/
+PUBLIC int do_iopenable(m_ptr)
+register message *m_ptr;       /* pointer to request message */
+{
+  int proc_nr;
+
+#if 1 /* ENABLE_USERPRIV && ENABLE_USERIOPL */
+  proc_nr= m_ptr->PROC_NR;
+  if (proc_nr == SELF)
+       proc_nr = m_ptr->m_source;
+  enable_iop(proc_addr(proc_nr));
+  return(OK);
+#else
+  return(EPERM);
+#endif
+}
+
+
diff --git a/kernel/system/do_vm.c b/kernel/system/do_vm.c
new file mode 100644 (file)
index 0000000..f1114fa
--- /dev/null
@@ -0,0 +1,245 @@
+/* The system call implemented in this file:
+ *   m_type:   SYS_VM_MAP
+ *
+ * The parameters for this system call are:
+ *    m4_l1:   Process that requests map
+ *    m4_l2:   Map (TRUE) or unmap (FALSE)
+ *    m4_l3:   Base address
+ *    m4_l4:   Size 
+ *    m4_l5:   Memory address 
+ */
+#include "../system.h"
+
+#include <sys/vm.h>
+
+PRIVATE int vm_needs_init= 1;
+PRIVATE u32_t vm_cr3;
+
+FORWARD _PROTOTYPE( void vm_init, (void)                               );
+FORWARD _PROTOTYPE( void phys_put32, (phys_bytes addr, u32_t value)    );
+FORWARD _PROTOTYPE( u32_t phys_get32, (phys_bytes addr)                        );
+FORWARD _PROTOTYPE( void vm_set_cr3, (u32_t value)                     );
+FORWARD _PROTOTYPE( void set_cr3, (void)                               );
+FORWARD _PROTOTYPE( void vm_enable_paging, (void)                      );
+FORWARD _PROTOTYPE( void map_range, (u32_t base, u32_t size,
+                                                       u32_t offset)   );
+
+/*===========================================================================*
+ *                             do_vm_setbuf                                 *
+ *===========================================================================*/
+PUBLIC int do_vm_map(m_ptr)
+message *m_ptr;                        /* pointer to request message */
+{
+       int proc_nr, do_map;
+       phys_bytes base, size, offset, p_phys;
+       struct proc *pp;
+
+       /* do_serial_debug= 1; */
+
+       kprintf("in do_vm_map\n");
+
+       if (vm_needs_init)
+       {
+               vm_needs_init= 0;
+               vm_init();
+       }
+
+       proc_nr= m_ptr->m4_l1;
+       do_map= m_ptr->m4_l2;
+       base= m_ptr->m4_l3;
+       size= m_ptr->m4_l4;
+       offset= m_ptr->m4_l5;
+
+       pp= proc_addr(proc_nr);
+       p_phys= umap_local(pp, D, base, size);
+       if (p_phys == 0)
+               return EFAULT;
+       kprintf("got 0x%x for 0x%x [D].mem_start = 0x%x\n", 
+               p_phys, base, pp->p_memmap[D].mem_phys);
+
+       if (do_map)
+       {
+               kprintf(
+               "do_vm_map: mapping 0x%x @ 0x%x to 0x%x @ proc %d\n",
+                       size, offset, base, proc_nr);
+               pp->p_misc_flags |= MF_VM;
+
+               map_range(p_phys, size, offset);
+       }
+       else
+       {
+               map_range(p_phys, size, p_phys);
+       }
+       vm_set_cr3(vm_cr3);
+
+       return OK;
+}
+
+/*===========================================================================*
+ *                             vm_map_default                               *
+ *===========================================================================*/
+PUBLIC void vm_map_default(pp)
+struct proc *pp;
+{
+       phys_bytes base_clicks, size_clicks;
+
+       if (vm_needs_init)
+               panic("vm_map_default: VM not initialized?", NO_NUM);
+       pp->p_misc_flags &= ~MF_VM;
+       base_clicks= pp->p_memmap[D].mem_phys;
+       size_clicks= pp->p_memmap[S].mem_phys+pp->p_memmap[S].mem_len -
+               base_clicks;
+       map_range(base_clicks << CLICK_SHIFT, size_clicks << CLICK_SHIFT,
+               base_clicks << CLICK_SHIFT);
+       vm_set_cr3(vm_cr3);
+}
+
+PRIVATE void vm_init(void)
+{
+       int o;
+       phys_bytes p, pt_size;
+       phys_bytes vm_dir_base, vm_pt_base, phys_mem;
+       u32_t entry;
+       unsigned pages;
+
+       kprintf("in vm_init\n");
+
+kprintf("%s, %d\n", __FILE__, __LINE__);
+       if (!vm_size)
+               panic("vm_init: no space for page tables", NO_NUM);
+
+       /* Align page directory */
+       o= (vm_base % PAGE_SIZE);
+       if (o != 0)
+               o= PAGE_SIZE-o;
+       vm_dir_base= vm_base+o;
+
+       /* Page tables start after the page directory */
+       vm_pt_base= vm_dir_base+PAGE_SIZE;
+
+       pt_size= (vm_base+vm_size)-vm_pt_base;
+       pt_size -= (pt_size % PAGE_SIZE);
+
+       /* Compute the number of pages based on vm_mem_high */
+       pages= (vm_mem_high-1)/PAGE_SIZE + 1;
+
+       if (pages * I386_VM_PT_ENT_SIZE > pt_size)
+               panic("vm_init: page table too small", NO_NUM);
+
+kprintf("%s, %d\n", __FILE__, __LINE__);
+
+       for (p= 0; p*I386_VM_PT_ENT_SIZE < pt_size; p++)
+       {
+               phys_mem= p*PAGE_SIZE;
+               entry= phys_mem | I386_VM_USER | I386_VM_WRITE |
+                       I386_VM_PRESENT;
+               if (phys_mem >= vm_mem_high)
+                       entry= 0;
+               phys_put32(vm_pt_base + p*I386_VM_PT_ENT_SIZE, entry);
+       }
+
+       for (p= 0; p < I386_VM_DIR_ENTRIES; p++)
+       {
+               phys_mem= vm_pt_base + p*PAGE_SIZE;
+               entry= phys_mem | I386_VM_USER | I386_VM_WRITE |
+                       I386_VM_PRESENT;
+               if (phys_mem >= vm_pt_base + pt_size)
+                       entry= 0;
+               phys_put32(vm_dir_base + p*I386_VM_PT_ENT_SIZE, entry);
+       }
+
+kprintf("%s, %d\n", __FILE__, __LINE__);
+       vm_set_cr3(vm_dir_base);
+       level0(vm_enable_paging);
+}
+
+PRIVATE void phys_put32(addr, value)
+phys_bytes addr;
+u32_t value;
+{
+#if 0
+kprintf("%s, %d: %d bytes from 0x%x to 0x%x\n", __FILE__, __LINE__,
+       sizeof(value), vir2phys((vir_bytes)&value), addr);
+#endif
+
+       phys_copy(vir2phys((vir_bytes)&value), addr, sizeof(value));
+}
+
+PRIVATE u32_t phys_get32(addr)
+phys_bytes addr;
+{
+       u32_t value;
+
+       phys_copy(addr, vir2phys((vir_bytes)&value), sizeof(value));
+
+       return value;
+}
+
+PRIVATE void vm_set_cr3(value)
+u32_t value;
+{
+kprintf("%s, %d\n", __FILE__, __LINE__);
+       vm_cr3= value;
+kprintf("%s, %d\n", __FILE__, __LINE__);
+       level0(set_cr3);
+kprintf("%s, %d\n", __FILE__, __LINE__);
+}
+
+PRIVATE void set_cr3()
+{
+       write_cr3(vm_cr3);
+}
+
+PRIVATE void vm_enable_paging(void)
+{
+       u32_t cr0;
+
+       cr0= read_cr0();
+       write_cr0(cr0 | I386_CR0_PG);
+}
+
+PRIVATE void map_range(base, size, offset)
+u32_t base;
+u32_t size;
+u32_t offset;
+{
+       u32_t curr_pt, curr_pt_addr, entry;
+       int dir_ent, pt_ent;
+
+       if (base % PAGE_SIZE != 0)
+               panic("map_range: bad base", base);
+       if (size % PAGE_SIZE != 0)
+               panic("map_range: bad size", size);
+       if (offset % PAGE_SIZE != 0)
+               panic("map_range: bad offset", offset);
+
+       curr_pt= -1;
+       curr_pt_addr= 0;
+       while (size != 0)
+       {
+               dir_ent= (base >> I386_VM_DIR_ENT_SHIFT);
+               pt_ent= (base >> I386_VM_PT_ENT_SHIFT) & I386_VM_PT_ENT_MASK;
+               if (dir_ent != curr_pt)
+               {
+                       /* Get address of page table */
+                       curr_pt= dir_ent;
+                       curr_pt_addr= phys_get32(vm_cr3 +
+                               dir_ent * I386_VM_PT_ENT_SIZE);
+                       curr_pt_addr &= I386_VM_ADDR_MASK;
+                       kprintf("got address 0x%x for page table 0x%x\n",
+                               curr_pt_addr, curr_pt);
+               }
+               entry= offset | I386_VM_USER | I386_VM_WRITE |
+                       I386_VM_PRESENT;
+#if 0
+               kprintf(
+               "putting 0x%x at dir_ent 0x%x, pt_ent 0x%x (addr 0x%x)\n",
+                       entry,  dir_ent, pt_ent,
+                       curr_pt_addr + pt_ent * I386_VM_PT_ENT_SIZE);
+#endif
+               phys_put32(curr_pt_addr + pt_ent * I386_VM_PT_ENT_SIZE, entry);
+               offset += PAGE_SIZE;
+               base += PAGE_SIZE;
+               size -= PAGE_SIZE;
+       }
+}
diff --git a/kernel/system/do_vm_setbuf.c b/kernel/system/do_vm_setbuf.c
new file mode 100644 (file)
index 0000000..75c9af7
--- /dev/null
@@ -0,0 +1,25 @@
+/* The system call implemented in this file:
+ *   m_type:   SYS_VM_SETBUF
+ *
+ * The parameters for this system call are:
+ *    m4_l1:   Start of the buffer
+ *    m4_l2:   Length of the buffer
+ *    m4_l3:   End of main memory
+ */
+#include "../system.h"
+
+/*===========================================================================*
+ *                             do_vm_setbuf                                 *
+ *===========================================================================*/
+PUBLIC int do_vm_setbuf(m_ptr)
+message *m_ptr;                        /* pointer to request message */
+{
+       vm_base= m_ptr->m4_l1;
+       vm_size= m_ptr->m4_l2;
+       vm_mem_high= m_ptr->m4_l3;
+
+       kprintf("do_vm_setbuf: got 0x%x @ 0x%x for 0x%x\n",
+               vm_size, vm_base, vm_mem_high);
+
+       return OK;
+}
index 0f55f32b2e6929f2bf13014cc592ebbca7d7b029..9c9687af714b1727433b5d315067e5102cce7b87 100755 (executable)
@@ -66,9 +66,9 @@ PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)];
  * structure 0 is shared by user processes. 
  */
 #define s(n)           (1 << s_nr_to_id(n))
-#define SRV_M (~0)
-#define SYS_M (~0)
-#define USR_M (s(PM_PROC_NR) | s(FS_PROC_NR) | s(RS_PROC_NR))
+#define SRV_M  (~0)
+#define SYS_M  (~0)
+#define USR_M (s(PM_PROC_NR) | s(FS_PROC_NR) | s(RS_PROC_NR) | s(SYSTEM))
 #define DRV_M (USR_M | s(SYSTEM) | s(CLOCK) | s(LOG_PROC_NR) | s(TTY_PROC_NR))
 
 /* Define kernel calls that processes are allowed to make. This is not looking
@@ -84,7 +84,7 @@ PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)];
     | c(SYS_GETINFO) | c(SYS_EXIT) | c(SYS_TIMES) | c(SYS_SETALARM))
 #define DRV_C  (FS_C | c(SYS_SEGCTL) | c(SYS_IRQCTL) | c(SYS_INT86) \
     | c(SYS_DEVIO) | c(SYS_VDEVIO) | c(SYS_SDEVIO)) 
-#define MEM_C  (DRV_C | c(SYS_PHYSCOPY) | c(SYS_PHYSVCOPY))
+#define MEM_C  (DRV_C | c(SYS_PHYSCOPY) | c(SYS_PHYSVCOPY) | c(SYS_VM_MAP))
 
 /* The system image table lists all programs that are part of the boot image. 
  * The order of the entries here MUST agree with the order of the programs
index fe7ee36075426a416950519488a43056fba0994d..47fcbb460f821120b40c7c0d6a903db402b6d8be 100755 (executable)
@@ -23,6 +23,7 @@
 
 #define END_OF_KMESS   -1
 FORWARD _PROTOTYPE(void kputc, (int c));
+FORWARD _PROTOTYPE( void ser_putc, (char c));
 
 /*===========================================================================*
  *                             panic                                        *
@@ -130,6 +131,8 @@ int c;                                      /* character to append */
  * the to output driver if an END_OF_KMESS is encountered. 
  */
   if (c != END_OF_KMESS) {
+      if (do_serial_debug)
+       ser_putc(c);
       kmess.km_buf[kmess.km_next] = c; /* put normal char in buffer */
       if (kmess.km_size < KMESS_BUF_SIZE)
           kmess.km_size += 1;          
@@ -139,3 +142,24 @@ int c;                                     /* character to append */
   }
 }
 
+#define COM1_BASE      0x3F8
+#define COM1_THR       (COM1_BASE + 0)
+#define                LSR_THRE        0x20
+#define COM1_LSR       (COM1_BASE + 5)
+
+PRIVATE void ser_putc(char c)
+{
+       int i;
+       int lsr, thr;
+
+       return;
+
+       lsr= COM1_LSR;
+       thr= COM1_THR;
+       for (i= 0; i<100000; i++)
+       {
+               if (inb(lsr) & LSR_THRE)
+                       break;
+       }
+       outb(thr, c);
+}