seL4 / sel4-tutorials

Tutorials for working with seL4 and/or CAmkES.

Home Page:https://docs.sel4.systems/Tutorials

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Cap fault in dynamic-3 tutorial

cmcl opened this issue · comments

The dynamic-3 tutorial involves spawning a new process which sends data to the root thread. I am hitting a weird error during the spawning process.

    /* TASK 5: spawn the process */
    /* hint 1: sel4utils_spawn_process_v()
     * int sel4utils_spawn_process_v(sel4utils_process_t *process, vka_t *vka, vspace_t *vspace, int argc, char *argv[], int resume)
     * @param process Initialised sel4utils process struct.
     * @param vka Vka interface to use for allocation of frames.
     * @param vspace The current vspace.
     * @param argc The number of arguments.
     * @param argv A pointer to an array of strings in the current vspace.
     * @param resume 1 to start the process, 0 to leave suspended.
     * @return 0 on success, -1 on error.
     */
    char *argv[] = { (char*)new_ep_cap };
    error = sel4utils_spawn_process_v(&new_process, &vka, &vspace, 1,  argv, 1);
    ZF_LOGF_IFERR(error, "Failed to spawn and start the new thread.\n"
                  "\tVerify: the new thread is being executed in the root thread's VSpace.\n"
                  "\tIn this case, the CSpaces are different, but the VSpaces are the same.\n"
                  "\tDouble check your vspace_t argument.\n");

new_ep_cap is a badged endpoint capability returned from a call to sel4utils_mint_cap_to_process. The spawn process in app.c provides the following hint and code:

    /* TASK 8: send and wait for a reply */
    /* hint 1: seL4_Call()
     * seL4_MessageInfo_t seL4_Call(seL4_CPtr dest, seL4_MessageInfo_t msgInfo)
     * @param dest The capability to be invoked.
     * @param msgInfo The messageinfo structure for the IPC.  This specifies information about the message to send (such as the number of message registers to send).
     * @return A seL4_MessageInfo_t structure.  This is information about the repy message.
     *
     * hint 2: send the endpoint cap using argv (see TASK 6 in the other main.c)
     */
    ZF_LOGF_IF(argc < 1,
               "Missing arguments.\n");
    seL4_CPtr ep = (seL4_CPtr) atol(argv[0]);

However, sending the endpoint capability in this way results in a cap fault:

Caught cap fault in send phase at address (nil)
while trying to handle:
vm fault on data at address 0x8 with status 0x4
in thread 0xffffff801fe08400 "dynamic-3" at address 0x43b9c9
With stack:
0x4a9c48: 0x40becd
0x4a9c50: 0x4a9cc0
0x4a9c58: 0x4a9ef8
0x4a9c60: 0x1004a9f80
0x4a9c68: 0x4af120
0x4a9c70: 0x4a9f80
0x4a9c78: 0x4af080
0x4a9c80: 0x6ca
0x4a9c88: 0x1c0
0x4a9c90: 0x1c0
0x4a9c98: 0x1c8
0x4a9ca0: 0x4a9ed0
0x4a9ca8: 0x40c4f1
0x4a9cb0: 0x4a9e40
0x4a9cb8: 0x0
0x4a9cc0: 0x4a9ed0

This error occurs even in cases where I do not use the endpoint capability in the spawned thread, i.e. commenting out the ep assignment.

Confusingly, there are also some (I think erroneous) hints in the root thread about using the badged endpoint capability which appears to conflict with the root thread's role as receiver:

seL4_Word sender_badge = 0;
    seL4_MessageInfo_t tag = seL4_MessageInfo_new(0, 0, 0, 0);
    seL4_Word msg;

    /* TASK 6: wait for a message */
    /* hint 1: seL4_Recv()
     * seL4_MessageInfo_t seL4_Recv(seL4_CPtr src, seL4_Word* sender)
     * @param src The capability to be invoked.
     * @param sender The badge of the endpoint capability that was invoked by the sender is written to this address.
     * @return A seL4_MessageInfo_t structure
     *
     * hint 2: seL4_MessageInfo_t is generated during build.
     * hint 3: use the badged endpoint cap that you minted above
     */```

A blind spot in my code:

 char *argv[] = { (char*)new_ep_cap };

is altogether incorrect even if the ep in the spawned thread is commented it. Somewhere in the sel4utils_spawn_process_v the string is copied over, and there is no string at 0x8 (or whatever the address of new_ep_cap turns out to be).

According to the tutorial, the solution would be:

    new_ep_cap = sel4utils_mint_cap_to_process(&new_process, ep_cap_path,
                                               seL4_AllRights, EP_BADGE);
    seL4_Word argc = 1;
    char string_args[argc][WORD_STRING_SIZE];
    char* argv[argc];
    sel4utils_create_word_args(string_args, argv, argc, new_ep_cap);

    error = sel4utils_spawn_process_v(&new_process, &vka, &vspace, argc, (char**) &argv, 1);

sel4utils_create_word_args should probably be added as a hint for that part of the task. Otherwise I don't know how else someone would be expected to know to call it to convert the word arg to a string.

For what it's worth, I used snprintf with a fixed-sized buffer which did the job, but thanks for pointing out sel4utils_create_word_args.