diff options
author | neal <neal> | 2008-02-16 14:15:36 +0000 |
---|---|---|
committer | neal <neal> | 2008-02-16 14:15:36 +0000 |
commit | b15d17d7d9b95e3e5ba2a800fea8bb81bcf43777 (patch) | |
tree | 779e89a7db7ecaf8abbb6194ccd10acf39a3d818 /viengoos | |
parent | e36e1d5f65c6bbd89a8b7d42ba8f5765f77b551a (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/ChangeLog | 18 | ||||
-rw-r--r-- | viengoos/ager.c | 86 | ||||
-rw-r--r-- | viengoos/object.c | 15 | ||||
-rw-r--r-- | viengoos/object.h | 52 | ||||
-rw-r--r-- | viengoos/server.c | 8 |
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; |