[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Fix x86/64 version of Mini-OS. It encompasses the following:
# HG changeset patch # User kaf24@xxxxxxxxxxxxxxxxxxxx # Node ID f6507937cb7c95fbcf662b1c23e742ce9c076753 # Parent dc3c59367403959b0ae135966c1acfe9678a8f0d Fix x86/64 version of Mini-OS. It encompasses the following: a) 64-bit switch_to scheduler macro (by Aravindh Puthiyaparambil) b) implements 64-bit hypervisor_callback c) fixes thread creation issues (thread_starter used to perform initialisation) Signed-off-by: Grzegorz Milos <gm281@xxxxxxxxx> diff -r dc3c59367403 -r f6507937cb7c extras/mini-os/console/console.c --- a/extras/mini-os/console/console.c Mon May 01 17:44:51 2006 +0100 +++ b/extras/mini-os/console/console.c Tue May 02 09:12:39 2006 +0100 @@ -128,7 +128,7 @@ void printk(const char *fmt, ...) { va_list args; va_start(args, fmt); - print(0, fmt, args); + print(1, fmt, args); va_end(args); } diff -r dc3c59367403 -r f6507937cb7c extras/mini-os/events.c --- a/extras/mini-os/events.c Mon May 01 17:44:51 2006 +0100 +++ b/extras/mini-os/events.c Tue May 02 09:12:39 2006 +0100 @@ -106,6 +106,17 @@ void unbind_virq( u32 port ) unbind_evtchn(port); } +#if defined(__x86_64__) +/* Allocate 4 pages for the irqstack */ +#define STACK_PAGES 4 +char irqstack[1024 * 4 * STACK_PAGES]; + +static struct pda +{ + int irqcount; /* offset 0 (used in x86_64.S) */ + char *irqstackptr; /* 8 */ +} cpu0_pda; +#endif /* * Initially all events are without a handler and disabled @@ -113,7 +124,12 @@ void init_events(void) void init_events(void) { int i; - +#if defined(__x86_64__) + asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0)); + wrmsrl(0xc0000101, &cpu0_pda); /* 0xc0000101 is MSR_GS_BASE */ + cpu0_pda.irqcount = -1; + cpu0_pda.irqstackptr = irqstack + 1024 * 4 * STACK_PAGES; +#endif /* inintialise event handler */ for ( i = 0; i < NR_EVS; i++ ) { diff -r dc3c59367403 -r f6507937cb7c extras/mini-os/hypervisor.c --- a/extras/mini-os/hypervisor.c Mon May 01 17:44:51 2006 +0100 +++ b/extras/mini-os/hypervisor.c Tue May 02 09:12:39 2006 +0100 @@ -41,8 +41,8 @@ void do_hypervisor_callback(struct pt_re shared_info_t *s = HYPERVISOR_shared_info; vcpu_info_t *vcpu_info = &s->vcpu_info[cpu]; + vcpu_info->evtchn_upcall_pending = 0; - /* NB. No need for a barrier here -- XCHG is a barrier on x86. */ l1 = xchg(&vcpu_info->evtchn_pending_sel, 0); while ( l1 != 0 ) diff -r dc3c59367403 -r f6507937cb7c extras/mini-os/include/mm.h --- a/extras/mini-os/include/mm.h Mon May 01 17:44:51 2006 +0100 +++ b/extras/mini-os/include/mm.h Tue May 02 09:12:39 2006 +0100 @@ -148,7 +148,7 @@ static __inline__ unsigned long machine_ } #if defined(__x86_64__) -#define VIRT_START 0xFFFFFFFF00000000UL +#define VIRT_START 0xFFFFFFFF80000000UL #elif defined(__i386__) #define VIRT_START 0xC0000000UL #endif diff -r dc3c59367403 -r f6507937cb7c extras/mini-os/include/os.h --- a/extras/mini-os/include/os.h Mon May 01 17:44:51 2006 +0100 +++ b/extras/mini-os/include/os.h Tue May 02 09:12:39 2006 +0100 @@ -434,6 +434,13 @@ static __inline__ unsigned long __ffs(un (val) = ((unsigned long)__a) | (((unsigned long)__d)<<32); \ } while(0) +#define wrmsr(msr,val1,val2) \ + __asm__ __volatile__("wrmsr" \ + : /* no outputs */ \ + : "c" (msr), "a" (val1), "d" (val2)) + +#define wrmsrl(msr,val) wrmsr(msr,(u32)((u64)(val)),((u64)(val))>>32) + #else /* ifdef __x86_64__ */ #error "Unsupported architecture" diff -r dc3c59367403 -r f6507937cb7c extras/mini-os/include/sched.h --- a/extras/mini-os/include/sched.h Mon May 01 17:44:51 2006 +0100 +++ b/extras/mini-os/include/sched.h Tue May 02 09:12:39 2006 +0100 @@ -7,8 +7,8 @@ struct thread { char *name; char *stack; - unsigned long eps; - unsigned long eip; + unsigned long sp; /* Stack pointer */ + unsigned long ip; /* Instruction pointer */ struct list_head thread_list; u32 flags; }; @@ -25,7 +25,9 @@ static inline struct thread* get_current struct thread **current; #ifdef __i386__ __asm__("andl %%esp,%0; ":"=r" (current) : "r" (~8191UL)); -#endif +#else + __asm__("andq %%rsp,%0; ":"=r" (current) : "r" (~8191UL)); +#endif return *current; } diff -r dc3c59367403 -r f6507937cb7c extras/mini-os/kernel.c --- a/extras/mini-os/kernel.c Mon May 01 17:44:51 2006 +0100 +++ b/extras/mini-os/kernel.c Tue May 02 09:12:39 2006 +0100 @@ -35,6 +35,8 @@ #include <lib.h> #include <sched.h> #include <xenbus.h> +#include <xen/features.h> +#include <xen/version.h> /* * Shared page for communicating with the hypervisor. @@ -84,6 +86,26 @@ static void init_xs(void *ign) test_xenbus(); } + + +u8 xen_features[XENFEAT_NR_SUBMAPS * 32]; + +void setup_xen_features(void) +{ + xen_feature_info_t fi; + int i, j; + + for (i = 0; i < XENFEAT_NR_SUBMAPS; i++) + { + fi.submap_idx = i; + if (HYPERVISOR_xen_version(XENVER_get_features, &fi) < 0) + break; + + for (j=0; j<32; j++) + xen_features[i*32+j] = !!(fi.submap & 1<<j); + } +} + /* * INITIAL C ENTRY POINT. @@ -127,7 +149,9 @@ void start_kernel(start_info_t *si) printk(" flags: 0x%x\n", (unsigned int)si->flags); printk(" cmd_line: %s\n", si->cmd_line ? (const char *)si->cmd_line : "NULL"); + printk(" stack: %p-%p\n", stack, stack + 8192); + setup_xen_features(); /* Init memory management. */ init_mm(); @@ -146,7 +170,7 @@ void start_kernel(start_info_t *si) /* Init XenBus from a separate thread */ create_thread("init_xs", init_xs, NULL); - + /* Everything initialised, start idle thread */ run_idle_thread(); } diff -r dc3c59367403 -r f6507937cb7c extras/mini-os/minios-x86_64.lds --- a/extras/mini-os/minios-x86_64.lds Mon May 01 17:44:51 2006 +0100 +++ b/extras/mini-os/minios-x86_64.lds Tue May 02 09:12:39 2006 +0100 @@ -3,7 +3,7 @@ ENTRY(_start) ENTRY(_start) SECTIONS { - . = 0xFFFFFFFF00000000; + . = 0xFFFFFFFF80000000; _text = .; /* Text and read-only data */ .text : { *(.text) diff -r dc3c59367403 -r f6507937cb7c extras/mini-os/sched.c --- a/extras/mini-os/sched.c Mon May 01 17:44:51 2006 +0100 +++ b/extras/mini-os/sched.c Tue May 02 09:12:39 2006 +0100 @@ -69,17 +69,27 @@ void idle_thread_fn(void *unused); void dump_stack(struct thread *thread) { - unsigned long *bottom = (unsigned long *)thread->stack + 2048; - unsigned long *pointer = (unsigned long *)thread->eps; + unsigned long *bottom = (unsigned long *)(thread->stack + 2*4*1024); + unsigned long *pointer = (unsigned long *)thread->sp; int count; + if(thread == current) + { +#ifdef __i386__ + asm("movl %%esp,%0" + : "=r"(pointer)); +#else + asm("movq %%rsp,%0" + : "=r"(pointer)); +#endif + } printk("The stack for \"%s\"\n", thread->name); - for(count = 0; count < 15 && pointer < bottom; count ++) + for(count = 0; count < 25 && pointer < bottom; count ++) { printk("[0x%lx] 0x%lx\n", pointer, *pointer); pointer++; } - if(pointer < bottom) printk("Not the whole stack printed\n"); + if(pointer < bottom) printk(" ... continues.\n"); } #ifdef __i386__ @@ -95,13 +105,29 @@ void dump_stack(struct thread *thread) "1:\t" \ "popl %%ebp\n\t" \ "popfl" \ - :"=m" (prev->eps),"=m" (prev->eip), \ + :"=m" (prev->sp),"=m" (prev->ip), \ "=S" (esi),"=D" (edi) \ - :"m" (next->eps),"m" (next->eip), \ + :"m" (next->sp),"m" (next->ip), \ "2" (prev), "d" (next)); \ } while (0) #elif __x86_64__ -/* FIXME */ +#define switch_threads(prev, next) do { \ + unsigned long rsi,rdi; \ + __asm__ __volatile__("pushfq\n\t" \ + "pushq %%rbp\n\t" \ + "movq %%rsp,%0\n\t" /* save RSP */ \ + "movq %4,%%rsp\n\t" /* restore RSP */ \ + "movq $1f,%1\n\t" /* save RIP */ \ + "pushq %5\n\t" /* restore RIP */ \ + "ret\n\t" \ + "1:\t" \ + "popq %%rbp\n\t" \ + "popfq" \ + :"=m" (prev->sp),"=m" (prev->ip), \ + "=S" (rsi),"=D" (rdi) \ + :"m" (next->sp),"m" (next->ip), \ + "2" (prev), "d" (next)); \ +} while (0) #endif void inline print_runqueue(void) @@ -151,17 +177,19 @@ void schedule(void) local_irq_restore(flags); /* Interrupting the switch is equivalent to having the next thread inturrupted at the return instruction. And therefore at safe point. */ -/* The thread switching only works for i386 at the moment */ -#ifdef __i386__ if(prev != next) switch_threads(prev, next); -#endif -} - - - -void exit_thread(struct thread *thread) +} + + +/* Gets run when a new thread is scheduled the first time ever, + defined in x86_[32/64].S */ +extern void thread_starter(void); + + +void exit_thread(void) { unsigned long flags; + struct thread *thread = current; printk("Thread \"%s\" exited.\n", thread->name); local_irq_save(flags); /* Remove from the thread list */ @@ -174,6 +202,12 @@ void exit_thread(struct thread *thread) schedule(); } +/* Pushes the specified value onto the stack of the specified thread */ +static void stack_push(struct thread *thread, unsigned long value) +{ + thread->sp -= sizeof(unsigned long); + *((unsigned long *)thread->sp) = value; +} struct thread* create_thread(char *name, void (*function)(void *), void *data) { @@ -187,23 +221,17 @@ struct thread* create_thread(char *name, printk("Thread \"%s\": pointer: 0x%lx, stack: 0x%lx\n", name, thread, thread->stack); - thread->eps = (unsigned long)thread->stack + 4096 * 2 - 4; + thread->sp = (unsigned long)thread->stack + 4096 * 2; /* Save pointer to the thread on the stack, used by current macro */ *((unsigned long *)thread->stack) = (unsigned long)thread; - *((unsigned long *)thread->eps) = (unsigned long)thread; - thread->eps -= 4; - *((unsigned long *)thread->eps) = (unsigned long)data; - - /* No return address */ - thread->eps -= 4; - *((unsigned long *)thread->eps) = (unsigned long)exit_thread; - - thread->eip = (unsigned long)function; + + stack_push(thread, (unsigned long) function); + stack_push(thread, (unsigned long) data); + thread->ip = (unsigned long) thread_starter; /* Not runable, not exited */ thread->flags = 0; set_runnable(thread); - local_irq_save(flags); if(idle_thread != NULL) { list_add_tail(&thread->thread_list, &idle_thread->thread_list); @@ -213,7 +241,6 @@ struct thread* create_thread(char *name, BUG(); } local_irq_restore(flags); - return thread; } @@ -240,11 +267,19 @@ void run_idle_thread(void) void run_idle_thread(void) { /* Switch stacks and run the thread */ +#if defined(__i386__) __asm__ __volatile__("mov %0,%%esp\n\t" "push %1\n\t" "ret" - :"=m" (idle_thread->eps) - :"m" (idle_thread->eip)); + :"=m" (idle_thread->sp) + :"m" (idle_thread->ip)); +#elif defined(__x86_64__) + __asm__ __volatile__("mov %0,%%rsp\n\t" + "push %1\n\t" + "ret" + :"=m" (idle_thread->sp) + :"m" (idle_thread->ip)); +#endif } diff -r dc3c59367403 -r f6507937cb7c extras/mini-os/x86_32.S --- a/extras/mini-os/x86_32.S Mon May 01 17:44:51 2006 +0100 +++ b/extras/mini-os/x86_32.S Tue May 02 09:12:39 2006 +0100 @@ -286,3 +286,11 @@ ENTRY(spurious_interrupt_bug) pushl $0 pushl $do_spurious_interrupt_bug jmp do_exception + +ENTRY(thread_starter) + popl %eax + popl %ebx + pushl %eax + call *%ebx + call exit_thread + diff -r dc3c59367403 -r f6507937cb7c extras/mini-os/x86_64.S --- a/extras/mini-os/x86_64.S Mon May 01 17:44:51 2006 +0100 +++ b/extras/mini-os/x86_64.S Tue May 02 09:12:39 2006 +0100 @@ -1,4 +1,5 @@ #include <os.h> +#include <xen/features.h> .section __xen_guest .ascii "GUEST_OS=Mini-OS" @@ -65,10 +66,253 @@ hypercall_page: 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 + + + +#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) - popq %rcx - popq %r11 - iretq + 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 @@ -228,3 +472,12 @@ ENTRY(exception_table) .quad do_alignment_check .quad do_machine_check .quad do_simd_coprocessor_error + + +ENTRY(thread_starter) + popq %rdi + popq %rbx + call *%rbx + call exit_thread + + _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |