Files
xen/extras/mini-os/x86_64.S
T
kaf24@firebug.cl.cam.ac.uk 7469df6c08 [MINIOS] Various address-space fixes.
1. Make Mini-OS start from 0x0.
2. Fixes the pagetable builder to handle half full, but already mapped
pt frames.=20
3. Add a bounds check to ensure than Mini-OS does not try to use Xen
virtual space.

Signed-off-by: Grzegorz Milos <gm281@cam.ac.uk>
Signed-off-by: Aravindh Puthiyaparambil
<aravindh.puthiyaparambil@unisys.com>
2006-05-31 07:43:06 +01:00

386 lines
7.9 KiB
ArmAsm

#include <os.h>
#include <xen/features.h>
.section __xen_guest
.ascii "GUEST_OS=Mini-OS"
.ascii ",XEN_VER=xen-3.0"
.ascii ",VIRT_BASE=0x0" /* &_text from minios_x86_64.lds */
.ascii ",ELF_PADDR_OFFSET=0x0"
.ascii ",HYPERCALL_PAGE=0x2"
.ascii ",LOADER=generic"
.byte 0
.text
#define ENTRY(X) .globl X ; X :
.globl _start, shared_info, hypercall_page
_start:
cld
movq stack_start(%rip),%rsp
movq %rsi,%rdi
call start_kernel
stack_start:
.quad stack+8192
/* Unpleasant -- the PTE that maps this page is actually overwritten */
/* to map the real shared-info page! :-) */
.org 0x1000
shared_info:
.org 0x2000
hypercall_page:
.org 0x3000
/* Offsets into shared_info_t. */
#define evtchn_upcall_pending /* 0 */
#define evtchn_upcall_mask 1
NMI_MASK = 0x80000000
#define RDI 112
#define ORIG_RAX 120 /* + error_code */
#define EFLAGS 144
#define REST_SKIP 6*8
.macro SAVE_REST
subq $REST_SKIP,%rsp
# CFI_ADJUST_CFA_OFFSET REST_SKIP
movq %rbx,5*8(%rsp)
# CFI_REL_OFFSET rbx,5*8
movq %rbp,4*8(%rsp)
# CFI_REL_OFFSET rbp,4*8
movq %r12,3*8(%rsp)
# CFI_REL_OFFSET r12,3*8
movq %r13,2*8(%rsp)
# CFI_REL_OFFSET r13,2*8
movq %r14,1*8(%rsp)
# CFI_REL_OFFSET r14,1*8
movq %r15,(%rsp)
# CFI_REL_OFFSET r15,0*8
.endm
.macro RESTORE_REST
movq (%rsp),%r15
# CFI_RESTORE r15
movq 1*8(%rsp),%r14
# CFI_RESTORE r14
movq 2*8(%rsp),%r13
# CFI_RESTORE r13
movq 3*8(%rsp),%r12
# CFI_RESTORE r12
movq 4*8(%rsp),%rbp
# CFI_RESTORE rbp
movq 5*8(%rsp),%rbx
# CFI_RESTORE rbx
addq $REST_SKIP,%rsp
# CFI_ADJUST_CFA_OFFSET -(REST_SKIP)
.endm
#define ARG_SKIP 9*8
.macro RESTORE_ARGS skiprax=0,addskip=0,skiprcx=0,skipr11=0,skipr8910=0,skiprdx=0
.if \skipr11
.else
movq (%rsp),%r11
# CFI_RESTORE r11
.endif
.if \skipr8910
.else
movq 1*8(%rsp),%r10
# CFI_RESTORE r10
movq 2*8(%rsp),%r9
# CFI_RESTORE r9
movq 3*8(%rsp),%r8
# CFI_RESTORE r8
.endif
.if \skiprax
.else
movq 4*8(%rsp),%rax
# CFI_RESTORE rax
.endif
.if \skiprcx
.else
movq 5*8(%rsp),%rcx
# CFI_RESTORE rcx
.endif
.if \skiprdx
.else
movq 6*8(%rsp),%rdx
# CFI_RESTORE rdx
.endif
movq 7*8(%rsp),%rsi
# CFI_RESTORE rsi
movq 8*8(%rsp),%rdi
# CFI_RESTORE rdi
.if ARG_SKIP+\addskip > 0
addq $ARG_SKIP+\addskip,%rsp
# CFI_ADJUST_CFA_OFFSET -(ARG_SKIP+\addskip)
.endif
.endm
.macro HYPERVISOR_IRET flag
# testb $3,1*8(%rsp) /* Don't need to do that in Mini-os, as */
# jnz 2f /* there is no userspace? */
testl $NMI_MASK,2*8(%rsp)
jnz 2f
testb $1,(xen_features+XENFEAT_supervisor_mode_kernel)
jnz 1f
/* Direct iret to kernel space. Correct CS and SS. */
orb $3,1*8(%rsp)
orb $3,4*8(%rsp)
1: iretq
2: /* Slow iret via hypervisor. */
andl $~NMI_MASK, 16(%rsp)
pushq $\flag
jmp hypercall_page + (__HYPERVISOR_iret * 32)
.endm
/*
* Exception entry point. This expects an error code/orig_rax on the stack
* and the exception handler in %rax.
*/
ENTRY(error_entry)
# _frame RDI
/* rdi slot contains rax, oldrax contains error code */
cld
subq $14*8,%rsp
# CFI_ADJUST_CFA_OFFSET (14*8)
movq %rsi,13*8(%rsp)
# CFI_REL_OFFSET rsi,RSI
movq 14*8(%rsp),%rsi /* load rax from rdi slot */
movq %rdx,12*8(%rsp)
# CFI_REL_OFFSET rdx,RDX
movq %rcx,11*8(%rsp)
# CFI_REL_OFFSET rcx,RCX
movq %rsi,10*8(%rsp) /* store rax */
# CFI_REL_OFFSET rax,RAX
movq %r8, 9*8(%rsp)
# CFI_REL_OFFSET r8,R8
movq %r9, 8*8(%rsp)
# CFI_REL_OFFSET r9,R9
movq %r10,7*8(%rsp)
# CFI_REL_OFFSET r10,R10
movq %r11,6*8(%rsp)
# CFI_REL_OFFSET r11,R11
movq %rbx,5*8(%rsp)
# CFI_REL_OFFSET rbx,RBX
movq %rbp,4*8(%rsp)
# CFI_REL_OFFSET rbp,RBP
movq %r12,3*8(%rsp)
# CFI_REL_OFFSET r12,R12
movq %r13,2*8(%rsp)
# CFI_REL_OFFSET r13,R13
movq %r14,1*8(%rsp)
# CFI_REL_OFFSET r14,R14
movq %r15,(%rsp)
# CFI_REL_OFFSET r15,R15
#if 0
cmpl $__KERNEL_CS,CS(%rsp)
je error_kernelspace
#endif
error_call_handler:
movq %rdi, RDI(%rsp)
movq %rsp,%rdi
movq ORIG_RAX(%rsp),%rsi # get error code
movq $-1,ORIG_RAX(%rsp)
call *%rax
.macro zeroentry sym
# INTR_FRAME
movq (%rsp),%rcx
movq 8(%rsp),%r11
addq $0x10,%rsp /* skip rcx and r11 */
pushq $0 /* push error code/oldrax */
# CFI_ADJUST_CFA_OFFSET 8
pushq %rax /* push real oldrax to the rdi slot */
# CFI_ADJUST_CFA_OFFSET 8
leaq \sym(%rip),%rax
jmp error_entry
# CFI_ENDPROC
.endm
.macro errorentry sym
# XCPT_FRAME
movq (%rsp),%rcx
movq 8(%rsp),%r11
addq $0x10,%rsp /* rsp points to the error code */
pushq %rax
# CFI_ADJUST_CFA_OFFSET 8
leaq \sym(%rip),%rax
jmp error_entry
# CFI_ENDPROC
.endm
#define XEN_GET_VCPU_INFO(reg) movq HYPERVISOR_shared_info,reg
#define XEN_PUT_VCPU_INFO(reg)
#define XEN_PUT_VCPU_INFO_fixup
#define XEN_LOCKED_BLOCK_EVENTS(reg) movb $1,evtchn_upcall_mask(reg)
#define XEN_LOCKED_UNBLOCK_EVENTS(reg) movb $0,evtchn_upcall_mask(reg)
#define XEN_TEST_PENDING(reg) testb $0xFF,evtchn_upcall_pending(reg)
#define XEN_BLOCK_EVENTS(reg) XEN_GET_VCPU_INFO(reg) ; \
XEN_LOCKED_BLOCK_EVENTS(reg) ; \
XEN_PUT_VCPU_INFO(reg)
#define XEN_UNBLOCK_EVENTS(reg) XEN_GET_VCPU_INFO(reg) ; \
XEN_LOCKED_UNBLOCK_EVENTS(reg) ; \
XEN_PUT_VCPU_INFO(reg)
ENTRY(hypervisor_callback)
zeroentry hypervisor_callback2
ENTRY(hypervisor_callback2)
movq %rdi, %rsp
11: movq %gs:8,%rax
incl %gs:0
cmovzq %rax,%rsp
pushq %rdi
call do_hypervisor_callback
popq %rsp
decl %gs:0
jmp error_exit
# ALIGN
restore_all_enable_events:
XEN_UNBLOCK_EVENTS(%rsi) # %rsi is already set up...
scrit: /**** START OF CRITICAL REGION ****/
XEN_TEST_PENDING(%rsi)
jnz 14f # process more events if necessary...
XEN_PUT_VCPU_INFO(%rsi)
RESTORE_ARGS 0,8,0
HYPERVISOR_IRET 0
14: XEN_LOCKED_BLOCK_EVENTS(%rsi)
XEN_PUT_VCPU_INFO(%rsi)
SAVE_REST
movq %rsp,%rdi # set the argument again
jmp 11b
ecrit: /**** END OF CRITICAL REGION ****/
retint_kernel:
retint_restore_args:
movl EFLAGS-REST_SKIP(%rsp), %eax
shr $9, %eax # EAX[0] == IRET_EFLAGS.IF
XEN_GET_VCPU_INFO(%rsi)
andb evtchn_upcall_mask(%rsi),%al
andb $1,%al # EAX[0] == IRET_EFLAGS.IF & event_mask
jnz restore_all_enable_events # != 0 => enable event delivery
XEN_PUT_VCPU_INFO(%rsi)
RESTORE_ARGS 0,8,0
HYPERVISOR_IRET 0
error_exit:
RESTORE_REST
/* cli */
XEN_BLOCK_EVENTS(%rsi)
jmp retint_kernel
ENTRY(failsafe_callback)
popq %rcx
popq %r11
iretq
ENTRY(coprocessor_error)
zeroentry do_coprocessor_error
ENTRY(simd_coprocessor_error)
zeroentry do_simd_coprocessor_error
ENTRY(device_not_available)
zeroentry do_device_not_available
ENTRY(debug)
# INTR_FRAME
# CFI_ADJUST_CFA_OFFSET 8 */
zeroentry do_debug
# CFI_ENDPROC
ENTRY(int3)
# INTR_FRAME
# CFI_ADJUST_CFA_OFFSET 8 */
zeroentry do_int3
# CFI_ENDPROC
ENTRY(overflow)
zeroentry do_overflow
ENTRY(bounds)
zeroentry do_bounds
ENTRY(invalid_op)
zeroentry do_invalid_op
ENTRY(coprocessor_segment_overrun)
zeroentry do_coprocessor_segment_overrun
ENTRY(invalid_TSS)
errorentry do_invalid_TSS
ENTRY(segment_not_present)
errorentry do_segment_not_present
/* runs on exception stack */
ENTRY(stack_segment)
# XCPT_FRAME
errorentry do_stack_segment
# CFI_ENDPROC
ENTRY(general_protection)
errorentry do_general_protection
ENTRY(alignment_check)
errorentry do_alignment_check
ENTRY(divide_error)
zeroentry do_divide_error
ENTRY(spurious_interrupt_bug)
zeroentry do_spurious_interrupt_bug
ENTRY(page_fault)
errorentry do_page_fault
ENTRY(thread_starter)
popq %rdi
popq %rbx
call *%rbx
call exit_thread