]> xenbits.xensource.com Git - people/liuw/mini-os.git/commitdiff
minios: add proper shutdown facilities
authorKeir Fraser <keir.fraser@citrix.com>
Mon, 9 Jun 2008 12:26:30 +0000 (13:26 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Mon, 9 Jun 2008 12:26:30 +0000 (13:26 +0100)
Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
27 files changed:
arch/ia64/common.c
arch/ia64/time.c
arch/x86/setup.c
arch/x86/time.c
arch/x86/traps.c
blkfront.c
console/console.c
events.c
fbfront.c
fs-front.c
gnttab.c
include/console.h
include/events.h
include/gnttab.h
include/ia64/os.h
include/ia64/traps.h
include/kernel.h [new file with mode: 0644]
include/mm.h
include/netfront.h
include/time.h
include/x86/os.h
include/xenbus.h
kernel.c
lwip-net.c
mm.c
netfront.c
xenbus/xenbus.c

index cd4cec1e209d461b4ff5f6f3db190423918c202e..c65f0a0d075afef07d9ec2215613641b017a3a78 100644 (file)
@@ -235,6 +235,12 @@ arch_init(start_info_t *si)
        initialized = 1;
 }
 
+void
+arch_fini(void)
+{
+       /* TODO */
+}
+
 void
 arch_print_info(void)
 {
index bbaa6b18645bb5e3c0d5d88db20a1256e0ccedc9..baf9096330c1bcc31d6abc416e99baa82c753770 100644 (file)
@@ -280,3 +280,9 @@ init_time(void)
        ia64_set_itm(new);
        ia64_srlz_d();
 }
+
+void
+fini_time(void)
+{
+       /* TODO */
+}
index ca9713131533448849f5539e9fd54b04ef06a360..3671fee332389d8078bd644d70e1fdf4f2787c5e 100644 (file)
@@ -99,6 +99,16 @@ arch_init(start_info_t *si)
 
 }
 
+void
+arch_fini(void)
+{
+#ifdef __i386__
+       HYPERVISOR_set_callbacks(0, 0, 0, 0);
+#else
+       HYPERVISOR_set_callbacks(0, 0, 0);
+#endif
+}
+
 void
 arch_print_info(void)
 {
index d7b387f95f86a0224dde189010713c64624e0f18..4af0b89b941bee4a7d6a9daca5d28bb7b5c3b7bd 100644 (file)
@@ -222,10 +222,17 @@ static void timer_handler(evtchn_port_t ev, struct pt_regs *regs, void *ign)
 
 
 
+static evtchn_port_t port;
 void init_time(void)
 {
-    evtchn_port_t port;
     printk("Initialising timer interface\n");
     port = bind_virq(VIRQ_TIMER, &timer_handler, NULL);
     unmask_evtchn(port);
 }
+
+void fini_time(void)
+{
+    /* Clear any pending timer */
+    HYPERVISOR_set_timer_op(0);
+    unbind_evtchn(port);
+}
index 5719f741e1edad5b9fb57121bc96027e8c492af7..003ffb52b37dc7df03e787b176f50a02706bfc8f 100644 (file)
@@ -268,3 +268,7 @@ void trap_init(void)
     HYPERVISOR_set_trap_table(trap_table);    
 }
 
+void trap_fini(void)
+{
+    HYPERVISOR_set_trap_table(NULL);
+}
index 2e2eea2271217f75fea38a586b9df9031e3f787c..e2ac96543412f2fc66397be195fad7d47d02b4bb 100644 (file)
@@ -240,6 +240,8 @@ void shutdown_blkfront(struct blkfront_dev *dev)
 
     xenbus_unwatch_path(XBT_NIL, path);
 
+    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
+
     free_blkfront(dev);
 }
 
index 94379ddb335af4de14629895f3a80b73d05914f7..3805943465550cbece16830e2a7c49c991446531 100644 (file)
@@ -150,3 +150,8 @@ void init_console(void)
     /* This is also required to notify the daemon */
     printk("done.\n");
 }
+
+void fini_console(void)
+{
+    /* Destruct the console and get the parameters of the restarted one */
+}
index f47fc388223f88ad2f7d1362e0a385547aeefe27..87f54ef5ebe47fb1672a0171f45de142d364f549 100644 (file)
--- a/events.c
+++ b/events.c
@@ -39,19 +39,29 @@ static unsigned long bound_ports[NR_EVS/(8*sizeof(unsigned long))];
 void unbind_all_ports(void)
 {
     int i;
+    int cpu = 0;
+    shared_info_t *s = HYPERVISOR_shared_info;
+    vcpu_info_t   *vcpu_info = &s->vcpu_info[cpu];
 
     for (i = 0; i < NR_EVS; i++)
     {
+        if (i == start_info.console.domU.evtchn ||
+            i == start_info.store_evtchn)
+            continue;
         if (test_and_clear_bit(i, bound_ports))
         {
             struct evtchn_close close;
+            printk("port %d still bound!\n", i);
             mask_evtchn(i);
             close.port = i;
             HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
+            clear_evtchn(i);
         }
     }
+    vcpu_info->evtchn_upcall_pending = 0;
+    vcpu_info->evtchn_pending_sel = 0;
 }
-  
+
 /*
  * Demux events to different handlers.
  */
@@ -86,17 +96,27 @@ evtchn_port_t bind_evtchn(evtchn_port_t port, evtchn_handler_t handler,
        ev_actions[port].data = data;
        wmb();
        ev_actions[port].handler = handler;
+       set_bit(port, bound_ports);
 
        return port;
 }
 
 void unbind_evtchn(evtchn_port_t port )
 {
+       struct evtchn_close close;
+
        if (ev_actions[port].handler == default_handler)
                printk("WARN: No handler for port %d when unbinding\n", port);
+       mask_evtchn(port);
+       clear_evtchn(port);
+
        ev_actions[port].handler = default_handler;
        wmb();
        ev_actions[port].data = NULL;
+       clear_bit(port, bound_ports);
+
+       close.port = port;
+       HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
 }
 
 evtchn_port_t bind_virq(uint32_t virq, evtchn_handler_t handler, void *data)
@@ -112,7 +132,6 @@ evtchn_port_t bind_virq(uint32_t virq, evtchn_handler_t handler, void *data)
                printk("Failed to bind virtual IRQ %d\n", virq);
                return -1;
     }
-    set_bit(op.port,bound_ports);
     bind_evtchn(op.port, handler, data);
        return op.port;
 }
@@ -147,6 +166,15 @@ void init_events(void)
     }
 }
 
+void fini_events(void)
+{
+    /* Dealloc all events */
+    unbind_all_ports();
+#if defined(__x86_64__)
+    wrmsrl(0xc0000101, NULL); /* 0xc0000101 is MSR_GS_BASE */
+#endif
+}
+
 void default_handler(evtchn_port_t port, struct pt_regs *regs, void *ignore)
 {
     printk("[Port %d] - event received\n", port);
@@ -185,7 +213,6 @@ int evtchn_bind_interdomain(domid_t pal, evtchn_port_t remote_port,
     int err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain, &op);
     if (err)
                return err;
-    set_bit(op.local_port,bound_ports);
     evtchn_port_t port = op.local_port;
     *local_port = bind_evtchn(port, handler, data);
     return err;
index 60c7552d005a147fa992be7e74cafcea35a1201a..55864f360e536b1a4998e86738bd295872dfccbb 100644 (file)
--- a/fbfront.c
+++ b/fbfront.c
@@ -225,6 +225,8 @@ void shutdown_kbdfront(struct kbdfront_dev *dev)
 
     xenbus_unwatch_path(XBT_NIL, path);
 
+    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
+
     free_kbdfront(dev);
 }
 
@@ -549,6 +551,8 @@ void shutdown_fbfront(struct fbfront_dev *dev)
 
     xenbus_unwatch_path(XBT_NIL, path);
 
+    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
+
     unbind_evtchn(dev->evtchn);
 
     free_fbfront(dev);
index 5b7bc6a4a2fb2db87e1dc55cdd6d0f4b9e0ae322..0b27df361bf40ac7e4a9bc7fc947bcbacbc42133 100644 (file)
@@ -1127,3 +1127,5 @@ void init_fs_frontend(void)
     if (!fs_import)
        printk("No FS import\n");
 }
+
+/* TODO: shutdown */
index dd66b043bf7dadaba2092f1596a600bc4474b822..d94c28b815fb4c346d73af7cb988b3a3b321197c 100644 (file)
--- a/gnttab.c
+++ b/gnttab.c
@@ -193,3 +193,14 @@ init_gnttab(void)
     gnttab_table = map_frames(frames, NR_GRANT_FRAMES);
     printk("gnttab_table mapped at %p.\n", gnttab_table);
 }
+
+void
+fini_gnttab(void)
+{
+    struct gnttab_setup_table setup;
+
+    setup.dom = DOMID_SELF;
+    setup.nr_frames = 0;
+
+    HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
+}
index ac9cb53e7b6a88650a9f2a70cdb228616a8ac153..4a61f1aaa0c67b2c6b6daae961d8bff46ccb111c 100644 (file)
@@ -51,6 +51,7 @@ void xencons_tx(void);
 
 void init_console(void);
 void console_print(char *data, int length);
+void fini_console(void);
 
 /* Low level functions defined in xencons_ring.c */
 extern struct wait_queue_head console_queue;
index ff202e38fe2454bf70c45404217415508c74186e..9ffb35d320c5ef224153127e12915a9998879010 100644 (file)
@@ -45,5 +45,6 @@ static inline int notify_remote_via_evtchn(evtchn_port_t port)
     return HYPERVISOR_event_channel_op(EVTCHNOP_send, &op);
 }
 
+void fini_events(void);
 
 #endif /* _EVENTS_H_ */
index f9524429550c076cf081b1564e63c8228560bb40..acd6c39f8cb0bf84427043ee6a71effcbd78c407 100644 (file)
@@ -11,5 +11,6 @@ grant_ref_t gnttab_grant_transfer(domid_t domid, unsigned long pfn);
 unsigned long gnttab_end_transfer(grant_ref_t gref);
 int gnttab_end_access(grant_ref_t ref);
 const char *gnttabop_error(int16_t status);
+void fini_gnttab(void);
 
 #endif /* !__GNTTAB_H__ */
index 2ae53313931186ec96fc5110565b66586a46dd42..bf3785fc825cb71d286c697be17682f36bd6abaf 100644 (file)
@@ -35,6 +35,7 @@
 #include "sal.h"
 #include "pal.h"
 #include "hypervisor.h"
+#include <kernel.h>
 
 
 typedef uint64_t paddr_t;              /* Physical address. */
@@ -46,9 +47,9 @@ typedef uint64_t caddr_t;             /* rr7/kernel memory address. */
 #include "mm.h"
 
 
-void do_exit(void) __attribute__((noreturn));
 void arch_init(start_info_t *si);      /* in common.c */
 void arch_print_info(void);            /* in common.c */
+void arch_fini(void);
 
 
 /* Size of xen_ia64_boot_param.command_line */
index 4c5e7be527776478a34e18c950557ced548b76ff..e79a952aec035137040fbf6fe586a62b196286b3 100644 (file)
@@ -38,6 +38,10 @@ inline static void trap_init(void)
 {
        //printk("trap_init() until now not needed!\n");
 }
+inline static void trap_fini(void)
+{
+       //printk("trap_fini() until now not needed!\n");
+}
 
 
 #endif /* !defined(__ASSEMBLY__) */
diff --git a/include/kernel.h b/include/kernel.h
new file mode 100644 (file)
index 0000000..b36f172
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _KERNEL_H_
+#define _KERNEL_H_
+
+extern void do_exit(void) __attribute__((noreturn));
+extern void stop_kernel(void);
+
+#endif /* _KERNEL_H_ */
index 28fb727f9fe912d87ecef639822bbf09e1b85610..7c8588ccf8f49afec74a3201d2bfb102b2138193 100644 (file)
@@ -75,5 +75,6 @@ extern unsigned long heap, brk, heap_mapped, heap_end;
 #endif
 
 int free_physical_pages(xen_pfn_t *mfns, int n);
+void fini_mm(void);
 
 #endif /* _MM_H_ */
index 526dc94b5c939d8a775361d1002273b1daa2c170..681ebf2c0fc2d8ea5cadaa0255fdecc1d0c98daf 100644 (file)
@@ -18,6 +18,7 @@ extern struct wait_queue_head netfront_queue;
  * N.B. _must_ be called from a thread; it's not safe to call this from 
  * app_main(). */
 void start_networking(void);
+void stop_networking(void);
 
 void networking_set_addr(struct ip_addr *ipaddr, struct ip_addr *netmask, struct ip_addr *gw);
 #endif
index e28bf171d7a073366dc45a490640881c5210b565..250af5c5cf1cfe4c529cd906a6d139627c69ff8c 100644 (file)
@@ -54,6 +54,7 @@ typedef long suseconds_t;
 
 /* prototypes */
 void     init_time(void);
+void     fini_time(void);
 s_time_t get_s_time(void);
 s_time_t get_v_time(void);
 u64      monotonic_clock(void);
index 1cab0a73db3429ab2b0ce081b6a51b571823f848..39faa0395d9d0bdedc6df949c246a59b05f55b73 100644 (file)
 #ifndef __ASSEMBLY__
 #include <types.h>
 #include <hypervisor.h>
+#include <kernel.h>
 
 #define USED    __attribute__ ((used))
 
-extern void do_exit(void) __attribute__((noreturn));
 #define BUG do_exit
 
 #endif
@@ -61,9 +61,11 @@ extern void do_exit(void) __attribute__((noreturn));
 extern shared_info_t *HYPERVISOR_shared_info;
 
 void trap_init(void);
+void trap_fini(void);
 
 void arch_init(start_info_t *si);
 void arch_print_info(void);
+void arch_fini(void);
 
 
 
index 2ed370f252661a870f8e478aee067f4b573990e2..f1585c9f70c91911092f1b2f9e723ebd5a8ff8d8 100644 (file)
@@ -90,4 +90,7 @@ char* xenbus_printf(xenbus_transaction_t xbt,
                                   char* node, char* path,
                                   char* fmt, ...);
 
+/* Reset the XenBus system. */
+void fini_xenbus(void);
+
 #endif /* XENBUS_H__ */
index ea92adca6abc854c90157004999407629704373f..e02b85880f1c6b4e169d50ce06592d0683685436 100644 (file)
--- a/kernel.c
+++ b/kernel.c
@@ -46,6 +46,7 @@
 #include <xen/features.h>
 #include <xen/version.h>
 
+static struct netfront_dev *net_dev;
 
 u8 xen_features[XENFEAT_NR_SUBMAPS * 32];
 
@@ -87,7 +88,7 @@ static void periodic_thread(void *p)
 
 static void netfront_thread(void *p)
 {
-    init_netfront(NULL, NULL, NULL, NULL);
+    net_dev = init_netfront(NULL, NULL, NULL, NULL);
 }
 
 static struct blkfront_dev *blk_dev;
@@ -347,9 +348,9 @@ static void refresh_cursor(int new_x, int new_y)
     fbfront_update(fb_dev, new_x, new_y, 9, 9);
 }
 
+static struct kbdfront_dev *kbd_dev;
 static void kbdfront_thread(void *p)
 {
-    struct kbdfront_dev *kbd_dev;
     DEFINE_WAIT(w);
     int x = WIDTH / 2, y = HEIGHT / 2, z = 0;
 
@@ -509,6 +510,49 @@ void start_kernel(start_info_t *si)
     run_idle_thread();
 }
 
+void stop_kernel(void)
+{
+    if (net_dev)
+        shutdown_netfront(net_dev);
+
+    if (blk_dev)
+        shutdown_blkfront(blk_dev);
+
+    if (fb_dev)
+        shutdown_fbfront(fb_dev);
+
+    if (kbd_dev)
+        shutdown_kbdfront(kbd_dev);
+
+    /* TODO: fs import */
+
+    local_irq_disable();
+
+    /* Reset grant tables */
+    fini_gnttab();
+
+    /* Reset the console driver. */
+    fini_console();
+    /* TODO: record new ring mfn & event in start_info */
+
+    /* Reset XenBus */
+    fini_xenbus();
+
+    /* Reset timers */
+    fini_time();
+
+    /* Reset memory management. */
+    fini_mm();
+
+    /* Reset events. */
+    fini_events();
+
+    /* Reset traps */
+    trap_fini();
+
+    /* Reset arch details */
+    arch_fini();
+}
 
 /*
  * do_exit: This is called whenever an IRET fails in entry.S.
index 2e68279c6f0e1abd0e99ff45784308acd669bc7e..4e7ffbdabfa015480c1987faf679513a526f1bfa 100644 (file)
@@ -376,3 +376,9 @@ void start_networking(void)
 
   tprintk("Network is ready.\n");
 }
+
+/* Shut down the network */
+void stop_networking(void)
+{
+  shutdown_netfront(dev);
+}
diff --git a/mm.c b/mm.c
index bc56030a25f1658d101002501be20293dee86cb9..fbb155881a1b0e3dadc407477f6bf520324dfbc4 100644 (file)
--- a/mm.c
+++ b/mm.c
@@ -419,6 +419,10 @@ void init_mm(void)
     arch_init_demand_mapping_area(max_pfn);
 }
 
+void fini_mm(void)
+{
+}
+
 void sanity_check(void)
 {
     int x;
index 5918853372e732a800ad5744c5d507aa3109cf5d..4feb0cc4a0865a365cc91ed1da2d775066c2f573 100644 (file)
@@ -501,6 +501,8 @@ void shutdown_netfront(struct netfront_dev *dev)
 
     xenbus_unwatch_path(XBT_NIL, path);
 
+    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
+
     free_netfront(dev);
 }
 
index 9065510e70b32cc03519f546c4a50b1390670c8d..8e721caec01070ed75878a19edec44a383765009 100644 (file)
@@ -124,7 +124,7 @@ char* xenbus_wait_for_value(const char* path, const char* value, xenbus_event_qu
 static void xenbus_thread_func(void *ign)
 {
     struct xsd_sockmsg msg;
-    unsigned prod = 0;
+    unsigned prod = xenstore_buf->rsp_prod;
 
     for (;;) 
     {
@@ -174,9 +174,14 @@ static void xenbus_thread_func(void *ign)
                         break;
                     }
 
-               event->next = *events;
-               *events = event;
-                wake_up(&xenbus_watch_queue);
+                if (events) {
+                    event->next = *events;
+                    *events = event;
+                    wake_up(&xenbus_watch_queue);
+                } else {
+                    printk("unexpected watch token %s\n", event->token);
+                    free(event);
+                }
             }
 
             else
@@ -265,6 +270,10 @@ void init_xenbus(void)
     DEBUG("xenbus on irq %d\n", err);
 }
 
+void fini_xenbus(void)
+{
+}
+
 /* 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