diff --git a/composition_scripts/sched.toml b/composition_scripts/sched.toml index 2e6d05e6b2..42fc9cc7ae 100644 --- a/composition_scripts/sched.toml +++ b/composition_scripts/sched.toml @@ -4,14 +4,14 @@ description = "Simplest system with both capability manager and scheduler, from [[components]] name = "booter" img = "no_interface.llbooter" -implements = [{interface = "init"}, {interface = "addr"}] +implements = [{interface = "init"}, {interface = "addr"}, {interface = "scb_mapping"}] deps = [{srv = "kernel", interface = "init", variant = "kernel"}] constructor = "kernel" [[components]] name = "capmgr" img = "capmgr.simple" -deps = [{srv = "booter", interface = "init"}, {srv = "booter", interface = "addr"}] +deps = [{srv = "booter", interface = "init"}, {srv = "booter", interface = "addr"}, {srv = "booter", interface = "scb_mapping"}] implements = [{interface = "capmgr"}, {interface = "init"}, {interface = "memmgr"}, {interface = "capmgr_create"}] constructor = "booter" diff --git a/src/components/implementation/capmgr/Makefile b/src/components/implementation/capmgr/Makefile index 72bb34a16b..8925e464d4 100644 --- a/src/components/implementation/capmgr/Makefile +++ b/src/components/implementation/capmgr/Makefile @@ -9,7 +9,7 @@ INTERFACE_EXPORTS = capmgr INTERFACE_DEPENDENCIES = # The library dependencies this component is reliant on for # compilation/linking (this is a list of directory names in lib/) -LIBRARY_DEPENDENCIES = component +LIBRARY_DEPENDENCIES = component dcb # Note: Both the interface and library dependencies should be # *minimal*. That is to say that removing a dependency should cause # the build to fail. The build system does not validate this diff --git a/src/components/implementation/capmgr/simple/Makefile b/src/components/implementation/capmgr/simple/Makefile index 6c5aa6bfa9..77d8326a62 100644 --- a/src/components/implementation/capmgr/simple/Makefile +++ b/src/components/implementation/capmgr/simple/Makefile @@ -9,7 +9,7 @@ INTERFACE_EXPORTS = capmgr capmgr_create init INTERFACE_DEPENDENCIES = init addr # The library dependencies this component is reliant on for # compilation/linking (this is a list of directory names in lib/) -LIBRARY_DEPENDENCIES = component sl_kernel initargs crt util +LIBRARY_DEPENDENCIES = component sl_kernel initargs crt util dcb # Note: Both the interface and library dependencies should be # *minimal*. That is to say that removing a dependency should cause # the build to fail. The build system does not validate this diff --git a/src/components/implementation/capmgr/simple/capmgr.c b/src/components/implementation/capmgr/simple/capmgr.c index 17fd7a6556..025bb4c5ee 100644 --- a/src/components/implementation/capmgr/simple/capmgr.c +++ b/src/components/implementation/capmgr/simple/capmgr.c @@ -16,6 +16,7 @@ #include #include #include +#include struct cm_rcv { struct crt_rcv rcv; @@ -41,6 +42,11 @@ struct cm_asnd { struct crt_asnd asnd; }; +struct cm_dcb { + dcbcap_t dcb_cap; + vaddr_t dcb_addr; +}; + /* * Shared memory should be manager -> client, and between * point-to-point channel recipients @@ -76,6 +82,9 @@ SS_STATIC_SLAB(asnd, struct cm_asnd, MAX_NUM_THREADS); SS_STATIC_SLAB(page, struct mm_page, MM_NPAGES); SS_STATIC_SLAB(span, struct mm_span, MM_NPAGES); +#define MAX_DCB_NUM PAGE_SIZE/sizeof(struct cos_dcb_info) +SS_STATIC_SLAB(dcb, struct cm_dcb, MAX_DCB_NUM); + static struct cm_comp * cm_self(void) { @@ -155,6 +164,22 @@ cm_thd_alloc_in(struct cm_comp *c, struct cm_comp *sched, thdclosure_index_t clo return t; } +struct cm_dcb * +cm_dcb_alloc_in(struct cm_comp *sched) +{ + compid_t id = (compid_t)cos_inv_token(); + struct cm_dcb *d = ss_dcb_alloc(); + dcbcap_t dcbcap; + vaddr_t dcbaddr = 0; + + dcbcap = crt_dcb_create_in(&sched->comp, &dcbaddr); + d->dcb_addr = dcbaddr; + d->dcb_cap = dcbcap; + ss_dcb_activate(d); + + return d; +} + /** * Allocate a page from the pool of physical memory into a component. * @@ -339,6 +364,28 @@ capmgr_comp_sched_get(compid_t cid) return atoi(sched); } +extern scbcap_t scb_mapping(compid_t id, vaddr_t scb_uaddr); + +int +capmgr_scb_mapping(void) +{ + compid_t schedid = (compid_t)cos_inv_token(); + struct cos_compinfo *ci; + struct cm_comp *s; + vaddr_t scb_uaddr; + + s = ss_comp_get(schedid); + assert(s); + + ci = cos_compinfo_get(s->comp.comp_res); + assert(ci); + + scb_uaddr = cos_page_bump_intern_valloc(ci, COS_SCB_SIZE); + assert(scb_uaddr); + + return scb_mapping(schedid, scb_uaddr); +} + static void capmgr_comp_init(void) { @@ -495,11 +542,13 @@ init_exit(int retval) } thdcap_t -capmgr_thd_create_ext(spdid_t client, thdclosure_index_t idx, thdid_t *tid) +capmgr_thd_create_ext(spdid_t client, thdclosure_index_t idx, thdid_t *tid, struct cos_dcb_info **dcb) +//capmgr_thd_create_ext(spdid_t client, thdclosure_index_t idx, thdid_t *tid) { compid_t schedid = (compid_t)cos_inv_token(); struct cm_thd *t; struct cm_comp *s, *c; + struct cm_dcb *d; if (schedid != capmgr_comp_sched_get(client)) { /* don't have permission to create execution in that component. */ @@ -510,6 +559,9 @@ capmgr_thd_create_ext(spdid_t client, thdclosure_index_t idx, thdid_t *tid) c = ss_comp_get(client); s = ss_comp_get(schedid); + + d = cm_dcb_alloc_in(s); + if (!c || !s) return 0; t = cm_thd_alloc_in(c, s, idx); if (!t) { @@ -517,6 +569,7 @@ capmgr_thd_create_ext(spdid_t client, thdclosure_index_t idx, thdid_t *tid) return 0; } *tid = t->thd.tid; + *dcb = (struct cos_dcb_info *)d->dcb_addr; return t->aliased_cap; } @@ -524,32 +577,39 @@ capmgr_thd_create_ext(spdid_t client, thdclosure_index_t idx, thdid_t *tid) thdcap_t capmgr_initthd_create(spdid_t client, thdid_t *tid) { - return capmgr_thd_create_ext(client, 0, tid); + struct cos_dcb_info *dcb; + + return capmgr_thd_create_ext(client, 0, tid, &dcb); } thdcap_t capmgr_initaep_create(spdid_t child, struct cos_aep_info *aep, int owntc, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, asndcap_t *sndret) { BUG(); return 0; } thdcap_t -capmgr_thd_create_thunk(thdclosure_index_t idx, thdid_t *tid) +capmgr_thd_create_thunk(thdclosure_index_t idx, thdid_t *tid, struct cos_dcb_info **dcb) { compid_t client = (compid_t)cos_inv_token(); - struct cm_thd *t; + struct cm_thd *t; struct cm_comp *c; + struct cm_dcb *d; assert(client > 0 && client <= MAX_NUM_COMPS); c = ss_comp_get(client); + d = cm_dcb_alloc_in(c); + assert(d); t = cm_thd_alloc_in(c, c, idx); + if (!t) { /* TODO: release resources */ return 0; } *tid = t->thd.tid; + *dcb = (struct cos_dcb_info *)d->dcb_addr; return t->aliased_cap; } -thdcap_t capmgr_aep_create_thunk(struct cos_aep_info *a, thdclosure_index_t idx, int owntc, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax) { BUG(); return 0; } -thdcap_t capmgr_aep_create_ext(spdid_t child, struct cos_aep_info *a, thdclosure_index_t idx, int owntc, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, arcvcap_t *extrcv) { BUG(); return 0; } +thdcap_t capmgr_aep_create_thunk(struct cos_aep_info *a, thdclosure_index_t idx, int owntc, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, struct cos_dcb_info **dcb) { BUG(); return 0; } +thdcap_t capmgr_aep_create_ext(spdid_t child, struct cos_aep_info *a, thdclosure_index_t idx, int owntc, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, struct cos_dcb_info **dcb, arcvcap_t *extrcv) { BUG(); return 0; } arcvcap_t capmgr_rcv_create(spdid_t child, thdid_t tid, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax) { BUG(); return 0; } asndcap_t capmgr_asnd_create(spdid_t child, thdid_t t) { BUG(); return 0; } asndcap_t capmgr_asnd_rcv_create(arcvcap_t rcv) { BUG(); return 0; } @@ -581,8 +641,11 @@ cos_init(void) if (!cm_comp_self_alloc("capmgr")) BUG(); /* Initialize the other component's for which we're responsible */ + scbcap_t scbc = cos_scb_alloc(ci); + assert(scbc); + vaddr_t scb_uaddr = cos_page_bump_intern_valloc(ci, COS_SCB_SIZE); + if (cos_scb_mapping(ci, ci->comp_cap, ci->pgtbl_cap, scbc, scb_uaddr)) BUG(); capmgr_comp_init(); - sl_init(SL_MIN_PERIOD_US); return; diff --git a/src/components/implementation/no_interface/llbooter/Makefile b/src/components/implementation/no_interface/llbooter/Makefile index 4ea23edb09..8dd9a68ef2 100644 --- a/src/components/implementation/no_interface/llbooter/Makefile +++ b/src/components/implementation/no_interface/llbooter/Makefile @@ -3,7 +3,7 @@ # # The set of interfaces that this component exports for use by other # components. This is a list of the interface names. -INTERFACE_EXPORTS = init addr +INTERFACE_EXPORTS = init addr scb_mapping # The interfaces this component is dependent on for compilation (this # is a list of directory names in interface/) INTERFACE_DEPENDENCIES = init diff --git a/src/components/implementation/no_interface/llbooter/llbooter.c b/src/components/implementation/no_interface/llbooter/llbooter.c index 188cbd4d4f..94850d9656 100644 --- a/src/components/implementation/no_interface/llbooter/llbooter.c +++ b/src/components/implementation/no_interface/llbooter/llbooter.c @@ -17,6 +17,7 @@ #include #include +#include #ifndef BOOTER_MAX_SINV #define BOOTER_MAX_SINV 256 @@ -411,6 +412,20 @@ addr_get(compid_t id, addr_t type) } } +int +scb_mapping(compid_t id, vaddr_t scb_uaddr) +{ + struct cos_compinfo *ci; + struct crt_comp *target; + + target = boot_comp_get(id); + + ci = cos_compinfo_get(target->comp_res); + if (cos_scb_mapping(ci, ci->comp_cap, ci->pgtbl_cap, ci->scb_cap, scb_uaddr)) BUG(); + return 0; +} + + static void booter_init(void) { @@ -418,7 +433,8 @@ booter_init(void) cos_meminfo_init(&(boot_info->mi), BOOT_MEM_KM_BASE, COS_MEM_KERN_PA_SZ, BOOT_CAPTBL_SELF_UNTYPED_PT); cos_defcompinfo_init(); - + vaddr_t scb_uaddr = cos_page_bump_intern_valloc(boot_info, COS_SCB_SIZE); + if (cos_scb_mapping(boot_info, BOOT_CAPTBL_SELF_COMP, BOOT_CAPTBL_SELF_PT, LLBOOT_CAPTBL_SCB, scb_uaddr)) BUG(); cos_hw_cycles_per_usec(BOOT_CAPTBL_SELF_INITHW_BASE); } diff --git a/src/components/implementation/sched/root_fprr/Makefile b/src/components/implementation/sched/root_fprr/Makefile index ad4a79925a..327c6bebe0 100644 --- a/src/components/implementation/sched/root_fprr/Makefile +++ b/src/components/implementation/sched/root_fprr/Makefile @@ -9,7 +9,7 @@ INTERFACE_EXPORTS = sched init INTERFACE_DEPENDENCIES = capmgr # The library dependencies this component is reliant on for # compilation/linking (this is a list of directory names in lib/) -LIBRARY_DEPENDENCIES = component sl_capmgr +LIBRARY_DEPENDENCIES = component sl_capmgr dcb # Note: Both the interface and library dependencies should be # *minimal*. That is to say that removing a dependency should cause # the build to fail. The build system does not validate this diff --git a/src/components/implementation/sched/root_fprr/init.c b/src/components/implementation/sched/root_fprr/init.c index db98616b61..4000af28cd 100644 --- a/src/components/implementation/sched/root_fprr/init.c +++ b/src/components/implementation/sched/root_fprr/init.c @@ -73,6 +73,8 @@ static compid_t init_schedule[MAX_NUM_COMPS] = { 0 }; /* internalizer threads simply orchestrate the initialization */ static struct sl_thd *__initializer_thd[NUM_CPU] CACHE_ALIGNED; +extern int capmgr_scb_mapping(void); + void schedinit_next(compid_t cid) { @@ -233,6 +235,7 @@ cos_init(void) cos_meminfo_init(&(ci->mi), BOOT_MEM_KM_BASE, COS_MEM_KERN_PA_SZ, BOOT_CAPTBL_SELF_UNTYPED_PT); cos_defcompinfo_init(); cos_init_args_cpubmp(cpubmp); + if (capmgr_scb_mapping()) BUG(); } void diff --git a/src/components/implementation/sched/sched.c b/src/components/implementation/sched/sched.c index dbb4028ff9..f4a1f224c8 100644 --- a/src/components/implementation/sched/sched.c +++ b/src/components/implementation/sched/sched.c @@ -88,7 +88,7 @@ sched_thd_create_closure(thdclosure_index_t idx) dci = sched_child_defci_get(sched_childinfo_find(c)); if (!dci) return 0; - t = sl_thd_aep_alloc_ext(dci, NULL, idx, 0, 0, 0, 0, 0, NULL); + t = sl_thd_aep_alloc_ext(dci, NULL, idx, 0, 0, 0, 0, 0, NULL, NULL); if (!t) return 0; return sl_thd_thdid(t); @@ -105,7 +105,7 @@ sched_aep_create_closure(thdclosure_index_t id, int owntc, cos_channelkey_t key, dci = sched_child_defci_get(sched_childinfo_find(c)); if (!dci) return 0; - t = sl_thd_aep_alloc_ext(dci, NULL, id, 1, owntc, key, ipiwin, ipimax, rcv); + t = sl_thd_aep_alloc_ext(dci, NULL, id, 1, owntc, key, ipiwin, ipimax, NULL, rcv); if (!t) return 0; return sl_thd_thdid(t); diff --git a/src/components/implementation/sched/sched_info.c b/src/components/implementation/sched/sched_info.c index 34b4619d42..679c4255f1 100644 --- a/src/components/implementation/sched/sched_info.c +++ b/src/components/implementation/sched/sched_info.c @@ -91,7 +91,7 @@ sched_childinfo_init_component(compid_t id) } assert(bitmap_check(schedinfo->cpubmp, cos_cpuid())); - initthd = sl_thd_initaep_alloc(child_dci, NULL, childflags & COMP_FLAG_SCHED, childflags & COMP_FLAG_SCHED ? 1 : 0, 0, 0, 0); /* TODO: rate information */ + initthd = sl_thd_initaep_alloc(child_dci, NULL, childflags & COMP_FLAG_SCHED, childflags & COMP_FLAG_SCHED ? 1 : 0, 0, 0, 0, NULL); /* TODO: rate information */ assert(initthd); /* Failure here? Capability manager likely needs to be depended on with capmgr_create */ sched_child_initthd_set(schedinfo, initthd); diff --git a/src/components/implementation/tests/kernel_tests/k_perf_tests.c b/src/components/implementation/tests/kernel_tests/k_perf_tests.c index 6696a8714b..8bfc75ef44 100644 --- a/src/components/implementation/tests/kernel_tests/k_perf_tests.c +++ b/src/components/implementation/tests/kernel_tests/k_perf_tests.c @@ -39,7 +39,7 @@ test_thds_create_switch(void) perfdata_init(&pd[cos_cpuid()], "COS THD => COS_THD_SWITCH", test_results, ARRAY_SIZE); - ts = cos_thd_alloc(&booter_info, booter_info.comp_cap, bounceback, NULL); + ts = cos_thd_alloc(&booter_info, booter_info.comp_cap, bounceback, NULL, 0, 0); if (EXPECT_LL_LT(1, ts, "Thread Creation: Cannot Allocate")) { return; } @@ -152,7 +152,7 @@ test_async_endpoints_perf(void) /* parent rcv capabilities */ tcp = cos_thd_alloc(&booter_info, booter_info.comp_cap, async_thd_parent_perf, - (void *)BOOT_CAPTBL_SELF_INITTHD_CPU_BASE); + (void *)BOOT_CAPTBL_SELF_INITTHD_CPU_BASE, 0, 0); if(EXPECT_LL_LT(1, tcp, "Test Async Endpoints")) return; tccp = cos_tcap_alloc(&booter_info); if(EXPECT_LL_LT(1, tccp, "Test Async Endpoints")) return; @@ -164,7 +164,7 @@ test_async_endpoints_perf(void) } /* child rcv capabilities */ - tcc = cos_thd_alloc(&booter_info, booter_info.comp_cap, async_thd_fn_perf, (void *)tcp); + tcc = cos_thd_alloc(&booter_info, booter_info.comp_cap, async_thd_fn_perf, (void *)tcp, 0, 0); if(EXPECT_LL_LT(1, tcc, "Test Async Endpoints")) return; tccc = cos_tcap_alloc(&booter_info); if(EXPECT_LL_LT(1, tccc, "Test Async Endpoints")) return; diff --git a/src/components/implementation/tests/kernel_tests/k_test_async.c b/src/components/implementation/tests/kernel_tests/k_test_async.c index 27203b6504..9d8a4a74f9 100644 --- a/src/components/implementation/tests/kernel_tests/k_test_async.c +++ b/src/components/implementation/tests/kernel_tests/k_test_async.c @@ -100,7 +100,7 @@ test_async_endpoints(void) /* parent rcv capabilities */ tcp = cos_thd_alloc(&booter_info, booter_info.comp_cap, async_thd_parent, - (void *)BOOT_CAPTBL_SELF_INITTHD_CPU_BASE); + (void *)BOOT_CAPTBL_SELF_INITTHD_CPU_BASE, 0, 0); if (EXPECT_LL_LT(1, tcp, "Test Async Endpoints")) { return; } @@ -118,7 +118,7 @@ test_async_endpoints(void) } /* child rcv capabilities */ - tcc = cos_thd_alloc(&booter_info, booter_info.comp_cap, async_thd_fn, (void *)tcp); + tcc = cos_thd_alloc(&booter_info, booter_info.comp_cap, async_thd_fn, (void *)tcp, 0, 0); if (EXPECT_LL_LT(1, tcc, "Test Async Endpoints")) { return; } diff --git a/src/components/implementation/tests/kernel_tests/k_test_captbl.c b/src/components/implementation/tests/kernel_tests/k_test_captbl.c index 4365195e08..1f0dadfd90 100644 --- a/src/components/implementation/tests/kernel_tests/k_test_captbl.c +++ b/src/components/implementation/tests/kernel_tests/k_test_captbl.c @@ -17,7 +17,7 @@ test_captbl_expands(void) int i; compcap_t cc; - cc = cos_comp_alloc(&booter_info, booter_info.captbl_cap, booter_info.pgtbl_cap, (vaddr_t)NULL); + cc = cos_comp_alloc(&booter_info, booter_info.captbl_cap, booter_info.pgtbl_cap, 0, (vaddr_t)NULL); if (EXPECT_LL_LT(1, cc, "Capability Table Expansion")) { return; } diff --git a/src/components/implementation/tests/kernel_tests/k_test_inv.c b/src/components/implementation/tests/kernel_tests/k_test_inv.c index fe40eb2c5c..6e0b59ee98 100644 --- a/src/components/implementation/tests/kernel_tests/k_test_inv.c +++ b/src/components/implementation/tests/kernel_tests/k_test_inv.c @@ -88,7 +88,7 @@ test_inv(void) perfdata_init(&result, "SINV", test_results, ARRAY_SIZE); - cc = cos_comp_alloc(&booter_info, booter_info.captbl_cap, booter_info.pgtbl_cap, (vaddr_t)NULL); + cc = cos_comp_alloc(&booter_info, booter_info.captbl_cap, booter_info.pgtbl_cap, 0, (vaddr_t)NULL); if (EXPECT_LL_LT(1, cc, "Invocation: Cannot Allocate")) return; ic = cos_sinv_alloc(&booter_info, cc, (vaddr_t)__inv_test_serverfn, 0xdead); if (EXPECT_LL_LT(1, ic, "Invocation: Cannot Allocate")) return; diff --git a/src/components/implementation/tests/kernel_tests/k_test_tcap.c b/src/components/implementation/tests/kernel_tests/k_test_tcap.c index 817302c6a8..e16353c4be 100644 --- a/src/components/implementation/tests/kernel_tests/k_test_tcap.c +++ b/src/components/implementation/tests/kernel_tests/k_test_tcap.c @@ -48,8 +48,7 @@ test_timer(void) long long time, mask; tcap_time_t timer, thd_timeout; - tc = cos_thd_alloc(&booter_info, booter_info.comp_cap, spinner, NULL); - + tc = cos_thd_alloc(&booter_info, booter_info.comp_cap, spinner, NULL, 0, 0); perfdata_init(&result, "COS THD => COS_THD_SWITCH", test_results, ARRAY_SIZE); for (i = 0; i <= TEST_ITER; i++){ @@ -139,7 +138,7 @@ exec_cluster_alloc(struct exec_cluster *e, cos_thd_fn_t fn, void *d, arcvcap_t p { e->tcc = cos_tcap_alloc(&booter_info); if (EXPECT_LL_LT(1, e->tcc, "Cluster Allocation: TCAP ALLOC")) return -1; - e->tc = cos_thd_alloc(&booter_info, booter_info.comp_cap, fn, d); + e->tc = cos_thd_alloc(&booter_info, booter_info.comp_cap, fn, d, 0, 0); if (EXPECT_LL_LT(1, e->tc, "Cluster Allocation: THD ALLOC")) return -1; e->rc = cos_arcv_alloc(&booter_info, e->tc, e->tcc, booter_info.comp_cap, parentc); if (EXPECT_LL_LT(1, e->rc, "Cluster Allocation: ARCV ALLOC")) return -1; diff --git a/src/components/implementation/tests/kernel_tests/k_test_thd.c b/src/components/implementation/tests/kernel_tests/k_test_thd.c index 38fb99a749..f369b42190 100644 --- a/src/components/implementation/tests/kernel_tests/k_test_thd.c +++ b/src/components/implementation/tests/kernel_tests/k_test_thd.c @@ -25,7 +25,7 @@ test_thds_create_switch(void) intptr_t i = THD_ARG; int ret; - ts = cos_thd_alloc(&booter_info, booter_info.comp_cap, test_thd_arg, (void *)i); + ts = cos_thd_alloc(&booter_info, booter_info.comp_cap, test_thd_arg, (void *)i, 0, 0); if (EXPECT_LL_LT(1, ts, "Thread Creation: Cannot Allocate")) { return; } @@ -72,7 +72,7 @@ test_mthds_ring(void) count = 0; for (i = 0; i < TEST_NTHDS; i++) { - thd_test[i] = cos_thd_alloc(&booter_info, booter_info.comp_cap, thd_fn_mthds_ring, (void *)i); + thd_test[i] = cos_thd_alloc(&booter_info, booter_info.comp_cap, thd_fn_mthds_ring, (void *)i, 0, 0); if (EXPECT_LL_LT(1, thd_test[i], "Thread Ring: Cannot Allocate")) { return; } @@ -113,7 +113,7 @@ test_mthds_classic(void) thdcap_t ts; int i, ret; - ts = cos_thd_alloc(&booter_info, booter_info.comp_cap, thd_fn_mthds_classic, NULL); + ts = cos_thd_alloc(&booter_info, booter_info.comp_cap, thd_fn_mthds_classic, NULL, 0, 0); if (EXPECT_LL_LT(1, ts, "Thread Classic: Cannot Allocate")) { return; } @@ -151,7 +151,7 @@ test_thds_tls(void) int ret; for (i = 0; i < TEST_NTHDS; i++) { - ts[i] = cos_thd_alloc(&booter_info, booter_info.comp_cap, thd_tls, (void *)i); + ts[i] = cos_thd_alloc(&booter_info, booter_info.comp_cap, thd_tls, (void *)i, 0, 0); if (EXPECT_LL_LT(1, ts[i], "Thread TLS: Cannot Allocate")) { return; } diff --git a/src/components/implementation/tests/kernel_tests/kernel_test_booter.c b/src/components/implementation/tests/kernel_tests/kernel_test_booter.c index d1bf38345d..2a8a863dde 100644 --- a/src/components/implementation/tests/kernel_tests/kernel_test_booter.c +++ b/src/components/implementation/tests/kernel_tests/kernel_test_booter.c @@ -27,8 +27,32 @@ cos_init(void) cos_hw_cycles_per_usec(BOOT_CAPTBL_SELF_INITHW_BASE); cos_meminfo_init(&booter_info.mi, BOOT_MEM_KM_BASE, COS_MEM_KERN_PA_SZ, BOOT_CAPTBL_SELF_UNTYPED_PT); - cos_compinfo_init(&booter_info, BOOT_CAPTBL_SELF_PT, BOOT_CAPTBL_SELF_CT, BOOT_CAPTBL_SELF_COMP, + //scbcap_t scbc = cos_scb_alloc(&booter_info); + cos_compinfo_init(&booter_info, BOOT_CAPTBL_SELF_PT, BOOT_CAPTBL_SELF_CT, BOOT_CAPTBL_SELF_COMP, LLBOOT_CAPTBL_SCB, (vaddr_t)cos_get_heap_ptr(), BOOT_CAPTBL_FREE, &booter_info); + vaddr_t scb_uaddr = cos_page_bump_intern_valloc(&booter_info, COS_SCB_SIZE); + cos_scb_mapping(&booter_info, BOOT_CAPTBL_SELF_COMP, BOOT_CAPTBL_SELF_PT, LLBOOT_CAPTBL_SCB, scb_uaddr); +} + +void +test_scb(void) +{ + thdcap_t thdc; + struct cos_scb_info *scb_info = cos_scb_info_get_core(); + + scb_info->curr_thd = BOOT_CAPTBL_SELF_INITTHD_CPU_BASE; + thdc = cos_introspect(&booter_info, booter_info.comp_cap, COMP_GET_SCB_CURTHD); + if (thdc == (thdcap_t)BOOT_CAPTBL_SELF_INITTHD_CPU_BASE) PRINTC("\t%s: \t\t\tSuccess\n", "SCB => Basic test"); + else PRINTC("\t%s: \t\t\tFail\n", "SCB"); +} + +void +test_dcb(void) +{ + struct cos_dcb_info *init_dcbpg = cos_init_dcb_get(); + + assert(init_dcbpg); + PRINTC("\t%s: \t\t\tSuccess\n", "DCB => Basic test"); } void @@ -37,6 +61,8 @@ test_run_unit_kernel(void) /* Kernel Tests */ printc("\n"); PRINTC("Unit Test Started:\n\n"); + test_scb(); + test_dcb(); test_timer(); test_tcap_budgets(); test_2timers(); @@ -53,7 +79,7 @@ main(void) int i; PRINTC("Kernel Tests\n"); - termthd[cos_cpuid()] = cos_thd_alloc(&booter_info, booter_info.comp_cap, term_fn, NULL); + termthd[cos_cpuid()] = cos_thd_alloc(&booter_info, booter_info.comp_cap, term_fn, NULL, 0, 0); assert(termthd[cos_cpuid()]); cyc_per_usec = cos_hw_cycles_per_usec(BOOT_CAPTBL_SELF_INITHW_BASE); diff --git a/src/components/implementation/tests/micro_xcores/micro_xcores.c b/src/components/implementation/tests/micro_xcores/micro_xcores.c index b1b744c42b..87865b3004 100644 --- a/src/components/implementation/tests/micro_xcores/micro_xcores.c +++ b/src/components/implementation/tests/micro_xcores/micro_xcores.c @@ -29,14 +29,14 @@ cos_init(void) if (first_init) { first_init = 0; cos_meminfo_init(&booter_info.mi, BOOT_MEM_KM_BASE, COS_MEM_KERN_PA_SZ, BOOT_CAPTBL_SELF_UNTYPED_PT); - cos_compinfo_init(&booter_info, BOOT_CAPTBL_SELF_PT, BOOT_CAPTBL_SELF_CT, BOOT_CAPTBL_SELF_COMP, + cos_compinfo_init(&booter_info, BOOT_CAPTBL_SELF_PT, BOOT_CAPTBL_SELF_CT, BOOT_CAPTBL_SELF_COMP, 0, (vaddr_t)cos_get_heap_ptr(), BOOT_CAPTBL_FREE, &booter_info); init_done = 1; } while (!init_done); - termthd[cos_cpuid()] = cos_thd_alloc(&booter_info, booter_info.comp_cap, term_fn, NULL); + termthd[cos_cpuid()] = cos_thd_alloc(&booter_info, booter_info.comp_cap, term_fn, NULL, 0, 0); assert(termthd[cos_cpuid()]); if (cos_cpuid() == 0) PRINTC("Micro Booter Xcore started.\n"); diff --git a/src/components/implementation/tests/micro_xcores/test_ipi_interference.c b/src/components/implementation/tests/micro_xcores/test_ipi_interference.c index f301f9d873..f96dd84ad7 100644 --- a/src/components/implementation/tests/micro_xcores/test_ipi_interference.c +++ b/src/components/implementation/tests/micro_xcores/test_ipi_interference.c @@ -190,7 +190,7 @@ test_ipi_interference(void) if (EXPECT_LL_LT(1, tcc, "IPI Interference: TCAP Allocation")) return; - t = cos_thd_alloc(&booter_info, booter_info.comp_cap, test_rcv_fn, NULL); + t = cos_thd_alloc(&booter_info, booter_info.comp_cap, test_rcv_fn, NULL, 0, 0); if (EXPECT_LL_LT(1, t, "IPI Inteference: Thread Allocation")) return; @@ -205,7 +205,7 @@ test_ipi_interference(void) rcv[cos_cpuid()] = r; while (!rcv[TEST_SND_CORE]) ; - t = cos_thd_alloc(&booter_info, booter_info.comp_cap, rcv_spinner, NULL); + t = cos_thd_alloc(&booter_info, booter_info.comp_cap, rcv_spinner, NULL, 0, 0); if (EXPECT_LL_LT(1, t, "IPI Interference: Thread Allocation")) return; @@ -230,7 +230,7 @@ test_ipi_interference(void) if (EXPECT_LL_LT(1, tcc, "IPI Interference: TCAP Allocation")) return; - t = cos_thd_alloc(&booter_info, booter_info.comp_cap, test_asnd_fn, NULL); + t = cos_thd_alloc(&booter_info, booter_info.comp_cap, test_asnd_fn, NULL, 0, 0); if (EXPECT_LL_LT(1, t, "IPI Interference: Thread Allocation")) return; diff --git a/src/components/implementation/tests/micro_xcores/test_ipi_n_n.c b/src/components/implementation/tests/micro_xcores/test_ipi_n_n.c index 73d57ec9e0..25da1d99eb 100644 --- a/src/components/implementation/tests/micro_xcores/test_ipi_n_n.c +++ b/src/components/implementation/tests/micro_xcores/test_ipi_n_n.c @@ -49,7 +49,7 @@ test_rcv_crt(void) asndcap_t snd = 0; if ((word_t)cos_cpuid() == i) continue; - thd = cos_thd_alloc(&booter_info, booter_info.comp_cap, test_ipi_fn, (void *)i); + thd = cos_thd_alloc(&booter_info, booter_info.comp_cap, test_ipi_fn, (void *)i, 0, 0); assert(thd); rcv = cos_arcv_alloc(&booter_info, thd, BOOT_CAPTBL_SELF_INITTCAP_CPU_BASE, booter_info.comp_cap, BOOT_CAPTBL_SELF_INITRCV_CPU_BASE); diff --git a/src/components/implementation/tests/micro_xcores/test_ipi_roundtrip.c b/src/components/implementation/tests/micro_xcores/test_ipi_roundtrip.c index 24dd2c13ad..d503f3a496 100644 --- a/src/components/implementation/tests/micro_xcores/test_ipi_roundtrip.c +++ b/src/components/implementation/tests/micro_xcores/test_ipi_roundtrip.c @@ -167,7 +167,7 @@ test_ipi_roundtrip(void) return; - t = cos_thd_alloc(&booter_info, booter_info.comp_cap, test_rcv_fn, NULL); + t = cos_thd_alloc(&booter_info, booter_info.comp_cap, test_rcv_fn, NULL, 0, 0); if (EXPECT_LL_LT(1, t, "IPI ROUNDTRIP: Thread Allocation")) return; @@ -196,7 +196,7 @@ test_ipi_roundtrip(void) /* Test Sender Time */ - t = cos_thd_alloc(&booter_info, booter_info.comp_cap, test_asnd_fn, NULL); + t = cos_thd_alloc(&booter_info, booter_info.comp_cap, test_asnd_fn, NULL, 0, 0); if (EXPECT_LL_LT(1, t, "IPI ROUNDTRIP: Thread Allocation")) return; diff --git a/src/components/implementation/tests/micro_xcores/test_ipi_switch.c b/src/components/implementation/tests/micro_xcores/test_ipi_switch.c index e13dbda15d..e92b551770 100644 --- a/src/components/implementation/tests/micro_xcores/test_ipi_switch.c +++ b/src/components/implementation/tests/micro_xcores/test_ipi_switch.c @@ -192,7 +192,7 @@ test_ipi_switch(void) if (EXPECT_LL_LT(1, tcc, "IPI SWITCH: TCAP Allocation")) return; - t = cos_thd_alloc(&booter_info, booter_info.comp_cap, test_rcv_fn, NULL); + t = cos_thd_alloc(&booter_info, booter_info.comp_cap, test_rcv_fn, NULL, 0, 0); if (EXPECT_LL_LT(1, t, "IPI SWITCH: Thread Allocation")) return; @@ -207,7 +207,7 @@ test_ipi_switch(void) rcv[cos_cpuid()] = r; while (!rcv[TEST_SND_CORE]) ; - t = cos_thd_alloc(&booter_info, booter_info.comp_cap, rcv_spinner, NULL); + t = cos_thd_alloc(&booter_info, booter_info.comp_cap, rcv_spinner, NULL, 0, 0); if (EXPECT_LL_LT(1, t, "IPI SWITCH: Thread Allocation")) return; @@ -226,7 +226,7 @@ test_ipi_switch(void) /* Test RCV1: Corresponding Send */ - t = cos_thd_alloc(&booter_info, booter_info.comp_cap, test_asnd_fn, NULL); + t = cos_thd_alloc(&booter_info, booter_info.comp_cap, test_asnd_fn, NULL, 0, 0); if (EXPECT_LL_LT(1, t, "IPI SWITCH: Thread Allocation")) return; diff --git a/src/components/implementation/tests/unit_capmgr/unit_capmgr.c b/src/components/implementation/tests/unit_capmgr/unit_capmgr.c index 5da92baeb4..f176f9248a 100644 --- a/src/components/implementation/tests/unit_capmgr/unit_capmgr.c +++ b/src/components/implementation/tests/unit_capmgr/unit_capmgr.c @@ -32,7 +32,8 @@ test_thds(void) int failure = 0; for (; i < TEST_N_THDS; i++) { - test_ts[cos_cpuid()][i] = capmgr_thd_create(__test_thd_fn, (void *)i, &tid); + /* Hard coded dcb address for now */ + test_ts[cos_cpuid()][i] = capmgr_thd_create(__test_thd_fn, (void *)i, &tid, NULL); assert(test_ts[cos_cpuid()][i]); if (cos_thd_switch(test_ts[cos_cpuid()][i])) { diff --git a/src/components/implementation/tests/unit_defcompinfo/unit_defcompinfo.c b/src/components/implementation/tests/unit_defcompinfo/unit_defcompinfo.c index cd3a55e8f4..8c321dd13d 100644 --- a/src/components/implementation/tests/unit_defcompinfo/unit_defcompinfo.c +++ b/src/components/implementation/tests/unit_defcompinfo/unit_defcompinfo.c @@ -56,7 +56,7 @@ test_aeps(void) asndcap_t snd; printc("\tCreating AEP [%lu]\n", i); - ret = cos_aep_tcap_alloc(&(test_aep[i]), BOOT_CAPTBL_SELF_INITTCAP_BASE, aep_thd_fn, (void *)i); + ret = cos_aep_tcap_alloc(&(test_aep[i]), BOOT_CAPTBL_SELF_INITTCAP_BASE, aep_thd_fn, (void *)i, 0, 0); assert(ret == 0); snd = cos_asnd_alloc(ci, test_aep[i].rcv, ci->captbl_cap); @@ -125,7 +125,7 @@ cos_init(void) cos_defcompinfo_init(); for (id = 0; id < CHILD_COMP_COUNT; id++) { - vaddr_t vm_range, addr; + vaddr_t vm_range, addr, dcbaddr; pgtblcap_t child_utpt; int is_sched = ((id == CHILD_SCHED_ID) ? 1 : 0); struct cos_compinfo *child_ci = cos_compinfo_get(&child_defci[id]); @@ -135,8 +135,10 @@ cos_init(void) assert(child_utpt); cos_meminfo_init(&(child_ci->mi), BOOT_MEM_KM_BASE, CHILD_UNTYPED_SIZE, child_utpt); + //cos_defcompinfo_child_alloc(&child_defci[id], (vaddr_t)&__cosrt_upcall_entry, + // (vaddr_t)BOOT_MEM_VM_BASE, BOOT_CAPTBL_FREE, is_sched); cos_defcompinfo_child_alloc(&child_defci[id], (vaddr_t)&__cosrt_upcall_entry, - (vaddr_t)BOOT_MEM_VM_BASE, BOOT_CAPTBL_FREE, is_sched); + (vaddr_t)BOOT_MEM_VM_BASE, BOOT_CAPTBL_FREE, is_sched, &dcbaddr); printc("\t\tCopying new capabilities\n"); ret = cos_cap_cpy_at(child_ci, BOOT_CAPTBL_SELF_CT, ci, child_ci->captbl_cap); @@ -147,6 +149,7 @@ cos_init(void) assert(ret == 0); ret = cos_cap_cpy_at(child_ci, BOOT_CAPTBL_SELF_COMP, ci, child_ci->comp_cap); assert(ret == 0); + /* FIXME: copy BOOT_CAPTBL_SELF_SCB cap?? */ ret = cos_cap_cpy_at(child_ci, BOOT_CAPTBL_SELF_INITTHD_BASE, ci, cos_sched_aep_get(&child_defci[id])->thd); diff --git a/src/components/implementation/tests/unit_pingpong/Makefile b/src/components/implementation/tests/unit_pingpong/Makefile index 6a48f05d9d..5b033dc93c 100644 --- a/src/components/implementation/tests/unit_pingpong/Makefile +++ b/src/components/implementation/tests/unit_pingpong/Makefile @@ -9,7 +9,7 @@ INTERFACE_EXPORTS = INTERFACE_DEPENDENCIES = init pong # The library dependencies this component is reliant on for # compilation/linking (this is a list of directory names in lib/) -LIBRARY_DEPENDENCIES = kernel ps +LIBRARY_DEPENDENCIES = kernel ps dcb # Note: Both the interface and library dependencies should be # *minimal*. That is to say that removing a dependency should cause # the build to fail. The build system does not validate this diff --git a/src/components/interface/capmgr/Makefile b/src/components/interface/capmgr/Makefile index d53ead973c..1ba243b30c 100644 --- a/src/components/interface/capmgr/Makefile +++ b/src/components/interface/capmgr/Makefile @@ -21,7 +21,7 @@ INCLUDE_PATHS = . INTERFACE_DEPENDENCIES = # The library dependencies this component is reliant on for # compilation/linking (this is a list of directory names in lib/) -LIBRARY_DEPENDENCIES = kernel stubs +LIBRARY_DEPENDENCIES = kernel stubs dcb # Note: Both the interface and library dependencies should be # *minimal*. That is to say that removing a dependency should cause # the build to fail. The build system does not validate this diff --git a/src/components/interface/capmgr/capmgr.h b/src/components/interface/capmgr/capmgr.h index 268ec4d43e..20fcf2fa3b 100644 --- a/src/components/interface/capmgr/capmgr.h +++ b/src/components/interface/capmgr/capmgr.h @@ -28,20 +28,23 @@ thdcap_t COS_STUB_DECL(capmgr_initthd_create)(spdid_t child, thdid_t *tid); thdcap_t capmgr_initaep_create(spdid_t child, struct cos_aep_info *aep, int owntc, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, asndcap_t *sndret); thdcap_t COS_STUB_DECL(capmgr_initaep_create)(spdid_t child, struct cos_aep_info *aep, int owntc, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, asndcap_t *sndret); -thdcap_t capmgr_thd_create(cos_thd_fn_t fn, void *data, thdid_t *tid); -thdcap_t capmgr_aep_create(struct cos_aep_info *a, cos_aepthd_fn_t fn, void *data, int owntc, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax); +thdcap_t capmgr_thd_create(cos_thd_fn_t fn, void *data, thdid_t *tid, struct cos_dcb_info **dcb); +thdcap_t capmgr_aep_create(struct cos_aep_info *a, cos_aepthd_fn_t fn, void *data, int owntc, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, struct cos_dcb_info **dcb); -thdcap_t capmgr_thd_create_thunk(thdclosure_index_t idx, thdid_t *tid); -thdcap_t COS_STUB_DECL(capmgr_thd_create_thunk)(thdclosure_index_t idx, thdid_t *tid); +thdcap_t capmgr_thd_create_thunk(thdclosure_index_t idx, thdid_t *tid, struct cos_dcb_info **dcb); +thdcap_t COS_STUB_DECL(capmgr_thd_create_thunk)(thdclosure_index_t idx, thdid_t *tid, struct cos_dcb_info **dcb); -thdcap_t capmgr_aep_create_thunk(struct cos_aep_info *a, thdclosure_index_t idx, int owntc, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax); -thdcap_t COS_STUB_DECL(capmgr_aep_create_thunk)(struct cos_aep_info *a, thdclosure_index_t idx, int owntc, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax); +thdcap_t capmgr_aep_create_thunk(struct cos_aep_info *a, thdclosure_index_t idx, int owntc, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, struct cos_dcb_info **dcb); +thdcap_t COS_STUB_DECL(capmgr_aep_create_thunk)(struct cos_aep_info *a, thdclosure_index_t idx, int owntc, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, struct cos_dcb_info **dcb); -thdcap_t capmgr_thd_create_ext(spdid_t child, thdclosure_index_t idx, thdid_t *tid); -thdcap_t COS_STUB_DECL(capmgr_thd_create_ext)(spdid_t child, thdclosure_index_t idx, thdid_t *tid); +thdcap_t capmgr_thd_create_ext(spdid_t child, thdclosure_index_t idx, thdid_t *tid, struct cos_dcb_info **dcb); +thdcap_t COS_STUB_DECL(capmgr_thd_create_ext)(spdid_t child, thdclosure_index_t idx, thdid_t *tid, struct cos_dcb_info **dcb); -thdcap_t capmgr_aep_create_ext(spdid_t child, struct cos_aep_info *a, thdclosure_index_t idx, int owntc, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, arcvcap_t *extrcv); -thdcap_t COS_STUB_DECL(capmgr_aep_create_ext)(spdid_t child, struct cos_aep_info *a, thdclosure_index_t idx, int owntc, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, arcvcap_t *extrcv); +thdcap_t capmgr_aep_create_ext(spdid_t child, struct cos_aep_info *a, thdclosure_index_t idx, int owntc, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, struct cos_dcb_info **dcb, arcvcap_t *extrcv); +thdcap_t COS_STUB_DECL(capmgr_aep_create_ext)(spdid_t child, struct cos_aep_info *a, thdclosure_index_t idx, int owntc, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, struct cos_dcb_info **dcb, arcvcap_t *extrcv); + +thdcap_t capmgr_thd_retrieve(spdid_t child, thdid_t t, thdid_t *inittid); +thdcap_t capmgr_thd_retrieve_next(spdid_t child, thdid_t *tid); arcvcap_t capmgr_rcv_create(spdid_t child, thdid_t tid, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax); arcvcap_t COS_STUB_DECL(capmgr_rcv_create)(spdid_t child, thdid_t tid, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax); @@ -52,7 +55,13 @@ asndcap_t COS_STUB_DECL(capmgr_asnd_create)(spdid_t child, thdid_t t); asndcap_t capmgr_asnd_rcv_create(arcvcap_t rcv); asndcap_t COS_STUB_DECL(capmgr_asnd_rcv_create)(arcvcap_t rcv); +int capmgr_scb_mapping(void); +int COS_STUB_DECL(capmgr_scb_mapping)(void); + asndcap_t capmgr_asnd_key_create(cos_channelkey_t key); asndcap_t COS_STUB_DECL(capmgr_asnd_key_create)(cos_channelkey_t key); +int capmgr_thd_migrate(thdid_t tid, thdcap_t tc, cpuid_t core); + + #endif /* CAPMGR_H */ diff --git a/src/components/interface/capmgr/lib.c b/src/components/interface/capmgr/lib.c index d190ceed4c..e000076387 100644 --- a/src/components/interface/capmgr/lib.c +++ b/src/components/interface/capmgr/lib.c @@ -2,17 +2,17 @@ #include thdcap_t -capmgr_thd_create(cos_thd_fn_t fn, void *data, thdid_t *tid) +capmgr_thd_create(cos_thd_fn_t fn, void *data, thdid_t *tid, struct cos_dcb_info **dcb) { thdclosure_index_t idx = cos_thd_init_alloc(fn, data); if (idx < 1) return 0; - return capmgr_thd_create_thunk(idx, tid); + return capmgr_thd_create_thunk(idx, tid, dcb); } thdcap_t -capmgr_aep_create(struct cos_aep_info *a, cos_aepthd_fn_t fn, void *data, int owntc, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax) +capmgr_aep_create(struct cos_aep_info *a, cos_aepthd_fn_t fn, void *data, int owntc, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, struct cos_dcb_info **dcb) { thdclosure_index_t idx = cos_thd_init_alloc(cos_aepthd_fn, (void *)a); @@ -20,5 +20,5 @@ capmgr_aep_create(struct cos_aep_info *a, cos_aepthd_fn_t fn, void *data, int ow a->fn = fn; a->data = data; - return capmgr_aep_create_thunk(a, idx, owntc, key, ipiwin, ipimax); + return capmgr_aep_create_thunk(a, idx, owntc, key, ipiwin, ipimax, dcb); } diff --git a/src/components/interface/capmgr/stubs/c_stub.c b/src/components/interface/capmgr/stubs/c_stub.c index 938cf425a3..d37e20c0b6 100644 --- a/src/components/interface/capmgr/stubs/c_stub.c +++ b/src/components/interface/capmgr/stubs/c_stub.c @@ -21,6 +21,38 @@ COS_CLIENT_STUB(arcvcap_t, capmgr_rcv_create, spdid_t child, thdid_t tid, cos_ch return cos_sinv(uc->cap_no, spd_tid, key_ipimax, ipiwin32b, 0); } +/*COS_CLIENT_STUB(scbcap_t, capmgr_scb_mapping, spdid_t child) +{ + COS_CLIENT_INVCAP; + word_t spd_tid = (u32_t)child; + + return cos_sinv(uc->cap_no, child, 0, 0, 0); +} + +COS_CLIENT_STUB(thdcap_t, capmgr_thd_retrieve, spdid_t child, thdid_t tid, thdid_t *inittid) +{ + COS_CLIENT_INVCAP; + word_t unused, tid_ret; + thdcap_t ret; + + ret = cos_sinv_2rets(uc->cap_no, child, tid, 0, 0, &tid_ret, &unused); + *inittid = tid_ret; + + return ret; +} + +COS_CLIENT_STUB(thdcap_t, capmgr_thd_retrieve_next, spdid_t child, thdid_t *tid) +{ + COS_CLIENT_INVCAP; + word_t unused, tid_ret; + thdcap_t ret; + + ret = cos_sinv_2rets(uc->cap_no, child, 0, 0, 0, &tid_ret, &unused); + *tid = tid_ret; + + return ret; +}*/ + COS_CLIENT_STUB(thdcap_t, capmgr_initthd_create, spdid_t child, thdid_t *tid) { COS_CLIENT_INVCAP; @@ -33,34 +65,38 @@ COS_CLIENT_STUB(thdcap_t, capmgr_initthd_create, spdid_t child, thdid_t *tid) return ret; } -COS_CLIENT_STUB(thdcap_t, capmgr_thd_create_thunk, thdclosure_index_t id, thdid_t *tid) +COS_CLIENT_STUB(thdcap_t, capmgr_thd_create_thunk, thdclosure_index_t id, thdid_t *tid, struct cos_dcb_info **dcb) { COS_CLIENT_INVCAP; - word_t unused, tid_ret; + word_t dcb_ret, tid_ret; thdcap_t ret; - ret = cos_sinv_2rets(uc->cap_no, id, 0, 0, 0, &tid_ret, &unused); + ret = cos_sinv_2rets(uc->cap_no, id, 0, 0, 0, &tid_ret, &dcb_ret); + *dcb = (struct cos_dcb_info *)dcb_ret; *tid = tid_ret; return ret; } -COS_CLIENT_STUB(thdcap_t, capmgr_thd_create_ext, spdid_t child, thdclosure_index_t idx, thdid_t *tid) +COS_CLIENT_STUB(thdcap_t, capmgr_thd_create_ext, spdid_t child, thdclosure_index_t idx, thdid_t *tid, struct cos_dcb_info **dcb) { COS_CLIENT_INVCAP; - word_t unused, tid_ret; + word_t dcb_ret, tid_ret; thdcap_t ret; - ret = cos_sinv_2rets(uc->cap_no, child, idx, 0, 0, &tid_ret, &unused); + ret = cos_sinv_2rets(uc->cap_no, child, idx, 0, 0, &tid_ret, &dcb_ret); + *dcb = (struct cos_dcb_info *)dcb_ret; *tid = tid_ret; return ret; } -COS_CLIENT_STUB(thdcap_t, capmgr_aep_create_thunk, struct cos_aep_info *aep, thdclosure_index_t idx, int owntc, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax) +COS_CLIENT_STUB(thdcap_t, capmgr_aep_create_thunk, struct cos_aep_info *aep, thdclosure_index_t idx, int owntc, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, struct cos_dcb_info **dcb) { COS_CLIENT_INVCAP; - word_t tcrcvret = 0; + word_t tcrcvret = 0; + word_t thdtidret = 0; + word_t dcb_ret = 0; thdcap_t thd = 0; thdid_t tid = 0; u32_t owntc_idx = (owntc << 16) | idx; @@ -69,18 +105,24 @@ COS_CLIENT_STUB(thdcap_t, capmgr_aep_create_thunk, struct cos_aep_info *aep, thd if (idx < 1) return 0; - thd = cos_sinv_2rets(uc->cap_no, owntc_idx, key_ipimax, ipiwin32b, 0, &tid, &tcrcvret); - if (!thd) return 0; + thdtidret = cos_sinv_2rets(uc->cap_no, owntc_idx, key_ipimax, ipiwin32b, 0, &dcb_ret, &tcrcvret); + if (!thdtidret) return 0; + thd = thdtidret >> 16; + tid = (thdtidret << 16) >> 16; + if (!thd || !tid) return 0; aep->thd = thd; aep->rcv = (tcrcvret << 16) >> 16; aep->tc = (tcrcvret >> 16); aep->tid = tid; + *dcb = (struct cos_dcb_info *)dcb_ret; + return thd; } -COS_CLIENT_STUB(thdcap_t, capmgr_aep_create_ext, spdid_t child, struct cos_aep_info *aep, thdclosure_index_t idx, int owntc, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, arcvcap_t *extrcv) +/* FIXME: Won't work now */ +COS_CLIENT_STUB(thdcap_t, capmgr_aep_create_ext, spdid_t child, struct cos_aep_info *aep, thdclosure_index_t idx, int owntc, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, struct cos_dcb_info **dcb, arcvcap_t *extrcv) { COS_CLIENT_INVCAP; word_t drcvtidret = 0; diff --git a/src/components/interface/capmgr/stubs/s_stub.c b/src/components/interface/capmgr/stubs/s_stub.c index a71bf74033..23e10fba8d 100644 --- a/src/components/interface/capmgr/stubs/s_stub.c +++ b/src/components/interface/capmgr/stubs/s_stub.c @@ -13,14 +13,47 @@ COS_SERVER_3RET_STUB(arcvcap_t, capmgr_rcv_create) return capmgr_rcv_create(child, tid, key, ipiwin, ipimax); } +/*COS_SERVER_3RET_STUB(scbcap_t, capmgr_scb_mapping) +{ + spdid_t child = p0; + scbcap_t ret; + + ret = capmgr_scb_mapping(child); + + return ret; +} + +COS_SERVER_3RET_STUB(thdcap_t, capmgr_thd_retrieve) +{ + thdid_t retthd = 0; + thdcap_t ret; + + ret = capmgr_thd_retrieve(p0, p1, &retthd); + *r1 = retthd; + + return ret; +} + +COS_SERVER_3RET_STUB(thdcap_t, capmgr_thd_retrieve_next) +{ + thdid_t retthd = 0; + thdcap_t ret; + + ret = capmgr_thd_retrieve_next(p0, &retthd); + *r1 = retthd; + + return ret; +}*/ COS_SERVER_3RET_STUB(thdcap_t, capmgr_thd_create_thunk) { thdid_t retthd = 0; + struct cos_dcb_info *retdcb; thdcap_t ret; - ret = capmgr_thd_create_thunk(p0, &retthd); + ret = capmgr_thd_create_thunk(p0, &retthd, &retdcb); *r1 = retthd; + *r2 = (word_t)retdcb; return ret; } @@ -28,10 +61,12 @@ COS_SERVER_3RET_STUB(thdcap_t, capmgr_thd_create_thunk) COS_SERVER_3RET_STUB(thdcap_t, capmgr_thd_create_ext) { thdid_t retthd = 0; + struct cos_dcb_info *retdcb; thdcap_t ret; - ret = capmgr_thd_create_ext(p0, p1, &retthd); + ret = capmgr_thd_create_ext(p0, p1, &retthd, &retdcb); *r1 = retthd; + *r2 = (word_t)retdcb; return ret; } @@ -73,14 +108,16 @@ COS_SERVER_3RET_STUB(thdcap_t, capmgr_aep_create_thunk) u32_t ipimax = (p1 << 16) >> 16; u32_t ipiwin32b = (u32_t)p2; struct cos_aep_info aep; + struct cos_dcb_info *retdcb; asndcap_t snd; - thdcap_t thd; + thdcap_t thdtidret; - thd = capmgr_aep_create_thunk(&aep, thunk, owntc, key, ipimax, ipiwin32b); - *r1 = aep.tid; + thdtidret = capmgr_aep_create_thunk(&aep, thunk, owntc, key, ipimax, ipiwin32b, &retdcb); + *r1 = (word_t)retdcb; *r2 = (aep.rcv << 16) | aep.tc; + assert(0); - return thd; + return thdtidret; } COS_SERVER_3RET_STUB(thdcap_t, capmgr_aep_create_ext) @@ -93,9 +130,11 @@ COS_SERVER_3RET_STUB(thdcap_t, capmgr_aep_create_ext) microsec_t ipiwin = p3; u32_t ipimax = ((p2 << 16) >> 16); arcvcap_t extrcv = 0; + struct cos_dcb_info *dcbret; thdcap_t ret; + assert(0); - ret = capmgr_aep_create_ext(child, &aep, idx, owntc, key, ipiwin, ipimax, &extrcv); + ret = capmgr_aep_create_ext(child, &aep, idx, owntc, key, ipiwin, ipimax, &dcbret, &extrcv); *r1 = aep.tid | (extrcv << 16); *r2 = (aep.rcv << 16) | aep.tc; diff --git a/src/components/interface/capmgr/stubs/stubs.S b/src/components/interface/capmgr/stubs/stubs.S index 6af692eec4..6999b31416 100644 --- a/src/components/interface/capmgr/stubs/stubs.S +++ b/src/components/interface/capmgr/stubs/stubs.S @@ -7,6 +7,9 @@ #include +//cos_asm_stub_indirect(capmgr_thd_retrieve) +//cos_asm_stub_indirect(capmgr_thd_retrieve_next) + cos_asm_stub_indirect(capmgr_initthd_create) cos_asm_stub_indirect(capmgr_thd_create_thunk) cos_asm_stub_indirect(capmgr_thd_create_ext) @@ -17,6 +20,8 @@ cos_asm_stub_indirect(capmgr_aep_create_ext) cos_asm_stub_indirect(capmgr_rcv_create) +cos_asm_stub(capmgr_scb_mapping) cos_asm_stub(capmgr_asnd_create) cos_asm_stub(capmgr_asnd_rcv_create) cos_asm_stub(capmgr_asnd_key_create) + diff --git a/src/components/lib/component/arch/x86/cos_component.h b/src/components/lib/component/arch/x86/cos_component.h index ac4431c22d..cbd2a25e7f 100644 --- a/src/components/lib/component/arch/x86/cos_component.h +++ b/src/components/lib/component/arch/x86/cos_component.h @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -256,7 +257,33 @@ cos_compid_set(compid_t cid) static inline void * cos_get_heap_ptr(void) { - return (void *)__cosrt_comp_info.cos_heap_ptr; + /* page at heap_ptr is actually the SCB_PAGE for any component. */ + //unsigned int off = COS_SCB_SIZE + (PAGE_SIZE * NUM_CPU); + //void *heap_ptr = (void *)(__cosrt_comp_info.cos_heap_ptr + off); + void *heap_ptr = (void *)(__cosrt_comp_info.cos_heap_ptr); + + return heap_ptr; +} + +static inline struct cos_scb_info * +cos_scb_info_get(void) +{ + return (struct cos_scb_info *)(__cosrt_comp_info.cos_heap_ptr); +} + +static inline struct cos_scb_info * +cos_scb_info_get_core(void) +{ + return cos_scb_info_get() + cos_cpuid(); +} + +static inline struct cos_dcb_info * +cos_init_dcb_get(void) +{ + /* created at boot-time for the first component in the system! */ + if (cos_spd_id() == 0) return (struct cos_dcb_info *)(__cosrt_comp_info.cos_heap_ptr + COS_SCB_SIZE + (PAGE_SIZE * cos_cpuid())); + + return NULL; } static inline void diff --git a/src/components/lib/crt/crt.c b/src/components/lib/crt/crt.c index 3cc35911a0..a7bbca5e5a 100644 --- a/src/components/lib/crt/crt.c +++ b/src/components/lib/crt/crt.c @@ -217,7 +217,7 @@ crt_comp_create_with(struct crt_comp *c, char *name, compid_t id, struct crt_com if (crt_comp_init(c, name, id, NULL, r->info)) BUG(); cos_compinfo_init(cos_compinfo_get(c->comp_res), - r->ptc, r->ctc, r->compc, r->heap_ptr, r->captbl_frontier, + r->ptc, r->ctc, r->compc, 0, r->heap_ptr, r->captbl_frontier, cos_compinfo_get(cos_defcompinfo_curr_get())); return 0; } @@ -266,7 +266,7 @@ crt_comp_create_from(struct crt_comp *c, char *name, compid_t id, struct crt_chk assert(inv.server->id != chkpt->c->id); } - ret = cos_compinfo_alloc(ci, c->ro_addr, BOOT_CAPTBL_FREE, c->entry_addr, root_ci); + ret = cos_compinfo_alloc(ci, 0, c->ro_addr, BOOT_CAPTBL_FREE, c->entry_addr, root_ci); assert(!ret); mem = cos_page_bump_allocn(root_ci, chkpt->tot_sz_mem); @@ -332,8 +332,10 @@ crt_comp_create(struct crt_comp *c, char *name, compid_t id, void *elf_hdr, vadd printc("\t\t elf obj: ro [0x%lx, 0x%lx), data [0x%lx, 0x%lx), bss [0x%lx, 0x%lx).\n", c->ro_addr, c->ro_addr + ro_sz, c->rw_addr, c->rw_addr + data_sz, c->rw_addr + data_sz, c->rw_addr + data_sz + bss_sz); - - ret = cos_compinfo_alloc(ci, c->ro_addr, BOOT_CAPTBL_FREE, c->entry_addr, root_ci); + + /* FIXME: This is a hack making every component has SCB by default. */ + scbcap_t scbc = cos_scb_alloc(root_ci); + ret = cos_compinfo_alloc(ci, scbc, c->ro_addr, BOOT_CAPTBL_FREE, c->entry_addr, root_ci); assert(!ret); tot_sz = round_up_to_page(round_up_to_page(ro_sz) + data_sz + bss_sz); @@ -362,6 +364,8 @@ crt_comp_create(struct crt_comp *c, char *name, compid_t id, void *elf_hdr, vadd /* FIXME: cos_time.h assumes we have access to this... */ ret = cos_cap_cpy_at(ci, BOOT_CAPTBL_SELF_INITHW_BASE, root_ci, BOOT_CAPTBL_SELF_INITHW_BASE); assert(ret == 0); + //ret = cos_scb_mapping(ci, ci->comp_cap, ci->pgtbl_cap, scbc); + //assert(ret == 0); return 0; } @@ -656,11 +660,11 @@ crt_thd_create_in(struct crt_thd *t, struct crt_comp *c, thdclosure_index_t clos crt_refcnt_take(&c->refcnt); assert(target_ci->comp_cap); - thdcap = target_aep->thd = cos_initthd_alloc(ci, target_ci->comp_cap); + thdcap = target_aep->thd = cos_initthd_alloc(ci, target_ci->comp_cap, 0); assert(target_aep->thd); } else { crt_refcnt_take(&c->refcnt); - thdcap = cos_thd_alloc_ext(ci, target_ci->comp_cap, closure_id); + thdcap = cos_thd_alloc_ext(ci, target_ci->comp_cap, closure_id, 0, 0); assert(thdcap); } @@ -771,9 +775,9 @@ crt_rcv_create_in(struct crt_rcv *r, struct crt_comp *c, struct crt_rcv *sched, crt_refcnt_take(&c->refcnt); assert(target_ci->comp_cap); if (closure_id == 0) { - thdcap = cos_initthd_alloc(cos_compinfo_get(defci), target_ci->comp_cap); + thdcap = cos_initthd_alloc(cos_compinfo_get(defci), target_ci->comp_cap, 0); } else { - thdcap = cos_thd_alloc_ext(cos_compinfo_get(defci), target_ci->comp_cap, closure_id); + thdcap = cos_thd_alloc_ext(cos_compinfo_get(defci), target_ci->comp_cap, closure_id, 0, 0); } assert(thdcap); @@ -1303,3 +1307,20 @@ crt_compinit_exit(struct crt_comp *c, int retval) while (1) ; } +dcbcap_t +crt_dcb_create_in(struct crt_comp *c, vaddr_t *dcb_addr) +{ + struct cos_defcompinfo *defci = cos_defcompinfo_curr_get(); + struct cos_compinfo *ci = cos_compinfo_get(defci); + struct cos_compinfo *target_ci = cos_compinfo_get(c->comp_res); + dcbcap_t dcb_cap; + vaddr_t dcbaddr; + + dcbaddr = cos_page_bump_intern_valloc(target_ci, PAGE_SIZE); + assert(dcbaddr); + dcb_cap = cos_dcb_alloc(ci, target_ci->pgtbl_cap, dcbaddr); + assert(dcb_cap); + *dcb_addr = dcbaddr; + + return dcb_cap; +} diff --git a/src/components/lib/crt/crt.h b/src/components/lib/crt/crt.h index 6877ed59cc..18408c98e0 100644 --- a/src/components/lib/crt/crt.h +++ b/src/components/lib/crt/crt.h @@ -213,5 +213,6 @@ void crt_compinit_exit(struct crt_comp *c, int retval); int crt_chkpt_create(struct crt_chkpt *chkpt, struct crt_comp *c); int crt_chkpt_restore(struct crt_chkpt *chkpt, struct crt_comp *c); +dcbcap_t crt_dcb_create_in(struct crt_comp *c, vaddr_t *dcb_addr); #endif /* CRT_H */ diff --git a/src/components/lib/dcb/Makefile b/src/components/lib/dcb/Makefile new file mode 100644 index 0000000000..e1589570b2 --- /dev/null +++ b/src/components/lib/dcb/Makefile @@ -0,0 +1,63 @@ +# Required variables used to drive the compilation process. It is OK +# for many of these to be empty. +# +# The library names associated with .a files output that are linked +# (via, for example, -ldcb) into dependents. This list should be +# "dcb" for output files such as libdcb.a. +LIBRARY_OUTPUT = dcb +# The .o files that are mandatorily linked into dependents. This is +# rarely used, and only when normal .a linking rules will avoid +# linking some necessary objects. This list is of names (for example, +# dcb) which will generate dcb.lib.o. Do NOT include the list of .o +# files here. Please note that using this list is *very rare* and +# should only be used when the .a support above is not appropriate. +OBJECT_OUTPUT = +# The path within this directory that holds the .h files for +# dependents to compile with (./ by default). Will be fed into the -I +# compiler arguments. +INCLUDE_PATHS = . +# The interfaces this component is dependent on for compilation (this +# is a list of directory names in interface/) +INTERFACE_DEPENDENCIES = +# The library dependencies this component is reliant on for +# compilation/linking (this is a list of directory names in lib/) +LIBRARY_DEPENDENCIES = component +# Note: Both the interface and library dependencies should be +# *minimal*. That is to say that removing a dependency should cause +# the build to fail. The build system does not validate this +# minimality; that's on you! + +# There are two different *types* of Makefiles for libraries. +# 1. Those that are Composite-specific, and simply need an easy way to +# compile and itegrate their code. +# 2. Those that aim to integrate external libraries into +# Composite. These focus on "driving" the build process of the +# external library, then pulling out the resulting files and +# directories. These need to be flexible as all libraries are +# different. + +# Type 1, Composite library: This is the default Makefile for +# libraries written for composite. Get rid of this if you require a +# custom Makefile (e.g. if you use an existing +# (non-composite-specific) library. An example of this is `kernel`. +include Makefile.lib + +## Type 2, external library: If you need to specialize the Makefile +## for an external library, you can add the external code as a +## subdirectory, and drive its compilation, and integration with the +## system using a specialized Makefile. The Makefile must generate +## lib$(LIBRARY_OUTPUT).a and $(OBJECT_OUTPUT).lib.o, and have all of +## the necessary include paths in $(INCLUDE_PATHS). +## +## To access the Composite Makefile definitions, use the following. An +## example of a Makefile written in this way is in `ps/`. +# +# include Makefile.src Makefile.comp Makefile.dependencies +# .PHONY: all clean init distclean +## Fill these out with your implementation +# all: +# clean: +# +## Default rules: +# init: clean all +# distclean: clean diff --git a/src/components/lib/dcb/dcb.c b/src/components/lib/dcb/dcb.c new file mode 100644 index 0000000000..260959db89 --- /dev/null +++ b/src/components/lib/dcb/dcb.c @@ -0,0 +1,102 @@ +#include +#include +#include + +static struct cos_dcbinfo_data _cos_dcbinfo[NUM_CPU]; + +int +cos_dcb_test_111(void) { + assert(0); + return 1; +} + +void +cos_dcb_info_init_ext(struct cos_dcbinfo_data *cdi, struct cos_compinfo *ci, + dcbcap_t initdcbcap, vaddr_t initdcbaddr, dcboff_t start_off) +{ + memset(cdi, 0, sizeof(struct cos_dcbinfo_data)); + + cdi->dcbcaps[0] = initdcbcap; + cdi->dcbaddr[0] = initdcbaddr; + cdi->curr_cap_off = start_off; + cdi->curr_cap = 0; +} + +void +cos_dcb_info_init(struct cos_dcbinfo_data *cdi, struct cos_compinfo *ci) +{ + if (cos_spd_id() == 0) { + cos_dcb_info_init_ext(cdi, ci, LLBOOT_CAPTBL_CPU_INITDCB, + (vaddr_t)cos_init_dcb_get(), 1); + } else { + cos_dcb_info_init_ext(cdi, ci, 0, 0, 0); + } +} + +void +cos_dcb_info_init_curr(void) +{ + cos_dcb_info_init_curr_ext(0, 0, 0); +} + +void +cos_dcb_info_init_curr_ext(dcbcap_t initdcbcap, vaddr_t initdcbaddr, dcboff_t st_off) +{ + struct cos_compinfo *ci = cos_compinfo_get(cos_defcompinfo_curr_get()); + + if (initdcbcap == 0 && initdcbaddr == 0) { + + if (cos_spd_id() == 0) { + cos_dcb_info_init_ext(&_cos_dcbinfo[cos_cpuid()], ci, + LLBOOT_CAPTBL_CPU_INITDCB, (vaddr_t)cos_init_dcb_get(), 1); + + return; + } else { + initdcbaddr = cos_page_bump_intern_valloc(ci, PAGE_SIZE); + assert(initdcbaddr); + initdcbcap = cos_dcb_alloc(ci, ci->pgtbl_cap, initdcbaddr); + assert(initdcbcap); + st_off = 0; + } + } + cos_dcb_info_init_ext(&_cos_dcbinfo[cos_cpuid()], ci, initdcbcap, initdcbaddr, st_off); +} + +dcbcap_t +cos_dcb_info_alloc_curr(dcboff_t *dcboff, vaddr_t *dcbaddr) +{ + return cos_dcb_info_alloc(&_cos_dcbinfo[cos_cpuid()], dcboff, dcbaddr); +} + +dcbcap_t +cos_dcb_info_alloc(struct cos_dcbinfo_data *cdi, dcboff_t *dcboff, vaddr_t *dcbaddr) +{ + if (unlikely(cdi->dcbcaps[cdi->curr_cap] == 0)) { + *dcboff = 0; + *dcbaddr = 0; + + return 0; + } + if (cdi->curr_cap_off >= COS_DCB_PERPG_MAX) { + int ret; + unsigned short curr_off = cdi->curr_cap; + + assert(curr_off + 1 < (unsigned short)COS_DCB_MAX_CAPS && cdi->dcbcaps[curr_off + 1] == 0); + + cdi->dcbaddr[curr_off + 1] = cos_page_bump_intern_valloc(cdi->ci, PAGE_SIZE); + assert(cdi->dcbaddr[curr_off + 1]); + cdi->dcbcaps[curr_off + 1] = cos_dcb_alloc(cos_compinfo_get(cos_defcompinfo_curr_get()), + cdi->ci->pgtbl_cap, cdi->dcbaddr[curr_off + 1]); + + assert(cdi->dcbcaps[curr_off + 1]); + ret = ps_cas((unsigned long *)&cdi->curr_cap, curr_off, curr_off + 1); + assert(ret); + ret = ps_cas((unsigned long *)&cdi->curr_cap_off, cdi->curr_cap_off, 0); + assert(ret); + } + + *dcboff = ps_faa((unsigned long *)&cdi->curr_cap_off, 1); + *dcbaddr = cdi->dcbaddr[cdi->curr_cap] + (sizeof(struct cos_dcb_info) * (*dcboff)); + + return cdi->dcbcaps[cdi->curr_cap]; +} diff --git a/src/components/lib/dcb/dcb.h b/src/components/lib/dcb/dcb.h new file mode 100644 index 0000000000..93294645ff --- /dev/null +++ b/src/components/lib/dcb/dcb.h @@ -0,0 +1,29 @@ +#ifndef DCB_H +#define DCB_H + +#include +#include + +#define COS_DCB_PERPG_MAX (PAGE_SIZE / sizeof(struct cos_dcb_info)) + +#define COS_DCB_MAX_CAPS (MAX_NUM_THREADS / COS_DCB_PERPG_MAX + 1) + +struct cos_dcbinfo_data { + dcbcap_t dcbcaps[COS_DCB_MAX_CAPS]; + vaddr_t dcbaddr[COS_DCB_MAX_CAPS]; + dcboff_t curr_cap_off; + unsigned short curr_cap; + + struct cos_compinfo *ci; +} CACHE_ALIGNED; + +int cos_dcb_test_111(void); +void cos_dcb_info_init(struct cos_dcbinfo_data *cdi, struct cos_compinfo *ci); +void cos_dcb_info_init_ext(struct cos_dcbinfo_data *cdi, struct cos_compinfo *ci, dcbcap_t initdcbcap, vaddr_t initdcbaddr, dcboff_t start_off); +dcbcap_t cos_dcb_info_alloc(struct cos_dcbinfo_data *cdi, dcboff_t *dcboff, vaddr_t *dcbaddr); + +void cos_dcb_info_init_curr(void); +void cos_dcb_info_init_curr_ext(dcbcap_t initdcbcap, vaddr_t initdcbaddr, dcboff_t st_off); +dcbcap_t cos_dcb_info_alloc_curr(dcboff_t *dcboff, vaddr_t *dcbaddr); + +#endif /* COS_DCB_H */ diff --git a/src/components/lib/dcb/doc.md b/src/components/lib/dcb/doc.md new file mode 100644 index 0000000000..614aa37dc8 --- /dev/null +++ b/src/components/lib/dcb/doc.md @@ -0,0 +1,9 @@ +## dcb + +This is the skeleton library used by the `mklib.sh` script to aid in the creation of a new library. +It provides no functionality, and should never be depended on! +This documentation should be *replaced* in the documentation for a new library. + +### Description + +### Usage and Assumptions diff --git a/src/components/lib/kernel/cos_defkernel_api.c b/src/components/lib/kernel/cos_defkernel_api.c index cfb7597e98..3ae0c5e7f4 100644 --- a/src/components/lib/kernel/cos_defkernel_api.c +++ b/src/components/lib/kernel/cos_defkernel_api.c @@ -59,7 +59,7 @@ cos_defcompinfo_init_ext(tcap_t sched_tc, thdcap_t sched_thd, arcvcap_t sched_rc if (curr_defci_init_status == INITIALIZED) return; - cos_compinfo_init(ci, pgtbl_cap, captbl_cap, comp_cap, heap_ptr, cap_frontier, ci); + cos_compinfo_init(ci, pgtbl_cap, captbl_cap, comp_cap, 0, heap_ptr, cap_frontier, ci); curr_defci_init_status = INITIALIZED; cos_defcompinfo_sched_init_ext(sched_tc, sched_thd, sched_rcv); } @@ -91,7 +91,7 @@ cos_defcompinfo_sched_init(void) } static int -cos_aep_alloc_intern(struct cos_aep_info *aep, struct cos_defcompinfo *dst_dci, tcap_t tc, struct cos_aep_info *sched, cos_aepthd_fn_t fn, void *data, thdclosure_index_t idx) +cos_aep_alloc_intern(struct cos_aep_info *aep, struct cos_defcompinfo *dst_dci, tcap_t tc, struct cos_aep_info *sched, cos_aepthd_fn_t fn, void *data, thdclosure_index_t idx, dcbcap_t dcbcap, dcboff_t dcboff) { struct cos_defcompinfo *defci = cos_defcompinfo_curr_get(); struct cos_compinfo *ci = cos_compinfo_get(defci); @@ -101,9 +101,9 @@ cos_aep_alloc_intern(struct cos_aep_info *aep, struct cos_defcompinfo *dst_dci, assert(curr_defci_init_status == INITIALIZED); memset(aep, 0, sizeof(struct cos_aep_info)); - if (is_init) aep->thd = cos_initthd_alloc(ci, dst_ci->comp_cap); - else if (idx > 0) aep->thd = cos_thd_alloc_ext(ci, dst_ci->comp_cap, idx); - else aep->thd = cos_thd_alloc(ci, dst_ci->comp_cap, cos_aepthd_fn, (void *)aep); + if (is_init) aep->thd = cos_initthd_alloc(ci, dst_ci->comp_cap, dcbcap); + else if (idx > 0) aep->thd = cos_thd_alloc_ext(ci, dst_ci->comp_cap, idx, dcbcap, dcboff); + else aep->thd = cos_thd_alloc(ci, dst_ci->comp_cap, cos_aepthd_fn, (void *)aep, dcbcap, dcboff); assert(aep->thd); aep->tid = cos_introspect(ci, aep->thd, THD_GET_TID); if (!sched && is_init) return 0; @@ -125,7 +125,7 @@ cos_aep_alloc_intern(struct cos_aep_info *aep, struct cos_defcompinfo *dst_dci, int cos_defcompinfo_child_alloc(struct cos_defcompinfo *child_defci, vaddr_t entry, vaddr_t heap_ptr, capid_t cap_frontier, - int is_sched) + int is_sched, dcbcap_t *initdcbcap) { int ret; struct cos_defcompinfo *defci = cos_defcompinfo_curr_get(); @@ -133,11 +133,22 @@ cos_defcompinfo_child_alloc(struct cos_defcompinfo *child_defci, vaddr_t entry, struct cos_compinfo *ci = cos_compinfo_get(defci); struct cos_compinfo *child_ci = cos_compinfo_get(child_defci); struct cos_aep_info *child_aep = cos_sched_aep_get(child_defci); + vaddr_t dcbaddr = 0; + dcbcap_t dcbcap = 0; + scbcap_t scbcap = 0; + + scbcap = cos_scb_alloc(ci); + assert(scbcap); assert(curr_defci_init_status == INITIALIZED); - ret = cos_compinfo_alloc(child_ci, heap_ptr, cap_frontier, entry, ci); + ret = cos_compinfo_alloc(child_ci, scbcap, heap_ptr, cap_frontier, entry, ci); if (ret) return ret; - ret = cos_aep_alloc_intern(child_aep, child_defci, 0, is_sched ? sched_aep : NULL, NULL, NULL, 0); + dcbaddr = (vaddr_t)cos_page_bump_intern_valloc(child_ci, PAGE_SIZE); + assert(dcbaddr); + dcbcap = cos_dcb_alloc(ci, child_ci->pgtbl_cap, dcbaddr); + assert(dcbcap); + ret = cos_aep_alloc_intern(child_aep, child_defci, 0, is_sched ? sched_aep : NULL, NULL, NULL, 0, dcbcap, 0); + *initdcbcap = dcbcap; return ret; } @@ -151,29 +162,29 @@ cos_defcompinfo_childid_init(struct cos_defcompinfo *child_defci, spdid_t c) } int -cos_initaep_alloc(struct cos_defcompinfo *dst_dci, struct cos_aep_info *sched, int is_sched) +cos_initaep_alloc(struct cos_defcompinfo *dst_dci, struct cos_aep_info *sched, int is_sched, dcbcap_t dcap) { struct cos_defcompinfo *defci = cos_defcompinfo_curr_get(); struct cos_aep_info *sched_aep = cos_sched_aep_get(defci); struct cos_aep_info *child_aep = cos_sched_aep_get(dst_dci); struct cos_aep_info *sched_use = is_sched ? (sched ? sched : sched_aep) : NULL; - return cos_aep_alloc_intern(child_aep, dst_dci, 0, sched_use, NULL, NULL, 0); + return cos_aep_alloc_intern(child_aep, dst_dci, 0, sched_use, NULL, NULL, 0, dcap, 0); } int -cos_initaep_tcap_alloc(struct cos_defcompinfo *dst_dci, tcap_t tc, struct cos_aep_info *sched) +cos_initaep_tcap_alloc(struct cos_defcompinfo *dst_dci, tcap_t tc, struct cos_aep_info *sched, dcbcap_t dcap) { struct cos_defcompinfo *defci = cos_defcompinfo_curr_get(); struct cos_aep_info *sched_aep = cos_sched_aep_get(defci); struct cos_aep_info *child_aep = cos_sched_aep_get(dst_dci); struct cos_aep_info *sched_use = sched ? sched : sched_aep; - return cos_aep_alloc_intern(child_aep, dst_dci, tc, sched_use, NULL, NULL, 0); + return cos_aep_alloc_intern(child_aep, dst_dci, tc, sched_use, NULL, NULL, 0, dcap, 0); } int -cos_aep_alloc_ext(struct cos_aep_info *aep, struct cos_defcompinfo *dst_dci, struct cos_aep_info *sched, thdclosure_index_t idx) +cos_aep_alloc_ext(struct cos_aep_info *aep, struct cos_defcompinfo *dst_dci, struct cos_aep_info *sched, thdclosure_index_t idx, dcbcap_t dcap, dcboff_t doff) { struct cos_defcompinfo *defci = cos_defcompinfo_curr_get(); struct cos_aep_info *sched_aep = cos_sched_aep_get(defci); @@ -182,11 +193,11 @@ cos_aep_alloc_ext(struct cos_aep_info *aep, struct cos_defcompinfo *dst_dci, str if (!sched) sched_aep = cos_sched_aep_get(dst_dci); else sched_aep = sched; - return cos_aep_alloc_intern(aep, dst_dci, 0, sched_aep, NULL, NULL, idx); + return cos_aep_alloc_intern(aep, dst_dci, 0, sched_aep, NULL, NULL, idx, dcap, doff); } int -cos_aep_tcap_alloc_ext(struct cos_aep_info *aep, struct cos_defcompinfo *dst_dci, struct cos_aep_info *sched, tcap_t tc, thdclosure_index_t idx) +cos_aep_tcap_alloc_ext(struct cos_aep_info *aep, struct cos_defcompinfo *dst_dci, struct cos_aep_info *sched, tcap_t tc, thdclosure_index_t idx, dcbcap_t dcap, dcboff_t doff) { struct cos_defcompinfo *defci = cos_defcompinfo_curr_get(); struct cos_aep_info *sched_aep = cos_sched_aep_get(defci); @@ -196,25 +207,25 @@ cos_aep_tcap_alloc_ext(struct cos_aep_info *aep, struct cos_defcompinfo *dst_dci if (!sched) sched_aep = cos_sched_aep_get(dst_dci); else sched_aep = sched; - return cos_aep_alloc_intern(aep, dst_dci, tc, sched_aep, NULL, NULL, idx); + return cos_aep_alloc_intern(aep, dst_dci, tc, sched_aep, NULL, NULL, idx, dcap, doff); } int -cos_aep_alloc(struct cos_aep_info *aep, cos_aepthd_fn_t fn, void *data) +cos_aep_alloc(struct cos_aep_info *aep, cos_aepthd_fn_t fn, void *data, dcbcap_t dcap, dcboff_t doff) { struct cos_defcompinfo *defci = cos_defcompinfo_curr_get(); struct cos_aep_info *sched_aep = cos_sched_aep_get(defci); - return cos_aep_alloc_intern(aep, defci, 0, sched_aep, fn, data, 0); + return cos_aep_alloc_intern(aep, defci, 0, sched_aep, fn, data, 0, dcap, doff); } int -cos_aep_tcap_alloc(struct cos_aep_info *aep, tcap_t tc, cos_aepthd_fn_t fn, void *data) +cos_aep_tcap_alloc(struct cos_aep_info *aep, tcap_t tc, cos_aepthd_fn_t fn, void *data, dcbcap_t dcap, dcboff_t doff) { struct cos_defcompinfo *defci = cos_defcompinfo_curr_get(); struct cos_aep_info *sched_aep = cos_sched_aep_get(defci); - return cos_aep_alloc_intern(aep, defci, tc, sched_aep, fn, data, 0); + return cos_aep_alloc_intern(aep, defci, tc, sched_aep, fn, data, 0, dcap, doff); } int diff --git a/src/components/lib/kernel/cos_defkernel_api.h b/src/components/lib/kernel/cos_defkernel_api.h index fa083c27ef..35e1cb888f 100644 --- a/src/components/lib/kernel/cos_defkernel_api.h +++ b/src/components/lib/kernel/cos_defkernel_api.h @@ -36,7 +36,7 @@ struct cos_aep_info { thdid_t tid; arcvcap_t rcv; cos_aepthd_fn_t fn; - void * data; + void *data; }; /* Default Component information */ @@ -53,7 +53,7 @@ cos_aepthd_fn(void *data) { struct cos_aep_info *aep_info = (struct cos_aep_info *)data; cos_aepthd_fn_t aep_fn = aep_info->fn; - void * fn_data = aep_info->data; + void *fn_data = aep_info->data; (aep_fn)(aep_info->rcv, fn_data); @@ -96,44 +96,49 @@ void cos_defcompinfo_sched_init(void); * cos_defcompinfo_child_alloc: called to create a new child component including initial capabilities like pgtbl, * captbl, compcap, aep. if is_sched is set, scheduling end-point will also be created for the child component, else, * the current component's scheduler will remain the scheduler for the child component. + * TODO: initdcb cap and initdcb addr? */ int cos_defcompinfo_child_alloc(struct cos_defcompinfo *child_defci, vaddr_t entry, vaddr_t heap_ptr, - capid_t cap_frontier, int is_sched); + capid_t cap_frontier, int is_sched, dcbcap_t *initdcbcap); /* * cos_aep_alloc: creates a new async activation end-point which includes thread, tcap and rcv capabilities. * struct cos_aep_info passed in, must not be stack allocated. */ -int cos_aep_alloc(struct cos_aep_info *aep, cos_aepthd_fn_t fn, void *data); +int cos_aep_alloc(struct cos_aep_info *aep, cos_aepthd_fn_t fn, void *data, dcbcap_t dcap, dcboff_t doff); /* * cos_aep_alloc: creates a new async activation end-point, using an existing tcap. * struct cos_aep_info passed in, must not be stack allocated. */ -int cos_aep_tcap_alloc(struct cos_aep_info *aep, tcap_t tc, cos_aepthd_fn_t fn, void *data); +int cos_aep_tcap_alloc(struct cos_aep_info *aep, tcap_t tc, cos_aepthd_fn_t fn, void *data, dcbcap_t dcap, dcboff_t doff); /* * cos_initaep_alloc: create an initaep in the @child_dci and using sched->rcv as the parent, sets up cos_sched_ape_get(@child_dci) with the init capabilities. * if @sched == NULL, use the current scheduler in cos_sched_aep_get(cos_defcompinfo_get_cur()). * if @is_sched == 0, creates only the init thread (does not need @sched parameter) + * NOTE: dcbuaddr is the address in child_dci page-table. */ -int cos_initaep_alloc(struct cos_defcompinfo *child_dci, struct cos_aep_info *sched, int is_sched); +int cos_initaep_alloc(struct cos_defcompinfo *child_dci, struct cos_aep_info *sched, int is_sched, dcbcap_t dcap); /* * cos_initaep_tcap_alloc: same as cos_initaep_alloc with is_sched == 1, except it doesn't create a new tcap, * uses the tcap passed in @tc. + * NOTE: dcbuaddr is the address in child_dci page-table. */ -int cos_initaep_tcap_alloc(struct cos_defcompinfo *child_dci, tcap_t tc, struct cos_aep_info *sched); +int cos_initaep_tcap_alloc(struct cos_defcompinfo *child_dci, tcap_t tc, struct cos_aep_info *sched, dcbcap_t dcap); /* * cos_aep_alloc_ext: creates a new async activation end-point which includes thread, tcap and rcv capabilities in the child_dci component using sched_aep->rcv. * if @child_dci == NULL, create in the current component. + * NOTE: dcbuaddr is the address in child_dci page-table. */ -int cos_aep_alloc_ext(struct cos_aep_info *aep, struct cos_defcompinfo *child_dci, struct cos_aep_info *sched_aep, thdclosure_index_t idx); +int cos_aep_alloc_ext(struct cos_aep_info *aep, struct cos_defcompinfo *child_dci, struct cos_aep_info *sched_aep, thdclosure_index_t idx, dcbcap_t dcap, dcboff_t doff); /* * cos_aep_alloc_ext: creates a new async activation end-point which includes thread, tcap and rcv capabilities in the child_dci component using sched_aep->rcv. * if @child_dci == NULL, create in the current component. + * NOTE: dcbuaddr is the address in child_dci page-table. */ -int cos_aep_tcap_alloc_ext(struct cos_aep_info *aep, struct cos_defcompinfo *child_dci, struct cos_aep_info *sched_aep, tcap_t tc, thdclosure_index_t idx); +int cos_aep_tcap_alloc_ext(struct cos_aep_info *aep, struct cos_defcompinfo *child_dci, struct cos_aep_info *sched_aep, tcap_t tc, thdclosure_index_t idx, dcbcap_t dcap, dcboff_t doff); /* * cos_defswitch: thread switch api using the default scheduling tcap and rcv. diff --git a/src/components/lib/kernel/cos_kernel_api.c b/src/components/lib/kernel/cos_kernel_api.c index e23a2b7141..8cdf4afd0a 100644 --- a/src/components/lib/kernel/cos_kernel_api.c +++ b/src/components/lib/kernel/cos_kernel_api.c @@ -168,7 +168,7 @@ cos_comp_capfrontier_update(struct cos_compinfo *ci, capid_t cap_frontier) cos_capfrontier_init(ci, cap_frontier); } void -cos_compinfo_init(struct cos_compinfo *ci, pgtblcap_t pgtbl_cap, captblcap_t captbl_cap, compcap_t comp_cap, +cos_compinfo_init(struct cos_compinfo *ci, pgtblcap_t pgtbl_cap, captblcap_t captbl_cap, compcap_t comp_cap, scbcap_t scb_cap, vaddr_t heap_ptr, capid_t cap_frontier, struct cos_compinfo *ci_resources) { assert(ci && ci_resources); @@ -180,6 +180,7 @@ cos_compinfo_init(struct cos_compinfo *ci, pgtblcap_t pgtbl_cap, captblcap_t cap ci->pgtbl_cap = pgtbl_cap; ci->captbl_cap = captbl_cap; ci->comp_cap = comp_cap; + ci->scb_cap = scb_cap; ci->cap_frontier = 0; cos_vasfrontier_init(ci, heap_ptr); cos_capfrontier_init(ci, cap_frontier); @@ -662,8 +663,14 @@ __page_bump_valloc(struct cos_compinfo *ci, size_t sz) return ret_addr; } +vaddr_t +cos_page_bump_intern_valloc(struct cos_compinfo *ci, size_t sz) +{ + return __page_bump_valloc(ci, sz); +} + static vaddr_t -__page_bump_alloc(struct cos_compinfo *ci, size_t sz) +__page_bump_alloc(struct cos_compinfo *ci, size_t sz, int shared) { struct cos_compinfo *meta = __compinfo_metacap(ci); vaddr_t heap_vaddr, heap_cursor, heap_limit; @@ -688,7 +695,7 @@ __page_bump_alloc(struct cos_compinfo *ci, size_t sz) for (heap_cursor = heap_vaddr; heap_cursor < heap_limit; heap_cursor += PAGE_SIZE) { vaddr_t umem; - umem = __umem_bump_alloc(ci); + umem = shared ? __kmem_bump_alloc(ci) : __umem_bump_alloc(ci); if (!umem) return 0; /* Actually map in the memory. */ @@ -730,7 +737,7 @@ __alloc_mem_cap(struct cos_compinfo *ci, cap_t ct, vaddr_t *kmem, capid_t *cap) } static thdcap_t -__cos_thd_alloc(struct cos_compinfo *ci, compcap_t comp, thdclosure_index_t init_data) +__cos_thd_alloc(struct cos_compinfo *ci, compcap_t comp, thdclosure_index_t init_data, dcbcap_t dc, dcboff_t off) { vaddr_t kmem; capid_t cap; @@ -742,10 +749,12 @@ __cos_thd_alloc(struct cos_compinfo *ci, compcap_t comp, thdclosure_index_t init if (__alloc_mem_cap(ci, CAP_THD, &kmem, &cap)) return 0; assert(!(init_data & ~((1 << 16) - 1))); - /* TODO: Add cap size checking */ - ret = call_cap_op(ci->captbl_cap, CAPTBL_OP_THDACTIVATE, (init_data << 16) | cap, - __compinfo_metacap(ci)->mi.pgtbl_cap, kmem, comp); - if (ret) BUG(); + assert(!(off & ~((1 << 9) - 1))); + assert(kmem && (round_to_page(kmem) == kmem)); + + if (call_cap_op(ci->captbl_cap, CAPTBL_OP_THDACTIVATE, __compinfo_metacap(ci)->mi.pgtbl_cap | (cap << 16), + kmem, comp << 16 | dc, off << 16 | init_data)) + BUG(); return cap; } @@ -753,30 +762,61 @@ __cos_thd_alloc(struct cos_compinfo *ci, compcap_t comp, thdclosure_index_t init #include thdcap_t -cos_thd_alloc_ext(struct cos_compinfo *ci, compcap_t comp, thdclosure_index_t idx) +cos_thd_alloc_ext(struct cos_compinfo *ci, compcap_t comp, thdclosure_index_t idx, dcbcap_t dc, dcboff_t off) { if (idx < 1) return 0; - return __cos_thd_alloc(ci, comp, idx); + return __cos_thd_alloc(ci, comp, idx, dc, off); } thdcap_t -cos_thd_alloc(struct cos_compinfo *ci, compcap_t comp, cos_thd_fn_t fn, void *data) +cos_thd_alloc(struct cos_compinfo *ci, compcap_t comp, cos_thd_fn_t fn, void *data, dcbcap_t dc, dcboff_t off) { int idx = cos_thd_init_alloc(fn, data); thdcap_t ret; if (idx < 1) return 0; - ret = __cos_thd_alloc(ci, comp, idx); + ret = __cos_thd_alloc(ci, comp, idx, dc, off); if (!ret) cos_thd_init_free(idx); return ret; } thdcap_t -cos_initthd_alloc(struct cos_compinfo *ci, compcap_t comp) +cos_initthd_alloc(struct cos_compinfo *ci, compcap_t comp, dcbcap_t dc) +{ + return __cos_thd_alloc(ci, comp, 0, dc, 0); +} + +int +cos_thd_migrate(struct cos_compinfo *ci, thdcap_t t, cpuid_t c) +{ + return call_cap_op(ci->captbl_cap, CAPTBL_OP_THDMIGRATE, t, c, 0, 0); +} + +int +cos_thdcap_migrate(struct cos_compinfo *ci, thdcap_t t) { - return __cos_thd_alloc(ci, comp, 0); + return call_cap_op(ci->captbl_cap, CAPTBL_OP_THDMIGRATE, t, 0, 1, 0); +} + +dcbcap_t +cos_dcb_alloc(struct cos_compinfo *ci, pgtblcap_t ptcap, vaddr_t uaddr) +{ + vaddr_t kmem; + capid_t cap; + u32_t lid = livenessid_bump_alloc(); + + printd("cos_dcb_alloc\n"); + + assert(ci); + + if (__alloc_mem_cap(ci, CAP_DCB, &kmem, &cap)) return 0; + assert(kmem && (round_to_page(kmem) == kmem)); + if (call_cap_op(ci->captbl_cap, CAPTBL_OP_DCB_ACTIVATE, cap << 16 | lid, (__compinfo_metacap(ci)->mi.pgtbl_cap) << 16 | ptcap, kmem, uaddr)) + BUG(); + + return cap; } captblcap_t @@ -813,38 +853,69 @@ cos_pgtbl_alloc(struct cos_compinfo *ci) return cap; } +scbcap_t +cos_scb_alloc(struct cos_compinfo *ci) +{ + vaddr_t kmem; + capid_t cap; + u32_t lid = livenessid_bump_alloc(); + + printd("cos_scb_alloc\n"); + + assert(ci && lid); + + if (__alloc_mem_cap(ci, CAP_SCB, &kmem, &cap)) return 0; + assert(kmem && (round_to_page(kmem) == kmem)); + if (call_cap_op(ci->captbl_cap, CAPTBL_OP_SCB_ACTIVATE, cap, __compinfo_metacap(ci)->mi.pgtbl_cap, kmem, lid)) + BUG(); + + return cap; +} + int -cos_comp_alloc_with(struct cos_compinfo *ci, compcap_t comp, u32_t lid, captblcap_t ctc, pgtblcap_t ptc, vaddr_t entry) +cos_scb_mapping(struct cos_compinfo *ci, compcap_t comp, pgtblcap_t ptc, scbcap_t scbc, vaddr_t scb_uaddr) { - if (call_cap_op(ci->captbl_cap, CAPTBL_OP_COMPACTIVATE, comp, (ctc << 16) | ptc, lid, entry)) return 1; + if (call_cap_op(ci->captbl_cap, CAPTBL_OP_SCB_MAPPING, comp, ptc, scbc, scb_uaddr)) return 1; return 0; } compcap_t -cos_comp_alloc(struct cos_compinfo *ci, captblcap_t ctc, pgtblcap_t ptc, vaddr_t entry) +cos_comp_alloc_with(struct cos_compinfo *ci, compcap_t comp, u32_t lid, captblcap_t ctc, pgtblcap_t ptc, scbcap_t scbc, vaddr_t entry) +{ + if (call_cap_op(ci->captbl_cap, CAPTBL_OP_COMPACTIVATE, (lid << 16) | comp, (ctc << 16) | ptc, scbc, entry)) return 1; + + return 0; +} + +compcap_t +cos_comp_alloc(struct cos_compinfo *ci, captblcap_t ctc, pgtblcap_t ptc, scbcap_t scbc, vaddr_t entry) { capid_t cap; + /* FIXME: same or diff liveness ids in scb and comp resources? */ u32_t lid = livenessid_bump_alloc(); printd("cos_comp_alloc\n"); assert(ci && ctc && ptc && lid); + /* FIXME: packing scbc in 12 bits */ + assert(scbc < (1 << 12)); cap = __capid_bump_alloc(ci, CAP_COMP); if (!cap) return 0; - if (cos_comp_alloc_with(ci, cap, lid, ctc, ptc, entry)) BUG(); + if (cos_comp_alloc_with(ci, cap, lid, ctc, ptc, scbc, entry)) BUG(); return cap; } int -cos_compinfo_alloc(struct cos_compinfo *ci, vaddr_t heap_ptr, capid_t cap_frontier, vaddr_t entry, +cos_compinfo_alloc(struct cos_compinfo *ci, scbcap_t sc, vaddr_t heap_ptr, capid_t cap_frontier, vaddr_t entry, struct cos_compinfo *ci_resources) { pgtblcap_t ptc; captblcap_t ctc; compcap_t compc; + vaddr_t scb_vaddr; int pgtbl_lvl; printd("cos_compinfo_alloc\n"); @@ -853,10 +924,12 @@ cos_compinfo_alloc(struct cos_compinfo *ci, vaddr_t heap_ptr, capid_t cap_fronti assert(ptc); ctc = cos_captbl_alloc(ci_resources); assert(ctc); - compc = cos_comp_alloc(ci_resources, ctc, ptc, entry); + + //scb_vaddr = (vaddr_t)__page_bump_valloc(ci, COS_SCB_SIZE); + compc = cos_comp_alloc(ci_resources, ctc, ptc, sc, entry); assert(compc); - cos_compinfo_init(ci, ptc, ctc, compc, heap_ptr, cap_frontier, ci_resources); + cos_compinfo_init(ci, ptc, ctc, compc, sc, heap_ptr, cap_frontier, ci_resources); /* This is to make sure that "the address below vas_frontier has been allocated, follow the assumption we put in cos_vasfrontier_init()"*/ for (pgtbl_lvl = 0; pgtbl_lvl < COS_PGTBL_DEPTH - 1; pgtbl_lvl++) { @@ -938,10 +1011,29 @@ cos_hw_alloc(struct cos_compinfo *ci, u32_t bitmap) return cap; } +/* TODO: Can we alias/etc on this page with this logic? */ +void * +cos_dcbpg_bump_allocn(struct cos_compinfo *ci, size_t sz) +{ + assert(sz == PAGE_SIZE); + /* assert(sz % PAGE_SIZE == 0); */ + + return (void *)__page_bump_alloc(ci, sz, 1); +} + +void * +cos_scbpg_bump_allocn(struct cos_compinfo *ci, size_t sz) +{ + assert(sz == PAGE_SIZE); + /* assert(sz % PAGE_SIZE == 0); */ + + return (void *)__page_bump_alloc(ci, sz, 1); +} + void * cos_page_bump_alloc(struct cos_compinfo *ci) { - return (void *)__page_bump_alloc(ci, PAGE_SIZE); + return (void *)__page_bump_alloc(ci, PAGE_SIZE, 0); } void * @@ -949,7 +1041,7 @@ cos_page_bump_allocn(struct cos_compinfo *ci, size_t sz) { assert(sz % PAGE_SIZE == 0); - return (void *)__page_bump_alloc(ci, sz); + return (void *)__page_bump_alloc(ci, sz, 0); } capid_t @@ -996,9 +1088,7 @@ cos_thd_wakeup(thdcap_t thd, tcap_t tc, tcap_prio_t prio, tcap_res_t res) sched_tok_t cos_sched_sync(void) { - static sched_tok_t stok[NUM_CPU] CACHE_ALIGNED; - - return ps_faa((unsigned long *)&stok[cos_cpuid()], 1); + return ps_load(&cos_scb_info_get_core()->sched_tok); } int diff --git a/src/components/lib/kernel/cos_kernel_api.h b/src/components/lib/kernel/cos_kernel_api.h index 3ed0a6ae38..1bc20c8ff2 100644 --- a/src/components/lib/kernel/cos_kernel_api.h +++ b/src/components/lib/kernel/cos_kernel_api.h @@ -54,6 +54,9 @@ typedef capid_t compcap_t; typedef capid_t captblcap_t; typedef capid_t pgtblcap_t; typedef capid_t hwcap_t; +typedef capid_t scbcap_t; +typedef capid_t dcbcap_t; +typedef unsigned short dcboff_t; /* Memory source information */ struct cos_meminfo { @@ -65,7 +68,7 @@ struct cos_meminfo { /* Component captbl/pgtbl allocation information */ struct cos_compinfo { /* capabilities to higher-order capability tables (or -1) */ - capid_t pgtbl_cap, captbl_cap, comp_cap; + capid_t pgtbl_cap, captbl_cap, comp_cap, scb_cap; /* the frontier of unallocated caps, and the allocated captbl range */ capid_t cap_frontier, caprange_frontier; /* the frontier for each of the various sizes of capability per core! */ @@ -82,7 +85,7 @@ struct cos_compinfo { }; void cos_compinfo_init(struct cos_compinfo *ci, pgtblcap_t pgtbl_cap, captblcap_t captbl_cap, compcap_t comp_cap, - vaddr_t heap_ptr, capid_t cap_frontier, struct cos_compinfo *ci_resources);/* + scbcap_t scb_cap, vaddr_t heap_ptr, capid_t cap_frontier, struct cos_compinfo *ci_resources);/* * This only needs be called on compinfos that are managing resources * (i.e. likely only one). All of the capabilities will be relative * to this component's captbls. @@ -107,18 +110,27 @@ int cos_pgtbl_intern_expandwith(struct cos_compinfo *ci, pgtblcap_t intern, vadd * This uses the next three functions to allocate a new component and * correctly populate ci (allocating all resources from ci_resources). */ -int cos_compinfo_alloc(struct cos_compinfo *ci, vaddr_t heap_ptr, capid_t cap_frontier, vaddr_t entry, +int cos_compinfo_alloc(struct cos_compinfo *ci, scbcap_t sc, vaddr_t heap_ptr, capid_t cap_frontier, vaddr_t entry, struct cos_compinfo *ci_resources); captblcap_t cos_captbl_alloc(struct cos_compinfo *ci); pgtblcap_t cos_pgtbl_alloc(struct cos_compinfo *ci); -compcap_t cos_comp_alloc(struct cos_compinfo *ci, captblcap_t ctc, pgtblcap_t ptc, vaddr_t entry); +compcap_t cos_comp_alloc(struct cos_compinfo *ci, captblcap_t ctc, pgtblcap_t ptc, scbcap_t scbc, vaddr_t entry); +scbcap_t cos_scb_alloc(struct cos_compinfo *ci); +int cos_scb_mapping(struct cos_compinfo *ci, compcap_t comp, pgtblcap_t ptc, scbcap_t scbc, vaddr_t scb_uaddr); + +dcbcap_t cos_dcb_alloc(struct cos_compinfo *ci, pgtblcap_t ptc, vaddr_t dcb_uaddr); void cos_comp_capfrontier_update(struct cos_compinfo *ci, capid_t cap_frontier); typedef void (*cos_thd_fn_t)(void *); -thdcap_t cos_thd_alloc(struct cos_compinfo *ci, compcap_t comp, cos_thd_fn_t fn, void *data); -thdcap_t cos_thd_alloc_ext(struct cos_compinfo *ci, compcap_t comp, thdclosure_index_t idx); +thdcap_t cos_thd_alloc(struct cos_compinfo *ci, compcap_t comp, cos_thd_fn_t fn, void *data, dcbcap_t dc, + dcboff_t dcboff); +thdcap_t cos_thd_alloc_ext(struct cos_compinfo *ci, compcap_t comp, thdclosure_index_t idx, dcbcap_t dc, + dcboff_t dcboff); /* Create the initial (cos_init) thread */ -thdcap_t cos_initthd_alloc(struct cos_compinfo *ci, compcap_t comp); +thdcap_t cos_initthd_alloc(struct cos_compinfo *ci, compcap_t comp, dcbcap_t dc); +int cos_thd_migrate(struct cos_compinfo *ci, thdcap_t thdc, cpuid_t core); +/* update the thdcap to migrated core */ +int cos_thdcap_migrate(struct cos_compinfo *ci, thdcap_t thdc); sinvcap_t cos_sinv_alloc(struct cos_compinfo *srcci, compcap_t dstcomp, vaddr_t entry, invtoken_t token); arcvcap_t cos_arcv_alloc(struct cos_compinfo *ci, thdcap_t thdcap, tcap_t tcapcap, compcap_t compcap, arcvcap_t enotif); asndcap_t cos_asnd_alloc(struct cos_compinfo *ci, arcvcap_t arcvcap, captblcap_t ctcap); @@ -126,6 +138,9 @@ asndcap_t cos_asnd_alloc(struct cos_compinfo *ci, arcvcap_t arcvcap, captblcap_t void *cos_page_bump_alloc(struct cos_compinfo *ci); void *cos_page_bump_allocn(struct cos_compinfo *ci, size_t sz); +void *cos_dcbpg_bump_allocn(struct cos_compinfo *ci, size_t sz); +void *cos_scbpg_bump_allocn(struct cos_compinfo *ci, size_t sz); + capid_t cos_cap_cpy(struct cos_compinfo *dstci, struct cos_compinfo *srcci, cap_t srcctype, capid_t srccap); int cos_cap_cpy_at(struct cos_compinfo *dstci, capid_t dstcap, struct cos_compinfo *srcci, capid_t srccap); @@ -200,5 +215,6 @@ void cos_hw_shutdown(hwcap_t hwc); capid_t cos_capid_bump_alloc(struct cos_compinfo *ci, cap_t cap); +vaddr_t cos_page_bump_intern_valloc(struct cos_compinfo *ci, size_t sz); #endif /* COS_KERNEL_API_H */ diff --git a/src/components/lib/sl/Makefile b/src/components/lib/sl/Makefile index a9fe194416..68479147fb 100644 --- a/src/components/lib/sl/Makefile +++ b/src/components/lib/sl/Makefile @@ -21,7 +21,7 @@ INCLUDE_PATHS = . INTERFACE_DEPENDENCIES = capmgr # The library dependencies this component is reliant on for # compilation/linking (this is a list of directory names in lib/) -LIBRARY_DEPENDENCIES = component kernel ck +LIBRARY_DEPENDENCIES = component kernel ck dcb # Note: Both the interface and library dependencies should be # *minimal*. That is to say that removing a dependency should cause # the build to fail. The build system does not validate this diff --git a/src/components/lib/sl/sl.h b/src/components/lib/sl/sl.h index 9108a9467d..3852a1e195 100644 --- a/src/components/lib/sl/sl.h +++ b/src/components/lib/sl/sl.h @@ -66,6 +66,7 @@ struct sl_global_cpu { cycles_t timer_next; tcap_time_t timeout_next; + struct cos_scb_info *scb_info; struct ps_list_head event_head; /* all pending events for sched end-point */ }; @@ -77,6 +78,12 @@ sl__globals_cpu(void) return &(sl_global_cpu_data[cos_cpuid()]); } +static inline struct cos_scb_info * +sl_scb_info_cpu(void) +{ + return (sl__globals_cpu()->scb_info); +} + static inline void sl_thd_setprio(struct sl_thd *t, tcap_prio_t p) { @@ -282,8 +289,10 @@ struct sl_thd *sl_thd_aep_alloc(cos_aepthd_fn_t fn, void *data, int own_tcap, co */ struct sl_thd *sl_thd_comp_init(struct cos_defcompinfo *comp, int is_sched); -struct sl_thd *sl_thd_initaep_alloc(struct cos_defcompinfo *comp, struct sl_thd *sched_thd, int is_sched, int own_tcap, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax); -struct sl_thd *sl_thd_aep_alloc_ext(struct cos_defcompinfo *comp, struct sl_thd *sched_thd, thdclosure_index_t idx, int is_aep, int own_tcap, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, arcvcap_t *extrcv); +struct sl_thd *sl_thd_initaep_alloc_dcb(struct cos_defcompinfo *comp, struct sl_thd *sched_thd, int is_sched, int own_tcap, cos_channelkey_t key, dcbcap_t dcap, microsec_t ipiwin, u32_t ipimax); +struct sl_thd *sl_thd_aep_alloc_ext_dcb(struct cos_defcompinfo *comp, struct sl_thd *sched_thd, thdclosure_index_t idx, int is_aep, int own_tcap, cos_channelkey_t key, dcbcap_t dcap, dcboff_t doff, microsec_t ipiwin, u32_t ipimax, arcvcap_t *extrcv); +struct sl_thd *sl_thd_initaep_alloc(struct cos_defcompinfo *comp, struct sl_thd *sched_thd, int is_sched, int own_tcap, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, vaddr_t *dcbaddr); +struct sl_thd *sl_thd_aep_alloc_ext(struct cos_defcompinfo *comp, struct sl_thd *sched_thd, thdclosure_index_t idx, int is_aep, int own_tcap, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, vaddr_t *dcbaddr, arcvcap_t *extrcv); struct sl_thd *sl_thd_init_ext(struct cos_aep_info *aep, struct sl_thd *sched_thd); @@ -395,22 +404,24 @@ sl_thd_is_runnable(struct sl_thd *t) return (t->state == SL_THD_RUNNABLE || t->state == SL_THD_WOKEN); } +int sl_thd_kern_dispatch(thdcap_t t); + static inline int -sl_thd_activate(struct sl_thd *t, sched_tok_t tok) +sl_thd_activate(struct sl_thd *t, sched_tok_t tok, tcap_time_t timeout) { struct cos_defcompinfo *dci = cos_defcompinfo_curr_get(); struct cos_compinfo *ci = &dci->ci; - struct sl_global_cpu *g = sl__globals_cpu(); + struct sl_global_cpu *g = sl__globals_cpu(); int ret = 0; if (t->properties & SL_THD_PROPERTY_SEND) { - return cos_sched_asnd(t->sndcap, g->timeout_next, g->sched_rcv, tok); + return cos_sched_asnd(t->sndcap, timeout, g->sched_rcv, tok); } else if (t->properties & SL_THD_PROPERTY_OWN_TCAP) { return cos_switch(sl_thd_thdcap(t), sl_thd_tcap(t), t->prio, - g->timeout_next, g->sched_rcv, tok); + timeout, g->sched_rcv, tok); } else { ret = cos_defswitch(sl_thd_thdcap(t), t->prio, t == g->sched_thd ? - TCAP_TIME_NIL : g->timeout_next, tok); + TCAP_TIME_NIL : timeout, tok); if (likely(t != g->sched_thd && t != g->idle_thd)) return ret; if (unlikely(ret != -EPERM)) return ret; @@ -418,10 +429,99 @@ sl_thd_activate(struct sl_thd *t, sched_tok_t tok) * Attempting to activate scheduler thread or idle thread failed for no budget in it's tcap. * Force switch to the scheduler with current tcap. */ - return cos_switch(sl_thd_thdcap(g->sched_thd), 0, t->prio, 0, g->sched_rcv, tok); + return cos_switch(g->sched_thdcap, g->sched_tcap, t->prio, + timeout, g->sched_rcv, tok); } } +static inline int +sl_thd_dispatch(struct sl_thd *next, sched_tok_t tok, struct sl_thd *curr) +{ + volatile struct cos_scb_info *scb = sl_scb_info_cpu(); + struct cos_dcb_info *cd = sl_thd_dcbinfo(curr), *nd = sl_thd_dcbinfo(next); + assert(0); + + assert(curr != next); + if (unlikely(!cd || !nd)) return sl_thd_activate(next, tok, sl__globals_cpu()->timeout_next); + + /* + * jump labels in the asm routine: + * + * 1: slowpath dispatch using cos_thd_switch to switch to a thread + * if the dcb sp of the next thread is reset. + * (inlined slowpath sysenter to debug preemption problem) + * + * 2: if user-level dispatch routine completed successfully so + * the register states still retained and in the dispatched thread + * we reset its dcb sp! + * + * 3: if user-level dispatch was either preempted in the middle + * of this routine or kernel at some point had to switch to a + * thread that co-operatively switched away from this routine. + * NOTE: kernel takes care of resetting dcb sp in this case! + */ + + __asm__ __volatile__ ( \ + "pushl %%ebp\n\t" \ + "movl %%esp, %%ebp\n\t" \ + "movl $2f, (%%eax)\n\t" \ + "movl %%esp, 4(%%eax)\n\t" \ + "cmp $0, 4(%%ebx)\n\t" \ + "je 1f\n\t" \ + "movl %%edx, (%%ecx)\n\t" \ + "movl 4(%%ebx), %%esp\n\t" \ + "jmp *(%%ebx)\n\t" \ + ".align 4\n\t" \ + "1:\n\t" \ + "movl $3f, %%ecx\n\t" \ + "movl %%edx, %%eax\n\t" \ + "inc %%eax\n\t" \ + "shl $16, %%eax\n\t" \ + "movl $0, %%ebx\n\t" \ + "movl $0, %%esi\n\t" \ + "movl $0, %%edi\n\t" \ + "movl $0, %%edx\n\t" \ + "sysenter\n\t" \ + "jmp 3f\n\t" \ + ".align 4\n\t" \ + "2:\n\t" \ + "movl $0, 4(%%ebx)\n\t" \ + ".align 4\n\t" \ + "3:\n\t" \ + "popl %%ebp\n\t" \ + : + : "a" (cd), "b" (nd), + "S" ((u32_t)((u64_t)tok >> 32)), "D" ((u32_t)(((u64_t)tok << 32) >> 32)), + "c" (&(scb->curr_thd)), "d" (sl_thd_thdcap(next)) + : "memory", "cc"); + + scb = sl_scb_info_cpu(); + if (unlikely(ps_load(&scb->sched_tok) != tok)) return -EAGAIN; + + return 0; +} + +/*static inline int +sl_thd_activate(struct sl_thd *t, sched_tok_t tok) +{ + struct cos_defcompinfo *dci = cos_defcompinfo_curr_get(); + struct cos_compinfo *ci = &dci->ci; + struct sl_global_cpu *g = sl__globals_cpu(); + int ret = 0; + + if (t->properties & SL_THD_PROPERTY_SEND) { + return cos_sched_asnd(t->sndcap, g->timeout_next, g->sched_rcv, tok); + } else if (t->properties & SL_THD_PROPERTY_OWN_TCAP) { + return cos_switch(sl_thd_thdcap(t), sl_thd_tcap(t), t->prio, + g->timeout_next, g->sched_rcv, tok); + } else { + // TODO: can't use if you're reprogramming a timer/prio + return sl_thd_dispatch(t, tok, sl_thd_curr()); + //return cos_switch(sl_thd_thdcap(t), g->sched_tcap, t->prio, + // g->timeout_next, g->sched_rcv, tok); + } +}*/ + /* * Do a few things: 1. take the critical section if it isn't already * taken, 2. call schedule to find the next thread to run, 3. release @@ -512,8 +612,9 @@ sl_cs_exit_schedule_nospin_arg(struct sl_thd *to) assert(sl_thd_is_runnable(t)); sl_cs_exit(); + if (t == sl_thd_curr()) return 0; - ret = sl_thd_activate(t, tok); + ret = sl_thd_activate(t, tok, globals->timeout_next); /* * dispatch failed with -EPERM because tcap associated with thread t does not have budget. * Block the thread until it's next replenishment and return to the scheduler thread. @@ -524,7 +625,7 @@ sl_cs_exit_schedule_nospin_arg(struct sl_thd *to) if (unlikely(ret == -EPERM)) { assert(t != globals->sched_thd && t != globals->idle_thd); sl_thd_block_expiry(t); - if (unlikely(sl_thd_curr() != globals->sched_thd)) ret = sl_thd_activate(globals->sched_thd, tok); + if (unlikely(sl_thd_curr() != globals->sched_thd)) ret = sl_thd_activate(globals->sched_thd, tok, globals->timeout_next); } return ret; diff --git a/src/components/lib/sl/sl_plugins.h b/src/components/lib/sl/sl_plugins.h index 0a7d22db3f..74b860233a 100644 --- a/src/components/lib/sl/sl_plugins.h +++ b/src/components/lib/sl/sl_plugins.h @@ -16,6 +16,7 @@ */ struct sl_thd_policy *sl_thd_alloc_backend(thdid_t tid); void sl_thd_free_backend(struct sl_thd_policy *t); +struct sl_thd_policy *sl_thd_migrate_backend(struct sl_thd_policy *t, cpuid_t core); /* * cos_aep_info structs cannot be stack allocated! * The thread_alloc_backened needs to provide struct cos_aep_info without diff --git a/src/components/lib/sl/sl_sched.c b/src/components/lib/sl/sl_sched.c index b2d34f59b8..0cca739b1a 100644 --- a/src/components/lib/sl/sl_sched.c +++ b/src/components/lib/sl/sl_sched.c @@ -732,3 +732,10 @@ sl_sched_loop_nonblock(void) { sl_sched_loop_intern(1); } + +int +sl_thd_kern_dispatch(thdcap_t t) +{ + //return cos_switch(t, sl__globals_cpu()->sched_tcap, 0, sl__globals_cpu()->timeout_next, sl__globals_cpu()->sched_rcv, cos_sched_sync()); + return cos_thd_switch(t); +} diff --git a/src/components/lib/sl/sl_thd.h b/src/components/lib/sl/sl_thd.h index bd1035f27c..67c1d97ff1 100644 --- a/src/components/lib/sl/sl_thd.h +++ b/src/components/lib/sl/sl_thd.h @@ -95,8 +95,22 @@ struct sl_thd { struct event_info event_info; struct ps_list SL_THD_EVENT_LIST; /* list of events for the scheduler end-point */ + + struct cos_dcb_info *dcb; }; +static inline struct cos_dcb_info * +sl_thd_dcbinfo(struct sl_thd *t) +{ return t->dcb; } + +static inline unsigned long * +sl_thd_ip(struct sl_thd *t) +{ return &t->dcb->ip; } + +static inline unsigned long * +sl_thd_sp(struct sl_thd *t) +{ return &t->dcb->sp; } + static inline struct cos_aep_info * sl_thd_aepinfo(struct sl_thd *t) { return (t->aepinfo); } diff --git a/src/components/lib/sl/sl_thd_static_backend.c b/src/components/lib/sl/sl_thd_static_backend.c index 86aa4eac66..2985f8f5e5 100644 --- a/src/components/lib/sl/sl_thd_static_backend.c +++ b/src/components/lib/sl/sl_thd_static_backend.c @@ -17,26 +17,63 @@ static struct cos_aep_info __sl_aep_infos[NUM_CPU][SL_MAX_NUM_THDS]; static u32_t __sl_aep_free_off[NUM_CPU]; /* Default implementations of backend functions */ -struct sl_thd_policy * -sl_thd_alloc_backend(thdid_t tid) +static inline struct sl_thd_policy * +sl_thd_alloc_backend_core(cpuid_t core, thdid_t tid) { - assert(tid < SL_MAX_NUM_THDS); + assert(tid < SL_MAX_NUM_THDS && core >= 0 && core < NUM_CPU); - return &(__sl_threads[cos_cpuid()][tid]); + return &(__sl_threads[core][tid]); } -struct cos_aep_info * -sl_thd_alloc_aep_backend(void) +static inline struct cos_aep_info * +sl_thd_alloc_aep_backend_core(cpuid_t core) { + int off = 0; struct cos_aep_info *aep = NULL; - assert(__sl_aep_free_off[cos_cpuid()] < SL_MAX_NUM_THDS); - aep = &(__sl_aep_infos[cos_cpuid()][__sl_aep_free_off[cos_cpuid()]]); - ps_faa((unsigned long *)&(__sl_aep_free_off[cos_cpuid()]), 1); + assert(core < NUM_CPU && core >= 0); + off = ps_faa((unsigned long *)&__sl_aep_free_off[core], 1); + assert(off < SL_MAX_NUM_THDS); + aep = &__sl_aep_infos[core][off]; return aep; } +struct sl_thd_policy * +sl_thd_migrate_backend(struct sl_thd_policy *t, cpuid_t core) +{ + assert(core != cos_cpuid() && core >= 0 && core < NUM_CPU); + + struct cos_aep_info *a = sl_thd_alloc_aep_backend_core(core); + struct cos_aep_info *b = sl_thd_aepinfo(sl_mod_thd_get(t)); + struct sl_thd_policy *tc = sl_thd_alloc_backend_core(core, b->tid); + struct sl_thd *x = sl_mod_thd_get(tc), *y = sl_mod_thd_get(t); + + memset(a, 0, sizeof(struct cos_aep_info)); + a->tid = b->tid; + a->thd = b->thd; + assert(b->rcv == 0 && b->tc == 0); + memset(b, 0, sizeof(struct cos_aep_info)); + + memcpy(tc, t, sizeof(struct sl_thd_policy)); + x->aepinfo = a; + memset(t, 0, sizeof(struct sl_thd_policy)); + + return tc; +} + +struct sl_thd_policy * +sl_thd_alloc_backend(thdid_t tid) +{ + return sl_thd_alloc_backend_core(cos_cpuid(), tid); +} + +struct cos_aep_info * +sl_thd_alloc_aep_backend(void) +{ + return sl_thd_alloc_aep_backend_core(cos_cpuid()); +} + void sl_thd_free_backend(struct sl_thd_policy *t) { } diff --git a/src/components/lib/sl_capmgr/sl_capmgr.c b/src/components/lib/sl_capmgr/sl_capmgr.c index 011cb58113..ff05b68ff9 100644 --- a/src/components/lib/sl_capmgr/sl_capmgr.c +++ b/src/components/lib/sl_capmgr/sl_capmgr.c @@ -14,6 +14,7 @@ #include "../../interface/capmgr/memmgr.h" #include #include +#include extern void sl_thd_event_info_reset(struct sl_thd *t); extern void sl_thd_free_no_cs(struct sl_thd *t); @@ -55,7 +56,7 @@ sl_xcpu_asnd_alloc(void) } struct sl_thd * -sl_thd_alloc_init(struct cos_aep_info *aep, asndcap_t sndcap, sl_thd_property_t prps) +sl_thd_alloc_init(struct cos_aep_info *aep, asndcap_t sndcap, sl_thd_property_t prps, struct cos_dcb_info *dcb) { struct sl_thd_policy *tp = NULL; struct sl_thd *t = NULL; @@ -64,6 +65,7 @@ sl_thd_alloc_init(struct cos_aep_info *aep, asndcap_t sndcap, sl_thd_property_t if (!tp) goto done; t = sl_mod_thd_get(tp); + t->dcb = dcb; t->properties = prps; t->aepinfo = aep; t->sndcap = sndcap; @@ -88,20 +90,21 @@ struct sl_thd * sl_thd_alloc_no_cs(cos_thd_fn_t fn, void *data) { struct cos_defcompinfo *dci = cos_defcompinfo_curr_get(); - struct cos_compinfo *ci = &dci->ci; + struct cos_compinfo *ci = cos_compinfo_get(dci); struct sl_thd *t = NULL; struct cos_aep_info *aep = NULL; + struct cos_dcb_info *dcb = NULL; thdcap_t thdcap = 0; thdid_t tid = 0; aep = sl_thd_alloc_aep_backend(); if (!aep) goto done; - aep->thd = capmgr_thd_create(fn, data, &tid); + aep->thd = capmgr_thd_create(fn, data, &tid, &dcb); if (!aep->thd) goto done; aep->tid = tid; - t = sl_thd_alloc_init(aep, 0, 0); + t = sl_thd_alloc_init(aep, 0, 0, dcb); sl_mod_thd_create(sl_mod_thd_policy_get(t)); done: @@ -128,7 +131,7 @@ sl_thd_comp_init_no_cs(struct cos_defcompinfo *comp, sl_thd_property_t prps, asn assert(snd); } - t = sl_thd_alloc_init(aep, snd, prps); + t = sl_thd_alloc_init(aep, snd, prps, NULL); sl_mod_thd_create(sl_mod_thd_policy_get(t)); done: @@ -136,13 +139,14 @@ sl_thd_comp_init_no_cs(struct cos_defcompinfo *comp, sl_thd_property_t prps, asn } static struct sl_thd * -sl_thd_alloc_ext_no_cs(struct cos_defcompinfo *comp, thdclosure_index_t idx) +sl_thd_alloc_ext_no_cs(struct cos_defcompinfo *comp, thdclosure_index_t idx, vaddr_t *dcbuaddr) { struct cos_defcompinfo *dci = cos_defcompinfo_curr_get(); struct cos_compinfo *ci = cos_compinfo_get(dci); struct cos_compinfo *compci = cos_compinfo_get(comp); struct sl_thd *t = NULL; struct cos_aep_info *aep = NULL; + struct cos_dcb_info *dcb = NULL; if (comp == NULL || comp->id == 0) goto done; @@ -150,11 +154,11 @@ sl_thd_alloc_ext_no_cs(struct cos_defcompinfo *comp, thdclosure_index_t idx) aep = sl_thd_alloc_aep_backend(); if (!aep) goto done; - aep->thd = capmgr_thd_create_ext(comp->id, idx, &aep->tid); + aep->thd = capmgr_thd_create_ext(comp->id, idx, &aep->tid, &dcb); if (!aep->thd) goto done; aep->tc = sl_thd_tcap(sl__globals_cpu()->sched_thd); - t = sl_thd_alloc_init(aep, 0, 0); + t = sl_thd_alloc_init(aep, 0, 0, NULL); sl_mod_thd_create(sl_mod_thd_policy_get(t)); } else { struct cos_aep_info *compaep = cos_sched_aep_get(comp); @@ -173,7 +177,7 @@ sl_thd_alloc_ext_no_cs(struct cos_defcompinfo *comp, thdclosure_index_t idx) } static struct sl_thd * -sl_thd_aep_alloc_ext_no_cs(struct cos_defcompinfo *comp, struct sl_thd *sched, thdclosure_index_t idx, sl_thd_property_t prps, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, arcvcap_t *extrcv) +sl_thd_aep_alloc_ext_no_cs(struct cos_defcompinfo *comp, struct sl_thd *sched, thdclosure_index_t idx, sl_thd_property_t prps, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, vaddr_t *dcbuaddr, arcvcap_t *extrcv) { struct cos_aep_info *aep = NULL; struct sl_thd *t = NULL; @@ -198,10 +202,10 @@ sl_thd_aep_alloc_ext_no_cs(struct cos_defcompinfo *comp, struct sl_thd *sched, t if (!aep) goto done; if (prps & SL_THD_PROPERTY_OWN_TCAP) owntc = 1; - capmgr_aep_create_ext(comp->id, aep, idx, owntc, key, ipiwin, ipimax, extrcv); + capmgr_aep_create_ext(comp->id, aep, idx, owntc, key, ipiwin, ipimax, (struct cos_dcb_info **)dcbuaddr, extrcv); if (!aep->thd) goto done; - t = sl_thd_alloc_init(aep, 0, prps); + t = sl_thd_alloc_init(aep, 0, prps, NULL); sl_mod_thd_create(sl_mod_thd_policy_get(t)); } @@ -214,16 +218,17 @@ sl_thd_aep_alloc_no_cs(cos_aepthd_fn_t fn, void *data, sl_thd_property_t prps, c { struct sl_thd *t = NULL; struct cos_aep_info *aep = NULL; + struct cos_dcb_info *dcb = NULL; int owntc = 0; aep = sl_thd_alloc_aep_backend(); if (!aep) goto done; if (prps & SL_THD_PROPERTY_OWN_TCAP) owntc = 1; - capmgr_aep_create(aep, fn, data, owntc, key, ipiwin, ipimax); + capmgr_aep_create(aep, fn, data, owntc, key, ipiwin, ipimax, &dcb); if (aep->thd == 0) goto done; - t = sl_thd_alloc_init(aep, 0, prps); + t = sl_thd_alloc_init(aep, 0, prps, dcb); sl_mod_thd_create(sl_mod_thd_policy_get(t)); done: @@ -270,7 +275,15 @@ sl_thd_comp_init(struct cos_defcompinfo *comp, int is_sched) } struct sl_thd * -sl_thd_initaep_alloc(struct cos_defcompinfo *comp, struct sl_thd *sched_thd, int is_sched, int own_tcap, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax) +sl_thd_initaep_alloc_dcb(struct cos_defcompinfo *comp, struct sl_thd *sched_thd, int is_sched, int own_tcap, cos_channelkey_t key, dcbcap_t dcap, microsec_t ipiwin, u32_t ipimax) +{ + PRINTC("UNIMPLEMENTED: Using CAPMGR API which should manage the DCB capabilities\n"); + + return NULL; +} + +struct sl_thd * +sl_thd_initaep_alloc(struct cos_defcompinfo *comp, struct sl_thd *sched_thd, int is_sched, int own_tcap, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, vaddr_t *dcbuaddr) { struct sl_thd *t = NULL; @@ -278,18 +291,27 @@ sl_thd_initaep_alloc(struct cos_defcompinfo *comp, struct sl_thd *sched_thd, int sl_cs_enter(); if (!is_sched) { - t = sl_thd_alloc_ext_no_cs(comp, 0); + t = sl_thd_alloc_ext_no_cs(comp, 0, dcbuaddr); } else { t = sl_thd_aep_alloc_ext_no_cs(comp, sched_thd, 0, (is_sched ? SL_THD_PROPERTY_SEND : 0) - | (own_tcap ? SL_THD_PROPERTY_OWN_TCAP : 0), key, ipiwin, ipimax, NULL); + | (own_tcap ? SL_THD_PROPERTY_OWN_TCAP : 0), key, ipiwin, ipimax, dcbuaddr, NULL); } sl_cs_exit(); return t; } + +struct sl_thd * +sl_thd_aep_alloc_ext_dcb(struct cos_defcompinfo *comp, struct sl_thd *sched_thd, thdclosure_index_t idx, int is_aep, int own_tcap, cos_channelkey_t key, dcbcap_t dcap, dcboff_t doff, microsec_t ipiwin, u32_t ipimax, arcvcap_t *extrcv) +{ + PRINTC("UNIMPLEMENTED: Using CAPMGR API which should manage the DCB capabilities\n"); + + return NULL; +} + struct sl_thd * -sl_thd_aep_alloc_ext(struct cos_defcompinfo *comp, struct sl_thd *sched_thd, thdclosure_index_t idx, int is_aep, int own_tcap, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, arcvcap_t *extrcv) +sl_thd_aep_alloc_ext(struct cos_defcompinfo *comp, struct sl_thd *sched_thd, thdclosure_index_t idx, int is_aep, int own_tcap, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, vaddr_t *dcbuaddr, arcvcap_t *extrcv) { struct sl_thd *t = NULL; @@ -299,9 +321,9 @@ sl_thd_aep_alloc_ext(struct cos_defcompinfo *comp, struct sl_thd *sched_thd, thd sl_cs_enter(); if (!is_aep) own_tcap = 0; if (is_aep) { - t = sl_thd_aep_alloc_ext_no_cs(comp, sched_thd, idx, own_tcap ? SL_THD_PROPERTY_OWN_TCAP : 0, key, ipiwin, ipimax, extrcv); + t = sl_thd_aep_alloc_ext_no_cs(comp, sched_thd, idx, own_tcap ? SL_THD_PROPERTY_OWN_TCAP : 0, key, ipiwin, ipimax, dcbuaddr, extrcv); } else { - t = sl_thd_alloc_ext_no_cs(comp, idx); + t = sl_thd_alloc_ext_no_cs(comp, idx, dcbuaddr); } sl_cs_exit(); @@ -318,7 +340,7 @@ sl_thd_init_ext_no_cs(struct cos_aep_info *aepthd, struct sl_thd *sched) if (!aep) goto done; *aep = *aepthd; - t = sl_thd_alloc_init(aep, 0, 0); + t = sl_thd_alloc_init(aep, 0, 0, NULL); if (!t) goto done; /* use sched info for parent -> child notifications */ @@ -395,3 +417,39 @@ sl_thd_free(struct sl_thd *t) sl_thd_free_no_cs(t); sl_cs_exit(); } + +/*int +sl_thd_migrate_no_cs(struct sl_thd *t, cpuid_t core) +{ + struct sl_thd_policy *x = NULL; + int ret; + + if (t->properties) return -1; + if (t->state != SL_THD_RUNNABLE) return -1; + // capmgr should migrate the thdcap as well + ret = capmgr_thd_migrate(sl_thd_thdid(t), sl_thd_thdcap(t), core); + if (ret) return -1; + sl_mod_thd_delete(sl_mod_thd_policy_get(t)); + //ps_faa(&(sl__globals()->nthds_running[cos_cpuid()]), -1); + + x = sl_thd_migrate_backend(sl_mod_thd_policy_get(t), core); + if (!x) return -1; + + return 0; +} + +int +sl_thd_migrate(thdid_t tid, cpuid_t core) +{ + int ret; + struct sl_thd *c = sl_thd_curr(), *t = sl_thd_lkup(tid); + + if (core == cos_cpuid()) return -1; + if (sl_thd_rcvcap(t) || sl_thd_tcap(t)) return -1; + assert(c != t); + sl_cs_enter(); + ret = sl_thd_migrate_no_cs(t, core); + sl_cs_exit(); + + return ret; +}*/ diff --git a/src/components/lib/sl_kernel/Makefile b/src/components/lib/sl_kernel/Makefile index 2b82bbb314..c4f47ab301 100644 --- a/src/components/lib/sl_kernel/Makefile +++ b/src/components/lib/sl_kernel/Makefile @@ -21,7 +21,7 @@ INCLUDE_PATHS = . INTERFACE_DEPENDENCIES = # The library dependencies this component is reliant on for # compilation/linking (this is a list of directory names in lib/) -LIBRARY_DEPENDENCIES = component kernel sl ps util +LIBRARY_DEPENDENCIES = component kernel sl ps util dcb # Note: Both the interface and library dependencies should be # *minimal*. That is to say that removing a dependency should cause # the build to fail. The build system does not validate this diff --git a/src/components/lib/sl_kernel/sl_raw.c b/src/components/lib/sl_kernel/sl_raw.c index 26d800f0ef..e38c278067 100644 --- a/src/components/lib/sl_kernel/sl_raw.c +++ b/src/components/lib/sl_kernel/sl_raw.c @@ -11,6 +11,7 @@ #include #include #include +#include extern void sl_thd_event_info_reset(struct sl_thd *t); extern void sl_thd_free_no_cs(struct sl_thd *t); @@ -47,7 +48,7 @@ sl_xcpu_asnd_alloc(void) } struct sl_thd * -sl_thd_alloc_init(struct cos_aep_info *aep, asndcap_t sndcap, sl_thd_property_t prps) +sl_thd_alloc_init(struct cos_aep_info *aep, asndcap_t sndcap, sl_thd_property_t prps, struct cos_dcb_info *dcb) { struct sl_thd_policy *tp = NULL; struct sl_thd *t = NULL; @@ -57,6 +58,7 @@ sl_thd_alloc_init(struct cos_aep_info *aep, asndcap_t sndcap, sl_thd_property_t if (!tp) goto done; t = sl_mod_thd_get(tp); + t->dcb = dcb; t->properties = prps; t->aepinfo = aep; t->sndcap = sndcap; @@ -84,15 +86,21 @@ sl_thd_alloc_no_cs(cos_thd_fn_t fn, void *data) struct cos_compinfo *ci = cos_compinfo_get(dci); struct sl_thd *t = NULL; struct cos_aep_info *aep = NULL; + struct cos_dcb_info *dcb = NULL; + dcbcap_t dcap; + dcboff_t doff; aep = sl_thd_alloc_aep_backend(); if (!aep) goto done; + //dcap = cos_dcb_info_alloc_curr(&doff, (vaddr_t *)&dcb); + if (dcb && doff) assert(dcap); - aep->thd = cos_thd_alloc(ci, ci->comp_cap, fn, data); + aep->thd = cos_thd_alloc(ci, ci->comp_cap, fn, data, dcap, doff); if (!aep->thd) goto done; aep->tid = cos_introspect(ci, aep->thd, THD_GET_TID); if (!aep->tid) goto done; - t = sl_thd_alloc_init(aep, 0, 0); + + t = sl_thd_alloc_init(aep, 0, 0, dcb); sl_mod_thd_create(sl_mod_thd_policy_get(t)); done: @@ -118,7 +126,7 @@ sl_thd_comp_init_no_cs(struct cos_defcompinfo *comp, sl_thd_property_t prps, asn assert(snd); } - t = sl_thd_alloc_init(aep, snd, prps); + t = sl_thd_alloc_init(aep, snd, prps, NULL); sl_mod_thd_create(sl_mod_thd_policy_get(t)); done: @@ -126,7 +134,7 @@ sl_thd_comp_init_no_cs(struct cos_defcompinfo *comp, sl_thd_property_t prps, asn } static struct sl_thd * -sl_thd_alloc_ext_no_cs(struct cos_defcompinfo *comp, thdclosure_index_t idx) +sl_thd_alloc_ext_dcb_no_cs(struct cos_defcompinfo *comp, thdclosure_index_t idx, dcbcap_t dcbcap, dcboff_t dcboff) { struct cos_defcompinfo *dci = cos_defcompinfo_curr_get(); struct cos_compinfo *ci = cos_compinfo_get(dci); @@ -139,16 +147,16 @@ sl_thd_alloc_ext_no_cs(struct cos_defcompinfo *comp, thdclosure_index_t idx) aep = sl_thd_alloc_aep_backend(); if (!aep) goto done; - aep->thd = cos_thd_alloc_ext(ci, compci->comp_cap, idx); + aep->thd = cos_thd_alloc_ext(ci, compci->comp_cap, idx, dcbcap, dcboff); if (!aep->thd) goto done; aep->tid = cos_introspect(ci, aep->thd, THD_GET_TID); if (!aep->tid) goto done; - t = sl_thd_alloc_init(aep, 0, 0); + t = sl_thd_alloc_init(aep, 0, 0, NULL); sl_mod_thd_create(sl_mod_thd_policy_get(t)); } else { assert(idx == 0); - ret = cos_initaep_alloc(comp, NULL, 0); + ret = cos_initaep_alloc(comp, NULL, 0, dcbcap); if (ret) goto done; t = sl_thd_comp_init_no_cs(comp, 0, 0); @@ -164,18 +172,23 @@ sl_thd_aep_alloc_no_cs(cos_aepthd_fn_t fn, void *data, sl_thd_property_t prps, c struct cos_defcompinfo *dci = cos_defcompinfo_curr_get(); struct sl_thd *t = NULL; struct cos_aep_info *aep = NULL; + struct cos_dcb_info *dcb = NULL; int ret; + dcbcap_t dcap; + dcboff_t doff; aep = sl_thd_alloc_aep_backend(); if (!aep) goto done; + //dcap = cos_dcb_info_alloc_curr(&doff, (vaddr_t *)&dcb); + if (dcb && doff) assert(dcap); /* NOTE: Cannot use stack-allocated cos_aep_info struct here */ - if (prps & SL_THD_PROPERTY_OWN_TCAP) ret = cos_aep_alloc(aep, fn, data); + if (prps & SL_THD_PROPERTY_OWN_TCAP) ret = cos_aep_alloc(aep, fn, data, dcap, doff); else ret = cos_aep_tcap_alloc(aep, sl_thd_aepinfo(sl__globals_cpu()->sched_thd)->tc, - fn, data); + fn, data, dcap, doff); if (ret) goto done; - t = sl_thd_alloc_init(aep, 0, prps); + t = sl_thd_alloc_init(aep, 0, prps, dcb); sl_mod_thd_create(sl_mod_thd_policy_get(t)); done: @@ -183,7 +196,7 @@ sl_thd_aep_alloc_no_cs(cos_aepthd_fn_t fn, void *data, sl_thd_property_t prps, c } static struct sl_thd * -sl_thd_aep_alloc_ext_no_cs(struct cos_defcompinfo *comp, struct sl_thd *sched, thdclosure_index_t idx, sl_thd_property_t prps, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, arcvcap_t *extrcv) +sl_thd_aep_alloc_ext_dcb_no_cs(struct cos_defcompinfo *comp, struct sl_thd *sched, thdclosure_index_t idx, sl_thd_property_t prps, cos_channelkey_t key, dcbcap_t dcap, dcboff_t doff, microsec_t ipiwin, u32_t ipimax, arcvcap_t *extrcv) { struct cos_aep_info *aep = NULL; struct sl_thd *t = NULL; @@ -191,11 +204,11 @@ sl_thd_aep_alloc_ext_no_cs(struct cos_defcompinfo *comp, struct sl_thd *sched, t int ret = 0; if (prps & SL_THD_PROPERTY_SEND) { - assert(sched); + assert(sched && !doff); if (prps & SL_THD_PROPERTY_OWN_TCAP) { - ret = cos_initaep_alloc(comp, sl_thd_aepinfo(sched), prps & SL_THD_PROPERTY_SEND); + ret = cos_initaep_alloc(comp, sl_thd_aepinfo(sched), prps & SL_THD_PROPERTY_SEND, dcap); } else { - ret = cos_initaep_tcap_alloc(comp, sl_thd_tcap(sched), sl_thd_aepinfo(sched)); + ret = cos_initaep_tcap_alloc(comp, sl_thd_tcap(sched), sl_thd_aepinfo(sched), dcap); } if (ret) goto done; @@ -207,13 +220,13 @@ sl_thd_aep_alloc_ext_no_cs(struct cos_defcompinfo *comp, struct sl_thd *sched, t if (!aep) goto done; if (prps & SL_THD_PROPERTY_OWN_TCAP) { - ret = cos_aep_alloc_ext(aep, comp, sl_thd_aepinfo(sched), idx); + ret = cos_aep_alloc_ext(aep, comp, sl_thd_aepinfo(sched), idx, dcap, doff); } else { - ret = cos_aep_tcap_alloc_ext(aep, comp, sl_thd_aepinfo(sched), sl_thd_tcap(sched), idx); + ret = cos_aep_tcap_alloc_ext(aep, comp, sl_thd_aepinfo(sched), sl_thd_tcap(sched), idx, dcap, doff); } if (ret) goto done; - t = sl_thd_alloc_init(aep, 0, prps); + t = sl_thd_alloc_init(aep, 0, prps, NULL); sl_mod_thd_create(sl_mod_thd_policy_get(t)); if (extrcv) *extrcv = sl_thd_rcvcap(t); @@ -263,23 +276,39 @@ sl_thd_comp_init(struct cos_defcompinfo *comp, int is_sched) } struct sl_thd * -sl_thd_initaep_alloc(struct cos_defcompinfo *comp, struct sl_thd *sched_thd, int is_sched, int own_tcap, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax) +sl_thd_initaep_alloc(struct cos_defcompinfo *comp, struct sl_thd *sched_thd, int is_sched, int own_tcap, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, vaddr_t *dcbaddr) +{ + PRINTC("UNIMPLEMENTED: Using RAW API which cannot manage DCB resource for child components\n"); + + return NULL; +} + +struct sl_thd * +sl_thd_initaep_alloc_dcb(struct cos_defcompinfo *comp, struct sl_thd *sched_thd, int is_sched, int own_tcap, cos_channelkey_t key, dcbcap_t dcap, microsec_t ipiwin, u32_t ipimax) { struct sl_thd *t = NULL; if (!comp) return NULL; sl_cs_enter(); - if (!is_sched) t = sl_thd_alloc_ext_no_cs(comp, 0); - else t = sl_thd_aep_alloc_ext_no_cs(comp, sched_thd, 0, (is_sched ? SL_THD_PROPERTY_SEND : 0) - | (own_tcap ? SL_THD_PROPERTY_OWN_TCAP : 0), key, ipiwin, ipimax, NULL); + if (!is_sched) t = sl_thd_alloc_ext_dcb_no_cs(comp, 0, dcap, 0); + else t = sl_thd_aep_alloc_ext_dcb_no_cs(comp, sched_thd, 0, (is_sched ? SL_THD_PROPERTY_SEND : 0) + | (own_tcap ? SL_THD_PROPERTY_OWN_TCAP : 0), key, dcap, 0, ipiwin, ipimax, NULL); sl_cs_exit(); return t; } struct sl_thd * -sl_thd_aep_alloc_ext(struct cos_defcompinfo *comp, struct sl_thd *sched_thd, thdclosure_index_t idx, int is_aep, int own_tcap, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, arcvcap_t *extrcv) +sl_thd_aep_alloc_ext(struct cos_defcompinfo *comp, struct sl_thd *sched_thd, thdclosure_index_t idx, int is_aep, int own_tcap, cos_channelkey_t key, microsec_t ipiwin, u32_t ipimax, vaddr_t *dcbaddr, arcvcap_t *extrcv) +{ + PRINTC("UNIMPLEMENTED: Using RAW API which cannot manage DCB resource for child components\n"); + + return NULL; +} + +struct sl_thd * +sl_thd_aep_alloc_ext_dcb(struct cos_defcompinfo *comp, struct sl_thd *sched_thd, thdclosure_index_t idx, int is_aep, int own_tcap, cos_channelkey_t key, dcbcap_t dcap, dcboff_t doff, microsec_t ipiwin, u32_t ipimax, arcvcap_t *extrcv) { struct sl_thd *t = NULL; @@ -287,9 +316,9 @@ sl_thd_aep_alloc_ext(struct cos_defcompinfo *comp, struct sl_thd *sched_thd, thd sl_cs_enter(); if (!is_aep) own_tcap = 0; if (is_aep) { - t = sl_thd_aep_alloc_ext_no_cs(comp, sched_thd, idx, own_tcap ? SL_THD_PROPERTY_OWN_TCAP : 0, key, ipiwin, ipimax, extrcv); + t = sl_thd_aep_alloc_ext_dcb_no_cs(comp, sched_thd, idx, own_tcap ? SL_THD_PROPERTY_OWN_TCAP : 0, key, dcap, doff, ipiwin, ipimax, extrcv); } else { - t = sl_thd_alloc_ext_no_cs(comp, idx); + t = sl_thd_alloc_ext_dcb_no_cs(comp, idx, dcap, doff); } sl_cs_exit(); @@ -310,7 +339,7 @@ sl_thd_init_ext(struct cos_aep_info *aepthd, struct sl_thd *sched) *aep = *aepthd; /* TODO: use sched info for parent -> child notifications */ - t = sl_thd_alloc_init(aep, 0, 0); + t = sl_thd_alloc_init(aep, 0, 0, NULL); done: sl_cs_exit(); @@ -318,6 +347,14 @@ sl_thd_init_ext(struct cos_aep_info *aepthd, struct sl_thd *sched) return t; } +struct sl_thd * +sl_thd_retrieve_lazy(thdid_t tid) +{ + /* without capmgr, there is no lazy retrieval of threads! */ + assert(0); + return NULL; +} + struct sl_thd * sl_thd_retrieve(thdid_t tid) { @@ -333,3 +370,40 @@ sl_thd_free(struct sl_thd *t) sl_thd_free_no_cs(t); sl_cs_exit(); } + +int +sl_thd_migrate_no_cs(struct sl_thd *t, cpuid_t core) +{ + struct cos_defcompinfo *dci = cos_defcompinfo_curr_get(); + struct cos_compinfo *ci = cos_compinfo_get(dci); + struct sl_thd_policy *x = NULL; + int ret; + + if (t->properties) return -1; + if (t->state != SL_THD_RUNNABLE) return -1; + ret = cos_thd_migrate(ci, sl_thd_thdcap(t), core); + if (ret) return -1; + sl_mod_thd_delete(sl_mod_thd_policy_get(t)); + //ps_faa(&(sl__globals()->nthds_running[cos_cpuid()]), -1); + + x = sl_thd_migrate_backend(sl_mod_thd_policy_get(t), core); + if (!x) return -1; + + return 0; +} + +int +sl_thd_migrate(thdid_t tid, cpuid_t core) +{ + int ret; + struct sl_thd *c = sl_thd_curr(), *t = sl_thd_lkup(tid); + + if (core == cos_cpuid()) return -1; + assert(c != t); + sl_cs_enter(); + ret = sl_thd_migrate_no_cs(t, core); + sl_cs_exit(); + + return ret; +} + diff --git a/src/composer/src/resources.rs b/src/composer/src/resources.rs index cabf7be0a2..0ca46a286e 100644 --- a/src/composer/src/resources.rs +++ b/src/composer/src/resources.rs @@ -15,7 +15,7 @@ enum CapRes { Comp(ComponentId), } -const BOOT_CAPTBL_FREE: u32 = 52; +const BOOT_CAPTBL_FREE: u32 = 56; // The equivalent of the C __captbl_cap2sz(c) fn cap_sz(cap: &CapRes) -> u32 { diff --git a/src/kernel/capinv.c b/src/kernel/capinv.c index fd93314983..0bd4bec7db 100644 --- a/src/kernel/capinv.c +++ b/src/kernel/capinv.c @@ -16,6 +16,8 @@ #include "include/chal/defs.h" #include "include/hw.h" #include "include/chal/chal_proto.h" +#include "include/scb.h" +//#include "include/dcb.h" #define COS_DEFAULT_RET_CAP 0 @@ -83,6 +85,93 @@ printfn(struct pt_regs *regs) return 0; } +/* TODO: inline fast path and force non-inlined slow-path */ +static inline struct thread * +cap_ulthd_lazyupdate(struct pt_regs *regs, struct cos_cpu_local_info *cos_info, int interrupt, struct comp_info **ci_ptr) +{ + struct thread *thd = thd_current(cos_info); + struct cap_thd *ch_ult = NULL; + struct thread *ulthd = NULL; + capid_t ultc = 0; + int invstk_top = 0; + struct cos_scb_info *scb_core = NULL; /* per-core scb_info */ + + *ci_ptr = thd_invstk_current_compinfo(thd, cos_info, &invstk_top); + + assert(*ci_ptr && (*ci_ptr)->captbl); + + if (unlikely(!(*ci_ptr)->scb_data)) goto done; + scb_core = (((*ci_ptr)->scb_data) + get_cpuid()); + ultc = scb_core->curr_thd; + /* reset inconsistency from user-level thd! */ + if (!ultc && !interrupt) goto done; + + if (likely(ultc)) { + ch_ult = (struct cap_thd *)captbl_lkup((*ci_ptr)->captbl, ultc); + if (unlikely(!CAP_TYPECHK_CORE(ch_ult, CAP_THD))) ch_ult = NULL; + else ulthd = ch_ult->t; + } + + if (unlikely(interrupt)) { + struct thread *fixthd = thd; + + assert(scb_core->sched_tok < ~0U); + cos_faa((int *)&(scb_core->sched_tok), 1); + + if (ulthd) fixthd = ulthd; + + if (unlikely(fixthd->dcbinfo && fixthd->dcbinfo->sp)) { + regs->ip = fixthd->dcbinfo->ip + DCB_IP_KERN_OFF; + regs->sp = fixthd->dcbinfo->sp; + regs->dx = 0; /* sched token is in edx! */ + + fixthd->dcbinfo->sp = 0; + } + } + if (unlikely(!ultc || !ulthd || ulthd->dcbinfo == NULL)) goto done; + if (ulthd == thd) goto done; + /* check if kcurr and ucurr threads are both in the same page-table(component) */ + if (thd_current_pgtbl(ulthd) != thd_current_pgtbl(thd)) goto done; + thd_current_update(ulthd, thd, cos_info); + thd = ulthd; + +done: + return thd; +} + +void +cos_cap_ipi_handling(void) +{ + int idx, end; + struct IPI_receiving_rings *receiver_rings; + struct xcore_ring * ring; + + receiver_rings = &IPI_cap_dest[get_cpuid()]; + + /* We need to scan the entire buffer once. */ + idx = receiver_rings->start; + end = receiver_rings->start - 1; // end is int type. could be -1. + receiver_rings->start = (receiver_rings->start + 1) % NUM_CPU; + + /* scan the first half */ + for (; idx < NUM_CPU; idx++) { + ring = &receiver_rings->IPI_source[idx]; + if (ring->sender != ring->receiver) { + process_ring(ring); + } + } + + /* and scan the second half */ + for (idx = 0; idx <= end; idx++) { + ring = &receiver_rings->IPI_source[idx]; + if (ring->sender != ring->receiver) { + process_ring(ring); + } + } + + return; +} + void kmem_unalloc(unsigned long *pte) { @@ -246,6 +335,8 @@ cap_cpy(struct captbl *t, capid_t cap_to, capid_t capin_to, capid_t cap_from, ca type = ctfrom->type; sz = __captbl_cap2bytes(type); + /* don't allow cap copy on SCB/DCB */ + if (type == CAP_SCB || type == CAP_DCB) return -EINVAL; ctto = __cap_capactivate_pre(t, cap_to, capin_to, type, &ret); if (!ctto) return -EINVAL; @@ -548,11 +639,20 @@ cap_switch(struct pt_regs *regs, struct thread *curr, struct thread *next, struc static int cap_sched_tok_validate(struct thread *rcvt, sched_tok_t usr_tok, struct comp_info *ci, struct cos_cpu_local_info *cos_info) { + assert(ci->scb_data); + struct cos_scb_info *scb_core = ci->scb_data + get_cpuid(); + assert(rcvt && usr_tok < ~0U); - /* race-condition check for user-level thread switches */ - if (thd_rcvcap_get_counter(rcvt) > usr_tok) return -EAGAIN; - thd_rcvcap_set_counter(rcvt, usr_tok); + /* + * Kernel increments the sched_tok on preemption only. + * The rest is all co-operative, so if sched_tok in scb page + * increments after someone fetching a tok, then check for that! + * + * FIXME: make sure we're checking the scb of the scheduling component and not in any other component. + * I don't know if the comp_info here is of the scheduling component! + */ + if (unlikely(scb_core->sched_tok != usr_tok)) return -EAGAIN; return 0; } @@ -581,6 +681,10 @@ cap_thd_op(struct cap_thd *thd_cap, struct thread *thd, struct pt_regs *regs, st int ret; if (thd_cap->cpuid != get_cpuid() || thd_cap->cpuid != next->cpuid) return -EINVAL; + if (unlikely(thd->dcbinfo && thd->dcbinfo->sp)) { + assert((unsigned long)regs->cx == thd->dcbinfo->ip + DCB_IP_KERN_OFF); + assert((unsigned long)regs->bp == thd->dcbinfo->sp); + } if (arcv) { struct cap_arcv *arcv_cap; @@ -649,13 +753,11 @@ cap_ipi_process(struct pt_regs *regs) struct tcap *tcap_curr, *tcap_next; struct comp_info *ci; int i, scan_base; - unsigned long ip, sp; - thd_curr = thd_next = thd_current(cos_info); + thd_next = thd_curr = cap_ulthd_lazyupdate(regs, cos_info, 1, &ci); + assert(ci && ci->captbl); receiver_rings = &IPI_cap_dest[get_cpuid()]; tcap_curr = tcap_next = tcap_current(cos_info); - ci = thd_invstk_current(thd_curr, &ip, &sp, cos_info); - assert(ci && ci->captbl); scan_base = receiver_rings->start; receiver_rings->start = (receiver_rings->start + 1) % NUM_CPU; @@ -763,12 +865,11 @@ int cap_hw_asnd(struct cap_asnd *asnd, struct pt_regs *regs) { int curr_cpu = get_cpuid(); - struct cap_arcv * arcv; + struct cap_arcv *arcv; struct cos_cpu_local_info *cos_info; - struct thread * rcv_thd, *next, *thd; - struct tcap * rcv_tcap, *tcap, *tcap_next; - struct comp_info * ci; - unsigned long ip, sp; + struct thread *rcv_thd, *next, *thd; + struct tcap *rcv_tcap, *tcap, *tcap_next; + struct comp_info *ci; if (!CAP_TYPECHK(asnd, CAP_ASND)) return 1; assert(asnd->arcv_capid); @@ -784,12 +885,10 @@ cap_hw_asnd(struct cap_asnd *asnd, struct pt_regs *regs) cos_info = cos_cpu_local_info(); assert(cos_info); - thd = thd_current(cos_info); - tcap = tcap_current(cos_info); - assert(thd); - ci = thd_invstk_current(thd, &ip, &sp, cos_info); - assert(ci && ci->captbl); + thd = cap_ulthd_lazyupdate(regs, cos_info, 1, &ci); + assert(thd && ci && ci->captbl); assert(!(thd->state & THD_STATE_PREEMPTED)); + tcap = tcap_current(cos_info); rcv_thd = arcv->thd; rcv_tcap = rcv_thd->rcvcap.rcvcap_tcap; assert(rcv_tcap && tcap); @@ -832,16 +931,13 @@ int timer_process(struct pt_regs *regs) { struct cos_cpu_local_info *cos_info; - struct thread * thd_curr; - struct comp_info * comp; - unsigned long ip, sp; - cycles_t now; + struct thread *thd_curr; + struct comp_info *comp = NULL; cos_info = cos_cpu_local_info(); assert(cos_info); - thd_curr = thd_current(cos_info); + thd_curr = cap_ulthd_lazyupdate(regs, cos_info, 1, &comp); assert(thd_curr && thd_curr->cpuid == get_cpuid()); - comp = thd_invstk_current(thd_curr, &ip, &sp, cos_info); assert(comp); return expended_process(regs, thd_curr, comp, cos_info, 1); @@ -929,6 +1025,8 @@ cap_introspect(struct captbl *ct, capid_t capid, u32_t op, unsigned long *retval return tcap_introspect(((struct cap_tcap *)ch)->tcap, op, retval); case CAP_ARCV: return arcv_introspect(((struct cap_arcv *)ch), op, retval); + case CAP_COMP: + return comp_introspect(((struct cap_comp *)ch), op, retval); default: return -EINVAL; } @@ -945,7 +1043,6 @@ composite_syscall_handler(struct pt_regs *regs) struct comp_info * ci; struct thread * thd; capid_t cap; - unsigned long ip, sp; /* * We lookup this struct (which is on stack) only once, and @@ -955,8 +1052,16 @@ composite_syscall_handler(struct pt_regs *regs) int ret = -ENOENT; int thd_switch = 0; + /* Definitely do it for all the fast-path calls. */ + thd = cap_ulthd_lazyupdate(regs, cos_info, 0, &ci); + + assert(thd); cap = __userregs_getcap(regs); - thd = thd_current(cos_info); + + /* printk("thd %d calling cap %d (ip %x, sp %x), operation %d: %x, %x, %x, %x\n", thd->tid, cap, + * __userregs_getip(regs), __userregs_getsp(regs), __userregs_getop(regs), + * __userregs_get1(regs), __userregs_get2(regs), __userregs_get3(regs), __userregs_get4(regs)); + */ /* fast path: invocation return (avoiding captbl accesses) */ if (cap == COS_DEFAULT_RET_CAP) { @@ -971,14 +1076,12 @@ composite_syscall_handler(struct pt_regs *regs) return 0; } - ci = thd_invstk_current(thd, &ip, &sp, cos_info); - assert(ci && ci->captbl); - /* * We don't check the liveness of the current component * because it's guaranteed by component quiescence period, * which is at timer tick granularity. */ + assert(ci && ci->captbl); ch = captbl_lkup(ci->captbl, cap); if (unlikely(!ch)) { printk("cos: cap %d not found!\n", (int)cap); @@ -1145,22 +1248,38 @@ static int __attribute__((noinline)) composite_syscall_slowpath(struct pt_regs * break; } case CAPTBL_OP_THDACTIVATE: { - thdclosure_index_t init_data = __userregs_get1(regs) >> 16; - capid_t thd_cap = __userregs_get1(regs) & 0xFFFF; - capid_t pgtbl_cap = __userregs_get2(regs); - capid_t pgtbl_addr = __userregs_get3(regs); - capid_t compcap = __userregs_get4(regs); - - struct thread *thd; - unsigned long *pte = NULL; - - ret = cap_kmem_activate(ct, pgtbl_cap, pgtbl_addr, (unsigned long *)&thd, &pte); + u32_t reg3 = __userregs_get3(regs); + u32_t reg4 = __userregs_get4(regs); + capid_t pgtbl_addr = __userregs_get2(regs); + thdclosure_index_t init_data = (reg4 << 16) >> 16; + capid_t thd_cap = (capin >> 16); + capid_t pgtbl_cap = (capin << 16) >> 16; + capid_t compcap = (reg3 >> 16); + capid_t dcb_cap = (reg3 << 16) >> 16; + unsigned short dcboff = reg4 >> 16; + unsigned long *tpte = NULL, flags; + struct thread *thd; + struct cap_header *ctfrom; + + ret = cap_kmem_activate(ct, pgtbl_cap, pgtbl_addr, (unsigned long *)&thd, &tpte); if (unlikely(ret)) cos_throw(err, ret); - assert(thd && pte); + assert(thd && tpte); /* ret is returned by the overall function */ - ret = thd_activate(ct, cap, thd_cap, thd, compcap, init_data); - if (ret) kmem_unalloc(pte); + ret = thd_activate(ct, cap, thd_cap, thd, compcap, init_data, dcb_cap, dcboff); + if (ret) kmem_unalloc(tpte); + + break; + } + case CAPTBL_OP_THDMIGRATE: { + u32_t reg2 = __userregs_get2(regs); + u32_t reg3 = __userregs_get3(regs); + + if (reg3) { + ret = thd_migrate_cap(ct, capin); + } else { + ret = thd_migrate(ct, capin, reg2); + } break; } @@ -1182,7 +1301,7 @@ static int __attribute__((noinline)) composite_syscall_slowpath(struct pt_regs * case CAPTBL_OP_THDDEACTIVATE: { livenessid_t lid = __userregs_get2(regs); - ret = thd_deactivate(ct, op_cap, capin, lid, 0, 0, 0); + ret = thd_deactivate(ct, op_cap, capin, lid, 0, 0, 0, 0); break; } case CAPTBL_OP_THDTLSSET: { @@ -1198,7 +1317,7 @@ static int __attribute__((noinline)) composite_syscall_slowpath(struct pt_regs * capid_t pgtbl_cap = __userregs_get3(regs); capid_t cosframe_addr = __userregs_get4(regs); - ret = thd_deactivate(ct, op_cap, capin, lid, pgtbl_cap, cosframe_addr, 1); + ret = thd_deactivate(ct, op_cap, capin, lid, pgtbl_cap, cosframe_addr, 0, 1); break; } case CAPTBL_OP_CAPKMEM_FREEZE: { @@ -1210,10 +1329,12 @@ static int __attribute__((noinline)) composite_syscall_slowpath(struct pt_regs * case CAPTBL_OP_COMPACTIVATE: { capid_t captbl_cap = __userregs_get2(regs) >> 16; capid_t pgtbl_cap = __userregs_get2(regs) & 0xFFFF; - livenessid_t lid = __userregs_get3(regs); + livenessid_t lid = capin >> 16; + capid_t comp_cap = (capin << 16) >> 16; + capid_t scb_cap = __userregs_get3(regs); vaddr_t entry_addr = __userregs_get4(regs); - ret = comp_activate(ct, cap, capin, captbl_cap, pgtbl_cap, lid, entry_addr); + ret = comp_activate(ct, cap, comp_cap, captbl_cap, pgtbl_cap, scb_cap, lid, entry_addr); break; } case CAPTBL_OP_COMPDEACTIVATE: { @@ -1322,6 +1443,98 @@ static int __attribute__((noinline)) composite_syscall_slowpath(struct pt_regs * ret = hw_deactivate(op_cap, capin, lid); break; } + case CAPTBL_OP_SCB_ACTIVATE: { + capid_t scbcap = __userregs_get1(regs); + capid_t ptcap = __userregs_get2(regs); + vaddr_t addr = __userregs_get3(regs); + livenessid_t lid = __userregs_get4(regs); + + unsigned long *pte; + struct cos_scb_info *scb; + struct cap_scb *scbc; + + ret = cap_kmem_activate(ct, ptcap, addr, (unsigned long *)&scb, &pte); + if (ret) cos_throw(err, ret); + + ret = scb_activate(ct, cap, capin, (vaddr_t)scb, lid); + + scbc = (struct cap_scb *)captbl_lkup(ci->captbl, scbcap); + if (unlikely(!scbc || scbc->h.type != CAP_SCB)) return -EINVAL; + + + break; + } + case CAPTBL_OP_SCB_MAPPING: { + capid_t comp_cap = __userregs_get1(regs); + capid_t ptcap = __userregs_get2(regs); + capid_t scbcap = __userregs_get3(regs); + vaddr_t scb_uaddr = __userregs_get4(regs); + + struct cap_scb *scbc = NULL; + struct cap_comp *compc = NULL; + struct cap_pgtbl *ptc = NULL; + + //struct cos_cpu_local_info *cos_info = cos_cpu_local_info(); + //struct thread *thd = thd_current(cos_info); + //int invstk_top = 0; + //struct comp_info *ci_ptr = thd_invstk_current_compinfo(thd, cos_info, &invstk_top); + + scbc = (struct cap_scb *)captbl_lkup(ct, scbcap); + if ((unlikely(!scbc || scbc->h.type != CAP_SCB))) assert(0); // return -EINVAL; + + compc = (struct cap_comp *)captbl_lkup(ct, comp_cap); + assert(compc); + + ptc = (struct cap_pgtbl *)captbl_lkup(ct, ptcap); + assert(ptc); + + ret = scb_mapping(ct, scbc, ptc, compc, scb_uaddr); + + return ret; + } + case CAPTBL_OP_SCB_DEACTIVATE: { + u32_t r2 = __userregs_get2(regs); + livenessid_t lid = r2 >> 16; + capid_t ptcap = (r2 << 16) >> 16; + capid_t cf_addr = __userregs_get3(regs); + + ret = scb_deactivate(op_cap, capin, ptcap, cf_addr, lid); + + break; + } + case CAPTBL_OP_DCB_ACTIVATE: { + u32_t r1 = __userregs_get1(regs); + u32_t r2 = __userregs_get2(regs); + u32_t r3 = __userregs_get3(regs); + u32_t r4 = __userregs_get4(regs); + capid_t dcbcap = r1 >> 16; + capid_t ptcap = r2 >> 16; + livenessid_t lid = (r1 << 16) >> 16; + capid_t ptcapin = (r2 << 16) >> 16; + vaddr_t kaddr = r3; + vaddr_t uaddrin = r4; + struct cos_dcb_info *dcb; + unsigned long *pte; + + ret = cap_kmem_activate(ct, ptcap, kaddr, (unsigned long *)&dcb, &pte); + if (ret) cos_throw(err, ret); + ret = dcb_activate(ct, cap, dcbcap, (vaddr_t)dcb, lid, ptcapin, uaddrin); + break; + } + case CAPTBL_OP_DCB_DEACTIVATE: { + u32_t r2 = __userregs_get2(regs); + u32_t r3 = __userregs_get3(regs); + u32_t r4 = __userregs_get4(regs); + livenessid_t lid = r2 >> 16; + capid_t ptcap = (r2 << 16) >> 16; + vaddr_t cf_addr = r3 & (~0 << 12); + vaddr_t uaddrin = r4 & (~0 << 12); + capid_t ptcapin = (r4 << 20) >> 12 | ((r3 << 20) >> 20); + + ret = dcb_deactivate(op_cap, capin, lid, ptcap, cf_addr, ptcapin, uaddrin); + + break; + } default: goto err; } diff --git a/src/kernel/include/captbl.h b/src/kernel/include/captbl.h index 8ca57029af..cec4fbc063 100644 --- a/src/kernel/include/captbl.h +++ b/src/kernel/include/captbl.h @@ -55,7 +55,7 @@ typedef enum { #define CAP_HEAD_AMAP_SZ 4 #define CAP_HEAD_SZ_SZ 2 #define CAP_HEAD_FLAGS_SZ 3 -#define CAP_HEAD_TYPE_SZ 7 +#define CAP_HEAD_TYPE_SZ CAP_TYPE_MAXBITS /* * This is the header for each capability. Includes information about @@ -513,4 +513,4 @@ cap_init(void) assert(CAPTBL_EXPAND_SZ == 1 << CAPTBL_LEAF_ORD); } -#endif /* CAPTBL_H */ \ No newline at end of file +#endif /* CAPTBL_H */ diff --git a/src/kernel/include/component.h b/src/kernel/include/component.h index ef335bc944..492e403a07 100644 --- a/src/kernel/include/component.h +++ b/src/kernel/include/component.h @@ -12,40 +12,49 @@ #include "captbl.h" #include "pgtbl.h" #include "cap_ops.h" +#include "shared/cos_sched.h" /* 24B */ struct comp_info { struct liveness_data liveness; struct pgtbl_info pgtblinfo; struct captbl * captbl; + struct cos_scb_info *scb_data; } __attribute__((packed)); struct cap_comp { struct cap_header h; vaddr_t entry_addr; - struct cap_pgtbl * pgd; + struct cap_pgtbl *pgd; struct cap_captbl *ct_top; struct comp_info info; } __attribute__((packed)); +#include "scb.h" + static int -comp_activate(struct captbl *t, capid_t cap, capid_t capin, capid_t captbl_cap, capid_t pgtbl_cap, livenessid_t lid, - vaddr_t entry_addr) +comp_activate(struct captbl *t, capid_t cap, capid_t capin, capid_t captbl_cap, capid_t pgtbl_cap, capid_t scbcap, + livenessid_t lid, vaddr_t entry_addr) { - struct cap_comp * compc; - struct cap_pgtbl * ptc; + struct cap_comp *compc; + struct cap_pgtbl *ptc; struct cap_captbl *ctc; u32_t v; int ret = 0; + struct cap_scb *scbc = NULL; ctc = (struct cap_captbl *)captbl_lkup(t, captbl_cap); if (unlikely(!ctc || ctc->h.type != CAP_CAPTBL || ctc->lvl > 0)) return -EINVAL; ptc = (struct cap_pgtbl *)captbl_lkup(t, pgtbl_cap); if (unlikely(!ptc || ptc->h.type != CAP_PGTBL || ptc->lvl > 0)) return -EINVAL; + if (likely(scbcap)) { + scbc = (struct cap_scb *)captbl_lkup(t, scbcap); + if (unlikely(!scbc || scbc->h.type != CAP_SCB)) return -EINVAL; + } v = ptc->refcnt_flags; if (v & CAP_MEM_FROZEN_FLAG) return -EINVAL; - if (cos_cas_32((u32_t *)&ptc->refcnt_flags, v, v + 1) != CAS_SUCCESS) return -ECASFAIL; + if (cos_cas((unsigned long *)&ptc->refcnt_flags, v, v + 1) != CAS_SUCCESS) return -ECASFAIL; v = ctc->refcnt_flags; if (v & CAP_MEM_FROZEN_FLAG) cos_throw(undo_ptc, -EINVAL); @@ -53,10 +62,14 @@ comp_activate(struct captbl *t, capid_t cap, capid_t capin, capid_t captbl_cap, /* undo before return */ cos_throw(undo_ptc, -ECASFAIL); } - compc = (struct cap_comp *)__cap_capactivate_pre(t, cap, capin, CAP_COMP, &ret); if (!compc) cos_throw(undo_ctc, ret); + if (likely(scbc)) { + ret = scb_comp_update(t, scbc, compc); + if (ret) cos_throw(undo_capact, ret); + } + compc->entry_addr = entry_addr; compc->info.pgtblinfo.pgtbl = ptc->pgtbl; compc->info.pgtblinfo.asid = chal_asid_alloc(); @@ -68,6 +81,9 @@ comp_activate(struct captbl *t, capid_t cap, capid_t capin, capid_t captbl_cap, return 0; +/*undo_scb: + scb_comp_remove(t, scbc, pgtbl_cap, scb_uaddr);*/ +undo_capact: undo_ctc: cos_faa((int *)&ctc->refcnt_flags, -1); undo_ptc: @@ -79,8 +95,8 @@ static int comp_deactivate(struct cap_captbl *ct, capid_t capin, livenessid_t lid) { int ret; - struct cap_comp * compc; - struct cap_pgtbl * pgd; + struct cap_comp *compc; + struct cap_pgtbl *pgd; struct cap_captbl *ct_top; compc = (struct cap_comp *)captbl_lkup(ct->captbl, capin); @@ -89,6 +105,8 @@ comp_deactivate(struct cap_captbl *ct, capid_t capin, livenessid_t lid) ltbl_expire(&compc->info.liveness); pgd = compc->pgd; ct_top = compc->ct_top; + /* TODO: right way to remove scb info */ + if (likely(compc->info.scb_data)) scb_comp_remove(ct, 0, 0, 0); ret = cap_capdeactivate(ct, capin, CAP_COMP, lid); if (ret) return ret; @@ -107,4 +125,18 @@ comp_init(void) assert(sizeof(struct cap_comp) <= __captbl_cap2bytes(CAP_COMP)); } +static inline int +comp_introspect(struct cap_comp *t, unsigned long op, unsigned long *retval) +{ + switch (op) { + case COMP_GET_SCB_CURTHD: + *retval = t->info.scb_data->curr_thd; + + break; + default: + return -EINVAL; + } + return 0; +} + #endif /* COMPONENT_H */ diff --git a/src/kernel/include/dcb.h b/src/kernel/include/dcb.h new file mode 100644 index 0000000000..2d5bc1ceac --- /dev/null +++ b/src/kernel/include/dcb.h @@ -0,0 +1,109 @@ +/** + * Copyright 2019 by Phani Gadepalli, phanikishoreg@gwu.edu + * + * Redistribution of this file is permitted under the GNU General Public License v2. + */ + +#ifndef DCB_H +#define DCB_H + +#include "cap_ops.h" +#include "pgtbl.h" +#include "retype_tbl.h" +#include "component.h" +#include "thd.h" + +#define DCB_ENTRIES_MAX_PER_PAGE (PAGE_SIZE/sizeof(struct cos_dcb_info)) + +struct cap_dcb { + struct cap_header h; + struct liveness_data liveness; + unsigned int refcnt; + vaddr_t kern_addr; + cpuid_t cpuid; +} __attribute__((packed)); + +static int +dcb_activate(struct captbl *t, capid_t ctcap, capid_t dcbcap, vaddr_t kaddr, livenessid_t lid, capid_t ptcapin, vaddr_t uaddr) +{ + struct cap_dcb *dc; + struct cap_pgtbl *ptcin; + int ret; + paddr_t pf = chal_va2pa((void *)kaddr); + + ptcin = (struct cap_pgtbl *)captbl_lkup(t, ptcapin); + if (!ptcin || ptcin->h.type != CAP_PGTBL) return -EINVAL; + /* FIXME: hard coded page order */ + if (pgtbl_mapping_add(ptcin->pgtbl, uaddr, pf, PGTBL_USER_DEF, 12)) return -EINVAL; + + dc = (struct cap_dcb *)__cap_capactivate_pre(t, ctcap, dcbcap, CAP_DCB, &ret); + if (!dc) return -EINVAL; + + ltbl_get(lid, &dc->liveness); + dc->kern_addr = kaddr; + memset((void *)kaddr, 0, PAGE_SIZE); + dc->refcnt = 0; + dc->cpuid = get_cpuid(); + + __cap_capactivate_post(&dc->h, CAP_DCB); + + return 0; +} + +static int +dcb_deactivate(struct cap_captbl *ct, capid_t dcbcap, livenessid_t lid, capid_t ptcap, capid_t cosframe_addr, capid_t ptcapin, vaddr_t uaddrin) +{ + struct cap_dcb *dc; + struct cap_pgtbl *ptcin; + unsigned long *pte, addr, flags, old_v; + int ret; + + dc = (struct cap_dcb *)captbl_lkup(ct->captbl, dcbcap); + if (!dc || dc->h.type != CAP_DCB) return -EINVAL; + + if (!ptcapin || !uaddrin) return -EINVAL; + ptcin = (struct cap_pgtbl *)captbl_lkup(ct->captbl, ptcapin); + if (!ptcin || ptcin->h.type != CAP_PGTBL) return -EINVAL; + pte = pgtbl_lkup(ptcin->pgtbl, uaddrin, (u32_t *)&flags); + if (!pte) return -EINVAL; + if ((vaddr_t)pte != dc->kern_addr) return -EINVAL; + + if (dc->refcnt) return -EPERM; + + ltbl_expire(&dc->liveness); + ret = kmem_deact_pre((struct cap_header *)dc, ct->captbl, ptcap, cosframe_addr, &pte, &old_v); + if (ret) return ret; + ret = kmem_deact_post(pte, old_v); + if (ret) return ret; + dc->kern_addr = 0; + + return cap_capdeactivate(ct, dcbcap, CAP_DCB, lid); +} + +static inline int +dcb_thd_ref(struct cap_dcb *dc, struct thread *thd) +{ + if (dc->refcnt >= DCB_ENTRIES_MAX_PER_PAGE) return -EINVAL; + if (dc->cpuid != thd->cpuid) return -EINVAL; + if (!ltbl_isalive(&dc->liveness)) return -EPERM; + + dc->refcnt++; + + return 0; +} + +static inline int +dcb_thd_deref(struct cap_dcb *dc, struct thread *thd) +{ + if (!dc->refcnt) return -EINVAL; + if (dc->cpuid != thd->cpuid) return -EINVAL; + + if ((vaddr_t)thd->dcbinfo < dc->kern_addr || (vaddr_t)thd->dcbinfo > (dc->kern_addr + PAGE_SIZE)) return -EINVAL; + if (!ltbl_isalive(&dc->liveness)) return -EPERM; + + dc->refcnt--; + + return 0; +} + +#endif /* DCB_H */ diff --git a/src/kernel/include/scb.h b/src/kernel/include/scb.h new file mode 100644 index 0000000000..08fb06f8a4 --- /dev/null +++ b/src/kernel/include/scb.h @@ -0,0 +1,109 @@ +/** + * Copyright 2019 by Phani Gadepalli, phanikishoreg@gwu.edu + * + * Redistribution of this file is permitted under the GNU General Public License v2. + */ + +#ifndef SCB_H +#define SCB_H + +#include "component.h" +#include "cap_ops.h" +#include "pgtbl.h" +#include "retype_tbl.h" + +struct comp_info; + +struct cap_scb { + struct cap_header h; + struct liveness_data liveness; + struct cap_comp *compc; + vaddr_t kern_addr; +} __attribute__((packed)); + +static int +scb_activate(struct captbl *t, capid_t ctcap, capid_t scbcap, vaddr_t kaddr, livenessid_t lid) +{ + struct cap_scb *sc; + int ret; + + sc = (struct cap_scb *)__cap_capactivate_pre(t, ctcap, scbcap, CAP_SCB, &ret); + if (!sc) return -EINVAL; + + ltbl_get(lid, &sc->liveness); + sc->kern_addr = kaddr; + sc->compc = NULL; + memset((void *)kaddr, 0, COS_SCB_SIZE); + + __cap_capactivate_post(&sc->h, CAP_SCB); + + return 0; +} + +static int +scb_deactivate(struct cap_captbl *ct, capid_t scbcap, capid_t ptcap, capid_t cosframe_addr, livenessid_t lid) +{ + struct cap_scb *sc; + unsigned long old_v = 0, *pte = NULL; + int ret; + + sc = (struct cap_scb *)captbl_lkup(ct->captbl, scbcap); + if (!sc || sc->h.type != CAP_SCB) return -EINVAL; + + /* FIXME: component using this scbcap is still active! how to handle this? */ + if (sc->compc) return -EPERM; + + ltbl_expire(&sc->liveness); + ret = kmem_deact_pre((struct cap_header *)sc, ct->captbl, ptcap, cosframe_addr, &pte, &old_v); + if (ret) return ret; + ret = kmem_deact_post(pte, old_v); + if (ret) return ret; + + return cap_capdeactivate(ct, scbcap, CAP_SCB, lid); +} + +static inline int +scb_comp_update(struct captbl *ct, struct cap_scb *sc, struct cap_comp *compc) +{ + if (unlikely(!ltbl_isalive(&sc->liveness))) return -EPERM; + /* FIXME: hard coded pgtbl order */ + + sc->compc = compc; + compc->info.scb_data = (struct cos_scb_info *)(sc->kern_addr); + + return 0; +} + +static inline int +scb_mapping(struct captbl *ct, struct cap_scb *sc, struct cap_pgtbl *ptcin, struct cap_comp *compc, vaddr_t uaddrin) +{ + assert(sc->compc == compc || !sc->compc); + paddr_t pf = chal_va2pa((void *)(sc->kern_addr)); + + if (pgtbl_mapping_add(ptcin->pgtbl, uaddrin, pf, PGTBL_USER_DEF, 12)) return -EINVAL; + + return 0; +} + +static inline int +scb_comp_remove(struct cap_captbl *ct, struct cap_scb *sc, capid_t ptcapin, vaddr_t uaddrin) +{ + int ret; + + if (unlikely(!ct || !sc || !ptcapin || !uaddrin)) return -EINVAL; + + if (unlikely(!ltbl_isalive(&sc->liveness))) return -EPERM; + if (unlikely(!sc->compc)) return -EINVAL; + + /* TODO: unmap uaddrin in the user-land */ + + return 0; +} + +static inline struct liveness_data * +scb_liveness(struct cap_scb *sc) +{ + return &sc->liveness; +} + +#endif /* SCB_H */ diff --git a/src/kernel/include/shared/cos_sched.h b/src/kernel/include/shared/cos_sched.h new file mode 100644 index 0000000000..eef5664464 --- /dev/null +++ b/src/kernel/include/shared/cos_sched.h @@ -0,0 +1,52 @@ +#ifndef COS_SCHED_H +#define COS_SCHED_H + +#include "./cos_types.h" + +struct cos_thd_event { + u16_t blocked; + u32_t next_timeout; + u64_t elapsed_cycs; +} __attribute__((packed)); + +struct cos_sched_event { + thdid_t tid; + struct cos_thd_event evt; +} __attribute__((packed)); + +#define COS_SCHED_EVENT_RING_SIZE 16 + +struct cos_sched_ring { + int head, tail; + struct cos_sched_event event_buf[COS_SCHED_EVENT_RING_SIZE]; +} __attribute__((packed)); + +struct cos_scb_info { + capid_t curr_thd; + cycles_t timer_next; + sched_tok_t sched_tok; + struct cos_sched_ring sched_events; +} CACHE_ALIGNED; + +struct cos_dcb_info { + unsigned long ip; + unsigned long sp; + unsigned long pending; /* binary value. TODO: move it to ip or sp */ +} __attribute__((packed)); + +/* + * This is the "ip" the kernel uses to update the thread when it sees that the + * thread is still in user-level dispatch routine. + * This is the offset of instruction after resetting the "next" thread's "sp" to zero + * in a purely user-level dispatch. + * + * Whenever kernel is switching to a thread which has "sp" non-zero, it would switch + * to the "ip" saved in the dcb_info and reset the "sp" of the thread that the kernel + * is dispatching to! + * This is necessary because, if the kernel is dispatching to a thread that was in the + * user-level dispatch routine before, then the only registers that it can restore are + * "ip" and "sp", everything else is either clobbered or saved/loaded at user-level. + */ +#define DCB_IP_KERN_OFF 8 + +#endif /* COS_SCHED_H */ diff --git a/src/kernel/include/shared/cos_types.h b/src/kernel/include/shared/cos_types.h index 215f0fa383..b6817b1a2f 100644 --- a/src/kernel/include/shared/cos_types.h +++ b/src/kernel/include/shared/cos_types.h @@ -96,6 +96,7 @@ typedef enum { CAPTBL_OP_THDACTIVATE, CAPTBL_OP_THDDEACTIVATE, CAPTBL_OP_THDTLSSET, + CAPTBL_OP_THDMIGRATE, CAPTBL_OP_COMPACTIVATE, CAPTBL_OP_COMPDEACTIVATE, CAPTBL_OP_SINVACTIVATE, @@ -142,7 +143,14 @@ typedef enum { CAPTBL_OP_HW_L1FLUSH, CAPTBL_OP_HW_TLBFLUSH, CAPTBL_OP_HW_TLBSTALL, - CAPTBL_OP_HW_TLBSTALL_RECOUNT + CAPTBL_OP_HW_TLBSTALL_RECOUNT, + + CAPTBL_OP_SCB_ACTIVATE, + CAPTBL_OP_SCB_MAPPING, + CAPTBL_OP_SCB_DEACTIVATE, + + CAPTBL_OP_DCB_ACTIVATE, + CAPTBL_OP_DCB_DEACTIVATE, } syscall_op_t; typedef enum { @@ -160,8 +168,13 @@ typedef enum { CAP_QUIESCENCE, /* when deactivating, set to track quiescence state */ CAP_TCAP, /* tcap captable entry */ CAP_HW, /* hardware (interrupt) */ + CAP_SCB, /* Scheduler control block (SCB) */ + CAP_DCB, /* Dispatch control block (DCB) */ } cap_t; +/* maximum size allowed for CAP TYPE in a capability header */ +#define CAP_TYPE_MAXBITS 7 +#define CAP_TYPE_MAX (1 << CAP_TYPE_MAXBITS - 1) /* TODO: pervasive use of these macros */ /* v \in struct cap_* *, type \in cap_t */ #define CAP_TYPECHK(v, t) ((v) && (v)->h.type == (t)) @@ -210,6 +223,8 @@ typedef int cpuid_t; static inline cap_sz_t __captbl_cap2sz(cap_t c) { + /* if (unlikely(c > CAP_TYPE_MAX)) return CAP_SZ_ERR; */ + /* TODO: optimize for invocation and return */ switch (c) { case CAP_SRET: @@ -217,6 +232,8 @@ __captbl_cap2sz(cap_t c) case CAP_TCAP: return CAP_SZ_16B; case CAP_HW: /* TODO: 256bits = 32B * 8b */ + case CAP_SCB: + case CAP_DCB: return CAP_SZ_32B; case CAP_SINV: case CAP_COMP: @@ -281,7 +298,7 @@ enum BOOT_CAPTBL_LAST_CAP = BOOT_CAPTBL_SELF_INITRCV_BASE + NUM_CPU * CAP64B_IDSZ, /* round up to next entry */ - BOOT_CAPTBL_FREE = round_up_to_pow2(BOOT_CAPTBL_LAST_CAP, CAPMAX_ENTRY_SZ) + BOOT_CAPTBL_FREE = round_up_to_pow2(BOOT_CAPTBL_LAST_CAP+CAPMAX_ENTRY_SZ, CAPMAX_ENTRY_SZ) }; #define BOOT_CAPTBL_SELF_INITTHD_BASE_CPU(cpuid) (BOOT_CAPTBL_SELF_INITTHD_BASE + cpuid * CAP16B_IDSZ) @@ -292,6 +309,16 @@ enum #define BOOT_CAPTBL_SELF_INITTCAP_CPU_BASE (BOOT_CAPTBL_SELF_INITTCAP_BASE_CPU(cos_cpuid())) #define BOOT_CAPTBL_SELF_INITRCV_CPU_BASE (BOOT_CAPTBL_SELF_INITRCV_BASE_CPU(cos_cpuid())) +enum llboot_scb_dcb_caps +{ + LLBOOT_CAPTBL_SCB = round_up_to_pow2(BOOT_CAPTBL_LAST_CAP, CAPMAX_ENTRY_SZ), + LLBOOT_CAPTBL_INITDCB = LLBOOT_CAPTBL_SCB + CAP64B_IDSZ, + LLBOOT_CAPTBL_FREE = round_up_to_pow2(LLBOOT_CAPTBL_INITDCB + (CAP64B_IDSZ * NUM_CPU), CAPMAX_ENTRY_SZ), +}; + +#define LLBOOT_CAPTBL_INITDCB_CPU(cpuid) (LLBOOT_CAPTBL_INITDCB + (CAP64B_IDSZ * cpuid)) +#define LLBOOT_CAPTBL_CPU_INITDCB LLBOOT_CAPTBL_INITDCB_CPU(cos_cpuid()) + /* * The half of the first page of init captbl is devoted to root node. So, the * first page of captbl can contain 128 caps, and every extra page can hold 256 @@ -306,6 +333,8 @@ enum { /* thread id */ THD_GET_TID, + THD_GET_DCB_IP, + THD_GET_DCB_SP, }; enum @@ -322,6 +351,12 @@ enum ARCV_GET_THDID, }; +enum +{ + /* get current thread info from scb */ + COMP_GET_SCB_CURTHD, +}; + /* Macro used to define per core variables */ #define PERCPU(type, name) \ PERCPU_DECL(type, name); \ @@ -413,6 +448,31 @@ struct cos_stack_freelists { /* #error "Assembly in requires that COMP_INFO_STACK_FREELISTS != 1 || * COMP_INFO_TMEM_STK_RELINQ != 0. Change the defines, or change the assembly" */ /* #endif */ +/*struct cos_scb_info { + capid_t curr_thd; + cycles_t timer_next; + sched_tok_t sched_tok; +} CACHE_ALIGNED; + +struct cos_dcb_info { + unsigned long ip; + unsigned long sp; +} __attribute__((packed));*/ + +/* + * This is the "ip" the kernel uses to update the thread when it sees that the + * thread is still in user-level dispatch routine. + * This is the offset of instruction after resetting the "next" thread's "sp" to zero + * in a purely user-level dispatch. + * + * Whenever kernel is switching to a thread which has "sp" non-zero, it would switch + * to the "ip" saved in the dcb_info and reset the "sp" of the thread that the kernel + * is dispatching to! + * This is necessary because, if the kernel is dispatching to a thread that was in the + * user-level dispatch routine before, then the only registers that it can restore are + * "ip" and "sp", everything else is either clobbered or saved/loaded at user-level. + */ +#define DCB_IP_KERN_OFF 8 struct cos_component_information { struct cos_stack_freelists cos_stacks; @@ -513,4 +573,4 @@ typedef unsigned short int cos_channelkey_t; /* 0 == PRIVATE KEY. >= 1 GLOBAL KE */ #define PRINT_CAP_TEMP (BOOT_CAPTBL_PRINT_HACK) -#endif /* TYPES_H */ \ No newline at end of file +#endif /* TYPES_H */ diff --git a/src/kernel/include/thd.h b/src/kernel/include/thd.h index fd0ec066b3..2643214379 100644 --- a/src/kernel/include/thd.h +++ b/src/kernel/include/thd.h @@ -34,7 +34,7 @@ struct invstk_entry { */ struct rcvcap_info { /* how many other arcv end-points send notifications to this one? */ - int isbound, pending, refcnt, is_all_pending; + int isbound, pending, refcnt, is_all_pending, is_init; sched_tok_t sched_count; struct tcap * rcvcap_tcap; /* This rcvcap's tcap */ struct thread *rcvcap_thd_notif; /* The parent rcvcap thread for notifications */ @@ -69,6 +69,7 @@ struct thread { tcap_time_t timeout; struct thread *interrupted_thread; struct thread *scheduler_thread; + struct cos_dcb_info *dcbinfo; /* rcv end-point data-structures */ struct rcvcap_info rcvcap; @@ -89,6 +90,8 @@ struct cap_thd { cpuid_t cpuid; } __attribute__((packed)); +#include "dcb.h" + static void thd_upcall_setup(struct thread *thd, vaddr_t entry_addr, int option, int arg1, int arg2, int arg3) { @@ -322,16 +325,22 @@ thd_scheduler_set(struct thread *thd, struct thread *sched) } static int -thd_activate(struct captbl *t, capid_t cap, capid_t capin, struct thread *thd, capid_t compcap, thdclosure_index_t init_data) +thd_activate(struct captbl *t, capid_t cap, capid_t capin, struct thread *thd, capid_t compcap, thdclosure_index_t init_data, capid_t dcbcap, unsigned short dcboff) { struct cos_cpu_local_info *cli = cos_cpu_local_info(); - struct cap_thd *tc; - struct cap_comp *compc; + struct cap_thd *tc = NULL; + struct cap_comp *compc = NULL; + struct cap_dcb *dc = NULL; int ret; memset(thd, 0, sizeof(struct thread)); compc = (struct cap_comp *)captbl_lkup(t, compcap); if (unlikely(!compc || compc->h.type != CAP_COMP)) return -EINVAL; + if (likely(dcbcap)) { + dc = (struct cap_dcb *)captbl_lkup(t, dcbcap); + if (unlikely(!dc || dc->h.type != CAP_DCB)) return -EINVAL; + if (dcboff > PAGE_SIZE / sizeof(struct cos_dcb_info)) return -EINVAL; + } tc = (struct cap_thd *)__cap_capactivate_pre(t, cap, capin, CAP_THD, &ret); if (!tc) return ret; @@ -343,6 +352,12 @@ thd_activate(struct captbl *t, capid_t cap, capid_t capin, struct thread *thd, c thd->refcnt = 1; thd->invstk_top = 0; thd->cpuid = get_cpuid(); + if (likely(dc)) { + ret = dcb_thd_ref(dc, thd); + if (ret) goto err; /* TODO: cleanup captbl slot */ + thd->dcbinfo = (struct cos_dcb_info *)(dc->kern_addr + (dcboff * sizeof(struct cos_dcb_info))); + memset(thd->dcbinfo, 0, sizeof(struct cos_dcb_info)); + } assert(thd->tid <= MAX_NUM_THREADS); thd_scheduler_set(thd, thd_current(cli)); @@ -358,15 +373,69 @@ thd_activate(struct captbl *t, capid_t cap, capid_t capin, struct thread *thd, c __cap_capactivate_post(&tc->h, CAP_THD); return 0; + +err: + return ret; +} + +static inline int +thd_migrate_cap(struct captbl *ct, capid_t thd_cap) +{ + struct thread *thd; + struct cap_thd *tc; + + /* we migrated the capability to core */ + tc = (struct cap_thd *)captbl_lkup(ct, thd_cap); + if (!tc || tc->h.type != CAP_THD || get_cpuid() != tc->cpuid) return -EINVAL; + thd = tc->t; + tc->cpuid = thd->cpuid; + + return 0; +} + +static inline int +thd_migrate(struct captbl *ct, capid_t thd_cap, cpuid_t core) +{ + struct thread *thd; + struct cap_thd *tc; + + tc = (struct cap_thd *)captbl_lkup(ct, thd_cap); + if (!tc || tc->h.type != CAP_THD || get_cpuid() != tc->cpuid) return -EINVAL; + thd = tc->t; + if (NUM_CPU < 2 || core >= NUM_CPU || core < 0) return -EINVAL; + if (tc->cpuid != thd->cpuid) return -EINVAL; /* outdated capability */ + if (thd->cpuid == core) return -EINVAL; /* already migrated. invalid req */ + if (thd->cpuid != get_cpuid()) return -EPERM; /* only push migration */ + + if (thd_current(cos_cpu_local_info()) == thd) return -EPERM; /* not a running thread! */ + if (thd->invstk_top > 0) return -EPERM; /* not if its in an invocation */ + if (thd_bound2rcvcap(thd) || thd->rcvcap.rcvcap_thd_notif) return -EPERM; /* not if it's an AEP */ + if (thd->rcvcap.rcvcap_tcap) return -EPERM; /* not if it has its own tcap on this core */ + + thd->scheduler_thread = NULL; + thd->cpuid = core; + /* we also migrated the capability to core */ + tc->cpuid = core; + + /* + * TODO: + * given that the thread is not running right now, + * and we don't allow migrating a thread that's in an invocation for now, + * i think we can find the COREID_OFFSET/CPUID_OFFSET on stack and fix the + * core id right here?? + */ + + return 0; } static int thd_deactivate(struct captbl *ct, struct cap_captbl *dest_ct, unsigned long capin, livenessid_t lid, capid_t pgtbl_cap, - capid_t cosframe_addr, const int root) + capid_t cosframe_addr, capid_t dcbcap, const int root) { struct cos_cpu_local_info *cli = cos_cpu_local_info(); - struct cap_header * thd_header; - struct thread * thd; + struct cap_header *thd_header; + struct thread *thd; + struct cap_dcb *dcb = NULL; unsigned long old_v = 0, *pte = NULL; int ret; @@ -374,6 +443,10 @@ thd_deactivate(struct captbl *ct, struct cap_captbl *dest_ct, unsigned long capi if (!thd_header || thd_header->type != CAP_THD) cos_throw(err, -EINVAL); thd = ((struct cap_thd *)thd_header)->t; assert(thd->refcnt); + if (dcbcap) { + dcb = (struct cap_dcb *)captbl_lkup(ct, dcbcap); + if (!dcb || dcb->h.type != CAP_DCB) cos_throw(err, -EINVAL); + } if (thd->refcnt == 1) { if (!root) cos_throw(err, -EINVAL); @@ -399,6 +472,10 @@ thd_deactivate(struct captbl *ct, struct cap_captbl *dest_ct, unsigned long capi } } + if (dcb) { + ret = dcb_thd_deref(dcb, thd); + if (ret) cos_throw(err, ret); + } ret = cap_capdeactivate(dest_ct, capin, CAP_THD, lid); if (ret) cos_throw(err, ret); @@ -461,6 +538,21 @@ curr_invstk_top(struct cos_cpu_local_info *cos_info) return cos_info->invstk_top; } +static inline struct comp_info * +thd_invstk_peek_compinfo(struct thread *curr_thd, struct cos_cpu_local_info *cos_info, int peek_index) +{ + /* curr_thd should be the current thread! We are using cached invstk_top. */ + return &(curr_thd->invstk[peek_index].comp_info); +} + +static inline struct comp_info * +thd_invstk_current_compinfo(struct thread *curr_thd, struct cos_cpu_local_info *cos_info, int *invstk_top) +{ + *invstk_top = curr_invstk_top(cos_info); + + return &(curr_thd->invstk[*invstk_top].comp_info); +} + static inline struct comp_info * thd_invstk_current(struct thread *curr_thd, unsigned long *ip, unsigned long *sp, struct cos_cpu_local_info *cos_info) { @@ -520,6 +612,45 @@ thd_preemption_state_update(struct thread *curr, struct thread *next, struct pt_ memcpy(&curr->regs, regs, sizeof(struct pt_regs)); } +static int +thd_sched_events_produce(struct thread *thd, struct cos_cpu_local_info *cos_info) +{ + int delta = 0, inv_top = curr_invstk_top(cos_info); + struct cos_scb_info *scb = NULL; + struct cos_sched_ring *r = NULL; + struct comp_info *c = NULL; + + if (unlikely(inv_top != 0 || thd->rcvcap.is_init == 0)) return 0; + + c = thd_invstk_peek_compinfo(thd, cos_info, inv_top); + if (unlikely(!c || !c->scb_data)) return 0; + + scb = ((c->scb_data) + get_cpuid()); + r = &(scb->sched_events); + /* + * only produce more if the ring is empty! + * so the user only calls after dequeueing all previous events. + */ + if (unlikely(r->head != r->tail)) return -EAGAIN; + + r->head = r->tail = 0; + while (delta < COS_SCHED_EVENT_RING_SIZE) { + struct cos_sched_event *e = &(r->event_buf[delta]); + unsigned long thd_state; + + if (!thd_state_evt_deliver(thd, &thd_state, (unsigned long *)&(e->evt.elapsed_cycs), + (unsigned long *)&(e->evt.next_timeout))) break; + e->tid = (thd_state << 1) >> 1; + e->evt.blocked = (thd_state >> 31); + + delta++; + } + + r->tail += delta; + + return delta; +} + static inline void thd_rcvcap_pending_deliver(struct thread *thd, struct pt_regs *regs) { @@ -559,6 +690,13 @@ thd_switch_update(struct thread *thd, struct pt_regs *regs, int issame) */ } + if (unlikely(thd->dcbinfo && thd->dcbinfo->sp)) { + assert(preempt == 0); + regs->dx = regs->ip = thd->dcbinfo->ip + DCB_IP_KERN_OFF; + regs->cx = regs->sp = thd->dcbinfo->sp; + thd->dcbinfo->sp = 0; + } + if (issame && preempt == 0) { __userregs_set(regs, 0, __userregs_getsp(regs), __userregs_getip(regs)); } @@ -573,6 +711,12 @@ thd_introspect(struct thread *t, unsigned long op, unsigned long *retval) case THD_GET_TID: *retval = t->tid; break; + case THD_GET_DCB_IP: + *retval = t->dcbinfo->ip; + break; + case THD_GET_DCB_SP: + *retval = t->dcbinfo->sp; + break; default: return -EINVAL; } diff --git a/src/platform/i386/boot_comp.c b/src/platform/i386/boot_comp.c index db4832a55f..08baeb8ff0 100644 --- a/src/platform/i386/boot_comp.c +++ b/src/platform/i386/boot_comp.c @@ -11,14 +11,91 @@ #include #include #include +#include #include #include extern u8_t *boot_comp_pgd; +//vaddr_t dcb_addr[NUM_CPU], dcb_uaddr[NUM_CPU]; void *thd_mem[NUM_CPU], *tcap_mem[NUM_CPU]; struct captbl *glb_boot_ct; +/*int +boot_nptes(unsigned int sz) +{ + return round_up_to_pow2(sz, PGD_RANGE) / PGD_RANGE; +} + +int +boot_pgtbl_mappings_add(struct captbl *ct, capid_t pgdcap, capid_t ptecap, const char *label, void *kern_vaddr, + unsigned long user_vaddr, unsigned int range, int uvm) +{ + int ret; + u8_t * ptes; + unsigned int nptes = 0, i; + struct cap_pgtbl *pte_cap, *pgd_cap; + pgtbl_t pgtbl; + + pgd_cap = (struct cap_pgtbl *)captbl_lkup(ct, pgdcap); + if (!pgd_cap || !CAP_TYPECHK(pgd_cap, CAP_PGTBL)) assert(0); + pgtbl = (pgtbl_t)pgd_cap->pgtbl; + if (!uvm) nptes = boot_nptes(range); + else nptes = boot_nptes(range + COS_SCB_SIZE); + ptes = mem_boot_alloc(nptes); + assert(ptes); + + if (!uvm && range < COS_MEM_KERN_PA_SZ) { + printk("Insufficient %s memory! Available:%luMB, Required:%luMB\n", label, range >> 20, COS_MEM_KERN_PA_SZ >> 20); + printk("Reconfigure \"COS_MEM_KERN_PA_SZ\" to %luMB\n", range >> 20); + assert(0); + } + + printk("\tCreating %d %s PTEs for PGD @ 0x%x from [%x,%x) to [%x,%x).\n", nptes, label, + chal_pa2va((paddr_t)pgtbl), kern_vaddr, kern_vaddr + range, user_vaddr, user_vaddr + range); + + // + // Note the use of NULL here. We aren't actually adding a PTE + // currently. This is a hack and only used on boot-up. We'll + // reuse this capability entry to create _multiple_ ptes. We + // won't create captbl entries for each of them, so they + // cannot be aliased/removed later. The only adverse + // side-effect I can think of from this is that we cannot + // reclaim all of the boot-time memory, but that is so far + // into the future, I don't think we care. + + if (pgtbl_activate(ct, BOOT_CAPTBL_SELF_CT, ptecap, NULL, 1)) assert(0); + pte_cap = (struct cap_pgtbl *)captbl_lkup(ct, ptecap); + assert(pte_cap); + + // Hook in the PTEs + for (i = 0; i < nptes; i++) { + u8_t * p = ptes + i * PAGE_SIZE; + paddr_t pf = chal_va2pa(p); + + pgtbl_init_pte(p); + pte_cap->pgtbl = (pgtbl_t)p; + + // hook the pte into the boot component's page tables + ret = cap_cons(ct, pgdcap, ptecap, (capid_t)(user_vaddr + i * PGD_RANGE)); + assert(!ret); + } + + printk("\tMapping in %s.\n", label); + // Map in the actual memory. + for (i = 0; i < range / PAGE_SIZE; i++) { + u8_t * p = kern_vaddr + i * PAGE_SIZE; + paddr_t pf = chal_va2pa(p); + u32_t mapat = (u32_t)user_vaddr + i * PAGE_SIZE, flags = 0; + + if (uvm && pgtbl_mapping_add(pgtbl, mapat, pf, PGTBL_USER_DEF, PAGE_ORDER)) assert(0); + if (!uvm && pgtbl_cosframe_add(pgtbl, mapat, pf, PGTBL_COSFRAME, PAGE_ORDER)) assert(0); + assert((void *)p == pgtbl_lkup(pgtbl, user_vaddr + i * PAGE_SIZE, &flags)); + } + + return 0; +}*/ + /* FIXME: loops to create threads/tcaps/rcv caps per core. */ static void kern_boot_thd(struct captbl *ct, void *thd_mem, void *tcap_mem, const cpuid_t cpu_id) @@ -37,7 +114,9 @@ kern_boot_thd(struct captbl *ct, void *thd_mem, void *tcap_mem, const cpuid_t cp cos_info->cpuid = cpu_id; cos_info->invstk_top = 0; cos_info->overflow_check = 0xDEADBEEF; - ret = thd_activate(ct, BOOT_CAPTBL_SELF_CT, BOOT_CAPTBL_SELF_INITTHD_BASE_CPU(cpu_id), thd_mem, BOOT_CAPTBL_SELF_COMP, 0); + //ret = dcb_activate(ct, BOOT_CAPTBL_SELF_CT, LLBOOT_CAPTBL_INITDCB_CPU(cpu_id), NULL, 0, BOOT_CAPTBL_SELF_PT, NULL); + //assert(!ret); + ret = thd_activate(ct, BOOT_CAPTBL_SELF_CT, BOOT_CAPTBL_SELF_INITTHD_BASE_CPU(cpu_id), thd_mem, BOOT_CAPTBL_SELF_COMP, 0, 0, 0); assert(!ret); tcap_active_init(cos_info); @@ -164,7 +243,7 @@ boot_pgtbl_mappings_add(struct captbl *ct, capid_t pgdcap, capid_t ptecap, const pgtbl = (pgtbl_t)pgd_cap->pgtbl; printk("\tMapping in %s (@ [0x%p, 0x%p))\n", label, user_vaddr, user_vaddr + range); - /* Map in the actual memory. */ + // Map in the actual memory. for (i = 0; i < round_up_to_page(range) / PAGE_SIZE; i++) { u8_t * p = kern_vaddr + i * PAGE_SIZE; paddr_t pf = chal_va2pa(p); @@ -245,6 +324,7 @@ kern_boot_comp(const cpuid_t cpu_id) u8_t * boot_comp_captbl; pgtbl_t pgtbl = (pgtbl_t)chal_va2pa(&boot_comp_pgd), boot_vm_pgd; u32_t hw_bitmap = ~0; + vaddr_t scb_uaddr = 0, scb_kaddr = 0; assert(cpu_id >= 0); if (NUM_CPU > 1 && cpu_id > 0) { @@ -271,11 +351,17 @@ kern_boot_comp(const cpuid_t cpu_id) assert(!ret); } + scb_kaddr = (vaddr_t)mem_boot_alloc(1); + assert(scb_kaddr); + for (i = 0; i < NUM_CPU; i++) { thd_mem[i] = mem_boot_alloc(1); assert(thd_mem[i]); tcap_mem[i] = mem_boot_alloc(1); assert(tcap_mem[i]); + //dcb_addr[i] = mem_boot_alloc(1); + //assert(dcb_addr[i]); + //assert(thd_mem[i] && tcap_mem[i] && dcb_addr[i]); assert(thd_mem[i] && tcap_mem[i]); } @@ -298,6 +384,7 @@ kern_boot_comp(const cpuid_t cpu_id) ret = boot_elf_process(glb_boot_ct, BOOT_CAPTBL_SELF_PT, BOOT_CAPTBL_BOOTVM_PTE, "booter VM", mem_bootc_start(), mem_bootc_end() - mem_bootc_start()); assert(ret == 0); + //scb_uaddr = (vaddr_t)mem_bootc_end(); /* * Map in the untyped memory. This is more complicated as we @@ -327,10 +414,12 @@ kern_boot_comp(const cpuid_t cpu_id) /* Shut off further bump allocations */ glb_memlayout.allocs_avail = 0; + if (scb_activate(glb_boot_ct, BOOT_CAPTBL_SELF_CT, LLBOOT_CAPTBL_SCB, scb_kaddr, 0)) assert(0); - if (comp_activate(glb_boot_ct, BOOT_CAPTBL_SELF_CT, BOOT_CAPTBL_SELF_COMP, BOOT_CAPTBL_SELF_CT, BOOT_CAPTBL_SELF_PT, 0, - mem_bootc_entry())) + if (comp_activate(glb_boot_ct, BOOT_CAPTBL_SELF_CT, BOOT_CAPTBL_SELF_COMP, BOOT_CAPTBL_SELF_CT, BOOT_CAPTBL_SELF_PT, + LLBOOT_CAPTBL_SCB, 0, (vaddr_t)mem_bootc_entry())) assert(0); + printk("\tCreated boot component structure from page-table and capability-table.\n"); kern_boot_thd(glb_boot_ct, thd_mem[cpu_id], tcap_mem[cpu_id], cpu_id); diff --git a/src/platform/i386/chal/shared/cos_config.h b/src/platform/i386/chal/shared/cos_config.h index 1a95ff362c..96c1b0faba 100644 --- a/src/platform/i386/chal/shared/cos_config.h +++ b/src/platform/i386/chal/shared/cos_config.h @@ -89,6 +89,7 @@ /* Composite user memory uses physical memory above this. */ #define COS_MEM_START COS_MEM_KERN_PA +#define COS_SCB_SIZE (PAGE_SIZE) /* NUM_CPU_SOCKETS defined in cpu_ghz.h. The information is used for * intelligent IPI distribution. */