From 1cffa69d2cbdf2e84fc653621de27a73292fd40f Mon Sep 17 00:00:00 2001 From: Philip Homburg Date: Thu, 21 Feb 2008 16:33:34 +0000 Subject: [PATCH] Support for I/O MMU: do not re-use a memory segment until the I/O MMU has removed it from its map. --- servers/pm/alloc.c | 209 ++++++++++++++++++++++++++++++++++++++++++ servers/pm/forkexit.c | 2 +- servers/pm/main.c | 51 ++++++++--- servers/pm/mproc.h | 3 + servers/pm/proto.h | 5 + servers/pm/table.c | 13 ++- servers/pm/trace.c | 9 ++ 7 files changed, 279 insertions(+), 13 deletions(-) diff --git a/servers/pm/alloc.c b/servers/pm/alloc.c index 6035b38ce..d36c963f3 100644 --- a/servers/pm/alloc.c +++ b/servers/pm/alloc.c @@ -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) + { + printf("pm:do_adddma: dma table full\n"); + for (i= 0; imp_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) + { + 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) + { + /* 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; imp_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; imp_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 */ } diff --git a/servers/pm/main.c b/servers/pm/main.c index 44fd5e318..1f6123d69 100644 --- a/servers/pm/main.c +++ b/servers/pm/main.c @@ -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 diff --git a/servers/pm/mproc.h b/servers/pm/mproc.h index 047de24af..624e6e6f1 100644 --- a/servers/pm/mproc.h +++ b/servers/pm/mproc.h @@ -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) diff --git a/servers/pm/proto.h b/servers/pm/proto.h index 1cad787a8..392f8f6e3 100644 --- a/servers/pm/proto.h +++ b/servers/pm/proto.h @@ -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) ); diff --git a/servers/pm/table.c b/servers/pm/table.c index 35e0d1c9c..d25867cc5 100644 --- a/servers/pm/table.c +++ b/servers/pm/table.c @@ -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]; diff --git a/servers/pm/trace.c b/servers/pm/trace.c index 8f4c37314..261809735 100644 --- a/servers/pm/trace.c +++ b/servers/pm/trace.c @@ -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);