1/** 2 * \file 3 * \brief Domain management 4 * 5 * \bug This is misnamed. It is "local kernel notification 6 * management", part of which is domain management. 7 */ 8 9/* 10 * Copyright (c) 2010, 2011, ETH Zurich. 11 * All rights reserved. 12 * 13 * This file is distributed under the terms in the attached LICENSE file. 14 * If you do not find this file, copies can be found by writing to: 15 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 16 */ 17 18#include <barrelfish/barrelfish.h> 19#include <barrelfish/core_state.h> 20#include <barrelfish/dispatch.h> 21#include "monitor.h" 22#include <if/mem_defs.h> 23 24#if !defined(__arm__) && !defined(__aarch64__) 25static errval_t reclaim_memory(genpaddr_t base, uint8_t bits) 26{ 27 /* XXX: mem client is only defined for the bsp core. 28 * For app cores, just return */ 29 if (get_mem_client() == NULL) { 30 return SYS_ERR_OK; 31 } 32 33 // Fabricate new RAM cap and hand back to mem_serv 34 struct capability c = { 35 .type = ObjType_RAM, 36 .u.ram = { 37 .base = base, 38 .bytes = 1UL << bits, 39 } 40 }; 41 struct capref ramcap; 42 errval_t err = slot_alloc(&ramcap); 43 if(err_is_fail(err)) { 44 return err; 45 } 46 47 err = monitor_cap_create(ramcap, &c, my_core_id); 48 if(err_is_fail(err)) { 49 return err; 50 } 51 52 struct ram_alloc_state *ram_alloc_state = get_ram_alloc_state(); 53 errval_t result; 54 thread_mutex_lock(&ram_alloc_state->ram_alloc_lock); 55 struct mem_binding *b = get_mem_client(); 56 // XXX: This should not be an RPC! It could stall the monitor, but 57 // we trust mem_serv for the moment. 58 err = b->rpc_tx_vtbl.free_monitor(b, ramcap, base, bits, &result); 59 thread_mutex_unlock(&ram_alloc_state->ram_alloc_lock); 60 if(err_is_fail(err)) { 61 return err; 62 } 63 if(err_is_fail(result)) { 64 return result; 65 } 66 67 // XXX: this shouldn't be necessary as free_monitor uses give_away_cap 68 err = cap_destroy(ramcap); 69 if (err_no(err) == SYS_ERR_CAP_NOT_FOUND) { 70 err = SYS_ERR_OK; 71 } 72 if (err_is_fail(err)) { 73 DEBUG_ERR(err, "destroying reclaimed cap"); 74 } 75 return err; 76} 77#endif 78 79static void handle_notification(void *arg) 80{ 81 struct lmp_endpoint *ep = arg; 82 errval_t err; 83 84 do { // consume messages 85 struct lmp_recv_msg msg = LMP_RECV_MSG_INIT; 86 err = lmp_endpoint_recv(ep, &msg.buf, NULL); 87 88 if (err_is_ok(err)) { 89 if(msg.buf.msglen == 1) { 90 domainid_t domid = msg.words[0]; 91 92 // XXX: This is done by spawnd now 93 if (domid != 0) { 94 debug_printf("Dispatcher with domain ID %"PRIuDOMAINID" exited\n", 95 domid); 96 } 97 } else if(msg.buf.msglen == sizeof(struct RAM) / sizeof(uintptr_t) + 1) { 98#if !defined(__arm__) && !defined(__aarch64__) 99 //defined(__x86_64__) || defined(__i386__) 100 union rammsg { 101 uintptr_t msgwords[LMP_MSG_LENGTH]; 102 struct RAM ram; 103 } *u; 104 u = (union rammsg *)&msg.words; 105 106 /* printf("%s.%d: RAM cap deleted, base = %" PRIxGENPADDR ", bits = %u\n", */ 107 /* disp_name(), disp_get_core_id(), ram->base, ram->bits); */ 108 109 err = reclaim_memory(u->ram.base, log2ceil(u->ram.bytes)); 110 if(err_is_fail(err)) { 111 DEBUG_ERR(err, "reclaim_memory"); 112 } 113#else 114 /* XXX: Disabling memory reclamation on ARM. I 115 * couldn't get the compiler to accept the above code 116 * due to strict aliasing restrictions. I do believe 117 * though that the above is according to the C99 118 * spec. Please help fix it, so that it can be 119 * enabled. 120 */ 121#endif 122 } else { 123 printf("%s: Unknown kernel notification of length %zu received\n", 124 disp_name(), msg.buf.msglen); 125 } 126 } else if (err_no(err) != LIB_ERR_NO_LMP_MSG) { 127 DEBUG_ERR(err, "unexpected error from lmp_endpoint_recv"); 128 } 129 } while(err_is_ok(err)); 130 131 // re-register 132 struct event_closure cl = { 133 .handler = handle_notification, 134 .arg = arg, 135 }; 136 err = lmp_endpoint_register(ep, get_default_waitset(), cl); 137 assert(err_is_ok(err)); 138} 139 140void domain_mgmt_init(void) 141{ 142 errval_t err; 143 144 /* Register notification endpoint with kernel */ 145 struct capref epcap; 146 struct lmp_endpoint *notifyep; 147 // XXX: This has to be huge so we can receive a batch of 148 // notifications when deleting CNodes recursively. 149 err = endpoint_create(100 * 12, &epcap, ¬ifyep); 150 if (err_is_fail(err)) { 151 USER_PANIC_ERR(err, "failed creating endpoint"); 152 } 153 154 // register to receive on this endpoint 155 struct event_closure cl = { 156 .handler = handle_notification, 157 .arg = notifyep, 158 }; 159 err = lmp_endpoint_register(notifyep, get_default_waitset(), cl); 160 assert(err_is_ok(err)); 161 162 err = invoke_monitor_register(epcap); 163 if(err_is_fail(err)) { 164 USER_PANIC_ERR(err, "Could not register with kernel"); 165 } 166 else { 167#ifdef DEBUG_MONITOR_ALL 168 debug_printf("monitor ep registered\n"); 169#endif 170 } 171} 172