]> Zhao Yanbai Git Server - minix.git/commitdiff
SMP - fixed usage of stale TLB entries
authorTomas Hruby <thruby@few.vu.nl>
Fri, 4 Nov 2011 17:33:07 +0000 (17:33 +0000)
committerTomas Hruby <tom@minix3.org>
Fri, 13 Jan 2012 11:30:00 +0000 (11:30 +0000)
- when kernel copies from userspace, it must be sure that the TLB
  entries are not stale and thus the referenced memory is correct

- everytime we change a process' address space we set p_stale_tlb
  bits for all CPUs.

- Whenever a cpu finds its bit set when it wants to access the
  process' memory, it refreshes the TLB

- it is more conservative than it needs to be but it has low
  overhead than checking precisely

common/include/minix/bitmap.h
kernel/arch/i386/memory.c
kernel/proc.h
kernel/system/do_update.c
kernel/system/do_vmctl.c

index 6de75fe7a75bbd6272ea0bad2ca9ddec2aa0f2bd..7a4b74a9aba67901824afa2d44933f7dd123a893 100644 (file)
 #define SET_BIT(map,bit) ( MAP_CHUNK(map,bit) |= (1 << CHUNK_OFFSET(bit) ))
 #define UNSET_BIT(map,bit) ( MAP_CHUNK(map,bit) &= ~(1 << CHUNK_OFFSET(bit) ))
 
+#if defined(CONFIG_SMP) && defined(__GNUC__)
+#ifndef __ASSEMBLY__
+static inline bits_fill(bitchunk_t * chunks, unsigned bits)
+{
+       unsigned c, cnt;
+
+       cnt = BITMAP_CHUNKS(bits);
+       for (c = 0; c < cnt; c++)
+               bit_fill(chunks[c]);
+}
+#endif
+#endif
+
+
 #endif /* _BITMAP_H */
index d512f07bf8552a199f04f3db27f30ccc1e79a337..f70d2c0f684e065fa3241e18f20b5ac54faddeb2 100644 (file)
@@ -138,8 +138,8 @@ PRIVATE phys_bytes createpde(
 /*===========================================================================*
  *                             lin_lin_copy                                 *
  *===========================================================================*/
-PRIVATE int lin_lin_copy(const struct proc *srcproc, vir_bytes srclinaddr, 
-       const struct proc *dstproc, vir_bytes dstlinaddr, vir_bytes bytes)
+PRIVATE int lin_lin_copy(struct proc *srcproc, vir_bytes srclinaddr, 
+       struct proc *dstproc, vir_bytes dstlinaddr, vir_bytes bytes)
 {
        u32_t addr;
        proc_nr_t procslot;
@@ -167,6 +167,19 @@ PRIVATE int lin_lin_copy(const struct proc *srcproc, vir_bytes srclinaddr,
                vir_bytes chunk = bytes;
                int changed = 0;
 
+#ifdef CONFIG_SMP
+               unsigned cpu = cpuid;
+
+               if (GET_BIT(srcproc->p_stale_tlb, cpu)) {
+                       changed = 1;
+                       UNSET_BIT(srcproc->p_stale_tlb, cpu);
+               }
+               if (GET_BIT(dstproc->p_stale_tlb, cpu)) {
+                       changed = 1;
+                       UNSET_BIT(dstproc->p_stale_tlb, cpu);
+               }
+#endif
+
                /* Set up 4MB ranges. */
                srcptr = createpde(srcproc, srclinaddr, &chunk, 0, &changed);
                dstptr = createpde(dstproc, dstlinaddr, &chunk, 1, &changed);
index 3ee52abed67b29f6739ae4acb638f547ccf8611d..6d212ae7229b8acf220722d0d5412984b4b34f39 100644 (file)
@@ -38,6 +38,11 @@ struct proc {
   bitchunk_t p_cpu_mask[BITMAP_CHUNKS(CONFIG_MAX_CPUS)]; /* what CPUs is hte
                                                            process allowed to
                                                            run on */
+  bitchunk_t p_stale_tlb[BITMAP_CHUNKS(CONFIG_MAX_CPUS)]; /* On which cpu are
+                               possibly stale entries from this process and has
+                               to be fresed the next kernel touches this
+                               processes memory
+                                */
 #endif
 
   /* Accounting statistics that get passed to the process' scheduler */
index 4833d47741594c194ffe15ea90f124fe8962c4b9..206d825edd3952b7f8eaa7e2c535702e78db5285 100644 (file)
@@ -127,6 +127,11 @@ PUBLIC int do_update(struct proc * caller, message * m_ptr)
   printf("do_update: curr ptproc %d\n", get_cpulocal_var(ptproc)->p_endpoint);
 #endif
 
+#ifdef CONFIG_SMP
+  bits_fill(src_rp->p_stale_tlb, CONFIG_MAX_CPUS);
+  bits_fill(dst_rp->p_stale_tlb, CONFIG_MAX_CPUS);
+#endif
+
   return OK;
 }
 
index 2f10157cdaf4977f9ab92f0f2d6165a57d873aa7..65493973f9a75d2e8132d562c959e2153f44a5d7 100644 (file)
@@ -159,6 +159,16 @@ PUBLIC int do_vmctl(struct proc * caller, message * m_ptr)
                 * cpu
                 */
                RTS_UNSET(p, RTS_VMINHIBIT);
+#ifdef CONFIG_SMP
+               /*
+                * We don't know whether kernel has the changed mapping
+                * installed to access userspace memory. And if so, on what CPU.
+                * More over we don't know what mapping has changed and how and
+                * therefore we must invalidate all mappings we have anywhere.
+                * Next time we map memory, we map it fresh.
+                */
+               bits_fill(p->p_stale_tlb, CONFIG_MAX_CPUS);
+#endif
                return OK;
   }