WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] Mini-os Xenbus

To: xen-devel <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] Mini-os Xenbus
From: Grzegorz Milos <gm281@xxxxxxxxx>
Date: Thu, 23 Mar 2006 18:38:31 +0000
Delivery-date: Thu, 23 Mar 2006 18:39:57 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Thunderbird 1.5 (X11/20051025)
Minimal Xenbus implementation by Steven Smith replacing the old (broken) implementation. The changeset also contains several bug fixes including: BSS clearing, trap handler fix.

Signed-off-by: Grzegorz Milos <gm281@xxxxxxxxx>

Keir could you apply?

Thanks.
diff -r 410b49759f02 -r c247056431f8 extras/mini-os/Makefile
--- a/extras/mini-os/Makefile   Wed Mar 22 17:14:50 2006
+++ b/extras/mini-os/Makefile   Thu Mar 23 18:34:50 2006
@@ -41,8 +41,7 @@
 
 links:
        [ -e include/xen ] || ln -sf ../../../xen/include/public include/xen
-       [ -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
diff -r 410b49759f02 -r c247056431f8 extras/mini-os/console/console.c
--- a/extras/mini-os/console/console.c  Wed Mar 22 17:14:50 2006
+++ b/extras/mini-os/console/console.c  Thu Mar 23 18:34:50 2006
@@ -116,12 +116,12 @@
     {
         (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(buf), buf);
         return;
+    } else {
+        if(!console_initialised)
+            (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(buf), buf);
+        
+        console_print(buf, strlen(buf));
     }
-    
-    if(!console_initialised)
-        (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(buf), buf);
-        
-    console_print(buf, strlen(buf));
 }
 
 void printk(const char *fmt, ...)
diff -r 410b49759f02 -r c247056431f8 extras/mini-os/console/xencons_ring.c
--- a/extras/mini-os/console/xencons_ring.c     Wed Mar 22 17:14:50 2006
+++ b/extras/mini-os/console/xencons_ring.c     Thu Mar 23 18:34:50 2006
@@ -10,7 +10,6 @@
 
 
 /* TODO - need to define BUG_ON for whole mini-os, need crash-dump as well */
-extern void do_exit(void);
 #define BUG_ON(_cond)   do{if(_cond) do_exit();} while(0);
 
 static inline struct xencons_interface *xencons_interface(void)
@@ -29,7 +28,6 @@
     int sent = 0;
        struct xencons_interface *intf = xencons_interface();
        XENCONS_RING_IDX cons, prod;
-
        cons = intf->out_cons;
        prod = intf->out_prod;
        mb();
diff -r 410b49759f02 -r c247056431f8 extras/mini-os/events.c
--- a/extras/mini-os/events.c   Wed Mar 22 17:14:50 2006
+++ b/extras/mini-os/events.c   Thu Mar 23 18:34:50 2006
@@ -74,9 +74,9 @@
 
 void unbind_evtchn( u32 port )
 {
-       if (ev_actions[port].handler)
+       if (ev_actions[port].handler == default_handler)
                printk("WARN: No handler for port %d when unbinding\n", port);
-       ev_actions[port].handler = NULL;
+       ev_actions[port].handler = default_handler;
        ev_actions[port].status |= EVS_DISABLED;
 }
 
diff -r 410b49759f02 -r c247056431f8 extras/mini-os/include/os.h
--- a/extras/mini-os/include/os.h       Wed Mar 22 17:14:50 2006
+++ b/extras/mini-os/include/os.h       Thu Mar 23 18:34:50 2006
@@ -9,6 +9,7 @@
 
 #define NULL 0
 
+
 #if __GNUC__ == 2 && __GNUC_MINOR__ < 96
 #define __builtin_expect(x, expected_value) (x)
 #endif
@@ -20,6 +21,10 @@
 #ifndef __ASSEMBLY__
 #include <types.h>
 #include <hypervisor.h>
+
+extern void do_exit(void);
+#define BUG do_exit
+
 #endif
 #include <xen/xen.h>
 
diff -r 410b49759f02 -r c247056431f8 extras/mini-os/include/wait.h
--- a/extras/mini-os/include/wait.h     Wed Mar 22 17:14:50 2006
+++ b/extras/mini-os/include/wait.h     Thu Mar 23 18:34:50 2006
@@ -66,6 +66,14 @@
     }
 }
 
+#define add_waiter(w, wq) do {  \
+    unsigned long flags;        \
+    local_irq_save(flags);      \
+    add_wait_queue(&wq, &w);    \
+    block(current);             \
+    local_irq_restore(flags);   \
+} while (0)
+
 #define wait_event(wq, condition) do{             \
     unsigned long flags;                          \
     if(condition)                                 \
diff -r 410b49759f02 -r c247056431f8 extras/mini-os/include/xenbus.h
--- a/extras/mini-os/include/xenbus.h   Wed Mar 22 17:14:50 2006
+++ b/extras/mini-os/include/xenbus.h   Thu Mar 23 18:34:50 2006
@@ -1,224 +1,6 @@
-/******************************************************************************
- * xenbus.h
- *
- * Talks to Xen Store to figure out what devices we have.
- *
- * Copyright (C) 2005 Rusty Russell, IBM Corporation
- * Copyright (C) 2005 XenSource Ltd.
- * 
- * 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_H__
+#define XENBUS_H__
 
-#ifndef _ASM_XEN_XENBUS_H
-#define _ASM_XEN_XENBUS_H
+void init_xenbus(void);
 
-#include <errno.h>
-#include <xen/io/xenbus.h>
-#include <xen/io/xs_wire.h>
-
-/* Register callback to watch this node. */
-struct xenbus_watch
-{
-       struct list_head list;
-
-       /* Path being watched. */
-       const char *node;
-
-       /* Callback (executed in a process context with no locks held). */
-       void (*callback)(struct xenbus_watch *,
-                        const char **vec, unsigned int len);
-};
-
-
-/* A xenbus device. */
-struct xenbus_device {
-       const char *devicetype;
-       const char *nodename;
-       const char *otherend;
-       int otherend_id;
-       struct xenbus_watch otherend_watch;
-       int has_error;
-       void *data;
-};
-
-struct xenbus_device_id
-{
-       /* .../device/<device_type>/<identifier> */
-       char devicetype[32];    /* General class of device. */
-};
-
-/* A xenbus driver. */
-struct xenbus_driver {
-       char *name;
-       struct module *owner;
-       const struct xenbus_device_id *ids;
-       int (*probe)(struct xenbus_device *dev,
-                    const struct xenbus_device_id *id);
-       void (*otherend_changed)(struct xenbus_device *dev,
-                                XenbusState backend_state);
-       int (*remove)(struct xenbus_device *dev);
-       int (*suspend)(struct xenbus_device *dev);
-       int (*resume)(struct xenbus_device *dev);
-       int (*hotplug)(struct xenbus_device *, char **, int, char *, int);
-       int (*read_otherend_details)(struct xenbus_device *dev);
-};
-
-int xenbus_register_frontend(struct xenbus_driver *drv);
-int xenbus_register_backend(struct xenbus_driver *drv);
-void xenbus_unregister_driver(struct xenbus_driver *drv);
-
-struct xenbus_transaction;
-
-char **xenbus_directory(struct xenbus_transaction *t,
-                       const char *dir, const char *node, unsigned int *num);
-void *xenbus_read(struct xenbus_transaction *t,
-                 const char *dir, const char *node, unsigned int *len);
-int xenbus_write(struct xenbus_transaction *t,
-                const char *dir, const char *node, const char *string);
-int xenbus_mkdir(struct xenbus_transaction *t,
-                const char *dir, const char *node);
-int xenbus_exists(struct xenbus_transaction *t,
-                 const char *dir, const char *node);
-int xenbus_rm(struct xenbus_transaction *t, const char *dir, const char *node);
-struct xenbus_transaction *xenbus_transaction_start(void);
-int xenbus_transaction_end(struct xenbus_transaction *t, int abort);
-
-/* Single read and scanf: returns -errno or num scanned if > 0. */
-int xenbus_scanf(struct xenbus_transaction *t,
-                const char *dir, const char *node, const char *fmt, ...)
-       __attribute__((format(scanf, 4, 5)));
-
-/* Single printf and write: returns -errno or 0. */
-int xenbus_printf(struct xenbus_transaction *t,
-                 const char *dir, const char *node, const char *fmt, ...)
-       __attribute__((format(printf, 4, 5)));
-
-/* Generic read function: NULL-terminated triples of name,
- * sprintf-style type string, and pointer. Returns 0 or errno.*/
-int xenbus_gather(struct xenbus_transaction *t, const char *dir, ...);
-
-int register_xenbus_watch(struct xenbus_watch *watch);
-void unregister_xenbus_watch(struct xenbus_watch *watch);
-void xs_suspend(void);
-void xs_resume(void);
-
-/* Used by xenbus_dev to borrow kernel's store connection. */
-void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg);
-
-/* 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)
-
-
-/**
- * Register a watch on the given path, using the given xenbus_watch structure
- * for storage, and the given callback function as the callback.  Return 0 on
- * success, or -errno on error.  On success, the given path will be saved as
- * watch->node, and remains the caller's to free.  On error, watch->node will
- * be NULL, the device will switch to XenbusStateClosing, and the error will
- * be saved in the store.
- */
-int xenbus_watch_path(struct xenbus_device *dev, const char *path,
-                     struct xenbus_watch *watch, 
-                     void (*callback)(struct xenbus_watch *,
-                                      const char **, unsigned int));
-
-
-/**
- * Register a watch on the given path/path2, using the given xenbus_watch
- * structure for storage, and the given callback function as the callback.
- * Return 0 on success, or -errno on error.  On success, the watched path
- * (path/path2) will be saved as watch->node, and becomes the caller's to
- * kfree().  On error, watch->node will be NULL, so the caller has nothing to
- * free, the device will switch to XenbusStateClosing, and the error will be
- * saved in the store.
- */
-int xenbus_watch_path2(struct xenbus_device *dev, const char *path,
-                      const char *path2, struct xenbus_watch *watch, 
-                      void (*callback)(struct xenbus_watch *,
-                                       const char **, unsigned int));
-
-
-/**
- * Advertise in the store a change of the given driver to the given new_state.
- * Perform the change inside the given transaction xbt.  xbt may be NULL, in
- * which case this is performed inside its own transaction.  Return 0 on
- * success, or -errno on error.  On error, the device will switch to
- * XenbusStateClosing, and the error will be saved in the store.
- */
-int xenbus_switch_state(struct xenbus_device *dev,
-                       struct xenbus_transaction *xbt,
-                       XenbusState new_state);
-
-
-/**
- * Grant access to the given ring_mfn to the peer of the given device.  Return
- * 0 on success, or -errno on error.  On error, the device will switch to
- * XenbusStateClosing, and the error will be saved in the store.
- */
-int xenbus_grant_ring(struct xenbus_device *dev, unsigned long ring_mfn);
-
-
-/**
- * Allocate an event channel for the given xenbus_device, assigning the newly
- * created local port to *port.  Return 0 on success, or -errno on error.  On
- * error, the device will switch to XenbusStateClosing, and the error will be
- * saved in the store.
- */
-int xenbus_alloc_evtchn(struct xenbus_device *dev, int *port);
-
-
-/**
- * Return the state of the driver rooted at the given store path, or
- * XenbusStateClosed if no state can be read.
- */
-XenbusState xenbus_read_driver_state(const char *path);
-
-
-/***
- * Report the given negative errno into the store, along with the given
- * formatted message.
- */
-void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt,
-                     ...);
-
-
-/***
- * Equivalent to xenbus_dev_error(dev, err, fmt, args), followed by
- * xenbus_switch_state(dev, NULL, XenbusStateClosing) to schedule an orderly
- * closedown of this driver and its peer.
- */
-void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt,
-                     ...);
-
-
-#endif /* _ASM_XEN_XENBUS_H */
+#endif /* XENBUS_H__ */
diff -r 410b49759f02 -r c247056431f8 extras/mini-os/kernel.c
--- a/extras/mini-os/kernel.c   Wed Mar 22 17:14:50 2006
+++ b/extras/mini-os/kernel.c   Thu Mar 23 18:34:50 2006
@@ -35,7 +35,6 @@
 #include <lib.h>
 #include <sched.h>
 #include <xenbus.h>
-#include "xenbus/xenbus_comms.h"
 
 /*
  * Shared page for communicating with the hypervisor.
@@ -76,7 +75,15 @@
 }
 
 
-extern void init_console(void);
+void test_xenbus(void);
+
+/* Do initialisation from a thread once the scheduler's available */
+static void init_xs(void *ign)
+{
+    init_xenbus();
+
+    test_xenbus();
+}
 
 /*
  * INITIAL C ENTRY POINT.
@@ -84,11 +91,13 @@
 void start_kernel(start_info_t *si)
 {
     static char hello[] = "Bootstrapping...\n";
+
     (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(hello), hello);
 
     /* Copy the start_info struct to a globally-accessible area. */
+    /* WARN: don't do printk before here, it uses information from
+       shared_info. Use xprintk instead. */
     memcpy(&start_info, si, sizeof(*si));
-
     /* Grab the shared_info pointer and put it in a safe place. */
     HYPERVISOR_shared_info = map_shared_info(start_info.shared_info);
 
@@ -120,28 +129,24 @@
            si->cmd_line ? (const char *)si->cmd_line : "NULL");
 
 
-    /*
-     * If used for porting another OS, start here to figure out your
-     * guest os entry point. Otherwise continue below...
-     */
-    /* init memory management */
+    /* Init memory management. */
     init_mm();
 
-    /* set up events */
+    /* Set up events. */
     init_events();
     
-    /* init time and timers */
+    /* Init time and timers. */
     init_time();
 
-    /* init the console driver */
+    /* Init the console driver. */
     init_console();
-
-    /* init scheduler */
+ 
+   /* Init scheduler. */
     init_sched();
-
-    /* init xenbus */
-    xs_init();
-   
+ 
+    /* Init XenBus from a separate thread */
+    create_thread("init_xs", init_xs, NULL);
+    
     /* Everything initialised, start idle thread */
     run_idle_thread();
 }
@@ -156,6 +161,6 @@
 
 void do_exit(void)
 {
-    printk("do_exit called!\n");
+    printk("Do_exit called!\n");
     for ( ;; ) HYPERVISOR_sched_op(SCHEDOP_shutdown, SHUTDOWN_crash);
 }
diff -r 410b49759f02 -r c247056431f8 extras/mini-os/minios-x86_32.lds
--- a/extras/mini-os/minios-x86_32.lds  Wed Mar 22 17:14:50 2006
+++ b/extras/mini-os/minios-x86_32.lds  Thu Mar 23 18:34:50 2006
@@ -21,15 +21,6 @@
 
   _edata = .;                  /* End of data section */
 
-  . = ALIGN(8192);             /* init_task */
-  .data.init_task : { *(.data.init_task) }
-
-  . = ALIGN(4096);
-  .data.page_aligned : { *(.data.idt) }
-
-  . = ALIGN(32);
-  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
   __bss_start = .;             /* BSS */
   .bss : {
        *(.bss)
diff -r 410b49759f02 -r c247056431f8 extras/mini-os/mm.c
--- a/extras/mini-os/mm.c       Wed Mar 22 17:14:50 2006
+++ b/extras/mini-os/mm.c       Thu Mar 23 18:34:50 2006
@@ -51,7 +51,6 @@
 unsigned long *phys_to_machine_mapping;
 extern char *stack;
 extern char _text, _etext, _edata, _end;
-extern void do_exit(void);
 extern void page_walk(unsigned long virt_addr);
 
 /*********************
diff -r 410b49759f02 -r c247056431f8 extras/mini-os/sched.c
--- a/extras/mini-os/sched.c    Wed Mar 22 17:14:50 2006
+++ b/extras/mini-os/sched.c    Thu Mar 23 18:34:50 2006
@@ -65,6 +65,8 @@
 struct thread *idle_thread = NULL;
 LIST_HEAD(exited_threads);
 
+void idle_thread_fn(void *unused);
+
 void dump_stack(struct thread *thread)
 {
     unsigned long *bottom = (unsigned long *)thread->stack + 2048; 
@@ -132,7 +134,7 @@
             xfree(thread);
         }
     }
-    next = idle_thread;    
+    next = idle_thread;   
     /* Thread list needs to be protected */
     list_for_each(iterator, &idle_thread->thread_list)
     {
@@ -203,8 +205,13 @@
     set_runnable(thread);
     
     local_irq_save(flags);
-    if(idle_thread != NULL)
+    if(idle_thread != NULL) {
         list_add_tail(&thread->thread_list, &idle_thread->thread_list); 
+    } else if(function != idle_thread_fn)
+    {
+        printk("BUG: Not allowed to create thread before initialising 
scheduler.\n");
+        BUG();
+    }
     local_irq_restore(flags);
 
     return thread;
@@ -282,19 +289,9 @@
 
 void init_sched(void)
 {
-    printk("Initialising scheduler\n");
-       
+    printk("Initialising scheduler, idle_thread %p\n", idle_thread);
+
     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 410b49759f02 -r c247056431f8 extras/mini-os/traps.c
--- a/extras/mini-os/traps.c    Wed Mar 22 17:14:50 2006
+++ b/extras/mini-os/traps.c    Thu Mar 23 18:34:50 2006
@@ -29,11 +29,18 @@
 void machine_check(void);
 
 
-extern void do_exit(void);
-
 void dump_regs(struct pt_regs *regs)
 {
-    printk("FIXME: proper register dump (with the stack dump)\n");
+    printk("EIP: %x, EFLAGS %x.\n", regs->eip, regs->eflags);
+    printk("EBX: %08x ECX: %08x EDX: %08x\n",
+          regs->ebx, regs->ecx, regs->edx);
+    printk("ESI: %08x EDI: %08x EBP: %08x EAX: %08x\n",
+          regs->esi, regs->edi, regs->ebp, regs->eax);
+    printk("DS: %04x ES: %04x orig_eax: %08x, eip: %08x\n",
+          regs->xds, regs->xes, regs->orig_eax, regs->eip);
+    printk("CS: %04x EFLAGS: %08x esp: %08x ss: %04x\n",
+          regs->xcs, regs->eflags, regs->esp, regs->xss);
+
 }      
 
 
@@ -94,10 +101,14 @@
 
 }
 
-void do_page_fault(struct pt_regs *regs, unsigned long error_code,
-                                                                               
     unsigned long addr)
-{
-    printk("Page fault at linear address %p\n", addr);
+#define read_cr2() \
+        (HYPERVISOR_shared_info->vcpu_info[smp_processor_id()].arch.cr2)
+
+void do_page_fault(struct pt_regs *regs, unsigned long error_code)
+{
+    unsigned long addr = read_cr2();
+    printk("Page fault at linear address %p, regs %p, code %lx\n", addr, regs,
+          error_code);
     dump_regs(regs);
 #ifdef __x86_64__
     /* FIXME: _PAGE_PSE */
diff -r 410b49759f02 -r c247056431f8 extras/mini-os/x86_32.S
--- a/extras/mini-os/x86_32.S   Wed Mar 22 17:14:50 2006
+++ b/extras/mini-os/x86_32.S   Thu Mar 23 18:34:50 2006
@@ -30,10 +30,10 @@
 hypercall_page:
         .org 0x3000
 
-ES             = 0x20
-ORIG_EAX       = 0x24
-EIP            = 0x28
-CS             = 0x2C
+ES             = 0x1c
+ORIG_EAX       = 0x20
+EIP            = 0x24
+CS             = 0x28
 
 #define ENTRY(X) .globl X ; X :
 
@@ -94,32 +94,6 @@
        call *%edi
     addl $8,%esp
     
-/*    pushl %ds
-       pushl %eax
-       xorl %eax,%eax
-       pushl %ebp
-       pushl %edi
-       pushl %esi
-       pushl %edx
-       decl %eax                       # eax = -1
-       pushl %ecx
-       pushl %ebx
-       cld
-       movl %es,%ecx
-       movl ORIG_EAX(%esp), %esi       # get the error code
-       movl ES(%esp), %edi             # get the function address
-       movl %eax, ORIG_EAX(%esp)
-       movl %ecx, ES(%esp)
-       movl %esp,%edx
-       pushl %esi                      # push the error code
-       pushl %edx                      # push the pt_regs pointer
-       movl $(__KERNEL_DS),%edx
-       movl %edx,%ds
-       movl %edx,%es
-       call *%edi
-       addl $8,%esp  */
-
-        
 ret_from_exception:
         movb CS(%esp),%cl
        test $2,%cl          # slow return to ring 2 or 3
@@ -290,15 +264,16 @@
        pushl %ecx
        pushl %ebx
        cld
-       movl %es,%edi
-       movl ES(%esp), %ecx             /* get the faulting address */
-       movl ORIG_EAX(%esp), %edx       /* get the error code */
+       movl ORIG_EAX(%esp), %edi
        movl %eax, ORIG_EAX(%esp)
-       movl %edi, ES(%esp)
+       movl %es, %ecx
+       movl %ecx, ES(%esp)
        movl $(__KERNEL_DS),%eax
        movl %eax, %ds
        movl %eax, %es
-       movl %esp,%eax                  /* pt_regs pointer */
+       pushl %edi
+       movl %esp, %eax
+       pushl %eax
        call do_page_fault
        jmp ret_from_exception
 
diff -r 410b49759f02 -r c247056431f8 extras/mini-os/xenbus/xenbus.c
--- /dev/null   Wed Mar 22 17:14:50 2006
+++ b/extras/mini-os/xenbus/xenbus.c    Thu Mar 23 18:34:50 2006
@@ -0,0 +1,387 @@
+/* 
+ ****************************************************************************
+ * (C) 2006 - Cambridge University
+ ****************************************************************************
+ *
+ *        File: mm.c
+ *      Author: Steven Smith (sos22@xxxxxxxxx) 
+ *     Changes: Grzegorz Milos (gm281@xxxxxxxxx)
+ *              
+ *        Date: Mar 2006, chages Aug 2005
+ * 
+ * Environment: Xen Minimal OS
+ * Description: Minimal implementation of xenbus
+ *
+ ****************************************************************************
+ **/
+#include <os.h>
+#include <mm.h>
+#include <traps.h>
+#include <lib.h>
+#include <xenbus.h>
+#include <events.h>
+#include <errno.h>
+#include <sched.h>
+#include <wait.h>
+#include <xen/io/xs_wire.h>
+#include <spinlock.h>
+#include <xmalloc.h>
+
+#define BUG_ON(x) do { \
+    if (x) {printk("BUG at %s:%d\n", __FILE__, __LINE__); BUG(); } \
+} while (0)
+
+#define min(x,y) ({                       \
+        typeof(x) tmpx = (x);                 \
+        typeof(y) tmpy = (y);                 \
+        tmpx < tmpy ? tmpx : tmpy;            \
+        })
+
+#ifdef XENBUS_DEBUG
+#define DEBUG(_f, _a...) \
+    printk("MINI_OS(file=xenbus.c, line=%d) " _f , __LINE__, ## _a)
+#else
+#define DEBUG(_f, _a...)    ((void)0)
+#endif
+
+
+static struct xenstore_domain_interface *xenstore_buf;
+static DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
+struct xenbus_req_info 
+{
+    int in_use:1;
+    struct wait_queue_head waitq;
+    void *reply;
+};
+
+#define NR_REQS 32
+static struct xenbus_req_info req_info[NR_REQS];
+
+static void memcpy_from_ring(const void *Ring,
+        void *Dest,
+        int off,
+        int len)
+{
+    int c1, c2;
+    const char *ring = Ring;
+    char *dest = Dest;
+    c1 = min(len, XENSTORE_RING_SIZE - off);
+    c2 = len - c1;
+    memcpy(dest, ring + off, c1);
+    memcpy(dest + c1, ring, c2);
+}
+
+static void xenbus_thread_func(void *ign)
+{
+    struct xsd_sockmsg msg;
+    unsigned prod;
+
+    for (;;) 
+    {
+        wait_event(xb_waitq, prod != xenstore_buf->rsp_prod);
+        while (1) 
+        {
+            prod = xenstore_buf->rsp_prod;
+            DEBUG("Rsp_cons %d, rsp_prod %d.\n", xenstore_buf->rsp_cons,
+                    xenstore_buf->rsp_prod);
+            if (xenstore_buf->rsp_prod - xenstore_buf->rsp_cons < sizeof(msg))
+                break;
+            rmb();
+            memcpy_from_ring(xenstore_buf->rsp,
+                    &msg,
+                    MASK_XENSTORE_IDX(xenstore_buf->rsp_cons),
+                    sizeof(msg));
+            DEBUG("Msg len %d, %d avail, id %d.\n",
+                    msg.len + sizeof(msg),
+                    xenstore_buf->rsp_prod - xenstore_buf->rsp_cons,
+                    msg.req_id);
+            if (xenstore_buf->rsp_prod - xenstore_buf->rsp_cons <
+                    sizeof(msg) + msg.len)
+                break;
+
+            DEBUG("Message is good.\n");
+            req_info[msg.req_id].reply = malloc(sizeof(msg) + msg.len);
+            memcpy_from_ring(xenstore_buf->rsp,
+                    req_info[msg.req_id].reply,
+                    MASK_XENSTORE_IDX(xenstore_buf->rsp_cons),
+                    msg.len + sizeof(msg));
+            wake_up(&req_info[msg.req_id].waitq);
+            xenstore_buf->rsp_cons += msg.len + sizeof(msg);
+        }
+    }
+}
+
+static void xenbus_evtchn_handler(int port, struct pt_regs *regs)
+{
+    wake_up(&xb_waitq);
+}
+
+static int nr_live_reqs;
+static spinlock_t req_lock = SPIN_LOCK_UNLOCKED;
+static DECLARE_WAIT_QUEUE_HEAD(req_wq);
+
+/* Release a xenbus identifier */
+static void release_xenbus_id(int id)
+{
+    BUG_ON(!req_info[id].in_use);
+    spin_lock(&req_lock);
+    nr_live_reqs--;
+    if (nr_live_reqs == NR_REQS - 1)
+        wake_up(&req_wq);
+    spin_unlock(&req_lock);
+}
+
+/* Allocate an identifier for a xenbus request.  Blocks if none are
+   available. */
+static int allocate_xenbus_id(void)
+{
+    static int probe;
+    int o_probe;
+
+    while (1) 
+    {
+        spin_lock(&req_lock);
+        if (nr_live_reqs < NR_REQS)
+            break;
+        spin_unlock(&req_lock);
+        wait_event(req_wq, (nr_live_reqs < NR_REQS));
+    }
+
+    o_probe = probe;
+    for (;;) 
+    {
+        if (!req_info[o_probe].in_use)
+            break;
+        o_probe = (o_probe + 1) % NR_REQS;
+        BUG_ON(o_probe == probe);
+    }
+    nr_live_reqs++;
+    req_info[o_probe].in_use = 1;
+    probe = o_probe + 1;
+    spin_unlock(&req_lock);
+    init_waitqueue_head(&req_info[o_probe].waitq);
+    return o_probe;
+}
+
+/* Initialise xenbus. */
+void init_xenbus(void)
+{
+    int err;
+    DEBUG("init_xenbus called.\n");
+    xenstore_buf = mfn_to_virt(start_info.store_mfn);
+    create_thread("xenstore", xenbus_thread_func, NULL);
+    DEBUG("buf at %p.\n", xenstore_buf);
+    err = bind_evtchn(start_info.store_evtchn,
+            xenbus_evtchn_handler);
+    DEBUG("xenbus on irq %d\n", err);
+}
+
+struct write_req {
+    const void *data;
+    unsigned len;
+};
+
+/* Send data to xenbus.  This can block.  All of the requests are seen
+   by xenbus as if sent atomically.  The header is added
+   automatically, using type %type, req_id %req_id, and trans_id
+   %trans_id. */
+static void xb_write(int type, int req_id, int trans_id,
+        const struct write_req *req, int nr_reqs)
+{
+    XENSTORE_RING_IDX prod;
+    int r;
+    int len = 0;
+    const struct write_req *cur_req;
+    int req_off;
+    int total_off;
+    int this_chunk;
+    struct xsd_sockmsg m = {.type = type, .req_id = req_id,
+        .tx_id = trans_id };
+    struct write_req header_req = { &m, sizeof(m) };
+
+    for (r = 0; r < nr_reqs; r++)
+        len += req[r].len;
+    m.len = len;
+    len += sizeof(m);
+
+    cur_req = &header_req;
+
+    BUG_ON(len > XENSTORE_RING_SIZE);
+    /* Wait for the ring to drain to the point where we can send the
+       message. */
+    prod = xenstore_buf->req_prod;
+    if (prod + len - xenstore_buf->req_cons > XENSTORE_RING_SIZE) 
+    {
+        /* Wait for there to be space on the ring */
+        DEBUG("prod %d, len %d, cons %d, size %d; waiting.\n",
+                prod, len, xenstore_buf->req_cons, XENSTORE_RING_SIZE);
+        wait_event(xb_waitq,
+                xenstore_buf->req_prod + len - xenstore_buf->req_cons <=
+                XENSTORE_RING_SIZE);
+        DEBUG("Back from wait.\n");
+        prod = xenstore_buf->req_prod;
+    }
+
+    /* We're now guaranteed to be able to send the message without
+       overflowing the ring.  Do so. */
+    total_off = 0;
+    req_off = 0;
+    while (total_off < len) 
+    {
+        this_chunk = min(cur_req->len - req_off,
+                XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod));
+        memcpy((char *)xenstore_buf->req + MASK_XENSTORE_IDX(prod),
+                (char *)cur_req->data + req_off, this_chunk);
+        prod += this_chunk;
+        req_off += this_chunk;
+        total_off += this_chunk;
+        if (req_off == cur_req->len) 
+        {
+            req_off = 0;
+            if (cur_req == &header_req)
+                cur_req = req;
+            else
+                cur_req++;
+        }
+    }
+
+    DEBUG("Complete main loop of xb_write.\n");
+    BUG_ON(req_off != 0);
+    BUG_ON(total_off != len);
+    BUG_ON(prod > xenstore_buf->req_cons + XENSTORE_RING_SIZE);
+
+    /* Remote must see entire message before updating indexes */
+    wmb();
+
+    xenstore_buf->req_prod += len;
+
+    /* Send evtchn to notify remote */
+    notify_remote_via_evtchn(start_info.store_evtchn);
+}
+
+/* Send a mesasge to xenbus, in the same fashion as xb_write, and
+   block waiting for a reply.  The reply is malloced and should be
+   freed by the caller. */
+static void *xenbus_msg_reply(int type,
+        int trans,
+        struct write_req *io,
+        int nr_reqs)
+{
+    int id;
+    DEFINE_WAIT(w);
+    void *rep;
+    struct xsd_sockmsg *repmsg;
+
+    id = allocate_xenbus_id();
+    add_waiter(w, req_info[id].waitq);
+
+    xb_write(type, id, trans, io, nr_reqs);
+
+    schedule();
+    wake(current);
+
+    rep = req_info[id].reply;
+    repmsg = rep;
+    BUG_ON(repmsg->req_id != id);
+    release_xenbus_id(id);
+
+    return rep;
+}
+
+/* Send a debug message to xenbus.  Can block. */
+static void xenbus_debug_msg(const char *msg)
+{
+    int len = strlen(msg);
+    struct write_req req[] = {
+        { "print", sizeof("print") },
+        { msg, len },
+        { "", 1 }};
+    void *reply;
+    struct xsd_sockmsg *repmsg;
+
+    reply = xenbus_msg_reply(XS_DEBUG, 0, req, 3);
+    repmsg = reply;
+    DEBUG("Got a reply, type %d, id %d, len %d.\n",
+            repmsg->type, repmsg->req_id, repmsg->len);
+}
+
+/* List the contents of a directory.  Returns a malloc()ed array of
+   pointers to malloc()ed strings.  The array is NULL terminated.  May
+   block. */
+static char **xenbus_ls(const char *pre)
+{
+    void *reply;
+    struct xsd_sockmsg *repmsg;
+    struct write_req req[] = { { pre, strlen(pre)+1 } };
+    int nr_elems, x, i;
+    char **res;
+
+    repmsg = xenbus_msg_reply(XS_DIRECTORY, 0, req, 1);
+    reply = repmsg + 1;
+    for (x = nr_elems = 0; x < repmsg->len; x++)
+        nr_elems += (((char *)reply)[x] == 0);
+    res = malloc(sizeof(res[0]) * (nr_elems + 1));
+    for (x = i = 0; i < nr_elems; i++) {
+        int l = strlen((char *)reply + x);
+        res[i] = malloc(l + 1);
+        memcpy(res[i], (char *)reply + x, l + 1);
+        x += l + 1;
+    }
+    res[i] = NULL;
+    free(repmsg);
+    return res;
+}
+
+static char *xenbus_read(const char *path)
+{
+    struct write_req req[] = { {path, strlen(path) + 1}};
+    struct xsd_sockmsg *rep;
+    char *res;
+    rep = xenbus_msg_reply(XS_READ, 0, req, 1);
+    res = malloc(rep->len + 1);
+    memcpy(res, rep + 1, rep->len);
+    res[rep->len] = 0;
+    free(rep);
+    return res;
+}
+
+static void do_ls_test(const char *pre)
+{
+    char **dirs;
+    int x;
+
+    DEBUG("ls %s...\n", pre);
+    dirs = xenbus_ls(pre);
+    for (x = 0; dirs[x]; x++) 
+    {
+        DEBUG("ls %s[%d] -> %s\n", pre, x, dirs[x]);
+        free(dirs[x]);
+    }
+    free(dirs);
+}
+
+static void do_read_test(const char *path)
+{
+    char *res;
+    DEBUG("Read %s...\n", path);
+    res = xenbus_read(path);
+    DEBUG("Read %s -> %s.\n", path, res);
+    free(res);
+}
+
+/* Simple testing thing */
+void test_xenbus(void)
+{
+    DEBUG("Doing xenbus test.\n");
+    xenbus_debug_msg("Testing xenbus...\n");
+
+    DEBUG("Doing ls test.\n");
+    do_ls_test("device");
+    do_ls_test("device/vif");
+    do_ls_test("device/vif/0");
+
+    DEBUG("Doing read test.\n");
+    do_read_test("device/vif/0/mac");
+    do_read_test("device/vif/0/backend");
+    printk("Xenbus initialised.\n");
+}
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] Mini-os Xenbus, Grzegorz Milos <=