[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Xenbus implementation ported from Linux to Mini-os, simple thread support introduced
# HG changeset patch # User kaf24@xxxxxxxxxxxxxxxxxxxx # Node ID df1348e72390866e232f867be396962058d2f5b6 # Parent 6563a12e0ad762de25c8fd8b824b4d6579fd1480 Xenbus implementation ported from Linux to Mini-os, simple thread support introduced to simplify the porting. 64 bit version of Mini-os now compiles, but does not work because of the pagetables and some bits of scheduler not being written. Signed-off-by: Grzegorz Milos <gm281@xxxxxxxxx> diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/Makefile --- a/extras/mini-os/Makefile Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/Makefile Fri Sep 9 09:24:25 2005 @@ -31,16 +31,18 @@ OBJS := $(TARGET_ARCH).o OBJS += $(patsubst %.c,%.o,$(wildcard *.c)) OBJS += $(patsubst %.c,%.o,$(wildcard lib/*.c)) - +OBJS += $(patsubst %.c,%.o,$(wildcard xenbus/*.c)) + HDRS := $(wildcard include/*.h) HDRS += $(wildcard include/xen/*.h) default: $(TARGET) -xen-public: +links: [ -e include/xen ] || ln -sf ../../../xen/include/public include/xen - -$(TARGET): xen-public $(OBJS) + [ -e xenbus/xenstored.h ] || ln -sf ../../../tools/xenstore/xenstored.h xenbus/xenstored.h + +$(TARGET): links $(OBJS) $(LD) -N -T minios-$(TARGET_ARCH).lds $(OBJS) -o $@.elf gzip -f -9 -c $@.elf >$@.gz @@ -55,3 +57,4 @@ %.o: %.S $(HDRS) Makefile $(CC) $(CFLAGS) -D__ASSEMBLY__ -c $< -o $@ + diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/events.c --- a/extras/mini-os/events.c Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/events.c Fri Sep 9 09:24:25 2005 @@ -17,13 +17,13 @@ */ #include <os.h> +#include <mm.h> #include <hypervisor.h> #include <events.h> #include <lib.h> -#include <xen/event_channel.h> static ev_action_t ev_actions[NR_EVS]; -void default_handler(u32 port, struct pt_regs *regs); +void default_handler(int port, struct pt_regs *regs); /* @@ -32,7 +32,6 @@ int do_event(u32 port, struct pt_regs *regs) { ev_action_t *action; - if (port >= NR_EVS) { printk("Port number too large: %d\n", port); return 0; @@ -57,11 +56,23 @@ } +void bind_evtchn( u32 port, void (*handler)(int, struct pt_regs *) ) +{ + if(ev_actions[port].handler) + printk("WARN: Handler for port %d already registered, replacing\n", + port); + + ev_actions[port].handler = handler; + ev_actions[port].status &= ~EVS_DISABLED; + + /* Finally unmask the port */ + unmask_evtchn(port); +} + int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *) ) { evtchn_op_t op; int ret = 0; - u32 port; /* Try to bind the virq to a port */ op.cmd = EVTCHNOP_bind_virq; @@ -73,21 +84,12 @@ printk("Failed to bind virtual IRQ %d\n", virq); goto out; } - - port = op.u.bind_virq.port; - - if(ev_actions[port].handler) - printk("WARN: Handler for port %d already registered, replacing\n", - port); - - ev_actions[port].handler = handler; - ev_actions[port].status &= ~EVS_DISABLED; - - /* Finally unmask the port */ - unmask_evtchn(port); + bind_evtchn(op.u.bind_virq.port, handler); out: return ret; } + + /* * Initially all events are without a handler and disabled @@ -100,10 +102,10 @@ for ( i = 0; i < NR_EVS; i++ ) { ev_actions[i].status = EVS_DISABLED; - ev_actions[i].handler = NULL; + ev_actions[i].handler = default_handler; } } -void default_handler(u32 port, struct pt_regs *regs) { +void default_handler(int port, struct pt_regs *regs) { printk("[Port %d] - event received\n", port); } diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/include/events.h --- a/extras/mini-os/include/events.h Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/include/events.h Fri Sep 9 09:24:25 2005 @@ -20,6 +20,7 @@ #define _EVENTS_H_ #include<traps.h> +#include <xen/event_channel.h> #define NR_EVS 1024 @@ -39,6 +40,16 @@ /* prototypes */ int do_event(u32 port, struct pt_regs *regs); int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *) ); +void bind_evtchn( u32 virq, void (*handler)(int, struct pt_regs *) ); void init_events(void); +static inline int notify_via_evtchn(int port) +{ + evtchn_op_t op; + op.cmd = EVTCHNOP_send; + op.u.send.local_port = port; + return HYPERVISOR_event_channel_op(&op); +} + + #endif /* _EVENTS_H_ */ diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/include/hypervisor.h --- a/extras/mini-os/include/hypervisor.h Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/include/hypervisor.h Fri Sep 9 09:24:25 2005 @@ -13,7 +13,6 @@ #define _HYPERVISOR_H_ #include <types.h> - #include <xen/xen.h> #include <xen/io/domain_controller.h> @@ -40,48 +39,26 @@ /* * Assembler stubs for hyper-calls. */ - -#ifdef __i386__ -#define _a1 "b" -#define _a2 "c" -#define _a3 "d" -#define _a4 "S" -#else -#define _a1 "D" -#define _a2 "S" -#define _a3 "d" -#define _a4 "b" -#endif - -static __inline__ int HYPERVISOR_event_channel_op( - void *op) +#if defined(__i386__) +static inline int +HYPERVISOR_set_trap_table( + trap_info_t *table) { int ret; unsigned long ignore; + __asm__ __volatile__ ( TRAP_INSTR : "=a" (ret), "=b" (ignore) - : "0" (__HYPERVISOR_event_channel_op), "1" (op) - : "memory" ); - - return ret; -} - -static __inline__ int HYPERVISOR_set_trap_table(trap_info_t *table) -{ - int ret; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_set_trap_table), - _a1 (table) : "memory" ); - - return ret; -} - -static __inline__ int HYPERVISOR_mmu_update(mmu_update_t *req, - int count, - int *success_count, - domid_t domid) + : "0" (__HYPERVISOR_set_trap_table), "1" (table) + : "memory" ); + + return ret; +} + +static inline int +HYPERVISOR_mmu_update( + mmu_update_t *req, int count, int *success_count, domid_t domid) { int ret; unsigned long ign1, ign2, ign3, ign4; @@ -89,18 +66,16 @@ __asm__ __volatile__ ( TRAP_INSTR : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4) - : "0" (__HYPERVISOR_mmu_update), "1" (req), "2" (count), - "3" (success_count), "4" (domid) - : "memory" ); - - return ret; -} - - -static __inline__ int HYPERVISOR_mmuext_op(struct mmuext_op *op, - int count, - int *success_count, - domid_t domid) + : "0" (__HYPERVISOR_mmu_update), "1" (req), "2" (count), + "3" (success_count), "4" (domid) + : "memory" ); + + return ret; +} + +static inline int +HYPERVISOR_mmuext_op( + struct mmuext_op *op, int count, int *success_count, domid_t domid) { int ret; unsigned long ign1, ign2, ign3, ign4; @@ -108,70 +83,65 @@ __asm__ __volatile__ ( TRAP_INSTR : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4) - : "0" (__HYPERVISOR_mmuext_op), "1" (op), "2" (count), - "3" (success_count), "4" (domid) - : "memory" ); - - return ret; -} - - - -static __inline__ int HYPERVISOR_set_gdt(unsigned long *frame_list, int entries) -{ - int ret; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_set_gdt), - _a1 (frame_list), _a2 (entries) : "memory" ); - - - return ret; -} - -static __inline__ int HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp) -{ - int ret; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_stack_switch), - _a1 (ss), _a2 (esp) : "memory" ); - - return ret; -} - -#ifdef __i386__ -static __inline__ int HYPERVISOR_set_callbacks( + : "0" (__HYPERVISOR_mmuext_op), "1" (op), "2" (count), + "3" (success_count), "4" (domid) + : "memory" ); + + return ret; +} + +static inline int +HYPERVISOR_set_gdt( + unsigned long *frame_list, int entries) +{ + int ret; + unsigned long ign1, ign2; + + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1), "=c" (ign2) + : "0" (__HYPERVISOR_set_gdt), "1" (frame_list), "2" (entries) + : "memory" ); + + + return ret; +} + +static inline int +HYPERVISOR_stack_switch( + unsigned long ss, unsigned long esp) +{ + int ret; + unsigned long ign1, ign2; + + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1), "=c" (ign2) + : "0" (__HYPERVISOR_stack_switch), "1" (ss), "2" (esp) + : "memory" ); + + return ret; +} + +static inline int +HYPERVISOR_set_callbacks( unsigned long event_selector, unsigned long event_address, unsigned long failsafe_selector, unsigned long failsafe_address) { int ret; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_set_callbacks), - _a1 (event_selector), _a2 (event_address), - _a3 (failsafe_selector), _a4 (failsafe_address) : "memory" ); - - return ret; -} -#else -static __inline__ int HYPERVISOR_set_callbacks( - unsigned long event_address, - unsigned long failsafe_address, - unsigned long syscall_address) -{ - int ret; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_set_callbacks), - _a1 (event_address), _a2 (failsafe_address), - _a3 (syscall_address) : "memory" ); - - return ret; -} -#endif - -static __inline__ int + unsigned long ign1, ign2, ign3, ign4; + + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4) + : "0" (__HYPERVISOR_set_callbacks), "1" (event_selector), + "2" (event_address), "3" (failsafe_selector), "4" (failsafe_address) + : "memory" ); + + return ret; +} + +static inline int HYPERVISOR_fpu_taskswitch( int set) { @@ -187,67 +157,106 @@ return ret; } -static __inline__ int HYPERVISOR_yield(void) -{ - int ret; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_sched_op), - _a1 (SCHEDOP_yield) : "memory" ); - - return ret; -} - -static __inline__ int HYPERVISOR_block(void) -{ - int ret; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_sched_op), - _a1 (SCHEDOP_block) : "memory" ); - - return ret; -} - -static __inline__ int HYPERVISOR_shutdown(void) -{ - int ret; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_sched_op), - _a1 (SCHEDOP_shutdown | (SHUTDOWN_poweroff << SCHEDOP_reasonshift)) - : "memory" ); - - return ret; -} - -static __inline__ int HYPERVISOR_reboot(void) -{ - int ret; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_sched_op), - _a1 (SCHEDOP_shutdown | (SHUTDOWN_reboot << SCHEDOP_reasonshift)) - : "memory" ); - - return ret; -} - -static __inline__ int HYPERVISOR_suspend(unsigned long srec) -{ - int ret; +static inline int +HYPERVISOR_yield( + void) +{ + int ret; + unsigned long ign; + + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign) + : "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_yield) + : "memory", "ecx" ); + + return ret; +} + +static inline int +HYPERVISOR_block( + void) +{ + int ret; + unsigned long ign1; + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1) + : "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_block) + : "memory", "ecx" ); + + return ret; +} + +static inline int +HYPERVISOR_shutdown( + void) +{ + int ret; + unsigned long ign1; + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1) + : "0" (__HYPERVISOR_sched_op), + "1" (SCHEDOP_shutdown | (SHUTDOWN_poweroff << SCHEDOP_reasonshift)) + : "memory", "ecx" ); + + return ret; +} + +static inline int +HYPERVISOR_reboot( + void) +{ + int ret; + unsigned long ign1; + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1) + : "0" (__HYPERVISOR_sched_op), + "1" (SCHEDOP_shutdown | (SHUTDOWN_reboot << SCHEDOP_reasonshift)) + : "memory", "ecx" ); + + return ret; +} + +static inline int +HYPERVISOR_suspend( + unsigned long srec) +{ + int ret; + unsigned long ign1, ign2; + /* NB. On suspend, control software expects a suspend record in %esi. */ __asm__ __volatile__ ( TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_sched_op), - _a1 (SCHEDOP_shutdown | (SHUTDOWN_suspend << SCHEDOP_reasonshift)), - "S" (srec) : "memory" ); - - return ret; -} - -#ifdef __i386__ -static __inline__ long HYPERVISOR_set_timer_op( u64 timeout ) + : "=a" (ret), "=b" (ign1), "=S" (ign2) + : "0" (__HYPERVISOR_sched_op), + "b" (SCHEDOP_shutdown | (SHUTDOWN_suspend << SCHEDOP_reasonshift)), + "S" (srec) : "memory", "ecx"); + + return ret; +} + +static inline int +HYPERVISOR_crash( + void) +{ + int ret; + unsigned long ign1; + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1) + : "0" (__HYPERVISOR_sched_op), + "1" (SCHEDOP_shutdown | (SHUTDOWN_crash << SCHEDOP_reasonshift)) + : "memory", "ecx" ); + + return ret; +} + +static inline long +HYPERVISOR_set_timer_op( + u64 timeout) { int ret; unsigned long timeout_hi = (unsigned long)(timeout>>32); @@ -262,8 +271,516 @@ return ret; } + +#if 0 +static inline int +HYPERVISOR_dom0_op( + dom0_op_t *dom0_op) +{ + int ret; + unsigned long ign1; + + dom0_op->interface_version = DOM0_INTERFACE_VERSION; + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1) + : "0" (__HYPERVISOR_dom0_op), "1" (dom0_op) + : "memory"); + + return ret; +} +#endif + +static inline int +HYPERVISOR_set_debugreg( + int reg, unsigned long value) +{ + int ret; + unsigned long ign1, ign2; + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1), "=c" (ign2) + : "0" (__HYPERVISOR_set_debugreg), "1" (reg), "2" (value) + : "memory" ); + + return ret; +} + +static inline unsigned long +HYPERVISOR_get_debugreg( + int reg) +{ + unsigned long ret; + unsigned long ign; + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign) + : "0" (__HYPERVISOR_get_debugreg), "1" (reg) + : "memory" ); + + return ret; +} + +static inline int +HYPERVISOR_update_descriptor( + u64 ma, u64 desc) +{ + int ret; + unsigned long ign1, ign2, ign3, ign4; + + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4) + : "0" (__HYPERVISOR_update_descriptor), + "1" ((unsigned long)ma), "2" ((unsigned long)(ma>>32)), + "3" ((unsigned long)desc), "4" ((unsigned long)(desc>>32)) + : "memory" ); + + return ret; +} + +static inline int +HYPERVISOR_dom_mem_op( + unsigned int op, unsigned long *extent_list, + unsigned long nr_extents, unsigned int extent_order) +{ + int ret; + unsigned long ign1, ign2, ign3, ign4, ign5; + + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4), + "=D" (ign5) + : "0" (__HYPERVISOR_dom_mem_op), "1" (op), "2" (extent_list), + "3" (nr_extents), "4" (extent_order), "5" (DOMID_SELF) + : "memory" ); + + return ret; +} + +static inline int +HYPERVISOR_multicall( + void *call_list, int nr_calls) +{ + int ret; + unsigned long ign1, ign2; + + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1), "=c" (ign2) + : "0" (__HYPERVISOR_multicall), "1" (call_list), "2" (nr_calls) + : "memory" ); + + return ret; +} + +static inline int +HYPERVISOR_update_va_mapping( + unsigned long va, pte_t new_val, unsigned long flags) +{ + int ret; + unsigned long ign1, ign2, ign3, ign4; + + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4) + : "0" (__HYPERVISOR_update_va_mapping), + "1" (va), "2" ((new_val).pte_low), +#ifdef CONFIG_X86_PAE + "3" ((new_val).pte_high), #else -static __inline__ long HYPERVISOR_set_timer_op( u64 timeout ) + "3" (0), +#endif + "4" (flags) + : "memory" ); + + return ret; +} + +static inline int +HYPERVISOR_event_channel_op( + void *op) +{ + int ret; + unsigned long ignore; + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ignore) + : "0" (__HYPERVISOR_event_channel_op), "1" (op) + : "memory" ); + + return ret; +} + +static inline int +HYPERVISOR_xen_version( + int cmd) +{ + int ret; + unsigned long ignore; + + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ignore) + : "0" (__HYPERVISOR_xen_version), "1" (cmd) + : "memory" ); + + return ret; +} + +static inline int +HYPERVISOR_console_io( + int cmd, int count, char *str) +{ + int ret; + unsigned long ign1, ign2, ign3; + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3) + : "0" (__HYPERVISOR_console_io), "1" (cmd), "2" (count), "3" (str) + : "memory" ); + + return ret; +} + +static inline int +HYPERVISOR_physdev_op( + void *physdev_op) +{ + int ret; + unsigned long ign; + + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign) + : "0" (__HYPERVISOR_physdev_op), "1" (physdev_op) + : "memory" ); + + return ret; +} + +static inline int +HYPERVISOR_grant_table_op( + unsigned int cmd, void *uop, unsigned int count) +{ + int ret; + unsigned long ign1, ign2, ign3; + + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3) + : "0" (__HYPERVISOR_grant_table_op), "1" (cmd), "2" (uop), "3" (count) + : "memory" ); + + return ret; +} + +static inline int +HYPERVISOR_update_va_mapping_otherdomain( + unsigned long va, pte_t new_val, unsigned long flags, domid_t domid) +{ + int ret; + unsigned long ign1, ign2, ign3, ign4, ign5; + + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), + "=S" (ign4), "=D" (ign5) + : "0" (__HYPERVISOR_update_va_mapping_otherdomain), + "1" (va), "2" ((new_val).pte_low), +#ifdef CONFIG_X86_PAE + "3" ((new_val).pte_high), +#else + "3" (0), +#endif + "4" (flags), "5" (domid) : + "memory" ); + + return ret; +} + +static inline int +HYPERVISOR_vm_assist( + unsigned int cmd, unsigned int type) +{ + int ret; + unsigned long ign1, ign2; + + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1), "=c" (ign2) + : "0" (__HYPERVISOR_vm_assist), "1" (cmd), "2" (type) + : "memory" ); + + return ret; +} + +static inline int +HYPERVISOR_boot_vcpu( + unsigned long vcpu, vcpu_guest_context_t *ctxt) +{ + int ret; + unsigned long ign1, ign2; + + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1), "=c" (ign2) + : "0" (__HYPERVISOR_boot_vcpu), "1" (vcpu), "2" (ctxt) + : "memory"); + + return ret; +} + +static inline int +HYPERVISOR_vcpu_down( + int vcpu) +{ + int ret; + unsigned long ign1; + /* Yes, I really do want to clobber edx here: when we resume a + vcpu after unpickling a multi-processor domain, it returns + here, but clobbers all of the call clobbered registers. */ + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1) + : "0" (__HYPERVISOR_sched_op), + "1" (SCHEDOP_vcpu_down | (vcpu << SCHEDOP_vcpushift)) + : "memory", "ecx", "edx" ); + + return ret; +} + +static inline int +HYPERVISOR_vcpu_up( + int vcpu) +{ + int ret; + unsigned long ign1; + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1) + : "0" (__HYPERVISOR_sched_op), + "1" (SCHEDOP_vcpu_up | (vcpu << SCHEDOP_vcpushift)) + : "memory", "ecx" ); + + return ret; +} + +static inline int +HYPERVISOR_vcpu_pickle( + int vcpu, vcpu_guest_context_t *ctxt) +{ + int ret; + unsigned long ign1, ign2; + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1), "=c" (ign2) + : "0" (__HYPERVISOR_sched_op), + "1" (SCHEDOP_vcpu_pickle | (vcpu << SCHEDOP_vcpushift)), + "2" (ctxt) + : "memory" ); + + return ret; +} +#elif defined(__x86_64__) + +#define __syscall_clobber "r11","rcx","memory" + +/* + * Assembler stubs for hyper-calls. + */ +static inline int +HYPERVISOR_set_trap_table( + trap_info_t *table) +{ + int ret; + + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret) + : "0" ((unsigned long)__HYPERVISOR_set_trap_table), "D" (table) + : __syscall_clobber ); + + return ret; +} + +static inline int +HYPERVISOR_mmu_update( + mmu_update_t *req, int count, int *success_count, domid_t domid) +{ + int ret; + + __asm__ __volatile__ ( + "movq %5, %%r10;" TRAP_INSTR + : "=a" (ret) + : "0" ((unsigned long)__HYPERVISOR_mmu_update), "D" (req), "S" ((long)count), + "d" (success_count), "g" ((unsigned long)domid) + : __syscall_clobber, "r10" ); + + return ret; +} + +static inline int +HYPERVISOR_mmuext_op( + struct mmuext_op *op, int count, int *success_count, domid_t domid) +{ + int ret; + + __asm__ __volatile__ ( + "movq %5, %%r10;" TRAP_INSTR + : "=a" (ret) + : "0" (__HYPERVISOR_mmuext_op), "D" (op), "S" ((long)count), + "d" (success_count), "g" ((unsigned long)domid) + : __syscall_clobber, "r10" ); + + return ret; +} + +static inline int +HYPERVISOR_set_gdt( + unsigned long *frame_list, int entries) +{ + int ret; + + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret) + : "0" ((unsigned long)__HYPERVISOR_set_gdt), "D" (frame_list), "S" ((long)entries) + : __syscall_clobber ); + + + return ret; +} +static inline int +HYPERVISOR_stack_switch( + unsigned long ss, unsigned long esp) +{ + int ret; + + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret) + : "0" ((unsigned long)__HYPERVISOR_stack_switch), "D" (ss), "S" (esp) + : __syscall_clobber ); + + return ret; +} + +static inline int +HYPERVISOR_set_callbacks( + unsigned long event_address, unsigned long failsafe_address, + unsigned long syscall_address) +{ + int ret; + + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret) + : "0" ((unsigned long)__HYPERVISOR_set_callbacks), "D" (event_address), + "S" (failsafe_address), "d" (syscall_address) + : __syscall_clobber ); + + return ret; +} + +static inline int +HYPERVISOR_fpu_taskswitch( + int set) +{ + int ret; + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret) : "0" ((unsigned long)__HYPERVISOR_fpu_taskswitch), + "D" ((unsigned long) set) : __syscall_clobber ); + + return ret; +} + +static inline int +HYPERVISOR_yield( + void) +{ + int ret; + + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret) + : "0" ((unsigned long)__HYPERVISOR_sched_op), "D" ((unsigned long)SCHEDOP_yield) + : __syscall_clobber ); + + return ret; +} + +static inline int +HYPERVISOR_block( + void) +{ + int ret; + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret) + : "0" ((unsigned long)__HYPERVISOR_sched_op), "D" ((unsigned long)SCHEDOP_block) + : __syscall_clobber ); + + return ret; +} + +static inline int +HYPERVISOR_shutdown( + void) +{ + int ret; + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret) + : "0" ((unsigned long)__HYPERVISOR_sched_op), + "D" ((unsigned long)(SCHEDOP_shutdown | (SHUTDOWN_poweroff << SCHEDOP_reasonshift))) + : __syscall_clobber ); + + return ret; +} + +static inline int +HYPERVISOR_reboot( + void) +{ + int ret; + + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret) + : "0" ((unsigned long)__HYPERVISOR_sched_op), + "D" ((unsigned long)(SCHEDOP_shutdown | (SHUTDOWN_reboot << SCHEDOP_reasonshift))) + : __syscall_clobber ); + + return ret; +} + +static inline int +HYPERVISOR_suspend( + unsigned long srec) +{ + int ret; + + /* NB. On suspend, control software expects a suspend record in %esi. */ + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret) + : "0" ((unsigned long)__HYPERVISOR_sched_op), + "D" ((unsigned long)(SCHEDOP_shutdown | (SHUTDOWN_suspend << SCHEDOP_reasonshift))), + "S" (srec) + : __syscall_clobber ); + + return ret; +} + +/* + * We can have the timeout value in a single argument for the hypercall, but + * that will break the common code. + */ +static inline long +HYPERVISOR_set_timer_op( + u64 timeout) { int ret; diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/include/lib.h --- a/extras/mini-os/include/lib.h Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/include/lib.h Fri Sep 9 09:24:25 2005 @@ -60,10 +60,22 @@ /* printing */ #define printk printf #define kprintf printf -int printf(const char *fmt, ...); -int vprintf(const char *fmt, va_list ap); -int sprintf(char *buf, const char *cfmt, ...); -int vsprintf(char *buf, const char *cfmt, va_list ap); +#define _p(_x) ((void *)(unsigned long)(_x)) +void printf(const char *fmt, ...); +int vsnprintf(char *buf, size_t size, const char *fmt, va_list args); +int vscnprintf(char *buf, size_t size, const char *fmt, va_list args); +int snprintf(char * buf, size_t size, const char *fmt, ...); +int scnprintf(char * buf, size_t size, const char *fmt, ...); +int vsprintf(char *buf, const char *fmt, va_list args); +int sprintf(char * buf, const char *fmt, ...); +int vsscanf(const char * buf, const char * fmt, va_list args); +int sscanf(const char * buf, const char * fmt, ...); + +long simple_strtol(const char *cp,char **endp,unsigned int base); +unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base); +long long simple_strtoll(const char *cp,char **endp,unsigned int base); +unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base); + /* string and memory manipulation */ int memcmp(const void *cs, const void *ct, size_t count); @@ -77,6 +89,16 @@ size_t strlen(const char *s); char *strchr(const char *s, int c); char *strstr(const char *s1, const char *s2); +char * strcat(char * dest, const char * src); + + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +struct kvec { + void *iov_base; + size_t iov_len; +}; + #endif /* _LIB_H_ */ diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/include/mm.h --- a/extras/mini-os/include/mm.h Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/include/mm.h Fri Sep 9 09:24:25 2005 @@ -24,6 +24,15 @@ #ifndef _MM_H_ #define _MM_H_ + +#ifdef __i386__ +#include <xen/arch-x86_32.h> +#endif + +#ifdef __x86_64__ +#include <xen/arch-x86_64.h> +#endif + #ifdef __x86_64__ @@ -56,6 +65,8 @@ #define L1_PAGETABLE_ENTRIES 1024 #define L2_PAGETABLE_ENTRIES 1024 + +#elif defined(__x86_64__) #endif /* Given a virtual address, get an entry offset into a page table. */ @@ -97,13 +108,15 @@ extern unsigned long *phys_to_machine_mapping; #define pfn_to_mfn(_pfn) (phys_to_machine_mapping[(_pfn)]) -#define mfn_to_pfn(_mfn) (machine_to_phys_mapping[(_mfn)]) static __inline__ unsigned long phys_to_machine(unsigned long phys) { unsigned long machine = pfn_to_mfn(phys >> L1_PAGETABLE_SHIFT); machine = (machine << L1_PAGETABLE_SHIFT) | (phys & ~PAGE_MASK); return machine; } + + +#define mfn_to_pfn(_mfn) (machine_to_phys_mapping[(_mfn)]) static __inline__ unsigned long machine_to_phys(unsigned long machine) { unsigned long phys = mfn_to_pfn(machine >> L1_PAGETABLE_SHIFT); @@ -119,16 +132,15 @@ #define to_phys(x) ((unsigned long)(x)-VIRT_START) #define to_virt(x) ((void *)((unsigned long)(x)+VIRT_START)) -#define __va to_virt -#define __pa to_phys #define virt_to_pfn(_virt) (PFN_DOWN(to_phys(_virt))) +#define mach_to_virt(_mach) (to_virt(machine_to_phys(_mach))) +#define mfn_to_virt(_mfn) (mach_to_virt(_mfn << PAGE_SHIFT)) void init_mm(void); unsigned long alloc_pages(int order); #define alloc_page() alloc_pages(0); void free_pages(void *pointer, int order); -//int is_mfn_mapped(unsigned long mfn); static __inline__ int get_order(unsigned long size) { diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/include/os.h --- a/extras/mini-os/include/os.h Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/include/os.h Fri Sep 9 09:24:25 2005 @@ -15,15 +15,16 @@ #define unlikely(x) __builtin_expect((x),0) #define smp_processor_id() 0 -#define preempt_disable() ((void)0) -#define preempt_enable() ((void)0) - -#define force_evtchn_callback() ((void)HYPERVISOR_xen_version(0)) + #ifndef __ASSEMBLY__ #include <types.h> +#include <hypervisor.h> #endif #include <xen/xen.h> + + +#define force_evtchn_callback() ((void)HYPERVISOR_xen_version(0)) #define __KERNEL_CS FLAT_KERNEL_CS #define __KERNEL_DS FLAT_KERNEL_DS @@ -54,8 +55,6 @@ /* Everything below this point is not included by assembler (.S) files. */ #ifndef __ASSEMBLY__ -#define pt_regs xen_regs - void trap_init(void); /* @@ -69,10 +68,8 @@ #define __cli() \ do { \ vcpu_info_t *_vcpu; \ - preempt_disable(); \ _vcpu = &HYPERVISOR_shared_info->vcpu_data[smp_processor_id()]; \ _vcpu->evtchn_upcall_mask = 1; \ - preempt_enable_no_resched(); \ barrier(); \ } while (0) @@ -80,13 +77,11 @@ do { \ vcpu_info_t *_vcpu; \ barrier(); \ - preempt_disable(); \ _vcpu = &HYPERVISOR_shared_info->vcpu_data[smp_processor_id()]; \ _vcpu->evtchn_upcall_mask = 0; \ barrier(); /* unmask then check (avoid races) */ \ if ( unlikely(_vcpu->evtchn_upcall_pending) ) \ force_evtchn_callback(); \ - preempt_enable(); \ } while (0) #define __save_flags(x) \ @@ -100,15 +95,12 @@ do { \ vcpu_info_t *_vcpu; \ barrier(); \ - preempt_disable(); \ _vcpu = &HYPERVISOR_shared_info->vcpu_data[smp_processor_id()]; \ if ((_vcpu->evtchn_upcall_mask = (x)) == 0) { \ barrier(); /* unmask then check (avoid races) */ \ if ( unlikely(_vcpu->evtchn_upcall_pending) ) \ force_evtchn_callback(); \ - preempt_enable(); \ - } else \ - preempt_enable_no_resched(); \ + }\ } while (0) #define safe_halt() ((void)0) @@ -116,11 +108,9 @@ #define __save_and_cli(x) \ do { \ vcpu_info_t *_vcpu; \ - preempt_disable(); \ _vcpu = &HYPERVISOR_shared_info->vcpu_data[smp_processor_id()]; \ (x) = _vcpu->evtchn_upcall_mask; \ _vcpu->evtchn_upcall_mask = 1; \ - preempt_enable_no_resched(); \ barrier(); \ } while (0) @@ -135,6 +125,15 @@ /* This is a barrier for the compiler only, NOT the processor! */ #define barrier() __asm__ __volatile__("": : :"memory") + +#if defined(__i386__) +#define mb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory") +#define rmb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory") +#elif defined(__x86_64__) +#define mb() __asm__ __volatile__ ("mfence":::"memory") +#define rmb() __asm__ __volatile__ ("lfence":::"memory") +#endif + #define LOCK_PREFIX "" #define LOCK "" @@ -147,69 +146,71 @@ typedef struct { volatile int counter; } atomic_t; -#define xchg(ptr,v) \ - ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr)))) +/************************** i386 *******************************/ +#if defined (__i386__) + +#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr)))) struct __xchg_dummy { unsigned long a[100]; }; -#define __xg(x) ((volatile 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; +#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 + * @nr: Bit to clear * @addr: Address to count from * - * This operation is atomic and cannot be reordered. + * This operation is atomic and cannot be reordered. + * It can be reorderdered on other architectures other than x86. * 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; +static inline int test_and_clear_bit(int nr, volatile unsigned long * addr) +{ + int oldbit; + + __asm__ __volatile__( LOCK + "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 unsigned long *addr) +{ + return ((1UL << (nr & 31)) & (addr[nr >> 5])) != 0; +} + +static inline int variable_test_bit(int nr, const volatile unsigned long * 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) \ @@ -217,6 +218,152 @@ 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: there are no guarantees that this function will not be reordered + * on non x86 architectures, so if you are writting portable code, + * make sure not to rely on its reordering 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 unsigned long * addr) +{ + __asm__ __volatile__( LOCK + "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 unsigned long * addr) +{ + __asm__ __volatile__( LOCK + "btrl %1,%0" + :"=m" (ADDR) + :"Ir" (nr)); +} + +/** + * __ffs - find first bit in word. + * @word: The word to search + * + * Undefined if no bit exists, so code should check against 0 first. + */ +static inline unsigned long __ffs(unsigned long word) +{ + __asm__("bsfl %1,%0" + :"=r" (word) + :"rm" (word)); + return word; +} + + +/* + * These have to be done with inline assembly: that way the bit-setting + * is guaranteed to be atomic. All bit operations return 0 if the bit + * was cleared before the operation and != 0 if it was not. + * + * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). + */ +#define ADDR (*(volatile long *) addr) + +#define rdtscll(val) \ + __asm__ __volatile__("rdtsc" : "=A" (val)) + + + +#elif defined(__x86_64__)/* ifdef __i386__ */ +/************************** x86_84 *******************************/ + +#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr)))) +#define __xg(x) ((volatile long *)(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 %k0,%1" + :"=r" (x) + :"m" (*__xg(ptr)), "0" (x) + :"memory"); + break; + case 8: + __asm__ __volatile__("xchgq %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 clear + * @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) + :"dIr" (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 const void * addr) +{ + int oldbit; + + __asm__ __volatile__( + "btl %2,%1\n\tsbbl %0,%0" + :"=r" (oldbit) + :"m" (ADDR),"dIr" (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 @@ -230,10 +377,10 @@ */ static __inline__ void set_bit(int nr, volatile void * addr) { - __asm__ __volatile__( LOCK_PREFIX - "btsl %1,%0" - :"=m" (ADDR) - :"Ir" (nr)); + __asm__ __volatile__( LOCK_PREFIX + "btsl %1,%0" + :"=m" (ADDR) + :"dIr" (nr) : "memory"); } /** @@ -248,40 +395,43 @@ */ 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)); -} - - -#define rdtscll(val) \ - __asm__ __volatile__("rdtsc" : "=A" (val)) - + __asm__ __volatile__( LOCK_PREFIX + "btrl %1,%0" + :"=m" (ADDR) + :"dIr" (nr)); +} + +/** + * __ffs - find first bit in word. + * @word: The word to search + * + * Undefined if no bit exists, so code should check against 0 first. + */ static __inline__ unsigned long __ffs(unsigned long word) { - __asm__("bsfl %1,%0" - :"=r" (word) - :"rm" (word)); - return word; + __asm__("bsfq %1,%0" + :"=r" (word) + :"rm" (word)); + return word; } #define ADDR (*(volatile long *) addr) + +#define rdtscll(val) do { \ + unsigned int __a,__d; \ + asm volatile("rdtsc" : "=a" (__a), "=d" (__d)); \ + (val) = ((unsigned long)__a) | (((unsigned long)__d)<<32); \ +} while(0) + + +#else /* ifdef __x86_64__ */ +#error "Unsupported architecture" +#endif + + +/********************* common i386 and x86_64 ****************************/ + + static __inline__ void synch_set_bit(int nr, volatile void * addr) { @@ -306,6 +456,14 @@ return oldbit; } +static __inline__ int synch_test_and_clear_bit(int nr, volatile void * addr) +{ + int oldbit; + __asm__ __volatile__ ( + "lock btrl %2,%1\n\tsbbl %0,%0" + : "=r" (oldbit), "=m" (ADDR) : "Ir" (nr) : "memory"); + return oldbit; +} static __inline__ int synch_const_test_bit(int nr, const volatile void * addr) { @@ -326,9 +484,8 @@ (__builtin_constant_p(nr) ? \ synch_const_test_bit((nr),(addr)) : \ synch_var_test_bit((nr),(addr))) -#endif /* !__ASSEMBLY__ */ - -#define rdtsc(low,high) \ - __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high)) - + + + +#endif /* not assembly */ #endif /* _OS_H_ */ diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/include/time.h --- a/extras/mini-os/include/time.h Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/include/time.h Fri Sep 9 09:24:25 2005 @@ -58,6 +58,6 @@ s_time_t get_s_time(void); s_time_t get_v_time(void); void gettimeofday(struct timeval *tv); -void block(u32 millisecs); +void block_domain(u32 millisecs); #endif /* _TIME_H_ */ diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/include/traps.h --- a/extras/mini-os/include/traps.h Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/include/traps.h Fri Sep 9 09:24:25 2005 @@ -17,6 +17,7 @@ #ifndef _TRAPS_H_ #define _TRAPS_H_ +#ifdef __i386__ struct pt_regs { long ebx; long ecx; @@ -34,7 +35,38 @@ long esp; int xss; }; +#elif __x86_64__ +struct pt_regs { + unsigned long r15; + unsigned long r14; + unsigned long r13; + unsigned long r12; + unsigned long rbp; + unsigned long rbx; +/* arguments: non interrupts/non tracing syscalls only save upto here*/ + unsigned long r11; + unsigned long r10; + unsigned long r9; + unsigned long r8; + unsigned long rax; + unsigned long rcx; + unsigned long rdx; + unsigned long rsi; + unsigned long rdi; + unsigned long orig_rax; +/* end of arguments */ +/* cpu exception frame or undefined */ + unsigned long rip; + unsigned long cs; + unsigned long eflags; + unsigned long rsp; + unsigned long ss; +/* top of stack page */ +}; + + +#endif void dump_regs(struct pt_regs *regs); diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/include/types.h --- a/extras/mini-os/include/types.h Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/include/types.h Fri Sep 9 09:24:25 2005 @@ -44,11 +44,19 @@ typedef long long quad_t; typedef unsigned long long u_quad_t; typedef unsigned int uintptr_t; + +typedef struct { unsigned long pte_low; } pte_t; #elif defined(__x86_64__) typedef long quad_t; typedef unsigned long u_quad_t; typedef unsigned long uintptr_t; + +typedef struct { unsigned long pte; } pte_t; #endif + + + +#define INT_MAX ((int)(~0U>>1)) #define UINT_MAX (~0U) #endif /* _TYPES_H_ */ diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/kernel.c --- a/extras/mini-os/kernel.c Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/kernel.c Fri Sep 9 09:24:25 2005 @@ -33,6 +33,8 @@ #include <time.h> #include <types.h> #include <lib.h> +#include <sched.h> +#include <xenbus.h> /* * Shared page for communicating with the hypervisor. @@ -59,10 +61,12 @@ extern char shared_info[PAGE_SIZE]; +#define __pte(x) ((pte_t) { (0) } ) + static shared_info_t *map_shared_info(unsigned long pa) { if ( HYPERVISOR_update_va_mapping( - (unsigned long)shared_info, pa | 7, UVMF_INVLPG) ) + (unsigned long)shared_info, __pte(pa | 7), UVMF_INVLPG) ) { printk("Failed to map shared_info!!\n"); *(int*)0=0; @@ -77,7 +81,6 @@ void start_kernel(start_info_t *si) { static char hello[] = "Bootstrapping...\n"; - int i; (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(hello), hello); /* Copy the start_info struct to a globally-accessible area. */ @@ -96,7 +99,6 @@ (unsigned long)hypervisor_callback, (unsigned long)failsafe_callback, 0); #endif - trap_init(); /* ENABLE EVENT DELIVERY. This is disabled at start of day. */ @@ -119,7 +121,6 @@ * If used for porting another OS, start here to figure out your * guest os entry point. Otherwise continue below... */ - /* init memory management */ init_mm(); @@ -127,15 +128,15 @@ init_events(); /* init time and timers */ init_time(); + + /* init scheduler */ + init_sched(); - /* do nothing */ - i = 0; - for ( ; ; ) - { -// HYPERVISOR_yield(); - block(100); - i++; - } + /* init xenbus */ + xs_init(); + + /* Everything initialised, start idle thread */ + run_idle_thread(); } diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/lib/printf.c --- a/extras/mini-os/lib/printf.c Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/lib/printf.c Fri Sep 9 09:24:25 2005 @@ -1,20 +1,18 @@ -/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*- +/* **************************************************************************** * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge **************************************************************************** * * File: printf.c * Author: Rolf Neugebauer (neugebar@xxxxxxxxxxxxx) - * Changes: + * Changes: Grzegorz Milos (gm281@xxxxxxxxx) * - * Date: Aug 2003 + * Date: Aug 2003, Aug 2005 * * Environment: Xen Minimal OS * Description: Library functions for printing * (freebsd port, mainly sys/subr_prf.c) * - **************************************************************************** - * $Id: c-insert.c,v 1.7 2002/11/08 16:04:34 rn Exp $ **************************************************************************** * *- @@ -60,409 +58,748 @@ #include <types.h> #include <hypervisor.h> #include <lib.h> - -/**************************************************************************** - * RN: printf family of routines - * taken mainly from sys/subr_prf.c - ****************************************************************************/ -char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz"; -#define hex2ascii(hex) (hex2ascii_data[hex]) -#define NBBY 8 /* number of bits in a byte */ -#define MAXNBUF (sizeof(quad_t) * NBBY + 1) - -static int kvprintf(char const *fmt, void *arg, int radix, va_list ap); - - -int -printf(const char *fmt, ...) -{ - va_list ap; - int retval; - static char printk_buf[1024]; - - va_start(ap, fmt); - retval = kvprintf(fmt, printk_buf, 10, ap); - printk_buf[retval] = '\0'; - va_end(ap); - (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(printk_buf), - printk_buf); - return retval; -} - -int -vprintf(const char *fmt, va_list ap) -{ - int retval; - static char printk_buf[1024]; - retval = kvprintf(fmt, printk_buf, 10, ap); - printk_buf[retval] = '\0'; - (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(printk_buf), - printk_buf); - return retval; -} - -int -sprintf(char *buf, const char *cfmt, ...) -{ - int retval; - va_list ap; - - va_start(ap, cfmt); - retval = kvprintf(cfmt, (void *)buf, 10, ap); - buf[retval] = '\0'; - va_end(ap); - return retval; -} - -int -vsprintf(char *buf, const char *cfmt, va_list ap) -{ - int retval; - - retval = kvprintf(cfmt, (void *)buf, 10, ap); - buf[retval] = '\0'; - return retval; -} - - -/* - * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse - * order; return an optional length and a pointer to the last character - * written in the buffer (i.e., the first character of the string). - * The buffer pointed to by `nbuf' must have length >= MAXNBUF. - */ -static char * -ksprintn(char *nbuf, u_long ul, int base, int *lenp) -{ - char *p; - - p = nbuf; - *p = '\0'; - do { - *++p = hex2ascii(ul % base); - } while (ul /= base); - if (lenp) - *lenp = p - nbuf; - return (p); -} -/* ksprintn, but for a quad_t. */ -static char * -ksprintqn(char *nbuf, u_quad_t uq, int base, int *lenp) -{ - char *p; - - p = nbuf; - *p = '\0'; - do { - *++p = hex2ascii(uq % base); - } while (uq /= base); - if (lenp) - *lenp = p - nbuf; - return (p); -} - -/* - * Scaled down version of printf(3). +#include <mm.h> +#include <ctype.h> + +/** + * simple_strtoul - convert a string to an unsigned long + * @cp: The start of the string + * @endp: A pointer to the end of the parsed string will be placed here + * @base: The number base to use + */ +unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) +{ + unsigned long result = 0,value; + + if (!base) { + base = 10; + if (*cp == '0') { + base = 8; + cp++; + if ((*cp == 'x') && isxdigit(cp[1])) { + cp++; + base = 16; + } + } + } + while (isxdigit(*cp) && + (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) { + result = result*base + value; + cp++; + } + if (endp) + *endp = (char *)cp; + return result; +} + +/** + * simple_strtol - convert a string to a signed long + * @cp: The start of the string + * @endp: A pointer to the end of the parsed string will be placed here + * @base: The number base to use + */ +long simple_strtol(const char *cp,char **endp,unsigned int base) +{ + if(*cp=='-') + return -simple_strtoul(cp+1,endp,base); + return simple_strtoul(cp,endp,base); +} + +/** + * simple_strtoull - convert a string to an unsigned long long + * @cp: The start of the string + * @endp: A pointer to the end of the parsed string will be placed here + * @base: The number base to use + */ +unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base) +{ + unsigned long long result = 0,value; + + if (!base) { + base = 10; + if (*cp == '0') { + base = 8; + cp++; + if ((*cp == 'x') && isxdigit(cp[1])) { + cp++; + base = 16; + } + } + } + while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) + ? toupper(*cp) : *cp)-'A'+10) < base) { + result = result*base + value; + cp++; + } + if (endp) + *endp = (char *)cp; + return result; +} + +/** + * simple_strtoll - convert a string to a signed long long + * @cp: The start of the string + * @endp: A pointer to the end of the parsed string will be placed here + * @base: The number base to use + */ +long long simple_strtoll(const char *cp,char **endp,unsigned int base) +{ + if(*cp=='-') + return -simple_strtoull(cp+1,endp,base); + return simple_strtoull(cp,endp,base); +} + +static int skip_atoi(const char **s) +{ + int i=0; + + while (isdigit(**s)) + i = i*10 + *((*s)++) - '0'; + return i; +} + +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SPECIAL 32 /* 0x */ +#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ + +static char * number(char * buf, char * end, long long num, int base, int size, int precision, int type) +{ + char c,sign,tmp[66]; + const char *digits; + const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + int i; + + digits = (type & LARGE) ? large_digits : small_digits; + if (type & LEFT) + type &= ~ZEROPAD; + if (base < 2 || base > 36) + return buf; + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) { + if (num < 0) { + sign = '-'; + num = -num; + size--; + } else if (type & PLUS) { + sign = '+'; + size--; + } else if (type & SPACE) { + sign = ' '; + size--; + } + } + if (type & SPECIAL) { + if (base == 16) + size -= 2; + else if (base == 8) + size--; + } + i = 0; + if (num == 0) + tmp[i++]='0'; + else + { + /* XXX KAF: force unsigned mod and div. */ + unsigned long long num2=(unsigned long long)num; + unsigned int base2=(unsigned int)base; + while (num2 != 0) { tmp[i++] = digits[num2%base2]; num2 /= base2; } + } + if (i > precision) + precision = i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) { + while(size-->0) { + if (buf <= end) + *buf = ' '; + ++buf; + } + } + if (sign) { + if (buf <= end) + *buf = sign; + ++buf; + } + if (type & SPECIAL) { + if (base==8) { + if (buf <= end) + *buf = '0'; + ++buf; + } else if (base==16) { + if (buf <= end) + *buf = '0'; + ++buf; + if (buf <= end) + *buf = digits[33]; + ++buf; + } + } + if (!(type & LEFT)) { + while (size-- > 0) { + if (buf <= end) + *buf = c; + ++buf; + } + } + while (i < precision--) { + if (buf <= end) + *buf = '0'; + ++buf; + } + while (i-- > 0) { + if (buf <= end) + *buf = tmp[i]; + ++buf; + } + while (size-- > 0) { + if (buf <= end) + *buf = ' '; + ++buf; + } + return buf; +} + +/** +* vsnprintf - Format a string and place it in a buffer +* @buf: The buffer to place the result into +* @size: The size of the buffer, including the trailing null space +* @fmt: The format string to use +* @args: Arguments for the format string +* +* Call this function if you are already dealing with a va_list. +* You probably want snprintf instead. + */ +int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) +{ + int len; + unsigned long long num; + int i, base; + char *str, *end, c; + const char *s; + + int flags; /* flags to number() */ + + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + int qualifier; /* 'h', 'l', or 'L' for integer fields */ + /* 'z' support added 23/7/1999 S.H. */ + /* 'z' changed to 'Z' --davidm 1/25/99 */ + + str = buf; + end = buf + size - 1; + + if (end < buf - 1) { + end = ((void *) -1); + size = end - buf + 1; + } + + for (; *fmt ; ++fmt) { + if (*fmt != '%') { + if (str <= end) + *str = *fmt; + ++str; + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case '-': flags |= LEFT; goto repeat; + case '+': flags |= PLUS; goto repeat; + case ' ': flags |= SPACE; goto repeat; + case '#': flags |= SPECIAL; goto repeat; + case '0': flags |= ZEROPAD; goto repeat; + } + + /* get field width */ + field_width = -1; + if (isdigit(*fmt)) + field_width = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + field_width = va_arg(args, int); + if (field_width < 0) { + field_width = -field_width; + flags |= LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == '.') { + ++fmt; + if (isdigit(*fmt)) + precision = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + precision = va_arg(args, int); + } + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + qualifier = -1; + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') { + qualifier = *fmt; + ++fmt; + if (qualifier == 'l' && *fmt == 'l') { + qualifier = 'L'; + ++fmt; + } + } + if (*fmt == 'q') { + qualifier = 'L'; + ++fmt; + } + + /* default base */ + base = 10; + + switch (*fmt) { + case 'c': + if (!(flags & LEFT)) { + while (--field_width > 0) { + if (str <= end) + *str = ' '; + ++str; + } + } + c = (unsigned char) va_arg(args, int); + if (str <= end) + *str = c; + ++str; + while (--field_width > 0) { + if (str <= end) + *str = ' '; + ++str; + } + continue; + + case 's': + s = va_arg(args, char *); + if (!s) + s = "<NULL>"; + + len = strnlen(s, precision); + + if (!(flags & LEFT)) { + while (len < field_width--) { + if (str <= end) + *str = ' '; + ++str; + } + } + for (i = 0; i < len; ++i) { + if (str <= end) + *str = *s; + ++str; ++s; + } + while (len < field_width--) { + if (str <= end) + *str = ' '; + ++str; + } + continue; + + case 'p': + if (field_width == -1) { + field_width = 2*sizeof(void *); + flags |= ZEROPAD; + } + str = number(str, end, + (unsigned long) va_arg(args, void *), + 16, field_width, precision, flags); + continue; + + + case 'n': + /* FIXME: + * What does C99 say about the overflow case here? */ + if (qualifier == 'l') { + long * ip = va_arg(args, long *); + *ip = (str - buf); + } else if (qualifier == 'Z') { + size_t * ip = va_arg(args, size_t *); + *ip = (str - buf); + } else { + int * ip = va_arg(args, int *); + *ip = (str - buf); + } + continue; + + case '%': + if (str <= end) + *str = '%'; + ++str; + continue; + + /* integer number formats - set up the flags and "break" */ + case 'o': + base = 8; + break; + + case 'X': + flags |= LARGE; + case 'x': + base = 16; + break; + + case 'd': + case 'i': + flags |= SIGN; + case 'u': + break; + + default: + if (str <= end) + *str = '%'; + ++str; + if (*fmt) { + if (str <= end) + *str = *fmt; + ++str; + } else { + --fmt; + } + continue; + } + if (qualifier == 'L') + num = va_arg(args, long long); + else if (qualifier == 'l') { + num = va_arg(args, unsigned long); + if (flags & SIGN) + num = (signed long) num; + } else if (qualifier == 'Z') { + num = va_arg(args, size_t); + } else if (qualifier == 'h') { + num = (unsigned short) va_arg(args, int); + if (flags & SIGN) + num = (signed short) num; + } else { + num = va_arg(args, unsigned int); + if (flags & SIGN) + num = (signed int) num; + } + + str = number(str, end, num, base, + field_width, precision, flags); + } + if (str <= end) + *str = '\0'; + else if (size > 0) + /* don't write out a null byte if the buf size is zero */ + *end = '\0'; + /* the trailing null byte doesn't count towards the total + * ++str; + */ + return str-buf; +} + +/** + * snprintf - Format a string and place it in a buffer + * @buf: The buffer to place the result into + * @size: The size of the buffer, including the trailing null space + * @fmt: The format string to use + * @...: Arguments for the format string + */ +int snprintf(char * buf, size_t size, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i=vsnprintf(buf,size,fmt,args); + va_end(args); + return i; +} + +/** + * vsprintf - Format a string and place it in a buffer + * @buf: The buffer to place the result into + * @fmt: The format string to use + * @args: Arguments for the format string * - * Two additional formats: - * - * The format %b is supported to decode error registers. - * Its usage is: - * - * printf("reg=%b\n", regval, "<base><arg>*"); - * - * where <base> is the output base expressed as a control character, e.g. - * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, - * the first of which gives the bit number to be inspected (origin 1), and - * the next characters (up to a control character, i.e. a character <= 32), - * give the name of the register. Thus: - * - * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); - * - * would produce output: - * - * reg=3<BITTWO,BITONE> - * - * XXX: %D -- Hexdump, takes pointer and separator string: - * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX - * ("%*D", len, ptr, " " -> XX XX XX XX ... - */ - -/* RN: This normally takes a function for output. - * we always print to a string and the use HYPERCALL for write to console */ -static int -kvprintf(char const *fmt, void *arg, int radix, va_list ap) -{ - -#define PCHAR(c) {int cc=(c); *d++ = cc; retval++; } - - char nbuf[MAXNBUF]; - char *p, *q, *d; - u_char *up; - int ch, n; - u_long ul; - u_quad_t uq; - int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; - int dwidth; - char padc; - int retval = 0; - - ul = 0; - uq = 0; - d = (char *) arg; - - if (fmt == NULL) - fmt = "(fmt null)\n"; - - if (radix < 2 || radix > 36) - radix = 10; - - for (;;) { - padc = ' '; - width = 0; - while ((ch = (u_char)*fmt++) != '%') { - if (ch == '\0') - return retval; - PCHAR(ch); - } - qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; - sign = 0; dot = 0; dwidth = 0; -reswitch: switch (ch = (u_char)*fmt++) { - case '.': - dot = 1; - goto reswitch; - case '#': - sharpflag = 1; - goto reswitch; - case '+': - sign = 1; - goto reswitch; - case '-': - ladjust = 1; - goto reswitch; - case '%': - PCHAR(ch); - break; - case '*': - if (!dot) { - width = va_arg(ap, int); - if (width < 0) { - ladjust = !ladjust; - width = -width; + * Call this function if you are already dealing with a va_list. + * You probably want sprintf instead. + */ +int vsprintf(char *buf, const char *fmt, va_list args) +{ + return vsnprintf(buf, 0xFFFFFFFFUL, fmt, args); +} + + +/** + * sprintf - Format a string and place it in a buffer + * @buf: The buffer to place the result into + * @fmt: The format string to use + * @...: Arguments for the format string + */ +int sprintf(char * buf, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i=vsprintf(buf,fmt,args); + va_end(args); + return i; +} + + +void printf(const char *fmt, ...) +{ + static char buf[1024]; + va_list args; + + va_start(args, fmt); + (void)vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(buf), buf); +} + +/** + * vsscanf - Unformat a buffer into a list of arguments + * @buf: input buffer + * @fmt: format of buffer + * @args: arguments + */ +int vsscanf(const char * buf, const char * fmt, va_list args) +{ + const char *str = buf; + char *next; + char digit; + int num = 0; + int qualifier; + int base; + int field_width; + int is_sign = 0; + + while(*fmt && *str) { + /* skip any white space in format */ + /* white space in format matchs any amount of + * white space, including none, in the input. + */ + if (isspace(*fmt)) { + while (isspace(*fmt)) + ++fmt; + while (isspace(*str)) + ++str; + } + + /* anything that is not a conversion must match exactly */ + if (*fmt != '%' && *fmt) { + if (*fmt++ != *str++) + break; + continue; + } + + if (!*fmt) + break; + ++fmt; + + /* skip this conversion. + * advance both strings to next white space + */ + if (*fmt == '*') { + while (!isspace(*fmt) && *fmt) + fmt++; + while (!isspace(*str) && *str) + str++; + continue; + } + + /* get field width */ + field_width = -1; + if (isdigit(*fmt)) + field_width = skip_atoi(&fmt); + + /* get conversion qualifier */ + qualifier = -1; + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || + *fmt == 'Z' || *fmt == 'z') { + qualifier = *fmt++; + if (unlikely(qualifier == *fmt)) { + if (qualifier == 'h') { + qualifier = 'H'; + fmt++; + } else if (qualifier == 'l') { + qualifier = 'L'; + fmt++; } - } else { - dwidth = va_arg(ap, int); } - goto reswitch; - case '0': - if (!dot) { - padc = '0'; - goto reswitch; + } + base = 10; + is_sign = 0; + + if (!*fmt || !*str) + break; + + switch(*fmt++) { + case 'c': + { + char *s = (char *) va_arg(args,char*); + if (field_width == -1) + field_width = 1; + do { + *s++ = *str++; + } while (--field_width > 0 && *str); + num++; + } + continue; + case 's': + { + char *s = (char *) va_arg(args, char *); + if(field_width == -1) + field_width = INT_MAX; + /* first, skip leading white space in buffer */ + while (isspace(*str)) + str++; + + /* now copy until next white space */ + while (*str && !isspace(*str) && field_width--) { + *s++ = *str++; } - case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - for (n = 0;; ++fmt) { - n = n * 10 + ch - '0'; - ch = *fmt; - if (ch < '0' || ch > '9') - break; - } - if (dot) - dwidth = n; - else - width = n; - goto reswitch; - case 'b': - ul = va_arg(ap, int); - p = va_arg(ap, char *); - for (q = ksprintn(nbuf, ul, *p++, NULL); *q;) - PCHAR(*q--); - - if (!ul) - break; - - for (tmp = 0; *p;) { - n = *p++; - if (ul & (1 << (n - 1))) { - PCHAR(tmp ? ',' : '<'); - for (; (n = *p) > ' '; ++p) - PCHAR(n); - tmp = 1; - } else - for (; *p > ' '; ++p) - continue; - } - if (tmp) - PCHAR('>'); - break; - case 'c': - PCHAR(va_arg(ap, int)); - break; - case 'D': - up = va_arg(ap, u_char *); - p = va_arg(ap, char *); - if (!width) - width = 16; - while(width--) { - PCHAR(hex2ascii(*up >> 4)); - PCHAR(hex2ascii(*up & 0x0f)); - up++; - if (width) - for (q=p;*q;q++) - PCHAR(*q); - } - break; - case 'd': - if (qflag) - uq = va_arg(ap, quad_t); - else if (lflag) - ul = va_arg(ap, long); - else - ul = va_arg(ap, int); - sign = 1; - base = 10; - goto number; - case 'l': - if (lflag) { - lflag = 0; - qflag = 1; - } else - lflag = 1; - goto reswitch; + *s = '\0'; + num++; + } + continue; + case 'n': + /* return number of characters read so far */ + { + int *i = (int *)va_arg(args,int*); + *i = str - buf; + } + continue; case 'o': - if (qflag) - uq = va_arg(ap, u_quad_t); - else if (lflag) - ul = va_arg(ap, u_long); - else - ul = va_arg(ap, u_int); base = 8; - goto nosign; - case 'p': - ul = (uintptr_t)va_arg(ap, void *); - base = 16; - sharpflag = 0; - padc = '0'; - width = sizeof(uintptr_t)*2; - goto nosign; - case 'q': - qflag = 1; - goto reswitch; - case 'n': - case 'r': - if (qflag) - uq = va_arg(ap, u_quad_t); - else if (lflag) - ul = va_arg(ap, u_long); - else - ul = sign ? - (u_long)va_arg(ap, int) : va_arg(ap, u_int); - base = radix; - goto number; - case 's': - p = va_arg(ap, char *); - if (p == NULL) - p = "(null)"; - if (!dot) - n = strlen (p); - else - for (n = 0; n < dwidth && p[n]; n++) - continue; - - width -= n; - - if (!ladjust && width > 0) - while (width--) - PCHAR(padc); - while (n--) - PCHAR(*p++); - if (ladjust && width > 0) - while (width--) - PCHAR(padc); - break; - case 'u': - if (qflag) - uq = va_arg(ap, u_quad_t); - else if (lflag) - ul = va_arg(ap, u_long); - else - ul = va_arg(ap, u_int); - base = 10; - goto nosign; + break; case 'x': case 'X': - if (qflag) - uq = va_arg(ap, u_quad_t); - else if (lflag) - ul = va_arg(ap, u_long); - else - ul = va_arg(ap, u_int); base = 16; - goto nosign; + break; + case 'i': + base = 0; + case 'd': + is_sign = 1; + case 'u': + break; + case '%': + /* looking for '%' in str */ + if (*str++ != '%') + return num; + continue; + default: + /* invalid format; stop here */ + return num; + } + + /* have some sort of integer conversion. + * first, skip white space in buffer. + */ + while (isspace(*str)) + str++; + + digit = *str; + if (is_sign && digit == '-') + digit = *(str + 1); + + if (!digit + || (base == 16 && !isxdigit(digit)) + || (base == 10 && !isdigit(digit)) + || (base == 8 && (!isdigit(digit) || digit > '7')) + || (base == 0 && !isdigit(digit))) + break; + + switch(qualifier) { + case 'H': /* that's 'hh' in format */ + if (is_sign) { + signed char *s = (signed char *) va_arg(args,signed char *); + *s = (signed char) simple_strtol(str,&next,base); + } else { + unsigned char *s = (unsigned char *) va_arg(args, unsigned char *); + *s = (unsigned char) simple_strtoul(str, &next, base); + } + break; + case 'h': + if (is_sign) { + short *s = (short *) va_arg(args,short *); + *s = (short) simple_strtol(str,&next,base); + } else { + unsigned short *s = (unsigned short *) va_arg(args, unsigned short *); + *s = (unsigned short) simple_strtoul(str, &next, base); + } + break; + case 'l': + if (is_sign) { + long *l = (long *) va_arg(args,long *); + *l = simple_strtol(str,&next,base); + } else { + unsigned long *l = (unsigned long*) va_arg(args,unsigned long*); + *l = simple_strtoul(str,&next,base); + } + break; + case 'L': + if (is_sign) { + long long *l = (long long*) va_arg(args,long long *); + *l = simple_strtoll(str,&next,base); + } else { + unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*); + *l = simple_strtoull(str,&next,base); + } + break; + case 'Z': case 'z': - if (qflag) - uq = va_arg(ap, u_quad_t); - else if (lflag) - ul = va_arg(ap, u_long); - else - ul = sign ? - (u_long)va_arg(ap, int) : va_arg(ap, u_int); - base = 16; - goto number; -nosign: sign = 0; -number: - if (qflag) { - if (sign && (quad_t)uq < 0) { - neg = 1; - uq = -(quad_t)uq; - } - p = ksprintqn(nbuf, uq, base, &tmp); + { + size_t *s = (size_t*) va_arg(args,size_t*); + *s = (size_t) simple_strtoul(str,&next,base); + } + break; + default: + if (is_sign) { + int *i = (int *) va_arg(args, int*); + *i = (int) simple_strtol(str,&next,base); } else { - if (sign && (long)ul < 0) { - neg = 1; - ul = -(long)ul; - } - p = ksprintn(nbuf, ul, base, &tmp); + unsigned int *i = (unsigned int*) va_arg(args, unsigned int*); + *i = (unsigned int) simple_strtoul(str,&next,base); } - if (sharpflag && (qflag ? uq != 0 : ul != 0)) { - if (base == 8) - tmp++; - else if (base == 16) - tmp += 2; - } - if (neg) - tmp++; - - if (!ladjust && width && (width -= tmp) > 0) - while (width--) - PCHAR(padc); - if (neg) - PCHAR('-'); - if (sharpflag && (qflag ? uq != 0 : ul != 0)) { - if (base == 8) { - PCHAR('0'); - } else if (base == 16) { - PCHAR('0'); - PCHAR('x'); - } - } - - while (*p) - PCHAR(*p--); - - if (ladjust && width && (width -= tmp) > 0) - while (width--) - PCHAR(padc); - - break; - default: - PCHAR('%'); - if (lflag) - PCHAR('l'); - PCHAR(ch); - break; - } + break; + } + num++; + + if (!next) + break; + str = next; } -#undef PCHAR -} - + return num; +} + +/** + * sscanf - Unformat a buffer into a list of arguments + * @buf: input buffer + * @fmt: formatting of buffer + * @...: resulting arguments + */ +int sscanf(const char * buf, const char * fmt, ...) +{ + va_list args; + int i; + + va_start(args,fmt); + i = vsscanf(buf,fmt,args); + va_end(args); + return i; +} + + diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/lib/string.c --- a/extras/mini-os/lib/string.c Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/lib/string.c Fri Sep 9 09:24:25 2005 @@ -107,6 +107,19 @@ return sc - s; } + +char * strcat(char * dest, const char * src) +{ + char *tmp = dest; + + while (*dest) + dest++; + + while ((*dest++ = *src++) != '\0'); + + return tmp; +} + size_t strlen(const char * s) { const char *sc; diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/mm.c --- a/extras/mini-os/mm.c Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/mm.c Fri Sep 9 09:24:25 2005 @@ -198,7 +198,6 @@ #endif - /* * Initialise allocator, placing addresses [@min,@max] in free pool. * @min and @max are PHYSICAL addresses. @@ -486,16 +485,17 @@ phys_to_machine_mapping = (unsigned long *)start_info.mfn_list; /* First page follows page table pages and 3 more pages (store page etc) */ - start_pfn = PFN_UP(__pa(start_info.pt_base)) + start_info.nr_pt_frames + 3; + start_pfn = PFN_UP(to_phys(start_info.pt_base)) + start_info.nr_pt_frames + 3; max_pfn = start_info.nr_pages; printk(" start_pfn: %lx\n", start_pfn); printk(" max_pfn: %lx\n", max_pfn); +#ifdef __i386__ build_pagetable(&start_pfn, &max_pfn); - -#ifdef __i386__ +#endif + /* * now we can initialise the page allocator */ @@ -503,7 +503,5 @@ (u_long)to_virt(PFN_PHYS(start_pfn)), PFN_PHYS(start_pfn), (u_long)to_virt(PFN_PHYS(max_pfn)), PFN_PHYS(max_pfn)); init_page_allocator(PFN_PHYS(start_pfn), PFN_PHYS(max_pfn)); -#endif - printk("MM: done\n"); } diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/time.c --- a/extras/mini-os/time.c Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/time.c Fri Sep 9 09:24:25 2005 @@ -203,7 +203,7 @@ } -void block(u32 millisecs) +void block_domain(u32 millisecs) { struct timeval tv; gettimeofday(&tv); @@ -232,5 +232,6 @@ void init_time(void) { + printk("Initialising timer interface\n"); bind_virq(VIRQ_TIMER, &timer_handler); } diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/traps.c --- a/extras/mini-os/traps.c Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/traps.c Fri Sep 9 09:24:25 2005 @@ -33,36 +33,7 @@ void dump_regs(struct pt_regs *regs) { - unsigned long esp; - unsigned short ss; - -#ifdef __x86_64__ - esp = regs->rsp; - ss = regs->xss; -#else - esp = (unsigned long) (®s->esp); - ss = __KERNEL_DS; - if (regs->xcs & 2) { -printk("CS is true, esp is %x\n", regs->esp); - esp = regs->esp; - ss = regs->xss & 0xffff; - } -#endif - printf("EIP: %04x:[<%p>]\n", - 0xffff & regs->xcs , regs->eip); - printf("EFLAGS: %p\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); -#ifdef __x86_64__ - printf("r8 : %p r9 : %p r10: %p r11: %p\n", - regs->r8, regs->r9, regs->r10, regs->r11); - printf("r12: %p r13: %p r14: %p r15: %p\n", - regs->r12, regs->r13, regs->r14, regs->r15); -#endif - printf("ds: %04x es: %04x ss: %04x\n", - regs->xds & 0xffff, regs->xes & 0xffff, ss); + printk("FIXME: proper register dump (with the stack dump)\n"); } @@ -105,6 +76,7 @@ printk("Page fault at linear address %p\n", addr); dump_regs(regs); #ifdef __x86_64__ + /* FIXME: _PAGE_PSE */ { unsigned long *tab = (unsigned long *)start_info.pt_base; unsigned long page; @@ -112,23 +84,16 @@ printk("Pagetable walk from %p:\n", tab); page = tab[l4_table_offset(addr)]; - tab = __va(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT); + tab = to_virt(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT); printk(" L4 = %p (%p)\n", page, tab); - if ( !(page & AGERESENT) ) - goto out; page = tab[l3_table_offset(addr)]; - tab = __va(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT); + tab = to_virt(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT); printk(" L3 = %p (%p)\n", page, tab); - if ( !(page & AGERESENT) ) - goto out; page = tab[l2_table_offset(addr)]; - tab = __va(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT); - printk(" L2 = %p (%p) %s\n", page, tab, - (page & AGESE) ? "(2MB)" : ""); - if ( !(page & AGERESENT) || (page & AGESE) ) - goto out; + tab = to_virt(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT); + printk(" L2 = %p (%p)\n", page, tab); page = tab[l1_table_offset(addr)]; printk(" L1 = %p\n", page); diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/include/ctype.h --- /dev/null Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/include/ctype.h Fri Sep 9 09:24:25 2005 @@ -0,0 +1,79 @@ +#ifndef _CTYPE_H +#define _CTYPE_H + +/* + * NOTE! This ctype does not handle EOF like the standard C + * library is required to. + */ + +#define _U 0x01 /* upper */ +#define _L 0x02 /* lower */ +#define _D 0x04 /* digit */ +#define _C 0x08 /* cntrl */ +#define _P 0x10 /* punct */ +#define _S 0x20 /* white space (space/lf/tab) */ +#define _X 0x40 /* hex digit */ +#define _SP 0x80 /* hard space (0x20) */ + + +unsigned char _ctype[] = { +_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ +_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ +_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ +_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ +_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ +_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ +_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ +_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ +_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ +_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ +_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ +_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ +_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ +_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ +_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ +_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */ +_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */ +_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */ +_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */ +_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */ +_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */ +_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */ + +#define __ismask(x) (_ctype[(int)(unsigned char)(x)]) + +#define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0) +#define isalpha(c) ((__ismask(c)&(_U|_L)) != 0) +#define iscntrl(c) ((__ismask(c)&(_C)) != 0) +#define isdigit(c) ((__ismask(c)&(_D)) != 0) +#define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0) +#define islower(c) ((__ismask(c)&(_L)) != 0) +#define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0) +#define ispunct(c) ((__ismask(c)&(_P)) != 0) +#define isspace(c) ((__ismask(c)&(_S)) != 0) +#define isupper(c) ((__ismask(c)&(_U)) != 0) +#define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0) + +#define isascii(c) (((unsigned char)(c))<=0x7f) +#define toascii(c) (((unsigned char)(c))&0x7f) + +static inline unsigned char __tolower(unsigned char c) +{ + if (isupper(c)) + c -= 'A'-'a'; + return c; +} + +static inline unsigned char __toupper(unsigned char c) +{ + if (islower(c)) + c -= 'a'-'A'; + return c; +} + +#define tolower(c) __tolower(c) +#define toupper(c) __toupper(c) + +#endif diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/include/err.h --- /dev/null Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/include/err.h Fri Sep 9 09:24:25 2005 @@ -0,0 +1,31 @@ +#ifndef _ERR_H +#define _ERR_H + +#include <errno.h> + +/* + * Kernel pointers have redundant information, so we can use a + * scheme where we can return either an error code or a dentry + * pointer with the same return value. + * + * This should be a per-architecture thing, to allow different + * error and pointer decisions. + */ +#define IS_ERR_VALUE(x) ((x) > (unsigned long)-1000L) + +static inline void *ERR_PTR(long error) +{ + return (void *) error; +} + +static inline long PTR_ERR(const void *ptr) +{ + return (long) ptr; +} + +static inline long IS_ERR(const void *ptr) +{ + return IS_ERR_VALUE((unsigned long)ptr); +} + +#endif /* _LINUX_ERR_H */ diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/include/errno-base.h --- /dev/null Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/include/errno-base.h Fri Sep 9 09:24:25 2005 @@ -0,0 +1,39 @@ +#ifndef _ERRNO_BASE_H +#define _ERRNO_BASE_H + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Argument list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ + +#endif diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/include/errno.h --- /dev/null Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/include/errno.h Fri Sep 9 09:24:25 2005 @@ -0,0 +1,109 @@ +#ifndef _ERRNO_H +#define _ERRNO_H + +#include <errno-base.h> + +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ +#define ECANCELED 125 /* Operation Canceled */ +#define ENOKEY 126 /* Required key not available */ +#define EKEYEXPIRED 127 /* Key has expired */ +#define EKEYREVOKED 128 /* Key has been revoked */ +#define EKEYREJECTED 129 /* Key was rejected by service */ + +/* for robust mutexes */ +#define EOWNERDEAD 130 /* Owner died */ +#define ENOTRECOVERABLE 131 /* State not recoverable */ + +#endif diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/include/fcntl.h --- /dev/null Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/include/fcntl.h Fri Sep 9 09:24:25 2005 @@ -0,0 +1,89 @@ +#ifndef _I386_FCNTL_H +#define _I386_FCNTL_H + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define FASYNC 020000 /* fcntl, for BSD compatibility */ +#define O_DIRECT 040000 /* direct disk access hint */ +#define O_LARGEFILE 0100000 +#define O_DIRECTORY 0200000 /* must be a directory */ +#define O_NOFOLLOW 0400000 /* don't follow links */ +#define O_NOATIME 01000000 + +#define F_DUPFD 0 /* dup */ +#define F_GETFD 1 /* get close_on_exec */ +#define F_SETFD 2 /* set/clear close_on_exec */ +#define F_GETFL 3 /* get file->f_flags */ +#define F_SETFL 4 /* set file->f_flags */ +#define F_GETLK 5 +#define F_SETLK 6 +#define F_SETLKW 7 + +#define F_SETOWN 8 /* for sockets. */ +#define F_GETOWN 9 /* for sockets. */ +#define F_SETSIG 10 /* for sockets. */ +#define F_GETSIG 11 /* for sockets. */ + +#define F_GETLK64 12 /* using 'struct flock64' */ +#define F_SETLK64 13 +#define F_SETLKW64 14 + +/* for F_[GET|SET]FL */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* for posix fcntl() and lockf() */ +#define F_RDLCK 0 +#define F_WRLCK 1 +#define F_UNLCK 2 + +/* for old implementation of bsd flock () */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +/* for leases */ +#define F_INPROGRESS 16 + +/* operations for bsd flock(), also used by the kernel implementation */ +#define LOCK_SH 1 /* shared lock */ +#define LOCK_EX 2 /* exclusive lock */ +#define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +#define LOCK_UN 8 /* remove lock */ + +#define LOCK_MAND 32 /* This is a mandatory flock */ +#define LOCK_READ 64 /* ... Which allows concurrent read operations */ +#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */ +#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */ + +/* +struct flock { + short l_type; + short l_whence; + off_t l_start; + off_t l_len; + pid_t l_pid; +}; + +struct flock64 { + short l_type; + short l_whence; + loff_t l_start; + loff_t l_len; + pid_t l_pid; +}; + +#define F_LINUX_SPECIFIC_BASE 1024 +*/ +#endif diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/include/sched.h --- /dev/null Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/include/sched.h Fri Sep 9 09:24:25 2005 @@ -0,0 +1,38 @@ +#ifndef __SCHED_H__ +#define __SCHED_H__ + +#include <list.h> + +struct thread +{ + char *name; + char *stack; + unsigned long eps; + unsigned long eip; + struct list_head thread_list; + u32 flags; +}; + + + +void init_sched(void); +void run_idle_thread(void); +struct thread* create_thread(char *name, void (*function)(void *), void *data); +void schedule(void); + +static inline struct thread* get_current(void) +{ + struct thread **current; +#ifdef __i386__ + __asm__("andl %%esp,%0; ":"=r" (current) : "r" (~8191UL)); +#endif + return *current; +} + +#define current get_current() + + +void wake(struct thread *thread); +void block(struct thread *thread); + +#endif /* __SCHED_H__ */ diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/include/semaphore.h --- /dev/null Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/include/semaphore.h Fri Sep 9 09:24:25 2005 @@ -0,0 +1,46 @@ +#ifndef _SEMAPHORE_H_ +#define _SEMAPHORE_H_ + +#include <wait.h> + +/* + * Implementation of semaphore in Mini-os is simple, because + * there are no preemptive threads, the atomicity is guaranteed. + */ + +struct semaphore +{ + int count; + struct wait_queue_head wait; +}; + + +#define __SEMAPHORE_INITIALIZER(name, n) \ +{ \ + .count = n, \ + .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ +} + +#define __MUTEX_INITIALIZER(name) \ + __SEMAPHORE_INITIALIZER(name,1) + +#define __DECLARE_SEMAPHORE_GENERIC(name,count) \ + struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) + +#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1) + +#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0) + +static void inline down(struct semaphore *sem) +{ + wait_event(sem->wait, sem->count > 0); + sem->count--; +} + +static void inline up(struct semaphore *sem) +{ + sem->count++; + wake_up(&sem->wait); +} + +#endif /* _SEMAPHORE_H */ diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/include/wait.h --- /dev/null Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/include/wait.h Fri Sep 9 09:24:25 2005 @@ -0,0 +1,91 @@ +#ifndef __WAIT_H__ +#define __WAIT_H__ + +#include <sched.h> +#include <list.h> +#include <lib.h> +#include <os.h> + +struct wait_queue +{ + struct thread *thread; + struct list_head thread_list; +}; + +struct wait_queue_head +{ + /* TODO - lock required? */ + struct list_head thread_list; +}; + +#define DECLARE_WAIT_QUEUE_HEAD(name) \ + struct wait_queue_head name = \ + { .thread_list = { &(name).thread_list, &(name).thread_list} } + +#define __WAIT_QUEUE_HEAD_INITIALIZER(name) { \ + .thread_list = { &(name).thread_list, &(name).thread_list } } + + +#define DEFINE_WAIT(name) \ +struct wait_queue name = { \ + .thread = current, \ + .thread_list = LIST_HEAD_INIT((name).thread_list), \ +} + + + +static inline void init_waitqueue_entry(struct wait_queue *q, struct thread *thread) +{ + q->thread = thread; +} + + +static inline void add_wait_queue(struct wait_queue_head *h, struct wait_queue *q) +{ + if (list_empty(&q->thread_list)) + list_add(&q->thread_list, &h->thread_list); +} + +static inline void remove_wait_queue(struct wait_queue *q) +{ + list_del(&q->thread_list); +} + +static inline void wake_up(struct wait_queue_head *head) +{ + struct list_head *tmp, *next; + list_for_each_safe(tmp, next, &head->thread_list) + { + struct wait_queue *curr; + curr = list_entry(tmp, struct wait_queue, thread_list); + wake(curr->thread); + } +} + +#define wait_event(wq, condition) do{ \ + unsigned long flags; \ + if(condition) \ + break; \ + DEFINE_WAIT(__wait); \ + for(;;) \ + { \ + /* protect the list */ \ + local_irq_save(flags); \ + add_wait_queue(&wq, &__wait); \ + block(current); \ + local_irq_restore(flags); \ + if(condition) \ + break; \ + schedule(); \ + } \ + local_irq_save(flags); \ + /* need to wake up */ \ + wake(current); \ + remove_wait_queue(&__wait); \ + local_irq_restore(flags); \ +} while(0) + + + + +#endif /* __WAIT_H__ */ diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/include/xenbus.h --- /dev/null Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/include/xenbus.h Fri Sep 9 09:24:25 2005 @@ -0,0 +1,89 @@ +/****************************************************************************** + * xenbus.h + * + * Talks to Xen Store to figure out what devices we have. + * + * Copyright (C) 2005 Rusty Russell, IBM Corporation + * + * This file may be distributed separately from the Linux kernel, or + * incorporated into other software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef _ASM_XEN_XENBUS_H +#define _ASM_XEN_XENBUS_H + + +/* Caller must hold this lock to call these functions: it's also held + * across watch callbacks. */ +// TODO +//extern struct semaphore xenbus_lock; + +char **xenbus_directory(const char *dir, const char *node, unsigned int *num); +void *xenbus_read(const char *dir, const char *node, unsigned int *len); +int xenbus_write(const char *dir, const char *node, + const char *string, int createflags); +int xenbus_mkdir(const char *dir, const char *node); +int xenbus_exists(const char *dir, const char *node); +int xenbus_rm(const char *dir, const char *node); +int xenbus_transaction_start(const char *subtree); +int xenbus_transaction_end(int abort); + +/* Single read and scanf: returns -errno or num scanned if > 0. */ +int xenbus_scanf(const char *dir, const char *node, const char *fmt, ...) + __attribute__((format(scanf, 3, 4))); + +/* Single printf and write: returns -errno or 0. */ +int xenbus_printf(const char *dir, const char *node, const char *fmt, ...) + __attribute__((format(printf, 3, 4))); + +/* Generic read function: NULL-terminated triples of name, + * sprintf-style type string, and pointer. Returns 0 or errno.*/ +int xenbus_gather(const char *dir, ...); + +/* Register callback to watch this node. */ +struct xenbus_watch +{ + struct list_head list; + char *node; + void (*callback)(struct xenbus_watch *, const char *node); +}; + +int register_xenbus_watch(struct xenbus_watch *watch); +void unregister_xenbus_watch(struct xenbus_watch *watch); +void reregister_xenbus_watches(void); + +/* Called from xen core code. */ +void xenbus_suspend(void); +void xenbus_resume(void); + +#define XENBUS_IS_ERR_READ(str) ({ \ + if (!IS_ERR(str) && strlen(str) == 0) { \ + kfree(str); \ + str = ERR_PTR(-ERANGE); \ + } \ + IS_ERR(str); \ +}) + +#define XENBUS_EXIST_ERR(err) ((err) == -ENOENT || (err) == -ERANGE) + +int xs_init(void); + +#endif /* _ASM_XEN_XENBUS_H */ diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/sched.c --- /dev/null Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/sched.c Fri Sep 9 09:24:25 2005 @@ -0,0 +1,300 @@ +/* + **************************************************************************** + * (C) 2005 - Grzegorz Milos - Intel Research Cambridge + **************************************************************************** + * + * File: sched.c + * Author: Grzegorz Milos + * Changes: + * + * Date: Aug 2005 + * + * Environment: Xen Minimal OS + * Description: simple scheduler for Mini-Os + * + * The scheduler is non-preemptive (cooperative), and schedules according + * to Round Robin algorithm. + * + **************************************************************************** + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <os.h> +#include <hypervisor.h> +#include <time.h> +#include <mm.h> +#include <types.h> +#include <lib.h> +#include <xmalloc.h> +#include <list.h> +#include <sched.h> +#include <semaphore.h> + +#ifdef SCHED_DEBUG +#define DEBUG(_f, _a...) \ + printk("MINI_OS(file=sched.c, line=%d) " _f "\n", __LINE__, ## _a) +#else +#define DEBUG(_f, _a...) ((void)0) +#endif + + +#define RUNNABLE_FLAG 0x00000001 + +#define is_runnable(_thread) (_thread->flags & RUNNABLE_FLAG) +#define set_runnable(_thread) (_thread->flags |= RUNNABLE_FLAG) +#define clear_runnable(_thread) (_thread->flags &= ~RUNNABLE_FLAG) + + +struct thread *idle_thread; +LIST_HEAD(exited_threads); + +void dump_stack(struct thread *thread) +{ + unsigned long *bottom = (unsigned long *)thread->stack + 2048; + unsigned long *pointer = (unsigned long *)thread->eps; + int count; + printk("The stack for \"%s\"\n", thread->name); + for(count = 0; count < 15 && pointer < bottom; count ++) + { + printk("[0x%lx] 0x%lx\n", pointer, *pointer); + pointer++; + } + + if(pointer < bottom) printk("Not the whole stack printed\n"); +} + +#ifdef __i386__ +#define switch_threads(prev, next) do { \ + unsigned long esi,edi; \ + __asm__ __volatile__("pushfl\n\t" \ + "pushl %%ebp\n\t" \ + "movl %%esp,%0\n\t" /* save ESP */ \ + "movl %4,%%esp\n\t" /* restore ESP */ \ + "movl $1f,%1\n\t" /* save EIP */ \ + "pushl %5\n\t" /* restore EIP */ \ + "ret\n\t" \ + "1:\t" \ + "popl %%ebp\n\t" \ + "popfl" \ + :"=m" (prev->eps),"=m" (prev->eip), \ + "=S" (esi),"=D" (edi) \ + :"m" (next->eps),"m" (next->eip), \ + "2" (prev), "d" (next)); \ +} while (0) +#elif __x86_64__ +/* FIXME */ +#endif + +void inline print_runqueue(void) +{ + struct list_head *it; + struct thread *th; + list_for_each(it, &idle_thread->thread_list) + { + th = list_entry(it, struct thread, thread_list); + printk(" Thread \"%s\", runnable=%d\n", th->name, is_runnable(th)); + } + printk("\n"); +} + + +void schedule(void) +{ + struct thread *prev, *next, *thread; + struct list_head *iterator; + unsigned long flags; + prev = current; + local_irq_save(flags); + list_for_each(iterator, &exited_threads) + { + thread = list_entry(iterator, struct thread, thread_list); + if(thread != prev) + { + list_del(&thread->thread_list); + free_pages(thread->stack, 1); + xfree(thread); + } + } + next = idle_thread; + /* Thread list needs to be protected */ + list_for_each(iterator, &idle_thread->thread_list) + { + thread = list_entry(iterator, struct thread, thread_list); + if(is_runnable(thread)) + { + next = thread; + /* Put this thread on the end of the list */ + list_del(&thread->thread_list); + list_add_tail(&thread->thread_list, &idle_thread->thread_list); + break; + } + } + 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) +{ + unsigned long flags; + printk("Thread \"%s\" exited.\n", thread->name); + local_irq_save(flags); + /* Remove from the thread list */ + list_del(&thread->thread_list); + clear_runnable(thread); + /* Put onto exited list */ + list_add(&thread->thread_list, &exited_threads); + local_irq_restore(flags); + /* Schedule will free the resources */ + schedule(); +} + + +struct thread* create_thread(char *name, void (*function)(void *), void *data) +{ + struct thread *thread; + unsigned long flags; + + thread = xmalloc(struct thread); + /* Allocate 2 pages for stack, stack will be 2pages aligned */ + thread->stack = (char *)alloc_pages(1); + thread->name = name; + printk("Thread \"%s\": pointer: 0x%lx, stack: 0x%lx\n", name, thread, + thread->stack); + + thread->eps = (unsigned long)thread->stack + 4096 * 2 - 4; + /* 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; + + /* 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); + local_irq_restore(flags); + + return thread; +} + + +void block(struct thread *thread) +{ + clear_runnable(thread); +} + +void wake(struct thread *thread) +{ + set_runnable(thread); +} + +void idle_thread_fn(void *unused) +{ + for(;;) + { + schedule(); + printk("Blocking the domain\n"); + block_domain(10000); + } +} + +void run_idle_thread(void) +{ + /* Switch stacks and run the thread */ + __asm__ __volatile__("mov %0,%%esp\n\t" + "push %1\n\t" + "ret" + :"=m" (idle_thread->eps) + :"m" (idle_thread->eip)); +} + + + +DECLARE_MUTEX(mutex); + +void th_f1(void *data) +{ + struct timeval tv1, tv2; + + for(;;) + { + down(&mutex); + printk("Thread \"%s\" got semaphore, runnable %d\n", current->name, is_runnable(current)); + schedule(); + printk("Thread \"%s\" releases the semaphore\n", current->name); + up(&mutex); + + + gettimeofday(&tv1); + for(;;) + { + gettimeofday(&tv2); + if(tv2.tv_sec - tv1.tv_sec > 2) break; + } + + + schedule(); + } +} + +void th_f2(void *data) +{ + for(;;) + { + printk("Thread OTHER executing, data 0x%lx\n", data); + schedule(); + } +} + + + +void init_sched(void) +{ + printk("Initialising scheduler\n"); + + idle_thread = create_thread("Idle", idle_thread_fn, NULL); + INIT_LIST_HEAD(&idle_thread->thread_list); + + +/* create_thread("1", th_f1, (void *)0x1234); + create_thread("2", th_f1, (void *)0x1234); + create_thread("3", th_f1, (void *)0x1234); + create_thread("4", th_f1, (void *)0x1234); + create_thread("5", th_f1, (void *)0x1234); + create_thread("6", th_f1, (void *)0x1234); + create_thread("second", th_f2, NULL); +*/ +} + diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/xenbus/Makefile --- /dev/null Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/xenbus/Makefile Fri Sep 9 09:24:25 2005 @@ -0,0 +1,9 @@ +all: xenstore.h xenbus_comms.o xenbus_xs.o xenbus_probe.o + +xenstore.h: + [ -e xenstored.h ] || ln -sf ../../../tools/xenstore/xenstored.h xenstored.h + +clean: + #Taken care of by main Makefile + #rm xenstored.h + #rm *.o diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/xenbus/xenbus_comms.c --- /dev/null Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/xenbus/xenbus_comms.c Fri Sep 9 09:24:25 2005 @@ -0,0 +1,231 @@ +/****************************************************************************** + * xenbus_comms.c + * + * Low level code to talks to Xen Store: ringbuffer and event channel. + * + * Copyright (C) 2005 Rusty Russell, IBM Corporation + * + * This file may be distributed separately from the Linux kernel, or + * incorporated into other software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +#include <types.h> +#include <wait.h> +#include <mm.h> +#include <hypervisor.h> +#include <events.h> +#include <os.h> +#include <lib.h> + + +#ifdef XENBUS_COMMS_DEBUG +#define DEBUG(_f, _a...) \ + printk("MINI_OS(file=xenbus_comms.c, line=%d) " _f "\n", __LINE__, ## _a) +#else +#define DEBUG(_f, _a...) ((void)0) +#endif + + +#define RINGBUF_DATASIZE ((PAGE_SIZE / 2) - sizeof(struct ringbuf_head)) +struct ringbuf_head +{ + u32 write; /* Next place to write to */ + u32 read; /* Next place to read from */ + u8 flags; + char buf[0]; +} __attribute__((packed)); + +DECLARE_WAIT_QUEUE_HEAD(xb_waitq); + +static inline struct ringbuf_head *outbuf(void) +{ + return mfn_to_virt(start_info.store_mfn); +} + +static inline struct ringbuf_head *inbuf(void) +{ + return (struct ringbuf_head *)((char *)mfn_to_virt(start_info.store_mfn) + PAGE_SIZE/2); +} + +static void wake_waiting(int port, struct pt_regs *regs) +{ + wake_up(&xb_waitq); +} + +static int check_buffer(const struct ringbuf_head *h) +{ + return (h->write < RINGBUF_DATASIZE && h->read < RINGBUF_DATASIZE); +} + +/* We can't fill last byte: would look like empty buffer. */ +static void *get_output_chunk(const struct ringbuf_head *h, + void *buf, u32 *len) +{ + u32 read_mark; + + if (h->read == 0) + read_mark = RINGBUF_DATASIZE - 1; + else + read_mark = h->read - 1; + + /* Here to the end of buffer, unless they haven't read some out. */ + *len = RINGBUF_DATASIZE - h->write; + if (read_mark >= h->write) + *len = read_mark - h->write; + return (void *)((char *)buf + h->write); +} + +static const void *get_input_chunk(const struct ringbuf_head *h, + const void *buf, u32 *len) +{ + /* Here to the end of buffer, unless they haven't written some. */ + *len = RINGBUF_DATASIZE - h->read; + if (h->write >= h->read) + *len = h->write - h->read; + return (void *)((char *)buf + h->read); +} + +static void update_output_chunk(struct ringbuf_head *h, u32 len) +{ + h->write += len; + if (h->write == RINGBUF_DATASIZE) + h->write = 0; +} + +static void update_input_chunk(struct ringbuf_head *h, u32 len) +{ + h->read += len; + if (h->read == RINGBUF_DATASIZE) + h->read = 0; +} + +static int output_avail(struct ringbuf_head *out) +{ + unsigned int avail; + + get_output_chunk(out, out->buf, &avail); + return avail != 0; +} + +int xb_write(const void *data, unsigned len) +{ + struct ringbuf_head h; + struct ringbuf_head *out = outbuf(); + + do { + void *dst; + unsigned int avail; + + wait_event(xb_waitq, output_avail(out)); + + /* Read, then check: not that we don't trust store. + * Hell, some of my best friends are daemons. But, + * in this post-911 world... */ + h = *out; + mb(); + if (!check_buffer(&h)) { + return -1; /* ETERRORIST! */ + } + + dst = get_output_chunk(&h, out->buf, &avail); + if (avail > len) + avail = len; + memcpy(dst, data, avail); + data = (void *)((char *)data + avail); + len -= avail; + update_output_chunk(out, avail); + notify_via_evtchn(start_info.store_evtchn); + } while (len != 0); + + return 0; +} + +int xs_input_avail(void) +{ + unsigned int avail; + struct ringbuf_head *in = inbuf(); + + get_input_chunk(in, in->buf, &avail); + return avail != 0; +} + +int xb_read(void *data, unsigned len) +{ + struct ringbuf_head h; + struct ringbuf_head *in = inbuf(); + int was_full; + + while (len != 0) { + unsigned int avail; + const char *src; + + wait_event(xb_waitq, xs_input_avail()); + h = *in; + mb(); + if (!check_buffer(&h)) { + return -1; + } + + src = get_input_chunk(&h, in->buf, &avail); + if (avail > len) + avail = len; + was_full = !output_avail(&h); + + memcpy(data, src, avail); + data = (void *)((char *)data + avail); + len -= avail; + update_input_chunk(in, avail); + DEBUG("Finished read of %i bytes (%i to go)\n", avail, len); + /* If it was full, tell them we've taken some. */ + if (was_full) + notify_via_evtchn(start_info.store_evtchn); + } + + /* If we left something, wake watch thread to deal with it. */ + if (xs_input_avail()) + wake_up(&xb_waitq); + + return 0; +} + +/* Set up interrupt handler off store event channel. */ +int xb_init_comms(void) +{ + printk("Init xenbus comms, store event channel %d\n", start_info.store_evtchn); + if (!start_info.store_evtchn) + return 0; + printk("Binding virq\n"); + bind_evtchn(start_info.store_evtchn, &wake_waiting); + + /* FIXME zero out page -- domain builder should probably do this*/ + memset(mfn_to_virt(start_info.store_mfn), 0, PAGE_SIZE); + notify_via_evtchn(start_info.store_evtchn); + return 0; +} + +void xb_suspend_comms(void) +{ + + if (!start_info.store_evtchn) + return; + + // TODO + //unbind_evtchn_from_irqhandler(xen_start_info.store_evtchn, &xb_waitq); +} diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/xenbus/xenbus_comms.h --- /dev/null Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/xenbus/xenbus_comms.h Fri Sep 9 09:24:25 2005 @@ -0,0 +1,40 @@ +/* + * Private include for xenbus communications. + * + * Copyright (C) 2005 Rusty Russell, IBM Corporation + * + * This file may be distributed separately from the Linux kernel, or + * incorporated into other software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef _XENBUS_COMMS_H +#define _XENBUS_COMMS_H + +int xb_init_comms(void); +void xb_suspend_comms(void); + +/* Low level routines. */ +int xb_write(const void *data, unsigned len); +int xb_read(void *data, unsigned len); +int xs_input_avail(void); +extern struct wait_queue_head xb_waitq; + +#endif /* _XENBUS_COMMS_H */ diff -r 6563a12e0ad7 -r df1348e72390 extras/mini-os/xenbus/xenbus_xs.c --- /dev/null Fri Sep 9 09:13:45 2005 +++ b/extras/mini-os/xenbus/xenbus_xs.c Fri Sep 9 09:24:25 2005 @@ -0,0 +1,554 @@ +/****************************************************************************** + * xenbus_xs.c + * + * This is the kernel equivalent of the "xs" library. We don't need everything + * and we use xenbus_comms for communication. + * + * Copyright (C) 2005 Rusty Russell, IBM Corporation + * + * This file may be distributed separately from the Linux kernel, or + * incorporated into other software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +#include <errno.h> +#include <types.h> +#include <list.h> +#include <lib.h> +#include <err.h> +#include <os.h> +#include <xmalloc.h> +#include <fcntl.h> +#include <xenbus.h> +#include <wait.h> +#include <sched.h> +#include <semaphore.h> +#include "xenstored.h" +#include "xenbus_comms.h" + +#define streq(a, b) (strcmp((a), (b)) == 0) + +static char printf_buffer[4096]; +static LIST_HEAD(watches); +//TODO +DECLARE_MUTEX(xenbus_lock); + +static int get_error(const char *errorstring) +{ + unsigned int i; + + for (i = 0; !streq(errorstring, xsd_errors[i].errstring); i++) { + if (i == ARRAY_SIZE(xsd_errors) - 1) { + printk("XENBUS xen store gave: unknown error %s", + errorstring); + return EINVAL; + } + } + return xsd_errors[i].errnum; +} + +static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len) +{ + struct xsd_sockmsg msg; + void *ret; + int err; + + err = xb_read(&msg, sizeof(msg)); + if (err) + return ERR_PTR(err); + + ret = xmalloc_array(char, msg.len + 1); + if (!ret) + return ERR_PTR(-ENOMEM); + + err = xb_read(ret, msg.len); + if (err) { + xfree(ret); + return ERR_PTR(err); + } + ((char*)ret)[msg.len] = '\0'; + + *type = msg.type; + if (len) + *len = msg.len; + return ret; +} + +/* Emergency write. */ +void xenbus_debug_write(const char *str, unsigned int count) +{ + struct xsd_sockmsg msg; + + msg.type = XS_DEBUG; + msg.len = sizeof("print") + count + 1; + + xb_write(&msg, sizeof(msg)); + xb_write("print", sizeof("print")); + xb_write(str, count); + xb_write("", 1); +} + +/* Send message to xs, get kmalloc'ed reply. ERR_PTR() on error. */ +static void *xs_talkv(enum xsd_sockmsg_type type, + const struct kvec *iovec, + unsigned int num_vecs, + unsigned int *len) +{ + struct xsd_sockmsg msg; + void *ret = NULL; + unsigned int i; + int err; + + //WARN_ON(down_trylock(&xenbus_lock) == 0); + + msg.type = type; + msg.len = 0; + for (i = 0; i < num_vecs; i++) + msg.len += iovec[i].iov_len; + + err = xb_write(&msg, sizeof(msg)); + if (err) + return ERR_PTR(err); + + for (i = 0; i < num_vecs; i++) { + err = xb_write(iovec[i].iov_base, iovec[i].iov_len);; + if (err) + return ERR_PTR(err); + } + + /* Watches can have fired before reply comes: daemon detects + * and re-transmits, so we can ignore this. */ + do { + xfree(ret); + ret = read_reply(&msg.type, len); + if (IS_ERR(ret)) + return ret; + } while (msg.type == XS_WATCH_EVENT); + + if (msg.type == XS_ERROR) { + err = get_error(ret); + xfree(ret); + return ERR_PTR(-err); + } + + //BUG_ON(msg.type != type); + return ret; +} + +/* Simplified version of xs_talkv: single message. */ +static void *xs_single(enum xsd_sockmsg_type type, + const char *string, unsigned int *len) +{ + struct kvec iovec; + + iovec.iov_base = (void *)string; + iovec.iov_len = strlen(string) + 1; + return xs_talkv(type, &iovec, 1, len); +} + +/* Many commands only need an ack, don't care what it says. */ +static int xs_error(char *reply) +{ + if (IS_ERR(reply)) + return PTR_ERR(reply); + xfree(reply); + return 0; +} + +static unsigned int count_strings(const char *strings, unsigned int len) +{ + unsigned int num; + const char *p; + + for (p = strings, num = 0; p < strings + len; p += strlen(p) + 1) + num++; + + return num; +} + +/* Return the path to dir with /name appended. */ +static char *join(const char *dir, const char *name) +{ + static char buffer[4096]; + + //BUG_ON(down_trylock(&xenbus_lock) == 0); + /* XXX FIXME: might not be correct if name == "" */ + //BUG_ON(strlen(dir) + strlen("/") + strlen(name) + 1 > sizeof(buffer)); + + strcpy(buffer, dir); + if (!streq(name, "")) { + strcat(buffer, "/"); + strcat(buffer, name); + } + return buffer; +} + +char **xenbus_directory(const char *dir, const char *node, unsigned int *num) +{ + char *strings, *p, **ret; + unsigned int len; + + strings = xs_single(XS_DIRECTORY, join(dir, node), &len); + if (IS_ERR(strings)) + return (char **)strings; + + /* Count the strings. */ + *num = count_strings(strings, len); + + /* Transfer to one big alloc for easy freeing. */ + ret = (char **)xmalloc_array(char, *num * sizeof(char *) + len); + if (!ret) { + xfree(strings); + return ERR_PTR(-ENOMEM); + } + memcpy(&ret[*num], strings, len); + xfree(strings); + + strings = (char *)&ret[*num]; + for (p = strings, *num = 0; p < strings + len; p += strlen(p) + 1) + ret[(*num)++] = p; + return ret; +} + +/* Check if a path exists. Return 1 if it does. */ +int xenbus_exists(const char *dir, const char *node) +{ + char **d; + int dir_n; + + d = xenbus_directory(dir, node, &dir_n); + if (IS_ERR(d)) + return 0; + xfree(d); + return 1; +} + +/* Get the value of a single file. + * Returns a kmalloced value: call free() on it after use. + * len indicates length in bytes. + */ +void *xenbus_read(const char *dir, const char *node, unsigned int *len) +{ + return xs_single(XS_READ, join(dir, node), len); +} + +/* Write the value of a single file. + * Returns -err on failure. createflags can be 0, O_CREAT, or O_CREAT|O_EXCL. + */ +int xenbus_write(const char *dir, const char *node, + const char *string, int createflags) +{ + const char *flags, *path; + struct kvec iovec[3]; + + path = join(dir, node); + /* Format: Flags (as string), path, data. */ + if (createflags == 0) + flags = XS_WRITE_NONE; + else if (createflags == O_CREAT) + flags = XS_WRITE_CREATE; + else if (createflags == (O_CREAT|O_EXCL)) + flags = XS_WRITE_CREATE_EXCL; + else + return -EINVAL; + + iovec[0].iov_base = (void *)path; + iovec[0].iov_len = strlen(path) + 1; + iovec[1].iov_base = (void *)flags; + iovec[1].iov_len = strlen(flags) + 1; + iovec[2].iov_base = (void *)string; + iovec[2].iov_len = strlen(string); + + return xs_error(xs_talkv(XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL)); +} + +/* Create a new directory. */ +int xenbus_mkdir(const char *dir, const char *node) +{ + return xs_error(xs_single(XS_MKDIR, join(dir, node), NULL)); +} + +/* Destroy a file or directory (directories must be empty). */ +int xenbus_rm(const char *dir, const char *node) +{ + return xs_error(xs_single(XS_RM, join(dir, node), NULL)); +} + +/* Start a transaction: changes by others will not be seen during this + * transaction, and changes will not be visible to others until end. + * Transaction only applies to the given subtree. + * You can only have one transaction at any time. + */ +int xenbus_transaction_start(const char *subtree) +{ + return xs_error(xs_single(XS_TRANSACTION_START, subtree, NULL)); +} + +/* End a transaction. + * If abandon is true, transaction is discarded instead of committed. + */ +int xenbus_transaction_end(int abort) +{ + char abortstr[2]; + + if (abort) + strcpy(abortstr, "F"); + else + strcpy(abortstr, "T"); + return xs_error(xs_single(XS_TRANSACTION_END, abortstr, NULL)); +} + +/* Single read and scanf: returns -errno or num scanned. */ +int xenbus_scanf(const char *dir, const char *node, const char *fmt, ...) +{ + va_list ap; + int ret; + char *val; + + val = xenbus_read(dir, node, NULL); + if (IS_ERR(val)) + return PTR_ERR(val); + + va_start(ap, fmt); + ret = vsscanf(val, fmt, ap); + va_end(ap); + xfree(val); + /* Distinctive errno. */ + if (ret == 0) + return -ERANGE; + return ret; +} + +/* Single printf and write: returns -errno or 0. */ +int xenbus_printf(const char *dir, const char *node, const char *fmt, ...) +{ + va_list ap; + int ret; + + //BUG_ON(down_trylock(&xenbus_lock) == 0); + va_start(ap, fmt); + ret = vsnprintf(printf_buffer, sizeof(printf_buffer), fmt, ap); + va_end(ap); + + //BUG_ON(ret > sizeof(printf_buffer)-1); + return xenbus_write(dir, node, printf_buffer, O_CREAT); +} + + +/* Takes tuples of names, scanf-style args, and void **, NULL terminated. */ +int xenbus_gather(const char *dir, ...) +{ + va_list ap; + const char *name; + int ret = 0; + + va_start(ap, dir); + while (ret == 0 && (name = va_arg(ap, char *)) != NULL) { + const char *fmt = va_arg(ap, char *); + void *result = va_arg(ap, void *); + char *p; + + p = xenbus_read(dir, name, NULL); + if (IS_ERR(p)) { + ret = PTR_ERR(p); + break; + } + if (fmt) { + if (sscanf(p, fmt, result) == 0) + ret = -EINVAL; + xfree(p); + } else + *(char **)result = p; + } + va_end(ap); + return ret; +} + +static int xs_watch(const char *path, const char *token) +{ + struct kvec iov[2]; + + iov[0].iov_base = (void *)path; + iov[0].iov_len = strlen(path) + 1; + iov[1].iov_base = (void *)token; + iov[1].iov_len = strlen(token) + 1; + + return xs_error(xs_talkv(XS_WATCH, iov, ARRAY_SIZE(iov), NULL)); +} + +static char *xs_read_watch(char **token) +{ + enum xsd_sockmsg_type type; + char *ret; + + ret = read_reply(&type, NULL); + if (IS_ERR(ret)) + return ret; + + //BUG_ON(type != XS_WATCH_EVENT); + *token = ret + strlen(ret) + 1; + return ret; +} + +static int xs_acknowledge_watch(const char *token) +{ + return xs_error(xs_single(XS_WATCH_ACK, token, NULL)); +} + +static int xs_unwatch(const char *path, const char *token) +{ + struct kvec iov[2]; + + iov[0].iov_base = (char *)path; + iov[0].iov_len = strlen(path) + 1; + iov[1].iov_base = (char *)token; + iov[1].iov_len = strlen(token) + 1; + + return xs_error(xs_talkv(XS_UNWATCH, iov, ARRAY_SIZE(iov), NULL)); +} + +/* A little paranoia: we don't just trust token. */ +static struct xenbus_watch *find_watch(const char *token) +{ + struct xenbus_watch *i, *cmp; + + cmp = (void *)simple_strtoul(token, NULL, 16); + + list_for_each_entry(i, &watches, list) + if (i == cmp) + return i; + return NULL; +} + +/* Register callback to watch this node. */ +int register_xenbus_watch(struct xenbus_watch *watch) +{ + /* Pointer in ascii is the token. */ + char token[sizeof(watch) * 2 + 1]; + int err; + + sprintf(token, "%lX", (long)watch); + //BUG_ON(find_watch(token)); +printk("Registered watch for: %s\n", token); + err = xs_watch(watch->node, token); + if (!err) + list_add(&watch->list, &watches); + return err; +} + +void unregister_xenbus_watch(struct xenbus_watch *watch) +{ + char token[sizeof(watch) * 2 + 1]; + int err; + + sprintf(token, "%lX", (long)watch); + //BUG_ON(!find_watch(token)); + + err = xs_unwatch(watch->node, token); + list_del(&watch->list); + + if (err) + printk("XENBUS Failed to release watch %s: %i\n", + watch->node, err); +} + +/* Re-register callbacks to all watches. */ +void reregister_xenbus_watches(void) +{ + struct xenbus_watch *watch; + char token[sizeof(watch) * 2 + 1]; + + list_for_each_entry(watch, &watches, list) { + sprintf(token, "%lX", (long)watch); + xs_watch(watch->node, token); + } +} + +void watch_thread(void *unused) +{ + for (;;) { + char *token; + char *node = NULL; + + wait_event(xb_waitq, xs_input_avail()); + + /* If this is a spurious wakeup caused by someone + * doing an op, they'll hold the lock and the buffer + * will be empty by the time we get there. + */ + down(&xenbus_lock); + if (xs_input_avail()) + node = xs_read_watch(&token); + + if (node && !IS_ERR(node)) { + struct xenbus_watch *w; + int err; + + err = xs_acknowledge_watch(token); + if (err) + printk("XENBUS ack %s fail %i\n", node, err); + w = find_watch(token); + //BUG_ON(!w); + w->callback(w, node); + xfree(node); + } else + printk("XENBUS xs_read_watch: %li\n", PTR_ERR(node)); + up(&xenbus_lock); + } +} + + +static void ballon_changed(struct xenbus_watch *watch, const char *node) +{ + unsigned long new_target; + int err; + err = xenbus_scanf("memory", "target", "%lu", &new_target); + + if(err != 1) + { + printk("Unable to read memory/target\n"); + return; + } + + printk("Memory target changed to: %ld bytes, ignoring.\n", new_target); +} + + +static struct xenbus_watch ballon_watch = { + .node = "memory/target", + .callback = ballon_changed, +}; + + + +int xs_init(void) +{ + int err; + struct thread *watcher; + printk("xb_init_comms\n"); + err = xb_init_comms(); + if (err) + return err; + + watcher = create_thread("kxwatch", watch_thread, NULL); + down(&xenbus_lock); + register_xenbus_watch(&ballon_watch); + up(&xenbus_lock); + return 0; +} _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |