aboutsummaryrefslogtreecommitdiffstats
path: root/extras/mini-os/include
diff options
context:
space:
mode:
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2005-12-08 15:24:02 +0100
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2005-12-08 15:24:02 +0100
commit7fc4533b321fbe7ef6ce0ef05e3b99cebe13a39e (patch)
treeb862d841d85f51754110df948f0b471c5e4583de /extras/mini-os/include
parentbc70813814bf808d64f0331c2e450662058e07a7 (diff)
downloadxen-7fc4533b321fbe7ef6ce0ef05e3b99cebe13a39e.tar.gz
xen-7fc4533b321fbe7ef6ce0ef05e3b99cebe13a39e.tar.bz2
xen-7fc4533b321fbe7ef6ce0ef05e3b99cebe13a39e.zip
Merge in the newer Xenbus implementation from Linux to the Mini-OS. The new
version compiles and starts up, but I'm not really sure how to test the new xenbus implementation. * Added unbind_evtchn * Copied parts of the Linux spinlock implementation to make the changes to xenbus compared to Linux smaller. Also added a dummy rwsem implementation. * Updated the xenbus-files Signed-off-by: Simon Kagstrom <simon.kagstrom@bth.se>
Diffstat (limited to 'extras/mini-os/include')
-rw-r--r--extras/mini-os/include/events.h6
-rw-r--r--extras/mini-os/include/os.h2
-rw-r--r--extras/mini-os/include/semaphore.h39
-rw-r--r--extras/mini-os/include/spinlock.h121
-rw-r--r--extras/mini-os/include/wait.h4
-rw-r--r--extras/mini-os/include/xenbus.h191
-rw-r--r--extras/mini-os/include/xmalloc.h3
7 files changed, 336 insertions, 30 deletions
diff --git a/extras/mini-os/include/events.h b/extras/mini-os/include/events.h
index 76226efcd5..c4e7c67fd8 100644
--- a/extras/mini-os/include/events.h
+++ b/extras/mini-os/include/events.h
@@ -40,10 +40,12 @@ typedef struct _ev_action_t {
/* prototypes */
int do_event(u32 port, struct pt_regs *regs);
int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *) );
-void bind_evtchn( u32 virq, void (*handler)(int, struct pt_regs *) );
+int bind_evtchn( u32 virq, void (*handler)(int, struct pt_regs *) );
+void unbind_evtchn( u32 port );
void init_events(void);
+void unbind_virq( u32 port );
-static inline int notify_via_evtchn(int port)
+static inline int notify_remote_via_evtchn(int port)
{
evtchn_op_t op;
op.cmd = EVTCHNOP_send;
diff --git a/extras/mini-os/include/os.h b/extras/mini-os/include/os.h
index 805739f239..2fbb11c203 100644
--- a/extras/mini-os/include/os.h
+++ b/extras/mini-os/include/os.h
@@ -131,9 +131,11 @@ do { \
#if defined(__i386__)
#define mb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
#define rmb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
+#define wmb() __asm__ __volatile__ ("": : :"memory")
#elif defined(__x86_64__)
#define mb() __asm__ __volatile__ ("mfence":::"memory")
#define rmb() __asm__ __volatile__ ("lfence":::"memory")
+#define wmb() __asm__ __volatile__ ("sfence" ::: "memory") /* From CONFIG_UNORDERED_IO (linux) */
#endif
diff --git a/extras/mini-os/include/semaphore.h b/extras/mini-os/include/semaphore.h
index d30c81e674..47365d25fd 100644
--- a/extras/mini-os/include/semaphore.h
+++ b/extras/mini-os/include/semaphore.h
@@ -2,6 +2,7 @@
#define _SEMAPHORE_H_
#include <wait.h>
+#include <spinlock.h>
/*
* Implementation of semaphore in Mini-os is simple, because
@@ -14,6 +15,15 @@ struct semaphore
struct wait_queue_head wait;
};
+/*
+ * the semaphore definition
+ */
+struct rw_semaphore {
+ signed long count;
+ spinlock_t wait_lock;
+ struct list_head wait_list;
+ int debug;
+};
#define __SEMAPHORE_INITIALIZER(name, n) \
{ \
@@ -31,6 +41,12 @@ struct semaphore
#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
+static inline void init_MUTEX(struct semaphore *sem)
+{
+ sem->count = 1;
+ init_waitqueue_head(&sem->wait);
+}
+
static void inline down(struct semaphore *sem)
{
wait_event(sem->wait, sem->count > 0);
@@ -43,4 +59,27 @@ static void inline up(struct semaphore *sem)
wake_up(&sem->wait);
}
+/* FIXME! Thre read/write semaphores are unimplemented! */
+static inline void init_rwsem(struct rw_semaphore *sem)
+{
+ sem->count = 1;
+}
+
+static inline void down_read(struct rw_semaphore *sem)
+{
+}
+
+
+static inline void up_read(struct rw_semaphore *sem)
+{
+}
+
+static inline void up_write(struct rw_semaphore *sem)
+{
+}
+
+static inline void down_write(struct rw_semaphore *sem)
+{
+}
+
#endif /* _SEMAPHORE_H */
diff --git a/extras/mini-os/include/spinlock.h b/extras/mini-os/include/spinlock.h
new file mode 100644
index 0000000000..4274cd2869
--- /dev/null
+++ b/extras/mini-os/include/spinlock.h
@@ -0,0 +1,121 @@
+#ifndef __ASM_SPINLOCK_H
+#define __ASM_SPINLOCK_H
+
+#include <lib.h>
+
+/*
+ * Your basic SMP spinlocks, allowing only a single CPU anywhere
+ */
+
+typedef struct {
+ volatile unsigned int slock;
+} spinlock_t;
+
+#define SPINLOCK_MAGIC 0xdead4ead
+
+#define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 }
+
+#define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
+
+/*
+ * Simple spin lock operations. There are two variants, one clears IRQ's
+ * on the local processor, one does not.
+ *
+ * We make no fairness assumptions. They have a cost.
+ */
+
+#define spin_is_locked(x) (*(volatile signed char *)(&(x)->slock) <= 0)
+#define spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x))
+
+#define spin_lock_string \
+ "1:\n" \
+ LOCK \
+ "decb %0\n\t" \
+ "jns 3f\n" \
+ "2:\t" \
+ "rep;nop\n\t" \
+ "cmpb $0,%0\n\t" \
+ "jle 2b\n\t" \
+ "jmp 1b\n" \
+ "3:\n\t"
+
+#define spin_lock_string_flags \
+ "1:\n" \
+ LOCK \
+ "decb %0\n\t" \
+ "jns 4f\n\t" \
+ "2:\t" \
+ "testl $0x200, %1\n\t" \
+ "jz 3f\n\t" \
+ "#sti\n\t" \
+ "3:\t" \
+ "rep;nop\n\t" \
+ "cmpb $0, %0\n\t" \
+ "jle 3b\n\t" \
+ "#cli\n\t" \
+ "jmp 1b\n" \
+ "4:\n\t"
+
+/*
+ * This works. Despite all the confusion.
+ * (except on PPro SMP or if we are using OOSTORE)
+ * (PPro errata 66, 92)
+ */
+
+#define spin_unlock_string \
+ "xchgb %b0, %1" \
+ :"=q" (oldval), "=m" (lock->slock) \
+ :"0" (oldval) : "memory"
+
+static inline void _raw_spin_unlock(spinlock_t *lock)
+{
+ char oldval = 1;
+ __asm__ __volatile__(
+ spin_unlock_string
+ );
+}
+
+static inline int _raw_spin_trylock(spinlock_t *lock)
+{
+ char oldval;
+ __asm__ __volatile__(
+ "xchgb %b0,%1\n"
+ :"=q" (oldval), "=m" (lock->slock)
+ :"0" (0) : "memory");
+ return oldval > 0;
+}
+
+static inline void _raw_spin_lock(spinlock_t *lock)
+{
+ __asm__ __volatile__(
+ spin_lock_string
+ :"=m" (lock->slock) : : "memory");
+}
+
+static inline void _raw_spin_lock_flags (spinlock_t *lock, unsigned long flags)
+{
+ __asm__ __volatile__(
+ spin_lock_string_flags
+ :"=m" (lock->slock) : "r" (flags) : "memory");
+}
+
+#define _spin_trylock(lock) ({_raw_spin_trylock(lock) ? \
+ 1 : ({ 0;});})
+
+#define _spin_lock(lock) \
+do { \
+ _raw_spin_lock(lock); \
+} while(0)
+
+#define _spin_unlock(lock) \
+do { \
+ _raw_spin_unlock(lock); \
+} while (0)
+
+
+#define spin_lock(lock) _spin_lock(lock)
+#define spin_unlock(lock) _spin_unlock(lock)
+
+#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED
+
+#endif
diff --git a/extras/mini-os/include/wait.h b/extras/mini-os/include/wait.h
index 4c23855620..21781d818e 100644
--- a/extras/mini-os/include/wait.h
+++ b/extras/mini-os/include/wait.h
@@ -33,6 +33,10 @@ struct wait_queue name = { \
}
+static inline void init_waitqueue_head(struct wait_queue_head *h)
+{
+ INIT_LIST_HEAD(&h->thread_list);
+}
static inline void init_waitqueue_entry(struct wait_queue *q, struct thread *thread)
{
diff --git a/extras/mini-os/include/xenbus.h b/extras/mini-os/include/xenbus.h
index 9acd17f03f..539bf0911e 100644
--- a/extras/mini-os/include/xenbus.h
+++ b/extras/mini-os/include/xenbus.h
@@ -4,6 +4,7 @@
* 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:
@@ -30,45 +31,98 @@
#ifndef _ASM_XEN_XENBUS_H
#define _ASM_XEN_XENBUS_H
+#include <errno.h>
+#include <xen/io/xenbus.h>
+#include <xen/io/xs_wire.h>
-/* Caller must hold this lock to call these functions: it's also held
- * across watch callbacks. */
-// TODO
-//extern struct semaphore xenbus_lock;
+/* 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);
+};
-char **xenbus_directory(const char *dir, const char *node, unsigned int *num);
-void *xenbus_read(const char *dir, const char *node, unsigned int *len);
-int xenbus_write(const char *dir, const char *node,
- const char *string, int createflags);
-int xenbus_mkdir(const char *dir, const char *node);
-int xenbus_exists(const char *dir, const char *node);
-int xenbus_rm(const char *dir, const char *node);
-int xenbus_transaction_start(const char *subtree);
-int xenbus_transaction_end(int abort);
+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(const char *dir, const char *node, const char *fmt, ...)
- __attribute__((format(scanf, 3, 4)));
+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(const char *dir, const char *node, const char *fmt, ...)
- __attribute__((format(printf, 3, 4)));
+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(const char *dir, ...);
-
-/* Register callback to watch this node. */
-struct xenbus_watch
-{
- struct list_head list;
- char *node;
- void (*callback)(struct xenbus_watch *, const char *node);
-};
+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 reregister_xenbus_watches(void);
+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);
@@ -84,6 +138,87 @@ void xenbus_resume(void);
#define XENBUS_EXIST_ERR(err) ((err) == -ENOENT || (err) == -ERANGE)
-int xs_init(void);
+
+/**
+ * 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 */
diff --git a/extras/mini-os/include/xmalloc.h b/extras/mini-os/include/xmalloc.h
index e29a0387fc..f5e721fa16 100644
--- a/extras/mini-os/include/xmalloc.h
+++ b/extras/mini-os/include/xmalloc.h
@@ -7,6 +7,9 @@
/* Allocate space for array of typed objects. */
#define xmalloc_array(_type, _num) ((_type *)_xmalloc_array(sizeof(_type), __alignof__(_type), _num))
+#define malloc(size) _xmalloc(size, 4)
+#define free(ptr) xfree(ptr)
+
/* Free any of the above. */
extern void xfree(const void *);