From: iap10@labyrinth.cl.cam.ac.uk Date: Mon, 6 Oct 2003 18:17:03 +0000 (+0000) Subject: bitkeeper revision 1.485 (3f81b19fL5Y4lVlRaEpJI9r_IZlDcw) X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~18642 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=d5d4e6ed04a28dd9d7ba2b15f187214f2bd36ce1;p=xen.git bitkeeper revision 1.485 (3f81b19fL5Y4lVlRaEpJI9r_IZlDcw) Merge labyrinth.cl.cam.ac.uk:/auto/groups/xeno/users/rn212/xeno.mini into labyrinth.cl.cam.ac.uk:/auto/anfs/scratch/labyrinth/iap10/xeno-clone/xeno.bk --- d5d4e6ed04a28dd9d7ba2b15f187214f2bd36ce1 diff --cc extras/mini-os/h/os.h index 2645bea954,0000000000..9578b8f5b4 mode 100644,000000..100644 --- a/extras/mini-os/h/os.h +++ b/extras/mini-os/h/os.h @@@ -1,270 -1,0 +1,274 @@@ +/****************************************************************************** + * os.h + * + * random collection of macros and definition + */ + +#ifndef _OS_H_ +#define _OS_H_ + + +#define NULL 0 + +/* + * These are the segment descriptors provided for us by the hypervisor. + * For now, these are hardwired -- guest OSes cannot update the GDT + * or LDT. + * + * It shouldn't be hard to support descriptor-table frobbing -- let me + * know if the BSD or XP ports require flexibility here. + */ + + +/* + * these are also defined in hypervisor-if.h but can't be pulled in as + * they are used in start of day assembly. Need to clean up the .h files + * a bit more... + */ + +#ifndef FLAT_RING1_CS +#define FLAT_RING1_CS 0x0819 +#define FLAT_RING1_DS 0x0821 +#define FLAT_RING3_CS 0x082b +#define FLAT_RING3_DS 0x0833 +#endif + +#define __KERNEL_CS FLAT_RING1_CS +#define __KERNEL_DS FLAT_RING1_DS + +/* Everything below this point is not included by assembler (.S) files. */ +#ifndef __ASSEMBLY__ + +#include +#include + + +/* this struct defines the way the registers are stored on the + stack during an exception or interrupt. */ +struct pt_regs { + long ebx; + long ecx; + long edx; + long esi; + long edi; + long ebp; + long eax; + int xds; + int xes; + long orig_eax; + long eip; + int xcs; + long eflags; + long esp; + int xss; +}; + ++/* some function prototypes */ ++void trap_init(void); ++void dump_regs(struct pt_regs *regs); ++ + +/* + * STI/CLI equivalents. These basically set and clear the virtual + * event_enable flag in teh shared_info structure. Note that when + * the enable bit is set, there may be pending events to be handled. + * We may therefore call into do_hypervisor_callback() directly. + */ +#define unlikely(x) __builtin_expect((x),0) +#define __save_flags(x) \ +do { \ + (x) = test_bit(EVENTS_MASTER_ENABLE_BIT, \ + &HYPERVISOR_shared_info->events_mask); \ + barrier(); \ +} while (0) + +#define __restore_flags(x) \ +do { \ + shared_info_t *_shared = HYPERVISOR_shared_info; \ + if (x) set_bit(EVENTS_MASTER_ENABLE_BIT, &_shared->events_mask); \ + barrier(); \ + if ( unlikely(_shared->events) && (x) ) do_hypervisor_callback(NULL); \ +} while (0) + +#define __cli() \ +do { \ + clear_bit(EVENTS_MASTER_ENABLE_BIT, &HYPERVISOR_shared_info->events_mask);\ + barrier(); \ +} while (0) + +#define __sti() \ +do { \ + shared_info_t *_shared = HYPERVISOR_shared_info; \ + set_bit(EVENTS_MASTER_ENABLE_BIT, &_shared->events_mask); \ + barrier(); \ + if ( unlikely(_shared->events) ) do_hypervisor_callback(NULL); \ +} while (0) +#define cli() __cli() +#define sti() __sti() +#define save_flags(x) __save_flags(x) +#define restore_flags(x) __restore_flags(x) +#define save_and_cli(x) __save_and_cli(x) +#define save_and_sti(x) __save_and_sti(x) + + + +/* This is a barrier for the compiler only, NOT the processor! */ +#define barrier() __asm__ __volatile__("": : :"memory") + +#define LOCK_PREFIX "" +#define LOCK "" +#define ADDR (*(volatile long *) addr) +/* + * Make sure gcc doesn't try to be clever and move things around + * on us. We need to use _exactly_ the address the user gave us, + * not some alias that contains the same information. + */ +typedef struct { volatile int counter; } atomic_t; + + +/* + * This XCHG macro is straight from Linux. It is gross. + */ +#define xchg(ptr,v) \ + ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr)))) +struct __xchg_dummy { unsigned long a[100]; }; +#define __xg(x) ((struct __xchg_dummy *)(x)) +static inline unsigned long __xchg(unsigned long x, volatile void * ptr, + int size) +{ + switch (size) { + case 1: + __asm__ __volatile__("xchgb %b0,%1" + :"=q" (x) + :"m" (*__xg(ptr)), "0" (x) + :"memory"); + break; + case 2: + __asm__ __volatile__("xchgw %w0,%1" + :"=r" (x) + :"m" (*__xg(ptr)), "0" (x) + :"memory"); + break; + case 4: + __asm__ __volatile__("xchgl %0,%1" + :"=r" (x) + :"m" (*__xg(ptr)), "0" (x) + :"memory"); + break; + } + return x; +} + +/** + * test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +static __inline__ int test_and_clear_bit(int nr, volatile void * addr) +{ + int oldbit; + + __asm__ __volatile__( LOCK_PREFIX + "btrl %2,%1\n\tsbbl %0,%0" + :"=r" (oldbit),"=m" (ADDR) + :"Ir" (nr) : "memory"); + return oldbit; +} + +static __inline__ int constant_test_bit(int nr, const volatile void * addr) +{ + return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0; +} + +static __inline__ int variable_test_bit(int nr, volatile void * addr) +{ + int oldbit; + + __asm__ __volatile__( + "btl %2,%1\n\tsbbl %0,%0" + :"=r" (oldbit) + :"m" (ADDR),"Ir" (nr)); + return oldbit; +} + +#define test_bit(nr,addr) \ +(__builtin_constant_p(nr) ? \ + constant_test_bit((nr),(addr)) : \ + variable_test_bit((nr),(addr))) + + +/** + * set_bit - Atomically set a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * This function is atomic and may not be reordered. See __set_bit() + * if you do not require the atomic guarantees. + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +static __inline__ void set_bit(int nr, volatile void * addr) +{ + __asm__ __volatile__( LOCK_PREFIX + "btsl %1,%0" + :"=m" (ADDR) + :"Ir" (nr)); +} + +/** + * clear_bit - Clears a bit in memory + * @nr: Bit to clear + * @addr: Address to start counting from + * + * clear_bit() is atomic and may not be reordered. However, it does + * not contain a memory barrier, so if it is used for locking purposes, + * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() + * in order to ensure changes are visible on other processors. + */ +static __inline__ void clear_bit(int nr, volatile void * addr) +{ + __asm__ __volatile__( LOCK_PREFIX + "btrl %1,%0" + :"=m" (ADDR) + :"Ir" (nr)); +} + +/** + * atomic_inc - increment atomic variable + * @v: pointer of type atomic_t + * + * Atomically increments @v by 1. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +static __inline__ void atomic_inc(atomic_t *v) +{ + __asm__ __volatile__( + LOCK "incl %0" + :"=m" (v->counter) + :"m" (v->counter)); +} + + +/* useful hypervisor macros */ + +struct desc_struct { + unsigned long a,b; +}; +extern struct desc_struct default_ldt[]; + +#define asmlinkage __attribute__((regparm(0))) + +/* + * some random linux macros + */ + +#define rdtscll(val) \ + __asm__ __volatile__("rdtsc" : "=A" (val)) + + +#endif /* !__ASSEMBLY__ */ + +#endif /* _OS_H_ */ diff --cc extras/mini-os/kernel.c index 6486fac119,0000000000..196d8612c3 mode 100644,000000..100644 --- a/extras/mini-os/kernel.c +++ b/extras/mini-os/kernel.c @@@ -1,126 -1,0 +1,136 @@@ +/****************************************************************************** + * kernel.c + * + * Assorted crap goes here, including the initial C entry point, jumped at + * from head.S. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * Shared page for communicating with the hypervisor. + * Events flags go here, for example. + */ +shared_info_t *HYPERVISOR_shared_info; + +/* + * This structure contains start-of-day info, such as pagetable base pointer, + * address of the shared_info structure, and things like that. + */ +union start_info_union start_info_union; + +/* + * Just allocate the kernel stack here. SS:ESP is set up to point here + * in head.S. + */ +char stack[8192]; + + +/* Assembler interface fns in entry.S. */ +void hypervisor_callback(void); +void failsafe_callback(void); + - /* default exit event handler */ ++/* default event handlers */ +static void exit_handler(int ev, struct pt_regs *regs); ++static void debug_handler(int ev, struct pt_regs *regs); + - extern void trap_init(void); + +/* + * INITIAL C ENTRY POINT. + */ +void start_kernel(start_info_t *si) +{ + int i; + + /* Copy the start_info struct to a globally-accessible area. */ + memcpy(&start_info, si, sizeof(*si)); + + /* Grab the shared_info pointer and put it in a safe place. */ + HYPERVISOR_shared_info = start_info.shared_info; + + /* Set up event and failsafe callback addresses. */ + HYPERVISOR_set_callbacks( + __KERNEL_CS, (unsigned long)hypervisor_callback, + __KERNEL_CS, (unsigned long)failsafe_callback); + + + trap_init(); + + + /* ENABLE EVENT DELIVERY. This is disabled at start of day. */ + __sti(); + + /* print out some useful information */ + printk("Xeno Minimal OS!\n"); + printk("start_info: %p\n", si); + printk(" nr_pages: %lu", si->nr_pages); + printk(" shared_inf: %p\n", si->shared_info); + printk(" pt_base: %p", (void *)si->pt_base); + printk(" mod_start: 0x%lx\n", si->mod_start); + printk(" mod_len: %lu\n", si->mod_len); + printk(" net_rings: "); + for (i = 0; i < MAX_DOMAIN_VIFS; i++) { + printk(" %lx", si->net_rings[i]); + }; printk("\n"); + printk(" blk_ring: 0x%lx\n", si->blk_ring); + printk(" dom_id: %d\n", si->dom_id); + printk(" flags: 0x%lx\n", si->flags); + printk(" cmd_line: %s\n", si->cmd_line ? (const char *)si->cmd_line : "NULL"); + + + /* + * If used for porting another OS, start here to figure out your + * guest os entry point. Otherwise continue below... + */ + + /* init memory management */ + init_mm(); + + /* set up events */ + init_events(); + + /* install some handlers */ + add_ev_action(EV_DIE, &exit_handler); + enable_ev_action(EV_DIE); + enable_hypervisor_event(EV_DIE); + ++ add_ev_action(EV_DEBUG, &debug_handler); ++ enable_ev_action(EV_DEBUG); ++ enable_hypervisor_event(EV_DEBUG); ++ + /* init time and timers */ + init_time(); + + /* do nothing */ + for ( ; ; ) HYPERVISOR_yield(); +} + + +/* + * do_exit: This is called whenever an IRET fails in entry.S. + * This will generally be because an application has got itself into + * a really bad state (probably a bad CS or SS). It must be killed. + * Of course, minimal OS doesn't have applications :-) + */ + +void do_exit(void) +{ + printk("do_exit called!\n"); + for ( ;; ) ; +} +static void exit_handler(int ev, struct pt_regs *regs) { + do_exit(); +} + ++/* ++ * a debug handler to print out some state from the guest ++ */ ++static void debug_handler(int ev, struct pt_regs *regs) { ++ dump_regs(regs); ++} diff --cc extras/mini-os/traps.c index 6352559c0f,0000000000..8dec10c581 mode 100644,000000..100644 --- a/extras/mini-os/traps.c +++ b/extras/mini-os/traps.c @@@ -1,231 -1,0 +1,258 @@@ + +#include +#include ++#include +#include + +/* + * These are assembler stubs in entry.S. + * They are the actual entry points for virtual exceptions. + */ +void divide_error(void); +void debug(void); +void int3(void); +void overflow(void); +void bounds(void); +void invalid_op(void); +void device_not_available(void); +void double_fault(void); +void coprocessor_segment_overrun(void); +void invalid_TSS(void); +void segment_not_present(void); +void stack_segment(void); +void general_protection(void); +void page_fault(void); +void coprocessor_error(void); +void simd_coprocessor_error(void); +void alignment_check(void); +void spurious_interrupt_bug(void); +void machine_check(void); + + +extern void do_exit(void); + +int kstack_depth_to_print = 24; ++#define THREAD_SIZE (2*PAGE_SIZE) + +static inline int kernel_text_address(unsigned long addr) +{ + return ( (addr >> 20) > 0x800 && (addr >> 20) < 0x804 ); +} + +void show_trace(unsigned long * stack) +{ + int i; + unsigned long addr; + + if (!stack) + stack = (unsigned long*)&stack; + + printk("Call Trace: "); + i = 1; + while (((long) stack & (4095)) != 0) { + addr = *stack++; + if (kernel_text_address(addr)) { + printf("0x%lx", addr); + i++; + } + } + printk("\n"); +} + - void dump_regs(struct pt_regs *regs) { - printk("Register dump:"); - printk("ebx: \t 0x%lx", regs->ebx); - printk("ecx: \t 0x%lx", regs->ecx); - printk("edx: \t 0x%lx", regs->edx); - printk("esi: \t 0x%lx", regs->esi); - printk("edi: \t 0x%lx", regs->edi); - printk("ebp: \t 0x%lx", regs->ebp); - printk("eax: \t 0x%lx", regs->eax); - printk("xds: \t 0x%x", regs->xds); - printk("xes: \t 0x%x", regs->xes); - printk("orig_eax: \t 0x%lx", regs->orig_eax); - printk("eip: \t 0x%lx", regs->eip); - printk("xcs: \t 0x%x", regs->xcs); - printk("eflags: \t 0x%lx", regs->eflags); - printk("esp: \t 0x%lx", regs->esp); - printk("xss: \t 0x%x", regs->xss); - }; ++void show_stack(unsigned long * esp) ++{ ++ unsigned long *stack; ++ int i; ++ ++ if(esp==NULL) ++ esp=(unsigned long*)&esp; ++ ++ stack = esp; ++ for(i=0; i < kstack_depth_to_print; i++) { ++ if (((long) stack & (THREAD_SIZE-1)) == 0) ++ break; ++ printk("%08lx ", *stack++); ++ } ++ printk("\n"); ++ show_trace(esp); ++} ++ ++void dump_regs(struct pt_regs *regs) ++{ ++ int in_kernel = 1; ++ unsigned long esp; ++ unsigned short ss; ++ ++ esp = (unsigned long) (®s->esp); ++ ss = __KERNEL_DS; ++ if (regs->xcs & 2) { ++ in_kernel = 0; ++ esp = regs->esp; ++ ss = regs->xss & 0xffff; ++ } ++ printf("EIP: %04x:[<%08lx>]\n", ++ 0xffff & regs->xcs, regs->eip); ++ printf("EFLAGS: %08lx\n",regs->eflags); ++ printf("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n", ++ regs->eax, regs->ebx, regs->ecx, regs->edx); ++ printf("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n", ++ regs->esi, regs->edi, regs->ebp, esp); ++ printf("ds: %04x es: %04x ss: %04x\n", ++ regs->xds & 0xffff, regs->xes & 0xffff, ss); ++ printf("\n"); ++} ++ + +static inline void dump_code(unsigned eip) +{ + unsigned *ptr = (unsigned *)eip; + int x; + + printk("Bytes at eip:\n"); + for (x = -4; x < 5; x++) + printf("%x", ptr[x]); +} + + +/* + * C handlers here have their parameter-list constructed by the + * assembler stubs above. Each one gets a pointer to a list + * of register values (to be restored at end of exception). + * Some will also receive an error code -- this is the code that + * was generated by the processor for the underlying real exception. + * + * Note that the page-fault exception is special. It also receives + * the faulting linear address. Normally this would be found in + * register CR2, but that is not accessible in a virtualised OS. + */ + +static void inline do_trap(int trapnr, char *str, + struct pt_regs * regs, long error_code) +{ + printk("FATAL: Unhandled Trap (see mini-os:traps.c)"); + printf("%d %s", trapnr, str); + dump_regs(regs); + show_trace((void *)regs->esp); + dump_code(regs->eip); + + do_exit(); +} + +#define DO_ERROR(trapnr, str, name) \ +void do_##name(struct pt_regs * regs, long error_code) \ +{ \ + do_trap(trapnr, str, regs, error_code); \ +} + +#define DO_ERROR_INFO(trapnr, str, name, sicode, siaddr) \ +void do_##name(struct pt_regs * regs, long error_code) \ +{ \ + do_trap(trapnr, str, regs, error_code); \ +} + +DO_ERROR_INFO( 0, "divide error", divide_error, FPE_INTDIV, regs->eip) +DO_ERROR( 3, "int3", int3) +DO_ERROR( 4, "overflow", overflow) +DO_ERROR( 5, "bounds", bounds) +DO_ERROR_INFO( 6, "invalid operand", invalid_op, ILL_ILLOPN, regs->eip) +DO_ERROR( 7, "device not available", device_not_available) +DO_ERROR( 8, "double fault", double_fault) +DO_ERROR( 9, "coprocessor segment overrun", coprocessor_segment_overrun) +DO_ERROR(10, "invalid TSS", invalid_TSS) +DO_ERROR(11, "segment not present", segment_not_present) +DO_ERROR(12, "stack segment", stack_segment) +DO_ERROR_INFO(17, "alignment check", alignment_check, BUS_ADRALN, 0) +DO_ERROR(18, "machine check", machine_check) + +void do_page_fault(struct pt_regs * regs, long error_code, + unsigned long address) +{ + printk("Page fault\n"); + printk("Address: 0x%lx", address); + printk("Error Code: 0x%lx", error_code); + printk("eip: \t 0x%lx", regs->eip); + do_exit(); +} + +void do_general_protection(struct pt_regs * regs, long error_code) +{ + + HYPERVISOR_shared_info->events_mask = 0; + printk("GPF\n"); + printk("Error Code: 0x%lx", error_code); + dump_regs(regs); + dump_code(regs->eip); + do_exit(); +} + + +void do_debug(struct pt_regs * regs, long error_code) +{ + printk("Debug exception\n"); +#define TF_MASK 0x100 + regs->eflags &= ~TF_MASK; + dump_regs(regs); + do_exit(); +} + + + +void do_coprocessor_error(struct pt_regs * regs, long error_code) +{ + printk("Copro error\n"); + dump_regs(regs); + dump_code(regs->eip); + do_exit(); +} + +void simd_math_error(void *eip) +{ + printk("SIMD error\n"); +} + +void do_simd_coprocessor_error(struct pt_regs * regs, + long error_code) +{ + printk("SIMD copro error\n"); +} + +void do_spurious_interrupt_bug(struct pt_regs * regs, + long error_code) +{ +} + +/* + * Submit a virtual IDT to teh hypervisor. This consists of tuples + * (interrupt vector, privilege ring, CS:EIP of handler). + * The 'privilege ring' field specifies the least-privileged ring that + * can trap to that vector using a software-interrupt instruction (INT). + */ +static trap_info_t trap_table[] = { + { 0, 0, __KERNEL_CS, (unsigned long)divide_error }, + { 1, 0, __KERNEL_CS, (unsigned long)debug }, + { 3, 3, __KERNEL_CS, (unsigned long)int3 }, + { 4, 3, __KERNEL_CS, (unsigned long)overflow }, + { 5, 3, __KERNEL_CS, (unsigned long)bounds }, + { 6, 0, __KERNEL_CS, (unsigned long)invalid_op }, + { 7, 0, __KERNEL_CS, (unsigned long)device_not_available }, + { 8, 0, __KERNEL_CS, (unsigned long)double_fault }, + { 9, 0, __KERNEL_CS, (unsigned long)coprocessor_segment_overrun }, + { 10, 0, __KERNEL_CS, (unsigned long)invalid_TSS }, + { 11, 0, __KERNEL_CS, (unsigned long)segment_not_present }, + { 12, 0, __KERNEL_CS, (unsigned long)stack_segment }, + { 13, 0, __KERNEL_CS, (unsigned long)general_protection }, + { 14, 0, __KERNEL_CS, (unsigned long)page_fault }, + { 15, 0, __KERNEL_CS, (unsigned long)spurious_interrupt_bug }, + { 16, 0, __KERNEL_CS, (unsigned long)coprocessor_error }, + { 17, 0, __KERNEL_CS, (unsigned long)alignment_check }, + { 18, 0, __KERNEL_CS, (unsigned long)machine_check }, + { 19, 0, __KERNEL_CS, (unsigned long)simd_coprocessor_error }, + { 0, 0, 0, 0 } +}; + + + +void trap_init(void) +{ + HYPERVISOR_set_trap_table(trap_table); +}