diff options
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 |