mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
minios: add proper shutdown facilities
Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
This commit is contained in:
1 parent
0ba222a6fd
commit
c68ffdc4fa
27 files changed
+184
-12
No files matched your search
@@ -235,6 +235,12 @@ arch_init(start_info_t *si)
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
void
|
||||
arch_fini(void)
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
void
|
||||
arch_print_info(void)
|
||||
{
|
||||
|
||||
@@ -280,3 +280,9 @@ init_time(void)
|
||||
ia64_set_itm(new);
|
||||
ia64_srlz_d();
|
||||
}
|
||||
|
||||
void
|
||||
fini_time(void)
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -268,3 +268,7 @@ void trap_init(void)
|
||||
HYPERVISOR_set_trap_table(trap_table);
|
||||
}
|
||||
|
||||
void trap_fini(void)
|
||||
{
|
||||
HYPERVISOR_set_trap_table(NULL);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
+30
-3
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -1127,3 +1127,5 @@ void init_fs_frontend(void)
|
||||
if (!fs_import)
|
||||
printk("No FS import\n");
|
||||
}
|
||||
|
||||
/* TODO: shutdown */
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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_ */
|
||||
@@ -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__ */
|
||||
@@ -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 */
|
||||
|
||||
@@ -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__) */
|
||||
|
||||
@@ -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_ */
|
||||
@@ -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_ */
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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__ */
|
||||
+46
-2
@@ -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.
|
||||
|
||||
@@ -376,3 +376,9 @@ void start_networking(void)
|
||||
|
||||
tprintk("Network is ready.\n");
|
||||
}
|
||||
|
||||
/* Shut down the network */
|
||||
void stop_networking(void)
|
||||
{
|
||||
shutdown_netfront(dev);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||