diff options
author | kaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk> | 2005-12-08 15:24:02 +0100 |
---|---|---|
committer | kaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk> | 2005-12-08 15:24:02 +0100 |
commit | 7fc4533b321fbe7ef6ce0ef05e3b99cebe13a39e (patch) | |
tree | b862d841d85f51754110df948f0b471c5e4583de /extras/mini-os/include | |
parent | bc70813814bf808d64f0331c2e450662058e07a7 (diff) | |
download | xen-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.h | 6 | ||||
-rw-r--r-- | extras/mini-os/include/os.h | 2 | ||||
-rw-r--r-- | extras/mini-os/include/semaphore.h | 39 | ||||
-rw-r--r-- | extras/mini-os/include/spinlock.h | 121 | ||||
-rw-r--r-- | extras/mini-os/include/wait.h | 4 | ||||
-rw-r--r-- | extras/mini-os/include/xenbus.h | 191 | ||||
-rw-r--r-- | extras/mini-os/include/xmalloc.h | 3 |
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 *); |