aboutsummaryrefslogtreecommitdiffstats
path: root/extras/mini-os
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2008-06-09 13:26:30 +0100
committerKeir Fraser <keir.fraser@citrix.com>2008-06-09 13:26:30 +0100
commitc68ffdc4fa75f9ed29ccdea16c9a910442e2fc20 (patch)
treeec2dc82b665f6046a46a4c90b5397fe51f17fac4 /extras/mini-os
parent0ba222a6fd5c72bda66eb3678c44fe3e43bbc6c0 (diff)
downloadxen-c68ffdc4fa75f9ed29ccdea16c9a910442e2fc20.tar.gz
xen-c68ffdc4fa75f9ed29ccdea16c9a910442e2fc20.tar.bz2
xen-c68ffdc4fa75f9ed29ccdea16c9a910442e2fc20.zip
minios: add proper shutdown facilities
Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
Diffstat (limited to 'extras/mini-os')
-rw-r--r--extras/mini-os/arch/ia64/common.c6
-rw-r--r--extras/mini-os/arch/ia64/time.c6
-rw-r--r--extras/mini-os/arch/x86/setup.c10
-rw-r--r--extras/mini-os/arch/x86/time.c9
-rw-r--r--extras/mini-os/arch/x86/traps.c4
-rw-r--r--extras/mini-os/blkfront.c2
-rw-r--r--extras/mini-os/console/console.c5
-rw-r--r--extras/mini-os/events.c33
-rw-r--r--extras/mini-os/fbfront.c4
-rw-r--r--extras/mini-os/fs-front.c2
-rw-r--r--extras/mini-os/gnttab.c11
-rw-r--r--extras/mini-os/include/console.h1
-rw-r--r--extras/mini-os/include/events.h1
-rw-r--r--extras/mini-os/include/gnttab.h1
-rw-r--r--extras/mini-os/include/ia64/os.h3
-rw-r--r--extras/mini-os/include/ia64/traps.h4
-rw-r--r--extras/mini-os/include/kernel.h7
-rw-r--r--extras/mini-os/include/mm.h1
-rw-r--r--extras/mini-os/include/netfront.h1
-rw-r--r--extras/mini-os/include/time.h1
-rw-r--r--extras/mini-os/include/x86/os.h4
-rw-r--r--extras/mini-os/include/xenbus.h3
-rw-r--r--extras/mini-os/kernel.c48
-rw-r--r--extras/mini-os/lwip-net.c6
-rw-r--r--extras/mini-os/mm.c4
-rw-r--r--extras/mini-os/netfront.c2
-rw-r--r--extras/mini-os/xenbus/xenbus.c17
27 files changed, 184 insertions, 12 deletions
diff --git a/extras/mini-os/arch/ia64/common.c b/extras/mini-os/arch/ia64/common.c
index cd4cec1e20..c65f0a0d07 100644
--- a/extras/mini-os/arch/ia64/common.c
+++ b/extras/mini-os/arch/ia64/common.c
@@ -236,6 +236,12 @@ arch_init(start_info_t *si)
}
void
+arch_fini(void)
+{
+ /* TODO */
+}
+
+void
arch_print_info(void)
{
int major, minor;
diff --git a/extras/mini-os/arch/ia64/time.c b/extras/mini-os/arch/ia64/time.c
index bbaa6b1864..baf9096330 100644
--- a/extras/mini-os/arch/ia64/time.c
+++ b/extras/mini-os/arch/ia64/time.c
@@ -280,3 +280,9 @@ init_time(void)
ia64_set_itm(new);
ia64_srlz_d();
}
+
+void
+fini_time(void)
+{
+ /* TODO */
+}
diff --git a/extras/mini-os/arch/x86/setup.c b/extras/mini-os/arch/x86/setup.c
index ca97131315..3671fee332 100644
--- a/extras/mini-os/arch/x86/setup.c
+++ b/extras/mini-os/arch/x86/setup.c
@@ -100,6 +100,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)
{
printk(" stack: %p-%p\n", stack, stack + sizeof(stack));
diff --git a/extras/mini-os/arch/x86/time.c b/extras/mini-os/arch/x86/time.c
index d7b387f95f..4af0b89b94 100644
--- a/extras/mini-os/arch/x86/time.c
+++ b/extras/mini-os/arch/x86/time.c
@@ -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);
+}
diff --git a/extras/mini-os/arch/x86/traps.c b/extras/mini-os/arch/x86/traps.c
index 5719f741e1..003ffb52b3 100644
--- a/extras/mini-os/arch/x86/traps.c
+++ b/extras/mini-os/arch/x86/traps.c
@@ -268,3 +268,7 @@ void trap_init(void)
HYPERVISOR_set_trap_table(trap_table);
}
+void trap_fini(void)
+{
+ HYPERVISOR_set_trap_table(NULL);
+}
diff --git a/extras/mini-os/blkfront.c b/extras/mini-os/blkfront.c
index 2e2eea2271..e2ac965434 100644
--- a/extras/mini-os/blkfront.c
+++ b/extras/mini-os/blkfront.c
@@ -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);
}
diff --git a/extras/mini-os/console/console.c b/extras/mini-os/console/console.c
index 94379ddb33..3805943465 100644
--- a/extras/mini-os/console/console.c
+++ b/extras/mini-os/console/console.c
@@ -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 */
+}
diff --git a/extras/mini-os/events.c b/extras/mini-os/events.c
index f47fc38822..87f54ef5eb 100644
--- a/extras/mini-os/events.c
+++ b/extras/mini-os/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;
diff --git a/extras/mini-os/fbfront.c b/extras/mini-os/fbfront.c
index 60c7552d00..55864f360e 100644
--- a/extras/mini-os/fbfront.c
+++ b/extras/mini-os/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);
diff --git a/extras/mini-os/fs-front.c b/extras/mini-os/fs-front.c
index 5b7bc6a4a2..0b27df361b 100644
--- a/extras/mini-os/fs-front.c
+++ b/extras/mini-os/fs-front.c
@@ -1127,3 +1127,5 @@ void init_fs_frontend(void)
if (!fs_import)
printk("No FS import\n");
}
+
+/* TODO: shutdown */
diff --git a/extras/mini-os/gnttab.c b/extras/mini-os/gnttab.c
index dd66b043bf..d94c28b815 100644
--- a/extras/mini-os/gnttab.c
+++ b/extras/mini-os/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);
+}
diff --git a/extras/mini-os/include/console.h b/extras/mini-os/include/console.h
index ac9cb53e7b..4a61f1aaa0 100644
--- a/extras/mini-os/include/console.h
+++ b/extras/mini-os/include/console.h
@@ -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;
diff --git a/extras/mini-os/include/events.h b/extras/mini-os/include/events.h
index ff202e38fe..9ffb35d320 100644
--- a/extras/mini-os/include/events.h
+++ b/extras/mini-os/include/events.h
@@ -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_ */
diff --git a/extras/mini-os/include/gnttab.h b/extras/mini-os/include/gnttab.h
index f952442955..acd6c39f8c 100644
--- a/extras/mini-os/include/gnttab.h
+++ b/extras/mini-os/include/gnttab.h
@@ -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__ */
diff --git a/extras/mini-os/include/ia64/os.h b/extras/mini-os/include/ia64/os.h
index 2ae5331393..bf3785fc82 100644
--- a/extras/mini-os/include/ia64/os.h
+++ b/extras/mini-os/include/ia64/os.h
@@ -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 */
diff --git a/extras/mini-os/include/ia64/traps.h b/extras/mini-os/include/ia64/traps.h
index 4c5e7be527..e79a952aec 100644
--- a/extras/mini-os/include/ia64/traps.h
+++ b/extras/mini-os/include/ia64/traps.h
@@ -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/extras/mini-os/include/kernel.h b/extras/mini-os/include/kernel.h
new file mode 100644
index 0000000000..b36f172ed8
--- /dev/null
+++ b/extras/mini-os/include/kernel.h
@@ -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_ */
diff --git a/extras/mini-os/include/mm.h b/extras/mini-os/include/mm.h
index 28fb727f9f..7c8588ccf8 100644
--- a/extras/mini-os/include/mm.h
+++ b/extras/mini-os/include/mm.h
@@ -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_ */
diff --git a/extras/mini-os/include/netfront.h b/extras/mini-os/include/netfront.h
index 526dc94b5c..681ebf2c0f 100644
--- a/extras/mini-os/include/netfront.h
+++ b/extras/mini-os/include/netfront.h
@@ -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
diff --git a/extras/mini-os/include/time.h b/extras/mini-os/include/time.h
index e28bf171d7..250af5c5cf 100644
--- a/extras/mini-os/include/time.h
+++ b/extras/mini-os/include/time.h
@@ -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);
diff --git a/extras/mini-os/include/x86/os.h b/extras/mini-os/include/x86/os.h
index 1cab0a73db..39faa0395d 100644
--- a/extras/mini-os/include/x86/os.h
+++ b/extras/mini-os/include/x86/os.h
@@ -18,10 +18,10 @@
#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);
diff --git a/extras/mini-os/include/xenbus.h b/extras/mini-os/include/xenbus.h
index 2ed370f252..f1585c9f70 100644
--- a/extras/mini-os/include/xenbus.h
+++ b/extras/mini-os/include/xenbus.h
@@ -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__ */
diff --git a/extras/mini-os/kernel.c b/extras/mini-os/kernel.c
index ea92adca6a..e02b85880f 100644
--- a/extras/mini-os/kernel.c
+++ b/extras/mini-os/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.
diff --git a/extras/mini-os/lwip-net.c b/extras/mini-os/lwip-net.c
index 2e68279c6f..4e7ffbdabf 100644
--- a/extras/mini-os/lwip-net.c
+++ b/extras/mini-os/lwip-net.c
@@ -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/extras/mini-os/mm.c b/extras/mini-os/mm.c
index bc56030a25..fbb155881a 100644
--- a/extras/mini-os/mm.c
+++ b/extras/mini-os/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;
diff --git a/extras/mini-os/netfront.c b/extras/mini-os/netfront.c
index 5918853372..4feb0cc4a0 100644
--- a/extras/mini-os/netfront.c
+++ b/extras/mini-os/netfront.c
@@ -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);
}
diff --git a/extras/mini-os/xenbus/xenbus.c b/extras/mini-os/xenbus/xenbus.c
index 9065510e70..8e721caec0 100644
--- a/extras/mini-os/xenbus/xenbus.c
+++ b/extras/mini-os/xenbus/xenbus.c
@@ -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