1/*
2 * Architecture-specific context switch
3 */
4
5/*
6 * Copyright (c) 2015, ETH Zurich.
7 * All rights reserved.
8 *
9 * This file is distributed under the terms in the attached LICENSE file.
10 * If you do not find this file, copies can be found by writing to:
11 * ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
12 */
13
14#include <kernel.h>
15#include <dispatch.h>
16#include <paging_kernel_arch.h>
17#include <sysreg.h>
18
19/**
20 * \brief Switch context to 'dcb'.
21 *
22 * Switch to the dispatcher pointed to by 'dcb'. Sets 'dcb_current'.
23 *
24 * \param dcb        Pointer to dispatcher to which to switch context.
25 */
26void
27context_switch(struct dcb *dcb) {
28    struct dispatcher_shared_generic *disp =
29        get_dispatcher_shared_generic(dcb->disp);
30
31    assert(dcb != NULL);
32    assert(dcb->vspace != 0);
33
34    // VM guests do not have a user space dispatcher
35    if (!dcb->is_vm_guest) {
36        assert(dcb->disp != 0);
37    }
38
39    paging_context_switch(dcb->vspace);
40    context_switch_counter++;
41
42    if (!dcb->is_vm_guest) {
43        assert(dcb->disp_cte.cap.type == ObjType_Frame);
44
45        /* We set the read-only thread ID register (TPIDRRO_EL0) to the user's
46         * pointer to the dispatcher shared area, so that code in
47         * libbarrelfish can efficiently locate its dispatcher. The read-write
48         * version (TPIDR_EL0) is free to implement TLS. */
49        sysreg_write_tpidrro_el0((uint64_t)disp->udisp);
50
51    }
52
53    /* The EL1 thread ID register points to the same structure in the
54     * kernel window, and is used by trap code.  This is inaccessible to
55     * user-level code. */
56    sysreg_write_tpidr_el1((uint64_t)disp);
57}
58