]> Zhao Yanbai Git Server - minix.git/commitdiff
Support for I/O MMU: do not re-use a memory segment until the I/O MMU has
authorPhilip Homburg <philip@cs.vu.nl>
Thu, 21 Feb 2008 16:33:34 +0000 (16:33 +0000)
committerPhilip Homburg <philip@cs.vu.nl>
Thu, 21 Feb 2008 16:33:34 +0000 (16:33 +0000)
removed it from its map.

servers/pm/alloc.c
servers/pm/forkexit.c
servers/pm/main.c
servers/pm/mproc.h
servers/pm/proto.h
servers/pm/table.c
servers/pm/trace.c

index 6035b38cee5e3eb4903d8c44f3022ac3032c0e54..d36c963f35cd9d71270b9a3be5e403dcfe1810bb 100644 (file)
@@ -266,6 +266,215 @@ PUBLIC int mem_holes_copy(struct hole *holecopies, size_t *bytes, u32_t *hi)
        return OK;
 }
 
+#define NR_DMA 16
+
+PRIVATE struct dmatab
+{
+       int dt_flags;
+       endpoint_t dt_proc;
+       phys_bytes dt_base;
+       phys_bytes dt_size;
+       phys_clicks dt_seg_base;
+       phys_clicks dt_seg_size;
+} dmatab[NR_DMA];
+
+#define DTF_INUSE      1
+#define DTF_RELEASE_DMA        2
+#define DTF_RELEASE_SEG        4
+
+PRIVATE endpoint_t iommu_proc_e= ANY;
+
+/*===========================================================================*
+ *                             do_adddma                                    *
+ *===========================================================================*/
+PUBLIC int do_adddma()
+{
+       endpoint_t req_proc_e, target_proc_e;
+       int i, proc_n;
+       phys_bytes base, size;
+       struct mproc *rmp;
+
+       if (mp->mp_effuid != SUPER_USER)
+               return EPERM;
+
+       req_proc_e= m_in.m_source;
+       target_proc_e= m_in.m2_i1;
+       base= m_in.m2_l1;
+       size= m_in.m2_l2;
+
+       iommu_proc_e= req_proc_e;
+
+       /* Find empty slot */
+       for (i= 0; i<NR_DMA; i++)
+       {
+               if (!(dmatab[i].dt_flags & DTF_INUSE))
+                       break;
+       }
+       if (i >= NR_DMA)
+       {
+               printf("pm:do_adddma: dma table full\n");
+               for (i= 0; i<NR_DMA; i++)
+               {
+                       printf("%d: flags 0x%x proc %d base 0x%x size 0x%x\n",
+                               i, dmatab[i].dt_flags,
+                               dmatab[i].dt_proc,
+                               dmatab[i].dt_base,
+                               dmatab[i].dt_size);
+               }
+               panic(__FILE__, "adddma: table full", NO_NUM);
+               return ENOSPC;
+       }
+
+       /* Find target process */
+       if (pm_isokendpt(target_proc_e, &proc_n) != OK)
+       {
+               printf("pm:do_adddma: endpoint %d not found\n", target_proc_e);
+               return EINVAL;
+       }
+       rmp= &mproc[proc_n];
+       rmp->mp_flags |= HAS_DMA;
+
+       dmatab[i].dt_flags= DTF_INUSE;
+       dmatab[i].dt_proc= target_proc_e;
+       dmatab[i].dt_base= base;
+       dmatab[i].dt_size= size;
+
+       return OK;
+}
+
+/*===========================================================================*
+ *                             do_deldma                                    *
+ *===========================================================================*/
+PUBLIC int do_deldma()
+{
+       endpoint_t req_proc_e, target_proc_e;
+       int i, j, proc_n;
+       phys_bytes base, size;
+       struct mproc *rmp;
+
+       if (mp->mp_effuid != SUPER_USER)
+               return EPERM;
+
+       req_proc_e= m_in.m_source;
+       target_proc_e= m_in.m2_i1;
+       base= m_in.m2_l1;
+       size= m_in.m2_l2;
+
+       iommu_proc_e= req_proc_e;
+
+       /* Find slot */
+       for (i= 0; i<NR_DMA; i++)
+       {
+               if (!(dmatab[i].dt_flags & DTF_INUSE))
+                       continue;
+               if (dmatab[i].dt_proc == target_proc_e &&
+                       dmatab[i].dt_base == base &&
+                       dmatab[i].dt_size == size)
+               {
+                       break;
+               }
+       }
+       if (i >= NR_DMA)
+       {
+               printf("pm:do_deldma: slot not found\n");
+               return ESRCH;
+       }
+
+       if (dmatab[i].dt_flags & DTF_RELEASE_SEG)
+       {
+               /* Check if we have to release the segment */
+               for (j= 0; j<NR_DMA; j++)
+               {
+                       if (j == i)
+                               continue;
+                       if (!(dmatab[j].dt_flags & DTF_INUSE))
+                               continue;
+                       if (!(dmatab[j].dt_flags & DTF_RELEASE_SEG))
+                               continue;
+                       if (dmatab[i].dt_proc == target_proc_e)
+                               break;
+               }
+               if (j >= NR_DMA)
+               {
+                       /* Last segment */
+                       free_mem(dmatab[i].dt_seg_base,
+                               dmatab[i].dt_seg_size);
+               }
+       }
+
+       dmatab[i].dt_flags &= ~DTF_INUSE;
+
+       return OK;
+}
+
+/*===========================================================================*
+ *                             do_getdma                                    *
+ *===========================================================================*/
+PUBLIC int do_getdma()
+{
+       endpoint_t req_proc_e, target_proc_e;
+       int i, proc_n;
+       phys_bytes base, size;
+       struct mproc *rmp;
+
+       if (mp->mp_effuid != SUPER_USER)
+               return EPERM;
+
+       req_proc_e= m_in.m_source;
+       iommu_proc_e= req_proc_e;
+
+       /* Find slot to report */
+       for (i= 0; i<NR_DMA; i++)
+       {
+               if (!(dmatab[i].dt_flags & DTF_INUSE))
+                       continue;
+               if (!(dmatab[i].dt_flags & DTF_RELEASE_DMA))
+                       continue;
+
+               printf("do_getdma: setting reply to 0x%x@0x%x proc %d\n",
+                       dmatab[i].dt_size, dmatab[i].dt_base,
+                       dmatab[i].dt_proc);
+               mp->mp_reply.m2_i1= dmatab[i].dt_proc;
+               mp->mp_reply.m2_l1= dmatab[i].dt_base;
+               mp->mp_reply.m2_l2= dmatab[i].dt_size;
+
+               return OK;
+       }
+
+       /* Nothing */
+       return EAGAIN;
+}
+
+
+
+/*===========================================================================*
+ *                             release_dma                                  *
+ *===========================================================================*/
+PUBLIC void release_dma(proc_e, base, size)
+endpoint_t proc_e;
+phys_clicks base;
+phys_clicks size;
+{
+       int i, found_one;;
+
+       found_one= FALSE;
+       for (i= 0; i<NR_DMA; i++)
+       {
+               if (!(dmatab[i].dt_flags & DTF_INUSE))
+                       continue;
+               if (dmatab[i].dt_proc != proc_e)
+                       continue;
+               dmatab[i].dt_flags |= DTF_RELEASE_DMA | DTF_RELEASE_SEG;
+               dmatab[i].dt_seg_base= base;
+               dmatab[i].dt_seg_size= size;
+               found_one= TRUE;
+       }
+       if (found_one)
+               notify(iommu_proc_e);
+       else
+               free_mem(base, size);
+}
+
 #if ENABLE_SWAP
 /*===========================================================================*
  *                             swap_on                                      *
index 2a7c3567f3ae366ad86c0380f3efa7875f4c5001..1352472738d2edcdfb450e53f271f513e0eb32dc 100644 (file)
@@ -314,7 +314,7 @@ int for_trace;
   if (parent_waiting && right_child) {
        tell_parent(rmp);               /* tell parent */
   } else {
-       rmp->mp_flags &= (IN_USE|PRIV_PROC);
+       rmp->mp_flags &= (IN_USE|PRIV_PROC|HAS_DMA);
        rmp->mp_flags |= ZOMBIE;        /* parent not waiting, zombify child */
        sig_proc(p_mp, SIGCHLD);        /* send parent a "child died" signal */
   }
index 44fd5e31865b276f75173e119af9ba47106648a5..1f6123d69db6fffeda3b61699fe682201848d063 100644 (file)
@@ -155,10 +155,10 @@ PUBLIC int main()
                 */
                if ((rmp->mp_flags & (REPLY | ONSWAP | IN_USE | ZOMBIE)) ==
                   (REPLY | IN_USE)) {
-                       if ((s=send(rmp->mp_endpoint, &rmp->mp_reply)) != OK) {
-                               printf("PM can't reply to %d (%s)\n",
-                                       rmp->mp_endpoint, rmp->mp_name);
-                               panic(__FILE__, "PM can't reply", NO_NUM);
+                       s=sendnb(rmp->mp_endpoint, &rmp->mp_reply);
+                       if (s != OK) {
+                               printf("PM can't reply to %d (%s): %d\n",
+                                       rmp->mp_endpoint, rmp->mp_name, s);
                        }
                        rmp->mp_flags &= ~REPLY;
                }
@@ -713,6 +713,7 @@ message *m_ptr;
 {
        int r, proc_e, proc_n;
        struct mproc *rmp;
+       phys_clicks base, size;
 
        switch(m_ptr->m_type)
        {
@@ -749,9 +750,23 @@ message *m_ptr;
                        free_mem(rmp->mp_seg[T].mem_phys,       
                                rmp->mp_seg[T].mem_len);
                }
-               /* Free the data and stack segments. */
-               free_mem(rmp->mp_seg[D].mem_phys, rmp->mp_seg[S].mem_vir +
-                       rmp->mp_seg[S].mem_len - rmp->mp_seg[D].mem_vir);
+
+               base= rmp->mp_seg[D].mem_phys;
+               size= rmp->mp_seg[S].mem_vir + rmp->mp_seg[S].mem_len -
+                       rmp->mp_seg[D].mem_vir;
+
+               if (rmp->mp_flags & HAS_DMA)
+               {
+                       /* Delay freeing the memory segmented until the
+                        * DMA buffers have been released.
+                        */
+                       release_dma(rmp->mp_endpoint, base, size);
+               }
+               else
+               {
+                       /* Free the data and stack segments. */
+                       free_mem(base, size);
+               }
 
                if (m_ptr->m_type == PM_EXIT_REPLY_TR &&
                        rmp->mp_parent != INIT_PROC_NR)
@@ -847,7 +862,7 @@ message *m_ptr;
                        tell_parent(rmp);               /* tell parent */
                } else {
                        /* parent not waiting, zombify child */
-                       rmp->mp_flags &= (IN_USE|PRIV_PROC);
+                       rmp->mp_flags &= (IN_USE|PRIV_PROC|HAS_DMA);
                        rmp->mp_flags |= ZOMBIE;
                        /* send parent a "child died" signal */
                        sig_proc(p_mp, SIGCHLD);
@@ -872,9 +887,23 @@ message *m_ptr;
                        free_mem(rmp->mp_seg[T].mem_phys,       
                                rmp->mp_seg[T].mem_len);
                }
-               /* Free the data and stack segments. */
-               free_mem(rmp->mp_seg[D].mem_phys, rmp->mp_seg[S].mem_vir +
-                       rmp->mp_seg[S].mem_len - rmp->mp_seg[D].mem_vir);
+
+               base= rmp->mp_seg[D].mem_phys;
+               size= rmp->mp_seg[S].mem_vir + rmp->mp_seg[S].mem_len -
+                       rmp->mp_seg[D].mem_vir;
+
+               if (rmp->mp_flags & HAS_DMA)
+               {
+                       /* Delay freeing the memory segmented until the
+                        * DMA buffers have been released.
+                        */
+                       release_dma(rmp->mp_endpoint, base, size);
+               }
+               else
+               {
+                       /* Free the data and stack segments. */
+                       free_mem(base, size);
+               }
 
                /* Clean up if the parent has collected the exit
                 * status
index 047de24af29115a990bcb0cc7facae3293ae2214..624e6e6f15d0650366760f553c1b10aee7b82c37 100644 (file)
@@ -85,6 +85,9 @@ EXTERN struct mproc {
 #define PM_SIG_PENDING 0x4000  /* process got a signal while waiting for FS */
 #define PARTIAL_EXEC   0x8000  /* Process got a new map but no content */
 #define TOLD_PARENT   0x10000  /* Parent wait() completed, ZOMBIE off */
+#define HAS_DMA              0x20000   /* Process directly or indirectly granted
+                                * DMA buffers.
+                                */
 
 #define NIL_MPROC ((struct mproc *) 0)
 
index 1cad787a85d7fed9c44a7949c426c78917d9f470..392f8f6e3956ed842e90e499d2dbdcb37655a320 100644 (file)
@@ -11,6 +11,11 @@ struct memory;
 _PROTOTYPE( phys_clicks alloc_mem, (phys_clicks clicks)                        );
 _PROTOTYPE( void free_mem, (phys_clicks base, phys_clicks clicks)      );
 _PROTOTYPE( void mem_init, (struct memory *chunks, phys_clicks *free)  );
+_PROTOTYPE( int do_adddma, (void)                                      );
+_PROTOTYPE( int do_deldma, (void)                                      );
+_PROTOTYPE( int do_getdma, (void)                                      );
+_PROTOTYPE( void release_dma, (endpoint_t proc_e, phys_clicks base,
+                                               phys_clicks size)       );
 #if ENABLE_SWAP
 _PROTOTYPE( int swap_on, (char *file, u32_t offset, u32_t size)        );
 _PROTOTYPE( int swap_off, (void)                                       );
index 35e0d1c9c2fb2f9c999169704e8d972f5a68e8fd..d25867cc55afebeb1c5f7c8b46b511023d6c463a 100644 (file)
@@ -13,7 +13,7 @@
 /* Miscellaneous */
 char core_name[] = "core";     /* file name where core images are produced */
 
-_PROTOTYPE (int (*call_vec[NCALLS]), (void) ) = {
+_PROTOTYPE (int (*call_vec[]), (void) ) = {
        no_sys,         /*  0 = unused  */
        do_pm_exit,     /*  1 = exit    */
        do_fork,        /*  2 = fork    */
@@ -115,6 +115,17 @@ _PROTOTYPE (int (*call_vec[NCALLS]), (void) ) = {
        do_getsysinfo_up,/* 97 = getsysinfo_up */
        do_sprofile,    /* 98 = sprofile */
        do_cprofile,    /* 99 = cprofile */
+       no_sys,         /* 100 = unused */
+       no_sys,         /* 101 = unused */
+       no_sys,         /* 102 = unused */
+       no_sys,         /* 103 = unused */
+       no_sys,         /* 104 = unused */
+       no_sys,         /* 105 = unused */
+       no_sys,         /* 106 = unused */
+       no_sys,         /* 107 = unused */
+       do_adddma,      /* 108 = adddma */
+       do_deldma,      /* 109 = deldma */
+       do_getdma,      /* 110 = getdma */
 };
 /* This should not fail with "array size is negative": */
 extern int dummy[sizeof(call_vec) == NCALLS * sizeof(call_vec[0]) ? 1 : -1];
index 8f4c3731461302006cf229bb49d56e3842a36962..2618097354ea182328aa65b3fa3cc1b002398218 100644 (file)
@@ -69,6 +69,15 @@ PUBLIC int do_trace()
        if ((child=find_proc(m_in.pid))==NIL_MPROC)
                return(ESRCH);
 
+       /* Should check for shared text */
+
+       /* Make sure the text segment is not used as a source for shared
+        * text.
+        */
+       child->mp_ino= 0;
+       child->mp_dev= 0;
+       child->mp_ctime= 0;
+
        r= sys_trace(m_in.request,child->mp_endpoint,m_in.taddr,&m_in.data);
        if (r != OK) return(r);