2015-02-06 17:29:30 +01:00
|
|
|
/*
|
|
|
|
* \brief Transition between kernel/userland, and secure/non-secure world
|
|
|
|
* \author Martin Stein
|
|
|
|
* \author Stefan Kalkowski
|
|
|
|
* \date 2011-11-15
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2011-2013 Genode Labs GmbH
|
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
|
|
* under the terms of the GNU General Public License version 2.
|
|
|
|
*/
|
|
|
|
|
|
|
|
.include "macros.s"
|
|
|
|
|
2015-02-17 10:19:11 +01:00
|
|
|
/* size of pointer to CPU context */
|
|
|
|
.set CONTEXT_PTR_SIZE, 1 * 8
|
|
|
|
|
2015-02-17 17:17:34 +01:00
|
|
|
/* globally mapped buffer storage */
|
|
|
|
.set BUFFER_SIZE, 6 * 8
|
|
|
|
|
2015-02-18 00:22:34 +01:00
|
|
|
/* offsets of the member variables in a CPU context */
|
2015-02-21 01:24:00 +01:00
|
|
|
.set SP_OFFSET, 1 * 8
|
|
|
|
.set R8_OFFSET, 2 * 8
|
|
|
|
.set RAX_OFFSET, 10 * 8
|
|
|
|
.set ERRCODE_OFFSET, 17 * 8
|
|
|
|
.set FLAGS_OFFSET, 18 * 8
|
2015-02-21 01:31:37 +01:00
|
|
|
.set TRAPNO_OFFSET, 19 * 8
|
2015-02-21 01:24:00 +01:00
|
|
|
.set CR3_OFFSET, 21 * 8
|
2015-02-18 00:22:34 +01:00
|
|
|
|
2015-02-26 11:07:32 +01:00
|
|
|
.macro _isr_entry
|
|
|
|
.align 4, 0x90
|
|
|
|
.endm
|
|
|
|
|
|
|
|
.macro _exception vector
|
|
|
|
_isr_entry
|
|
|
|
push $0
|
|
|
|
push $\vector
|
|
|
|
jmp _mt_kernel_entry_pic
|
|
|
|
.endm
|
|
|
|
|
|
|
|
.macro _exception_with_code vector
|
|
|
|
_isr_entry
|
|
|
|
nop
|
|
|
|
nop
|
|
|
|
push $\vector
|
|
|
|
jmp _mt_kernel_entry_pic
|
|
|
|
.endm
|
|
|
|
|
2015-02-06 17:29:30 +01:00
|
|
|
.section .text
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Page aligned base of mode transition code.
|
|
|
|
*
|
|
|
|
* This position independent code switches between a kernel context and a
|
|
|
|
* user context and thereby between their address spaces. Due to the latter
|
|
|
|
* it must be mapped executable to the same region in every address space.
|
|
|
|
* To enable such switching, the kernel context must be stored within this
|
|
|
|
* region, thus one should map it solely accessable for privileged modes.
|
|
|
|
*/
|
|
|
|
.p2align MIN_PAGE_SIZE_LOG2
|
|
|
|
.global _mt_begin
|
|
|
|
_mt_begin:
|
|
|
|
|
2015-02-26 11:07:32 +01:00
|
|
|
/*
|
|
|
|
* On user exceptions the CPU has to jump to one of the following
|
|
|
|
* Interrupt Service Routines (ISRs) to switch to a kernel context.
|
|
|
|
*/
|
|
|
|
.global _mt_isrs
|
|
|
|
_mt_isrs:
|
|
|
|
_exception 0
|
|
|
|
_exception 1
|
|
|
|
_exception 2
|
|
|
|
_exception 3
|
|
|
|
_exception 4
|
|
|
|
_exception 5
|
|
|
|
_exception 6
|
|
|
|
_exception 7
|
|
|
|
_exception_with_code 8
|
|
|
|
_exception 9
|
|
|
|
_exception_with_code 10
|
|
|
|
_exception_with_code 11
|
|
|
|
_exception_with_code 12
|
|
|
|
_exception_with_code 13
|
|
|
|
_exception_with_code 14
|
|
|
|
_exception 15
|
|
|
|
_exception 16
|
|
|
|
_exception_with_code 17
|
|
|
|
_exception 18
|
|
|
|
_exception 19
|
|
|
|
|
|
|
|
.set vec, 20
|
|
|
|
.rept 236
|
|
|
|
_exception vec
|
|
|
|
.set vec, vec + 1
|
|
|
|
.endr
|
|
|
|
|
2015-02-06 17:29:30 +01:00
|
|
|
/* space for a copy of the kernel context */
|
|
|
|
.p2align 2
|
|
|
|
.global _mt_master_context_begin
|
|
|
|
_mt_master_context_begin:
|
|
|
|
|
|
|
|
/* space must be at least as large as 'Cpu_state' */
|
2015-02-21 01:24:00 +01:00
|
|
|
.space 22*8
|
2015-02-06 17:29:30 +01:00
|
|
|
|
|
|
|
.global _mt_master_context_end
|
|
|
|
_mt_master_context_end:
|
|
|
|
|
|
|
|
/* space for a client context-pointer per CPU */
|
|
|
|
.p2align 2
|
|
|
|
.global _mt_client_context_ptr
|
|
|
|
_mt_client_context_ptr:
|
2015-02-17 10:19:11 +01:00
|
|
|
.space CONTEXT_PTR_SIZE
|
2015-02-06 17:29:30 +01:00
|
|
|
|
|
|
|
/* a globally mapped buffer per CPU */
|
|
|
|
.p2align 2
|
|
|
|
.global _mt_buffer
|
|
|
|
_mt_buffer:
|
2015-02-17 17:17:34 +01:00
|
|
|
.space BUFFER_SIZE
|
2015-02-06 17:29:30 +01:00
|
|
|
|
|
|
|
.global _mt_kernel_entry_pic
|
|
|
|
_mt_kernel_entry_pic:
|
2015-02-20 16:04:01 +01:00
|
|
|
|
|
|
|
/* Copy client context RAX to buffer */
|
|
|
|
mov %rax, _mt_buffer
|
|
|
|
|
2015-02-20 16:05:46 +01:00
|
|
|
/* Switch to kernel page tables */
|
|
|
|
mov _mt_master_context_begin+CR3_OFFSET, %rax
|
|
|
|
mov %rax, %cr3
|
|
|
|
|
2015-02-20 16:06:50 +01:00
|
|
|
/* Save information on interrupt stack frame in client context */
|
|
|
|
mov _mt_client_context_ptr, %rax
|
|
|
|
popq TRAPNO_OFFSET(%rax)
|
|
|
|
popq ERRCODE_OFFSET(%rax)
|
|
|
|
popq (%rax)
|
|
|
|
popq FLAGS_OFFSET(%rax) /* Discard cs */
|
|
|
|
popq FLAGS_OFFSET(%rax)
|
|
|
|
popq SP_OFFSET(%rax)
|
|
|
|
|
2015-02-20 16:09:39 +01:00
|
|
|
/* Save register values to client context */
|
|
|
|
lea ERRCODE_OFFSET(%rax), %rsp
|
|
|
|
pushq %rbp
|
|
|
|
pushq %rsi
|
|
|
|
pushq %rdi
|
|
|
|
pushq %rdx
|
|
|
|
pushq %rcx
|
|
|
|
pushq %rbx
|
|
|
|
pushq _mt_buffer
|
|
|
|
pushq %r15
|
|
|
|
pushq %r14
|
|
|
|
pushq %r13
|
|
|
|
pushq %r12
|
|
|
|
pushq %r11
|
|
|
|
pushq %r10
|
|
|
|
pushq %r9
|
|
|
|
pushq %r8
|
|
|
|
|
2015-02-20 16:10:26 +01:00
|
|
|
/* Restore kernel segment registers */
|
|
|
|
mov $0x10, %rbx
|
|
|
|
mov %rbx, %ds
|
|
|
|
mov %rbx, %es
|
|
|
|
mov %rbx, %fs
|
|
|
|
mov %rbx, %gs
|
|
|
|
|
2015-02-20 16:11:41 +01:00
|
|
|
/* Restore register values from kernel context */
|
|
|
|
mov $_mt_master_context_begin+R8_OFFSET, %rsp
|
|
|
|
popq %r8
|
|
|
|
popq %r9
|
|
|
|
popq %r10
|
|
|
|
popq %r11
|
|
|
|
popq %r12
|
|
|
|
popq %r13
|
|
|
|
popq %r14
|
|
|
|
popq %r15
|
|
|
|
popq %rax
|
|
|
|
popq %rbx
|
|
|
|
popq %rcx
|
|
|
|
popq %rdx
|
|
|
|
popq %rdi
|
|
|
|
popq %rsi
|
|
|
|
popq %rbp
|
|
|
|
|
2015-02-20 16:12:24 +01:00
|
|
|
/* Restore kernel stack and continue kernel execution */
|
|
|
|
mov _mt_master_context_begin+SP_OFFSET, %rsp
|
2015-02-20 16:13:58 +01:00
|
|
|
jmp *_mt_master_context_begin
|
2015-02-06 17:29:30 +01:00
|
|
|
|
|
|
|
.global _mt_user_entry_pic
|
|
|
|
_mt_user_entry_pic:
|
2015-02-18 00:26:33 +01:00
|
|
|
|
|
|
|
/* Prepare stack frame in mt buffer (Intel SDM Vol. 3A, figure 6-8) */
|
|
|
|
mov _mt_client_context_ptr, %rax
|
|
|
|
mov $_mt_buffer+BUFFER_SIZE, %rsp
|
|
|
|
pushq $0x23
|
|
|
|
pushq SP_OFFSET(%rax)
|
2015-02-20 11:10:51 +01:00
|
|
|
|
|
|
|
/* Set I/O privilege level to 3 */
|
|
|
|
orq $0x3000, FLAGS_OFFSET(%rax)
|
|
|
|
btrq $9, FLAGS_OFFSET(%rax) /* XXX: Drop once interrupt handling is done */
|
|
|
|
pushq FLAGS_OFFSET(%rax)
|
|
|
|
|
2015-02-18 00:26:33 +01:00
|
|
|
pushq $0x1b
|
|
|
|
pushq (%rax)
|
|
|
|
|
2015-02-18 00:30:14 +01:00
|
|
|
/* Restore segment registers */
|
|
|
|
mov $0x23, %rbx
|
|
|
|
mov %rbx, %ds
|
|
|
|
mov %rbx, %es
|
|
|
|
mov %rbx, %fs
|
|
|
|
mov %rbx, %gs
|
|
|
|
|
2015-02-18 00:37:52 +01:00
|
|
|
/* Restore register values from client context */
|
|
|
|
lea R8_OFFSET(%rax), %rsp
|
|
|
|
popq %r8
|
|
|
|
popq %r9
|
|
|
|
popq %r10
|
|
|
|
popq %r11
|
|
|
|
popq %r12
|
|
|
|
popq %r13
|
|
|
|
popq %r14
|
|
|
|
popq %r15
|
|
|
|
popq _mt_buffer
|
|
|
|
popq %rbx
|
|
|
|
popq %rcx
|
|
|
|
popq %rdx
|
|
|
|
popq %rdi
|
|
|
|
popq %rsi
|
|
|
|
popq %rbp
|
|
|
|
|
2015-02-18 00:40:03 +01:00
|
|
|
/* Switch page tables */
|
|
|
|
mov CR3_OFFSET(%rax), %rax
|
|
|
|
mov %rax, %cr3
|
|
|
|
|
2015-02-18 00:41:56 +01:00
|
|
|
/* Set stack back to mt buffer and restore client RAX */
|
|
|
|
mov $_mt_buffer, %rsp
|
|
|
|
popq %rax
|
|
|
|
|
2015-02-18 00:46:43 +01:00
|
|
|
iretq
|
2015-02-06 17:29:30 +01:00
|
|
|
|
2015-02-26 11:48:20 +01:00
|
|
|
/************************************************
|
|
|
|
** Space for Interrupt Descriptor Table (IDT) **
|
|
|
|
** See Intel SDM Vol. 3A, section 6.10 **
|
|
|
|
************************************************/
|
|
|
|
|
|
|
|
.global _mt_idt
|
|
|
|
.align 8
|
|
|
|
_mt_idt:
|
|
|
|
.space 1 << MIN_PAGE_SIZE_LOG2
|
|
|
|
|
2015-02-26 20:43:00 +01:00
|
|
|
/***********************************************
|
|
|
|
** Space for 64-bit Task State Segment (TSS) **
|
|
|
|
** See Intel SDM Vol. 3A, section 7.7 **
|
|
|
|
***********************************************/
|
|
|
|
|
|
|
|
.global _mt_tss
|
|
|
|
.align 8
|
|
|
|
_mt_tss:
|
|
|
|
.space 104
|
|
|
|
|
2015-02-26 16:21:21 +01:00
|
|
|
/******************************************
|
|
|
|
** Global Descriptor Table (GDT) **
|
|
|
|
** See Intel SDM Vol. 3A, section 3.5.1 **
|
|
|
|
******************************************/
|
|
|
|
|
|
|
|
.align 4
|
|
|
|
.space 2
|
|
|
|
|
|
|
|
.global _gdt_ptr
|
|
|
|
_gdt_ptr:
|
|
|
|
.word _gdt_end - _gdt_start - 1 /* limit */
|
|
|
|
.long _gdt_start /* base address */
|
|
|
|
|
|
|
|
.align 8
|
|
|
|
_gdt_start:
|
|
|
|
/* Null descriptor */
|
|
|
|
.quad 0
|
|
|
|
/* 64-bit code segment descriptor */
|
|
|
|
.long 0
|
|
|
|
/* GDTE_LONG | GDTE_PRESENT | GDTE_CODE | GDTE_NON_SYSTEM */
|
|
|
|
.long 0x209800
|
|
|
|
/* 64-bit data segment descriptor */
|
|
|
|
.long 0
|
|
|
|
/* GDTE_LONG | GDTE_PRESENT | GDTE_TYPE_DATA_A | GDTE_TYPE_DATA_W | GDTE_NON_SYSTEM */
|
|
|
|
.long 0x209300
|
|
|
|
/* 64-bit user code segment descriptor */
|
|
|
|
.long 0
|
|
|
|
/* GDTE_LONG | GDTE_PRESENT | GDTE_CODE | GDTE_NON_SYSTEM */
|
|
|
|
.long 0x20f800
|
|
|
|
/* 64-bit user data segment descriptor */
|
|
|
|
.long 0
|
|
|
|
/* GDTE_LONG | GDTE_PRESENT | GDTE_TYPE_DATA_A | GDTE_TYPE_DATA_W | GDTE_NON_SYSTEM */
|
|
|
|
.long 0x20f300
|
|
|
|
/* Task segment descriptor */
|
2015-02-26 20:41:32 +01:00
|
|
|
.long 0x35b10068
|
2015-02-26 16:21:21 +01:00
|
|
|
/* GDTE_PRESENT | GDTE_SYS_TSS */
|
2015-02-26 20:41:32 +01:00
|
|
|
.long 0x8929
|
2015-02-26 16:21:21 +01:00
|
|
|
.long 0
|
|
|
|
.long 0
|
|
|
|
_gdt_end:
|
|
|
|
|
2015-02-06 17:29:30 +01:00
|
|
|
/* end of the mode transition code */
|
|
|
|
.global _mt_end
|
|
|
|
_mt_end:
|
|
|
|
1: jmp 1b
|