1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12 13#include <autoconf.h> 14#include <assert.h> 15#include <stdio.h> 16#include <stdlib.h> 17#include <sel4/sel4.h> 18#include <sel4utils/arch/util.h> 19 20#include <vka/object.h> 21 22#include "../test.h" 23#include "../helpers.h" 24 25#ifdef CONFIG_ARCH_X86 26 27#define START_PORT 0 28#define END_PORT BIT(16) 29#define PORT_STRIDE 256 30#define EXPECTED_FAULTS ((END_PORT - START_PORT) / PORT_STRIDE) 31 32static volatile int total_faults = 0; 33 34static void increment_pc(seL4_CPtr tcb, seL4_Word inc) 35{ 36 seL4_UserContext ctx; 37 seL4_Error error = seL4_TCB_ReadRegisters(tcb, 38 false, 39 0, 40 sizeof(ctx) / sizeof(seL4_Word), 41 &ctx); 42 test_eq(error, seL4_NoError); 43#ifdef CONFIG_ARCH_X86_64 44 ctx.rax = 1; 45 ctx.rip += inc; 46#else 47 ctx.eax = 1; 48 ctx.eip += inc; 49#endif 50 error = seL4_TCB_WriteRegisters(tcb, 51 true, 52 0, 53 sizeof(ctx) / sizeof(seL4_Word), 54 &ctx); 55 test_eq(error, seL4_NoError); 56} 57 58static int handle_fault(seL4_CPtr fault_ep, seL4_CPtr tcb, seL4_Word expected_fault, seL4_CPtr reply) 59{ 60 seL4_MessageInfo_t tag; 61 seL4_Word sender_badge = 0; 62 63 while (1) { 64 tag = api_recv(fault_ep, &sender_badge, reply); 65 66 test_check(seL4_MessageInfo_get_label(tag) == seL4_Fault_UserException); 67 68 total_faults++; 69 increment_pc(tcb, 1); 70 } 71 72 return 0; 73} 74 75static int do_ioports(int arg1, int arg2, int arg3, int arg4) 76{ 77 unsigned int i; 78 for (i = START_PORT; i < END_PORT; i += PORT_STRIDE) { 79 volatile unsigned char dummy = 0; 80 asm volatile("inb %1,%0" 81 : "=a"(dummy) 82 : "dN"((uint16_t)i) 83 ); 84 test_check(dummy == 1); 85 } 86 return 0; 87} 88 89static int test_native_ioports(env_t env) 90{ 91 helper_thread_t handler_thread; 92 helper_thread_t faulter_thread; 93 int error; 94 seL4_Word handler_arg0, handler_arg1; 95 /* The endpoint on which faults are received. */ 96 seL4_CPtr fault_ep = vka_alloc_endpoint_leaky(&env->vka); 97 seL4_CPtr faulter_vspace, faulter_cspace; 98 99 create_helper_thread(env, &faulter_thread); 100 create_helper_thread(env, &handler_thread); 101 faulter_cspace = env->cspace_root; 102 faulter_vspace = env->page_directory; 103 handler_arg0 = fault_ep; 104 handler_arg1 = get_helper_tcb(&faulter_thread); 105 set_helper_priority(env, &handler_thread, 100); 106 107 error = api_tcb_set_space(get_helper_tcb(&faulter_thread), 108 fault_ep, 109 faulter_cspace, 110 api_make_guard_skip_word(seL4_WordBits - env->cspace_size_bits), 111 faulter_vspace, seL4_NilData); 112 set_helper_priority(env, &faulter_thread, 100); 113 114 test_error_eq(error, seL4_NoError); 115 116 /* clear the faults */ 117 total_faults = 0; 118 119 start_helper(env, &handler_thread, (helper_fn_t) handle_fault, 120 handler_arg0, handler_arg1, 0, get_helper_reply(&handler_thread)); 121 start_helper(env, &faulter_thread, (helper_fn_t) do_ioports, 122 0, 0, 0, 0); 123 124 wait_for_helper(&faulter_thread); 125 126 test_check(total_faults == EXPECTED_FAULTS); 127 128 cleanup_helper(env, &handler_thread); 129 cleanup_helper(env, &faulter_thread); 130 131 return (total_faults == EXPECTED_FAULTS) ? SUCCESS : FAILURE; 132} 133DEFINE_TEST(IOPORTS1000, "Test fault if directly using I/O ports", test_native_ioports, true) 134 135#endif 136