summaryrefslogtreecommitdiff
path: root/viengoos
diff options
context:
space:
mode:
authorneal <neal>2008-02-16 14:15:36 +0000
committerneal <neal>2008-02-16 14:15:36 +0000
commitb15d17d7d9b95e3e5ba2a800fea8bb81bcf43777 (patch)
tree779e89a7db7ecaf8abbb6194ccd10acf39a3d818 /viengoos
parente36e1d5f65c6bbd89a8b7d42ba8f5765f77b551a (diff)
2008-02-16 Neal H. Walfield <neal@gnu.org>
* object.h (struct object_desc): Add fields mapped, shared and floating. (object_desc_unmap): Only unmap a page if DESC->MAPPED is true. (object_desc_flush): Call object_desc_unmap rather than copying the code. * object.c (object_find_soft): If ODESC->FLOATING is true, claim the object. Set ODESC->FLOATING to false. (folio_object_alloc): After clearing the page, flush it and then ODESC->DIRTY to false. Set ODESC->SHARED to false. * ager.c (SAMPLES): Rename from this... (FREQ): ... to this. Update users. (ager_loop): Don't just flush the whole address space; every FREQ iterations, unmap shared objects, set DESC->MAPPED to false, and DESC->FLOATING to true. * server.c (server_loop): When mapping a page, record it.
Diffstat (limited to 'viengoos')
-rw-r--r--viengoos/ChangeLog18
-rw-r--r--viengoos/ager.c86
-rw-r--r--viengoos/object.c15
-rw-r--r--viengoos/object.h52
-rw-r--r--viengoos/server.c8
5 files changed, 111 insertions, 68 deletions
diff --git a/viengoos/ChangeLog b/viengoos/ChangeLog
index 166faa7..84ae39d 100644
--- a/viengoos/ChangeLog
+++ b/viengoos/ChangeLog
@@ -1,5 +1,23 @@
2008-02-16 Neal H. Walfield <neal@gnu.org>
+ * object.h (struct object_desc): Add fields mapped, shared and
+ floating.
+ (object_desc_unmap): Only unmap a page if DESC->MAPPED is true.
+ (object_desc_flush): Call object_desc_unmap rather than copying
+ the code.
+ * object.c (object_find_soft): If ODESC->FLOATING is true, claim
+ the object. Set ODESC->FLOATING to false.
+ (folio_object_alloc): After clearing the page, flush it and then
+ ODESC->DIRTY to false. Set ODESC->SHARED to false.
+ * ager.c (SAMPLES): Rename from this...
+ (FREQ): ... to this. Update users.
+ (ager_loop): Don't just flush the whole address space; every FREQ
+ iterations, unmap shared objects, set DESC->MAPPED to false, and
+ DESC->FLOATING to true.
+ * server.c (server_loop): When mapping a page, record it.
+
+2008-02-16 Neal H. Walfield <neal@gnu.org>
+
* cap.c (cap_shootdown): Fix scoping problem. If an object of a
folio is identical with the start capability, return.
diff --git a/viengoos/ager.c b/viengoos/ager.c
index 5e16e99..e8a1b42 100644
--- a/viengoos/ager.c
+++ b/viengoos/ager.c
@@ -29,31 +29,27 @@
#include "activity.h"
#include "zalloc.h"
-/* When frames are shared amoung multiple activities, the first
- activity to access the frame is charged. This is unfair; the cost
- needs to be distributed among all users. We approximate this by
- changing the owner of the frame on a hard fault. The problem is
- how to observe these faults: l4_unmap does not tell us who faulted
- (indeed, which would be insufficient for us anyways--we need an
- activity).
-
- When a new user comes along, this is not a problem: the new user
- faults and the ownership changes.
-
- When there are multiple users and the main user becomes inactive,
- no minor faults will be observed.
-
- There are a couple of ways to see these faults: we unmap the frame
- when it becomes inactive. This will eventually happen unless the
- page is really hammered. This is the strategy we use when
- UNMAP_INACTIVE is non-zero.
-
- We can periodically unmap all pages. This is nice as ownership
- will regularly change hands for all frames, even those that don't
- become inactive. This helps to distribute the costs. This is the
- strategy we use when UNMAP_PERIODICALLY is non-zero. */
-#define UNMAP_INACTIVE 0
-#define UNMAP_PERIODICALLY 1
+/* A frames has a single claimant. When a frame is shared amoung
+ multiple activities, the first activity to access claims it (is
+ charged). To distribute the cost among all users, we charge a user
+ proportional to the frequency of access. This is achieved by
+ periodically revoking access to the frame and transferring the
+ claim to the next activity to access the frame.
+
+ The unmapping is required as when there are multiple users and the
+ main user becomes no longer users he frame, the frame may remain
+ active as other users continue to access it. The main user will
+ remain the claimant, however, as no minor faults will be observed
+ (the frame is active).
+
+ XXX: Currently, we unmap shared, mapped frames every every few
+ seconds. Unfortunately, this can lead to an attack whereby a
+ malicious activity is able to freeload by carefully timing access
+ to frames. Instead, we should unmap based on a random
+ distribution. */
+
+/* The frequency with which we assemble statistics. */
+#define FREQ (sizeof (((struct object_desc *)0)->age) * 8)
void
ager_loop (l4_thread_id_t main_thread)
@@ -101,8 +97,19 @@ ager_loop (l4_thread_id_t main_thread)
descs[count] = desc;
objects[count] = object_desc_to_object (desc);
+
fpages[count] = l4_fpage ((l4_word_t) objects[count], PAGESIZE);
+ if (iterations == FREQ && desc->shared)
+ /* we periodically unmap shared frames. See above for
+ details. */
+ {
+ fpages[count] = l4_fpage_add_rights (fpages[count],
+ L4_FPAGE_FULLY_ACCESSIBLE);
+ desc->mapped = false;
+ desc->floating = true;
+ }
+
count ++;
}
@@ -227,8 +234,7 @@ ager_loop (l4_thread_id_t main_thread)
}
/* Upmap everything every two seconds. */
-#define SAMPLES sizeof (((struct object_desc *)0)->age) * 8
- if (iterations == SAMPLES)
+ if (iterations == FREQ)
{
ss_mutex_lock (&kernel_lock);
@@ -280,10 +286,10 @@ ager_loop (l4_thread_id_t main_thread)
doit (child, frames);
}
- ACTIVITY_STATS (activity)->clean /= SAMPLES;
- ACTIVITY_STATS (activity)->dirty /= SAMPLES;
- ACTIVITY_STATS (activity)->active /= SAMPLES;
- ACTIVITY_STATS (activity)->active_local /= SAMPLES;
+ ACTIVITY_STATS (activity)->clean /= FREQ;
+ ACTIVITY_STATS (activity)->dirty /= FREQ;
+ ACTIVITY_STATS (activity)->active /= FREQ;
+ ACTIVITY_STATS (activity)->active_local /= FREQ;
activity->current_period ++;
if (activity->current_period == ACTIVITY_STATS_PERIODS + 1)
@@ -294,20 +300,16 @@ ager_loop (l4_thread_id_t main_thread)
}
doit (root_activity, memory_total);
-#if UNMAP_PERIODICALLY
- /* XXX: Walk all in-memory activities, advance the stat
- structure and average the fields that need averaging. */
- debug (1, "Unmapping all (%d of %d free). "
- "last interation now inactive: %d, now active: %d",
- zalloc_memory, memory_total, became_inactive, became_active);
-
- l4_unmap_fpage (l4_fpage_add_rights (L4_COMPLETE_ADDRESS_SPACE,
- L4_FPAGE_FULLY_ACCESSIBLE));
- iterations = 0;
-#endif
+ debug (1, "%d of %d (%d%%) free; "
+ "since last interation: %d became inactive, %d active",
+ zalloc_memory, memory_total,
+ (zalloc_memory * 100) / memory_total,
+ became_inactive, became_active);
ss_mutex_unlock (&kernel_lock);
+
+ iterations = 0;
}
else
iterations ++;
diff --git a/viengoos/object.c b/viengoos/object.c
index 8a4697f..d1b393f 100644
--- a/viengoos/object.c
+++ b/viengoos/object.c
@@ -236,10 +236,14 @@ object_find_soft (struct activity *activity, oid_t oid,
return object;
}
- if (! odesc->activity || ! object_active (odesc))
- /* Either the object is unowned or it is inactive. Claim
- ownership. */
- object_desc_claim (activity, odesc, policy, true);
+ if ((! odesc->activity || ! object_active (odesc))
+ || (odesc->activity != activity && odesc->floating))
+ /* Either the object is unowned, it is inactive or it is floating
+ (owned byt looking for a new owner). Claim ownership. */
+ {
+ object_desc_claim (activity, odesc, policy, true);
+ odesc->floating = false;
+ }
return object;
}
@@ -578,10 +582,13 @@ folio_object_alloc (struct activity *activity,
cap_shootdown (activity, &cap);
memset ((void *) object, 0, PAGESIZE);
+ object_desc_flush (odesc);
+ odesc->dirty = false;
object_desc_claim (activity, odesc, policy, true);
odesc->type = type;
+ odesc->shared = false;
}
}
diff --git a/viengoos/object.h b/viengoos/object.h
index fdd711c..6a3713e 100644
--- a/viengoos/object.h
+++ b/viengoos/object.h
@@ -123,14 +123,22 @@ struct object_desc
{
/* The version and OID of the object. */
oid_t oid;
- l4_word_t version : CAP_VERSION_BITS;
- l4_word_t type : CAP_TYPE_BITS;
+ uintptr_t version : CAP_VERSION_BITS;
+ uintptr_t type : CAP_TYPE_BITS;
/* Whether the page is dirty. */
- l4_word_t dirty: 1;
+ uintptr_t dirty: 1;
/* Whether the object has been selected for eviction. */
- l4_word_t eviction_candidate : 1;
+ uintptr_t eviction_candidate : 1;
+
+ /* Whether the object has been mapped to a process. */
+ uintptr_t mapped : 1;
+ /* Whether the object has been used by multiple activities. */
+ uintptr_t shared : 1;
+ /* The object is shared. The next one to access the object should
+ claim it. */
+ uintptr_t floating : 1;
/* Whether the object is live. */
bool live;
@@ -311,14 +319,22 @@ object_type (struct object *object)
static inline void
object_desc_unmap (struct object_desc *desc)
{
+ assert (desc->live);
+
+ if (desc->mapped)
+ {
#ifndef _L4_TEST_ENVIRONMENT
- struct object *object = object_desc_to_object (desc);
+ struct object *object = object_desc_to_object (desc);
- l4_fpage_t flush = l4_fpage ((l4_word_t) object, PAGESIZE);
- l4_fpage_t unmap = l4_fpage_add_rights (flush, L4_FPAGE_FULLY_ACCESSIBLE);
+ l4_fpage_t flush = l4_fpage ((l4_word_t) object, PAGESIZE);
+ l4_fpage_t unmap = l4_fpage_add_rights (flush,
+ L4_FPAGE_FULLY_ACCESSIBLE);
- desc->dirty |= !!l4_was_written (l4_unmap_fpage (unmap));
+ desc->dirty |= !!l4_was_written (l4_unmap_fpage (unmap));
#endif
+
+ desc->mapped = false;
+ }
}
/* Unmaps the object corresponding to DESC from all clients and also
@@ -326,20 +342,18 @@ object_desc_unmap (struct object_desc *desc)
static inline void
object_desc_flush (struct object_desc *desc)
{
-#ifndef _L4_TEST_ENVIRONMENT
- assert (desc->live);
-
- struct object *object = object_desc_to_object (desc);
-
- l4_fpage_t flush = l4_fpage ((l4_word_t) object, PAGESIZE);
- l4_fpage_t unmap = l4_fpage_add_rights (flush, L4_FPAGE_FULLY_ACCESSIBLE);
-
- desc->dirty |= !!l4_was_written (l4_unmap_fpage (unmap));
+ object_desc_unmap (desc);
if (! desc->dirty)
- /* We may have dirty it. */
- desc->dirty |= !!l4_was_written (l4_flush (flush));
+ /* We only need to see if we dirtied it. */
+ {
+#ifndef _L4_TEST_ENVIRONMENT
+ struct object *object = object_desc_to_object (desc);
+ l4_fpage_t flush = l4_fpage ((l4_word_t) object, PAGESIZE);
+
+ desc->dirty |= !!l4_was_written (l4_flush (flush));
#endif
+ }
}
/* Transfer ownership of DESC to the activity ACTIVITY. If ACTIVITY
diff --git a/viengoos/server.c b/viengoos/server.c
index 30f8d66..70ee657 100644
--- a/viengoos/server.c
+++ b/viengoos/server.c
@@ -142,8 +142,7 @@ server_loop (void)
ADDR (page_addr, ADDR_BITS - PAGESIZE_LOG2),
w ? cap_page : cap_rpage,
&writable);
- if (cap.type != cap_void)
- page = cap_to_object (activity, &cap);
+ page = cap_to_object (activity, &cap);
bool raise_fault = false;
if (! page)
@@ -182,13 +181,16 @@ server_loop (void)
continue;
}
- // DEBUG ("Replying with addr %x", (uintptr_t) page);
+ DEBUG (5, "Fault at %x, replying with %p (" OID_FMT ")",
+ fault, page, OID_PRINTF (cap.oid));
l4_map_item_t map_item
= l4_map_item (l4_fpage_add_rights (l4_fpage ((uintptr_t) page,
PAGESIZE),
access),
page_addr);
+ object_to_object_desc (page)->mapped = true;
+
/* Formulate the reply message. */
l4_pagefault_reply_formulate_in (msg, &map_item);
do_reply = 1;