ia64/xen-unstable
changeset 8284:7557f0b4098c
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>
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>
author | kaf24@firebug.cl.cam.ac.uk |
---|---|
date | Thu Dec 08 15:24:02 2005 +0100 (2005-12-08) |
parents | 5f7398785e02 |
children | 89a223305611 |
files | extras/mini-os/events.c extras/mini-os/include/events.h extras/mini-os/include/os.h extras/mini-os/include/semaphore.h extras/mini-os/include/spinlock.h extras/mini-os/include/wait.h extras/mini-os/include/xenbus.h extras/mini-os/include/xmalloc.h extras/mini-os/kernel.c extras/mini-os/xenbus/xenbus_comms.c extras/mini-os/xenbus/xenbus_comms.h extras/mini-os/xenbus/xenbus_xs.c |
line diff
1.1 --- a/extras/mini-os/events.c Thu Dec 08 15:21:36 2005 +0100 1.2 +++ b/extras/mini-os/events.c Thu Dec 08 15:24:02 2005 +0100 1.3 @@ -56,7 +56,7 @@ int do_event(u32 port, struct pt_regs *r 1.4 1.5 } 1.6 1.7 -void bind_evtchn( u32 port, void (*handler)(int, struct pt_regs *) ) 1.8 +int bind_evtchn( u32 port, void (*handler)(int, struct pt_regs *) ) 1.9 { 1.10 if(ev_actions[port].handler) 1.11 printk("WARN: Handler for port %d already registered, replacing\n", 1.12 @@ -67,6 +67,16 @@ void bind_evtchn( u32 port, void (*handl 1.13 1.14 /* Finally unmask the port */ 1.15 unmask_evtchn(port); 1.16 + 1.17 + return port; 1.18 +} 1.19 + 1.20 +void unbind_evtchn( u32 port ) 1.21 +{ 1.22 + if (!ev_actions[port].handler) 1.23 + printk("WARN: No handler for port %d when unbinding\n", port); 1.24 + ev_actions[port].handler = NULL; 1.25 + ev_actions[port].status |= EVS_DISABLED; 1.26 } 1.27 1.28 int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *) ) 1.29 @@ -90,6 +100,10 @@ out: 1.30 return ret; 1.31 } 1.32 1.33 +void unbind_virq( u32 port ) 1.34 +{ 1.35 + unbind_evtchn(port); 1.36 +} 1.37 1.38 1.39 /*
2.1 --- a/extras/mini-os/include/events.h Thu Dec 08 15:21:36 2005 +0100 2.2 +++ b/extras/mini-os/include/events.h Thu Dec 08 15:24:02 2005 +0100 2.3 @@ -40,10 +40,12 @@ typedef struct _ev_action_t { 2.4 /* prototypes */ 2.5 int do_event(u32 port, struct pt_regs *regs); 2.6 int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *) ); 2.7 -void bind_evtchn( u32 virq, void (*handler)(int, struct pt_regs *) ); 2.8 +int bind_evtchn( u32 virq, void (*handler)(int, struct pt_regs *) ); 2.9 +void unbind_evtchn( u32 port ); 2.10 void init_events(void); 2.11 +void unbind_virq( u32 port ); 2.12 2.13 -static inline int notify_via_evtchn(int port) 2.14 +static inline int notify_remote_via_evtchn(int port) 2.15 { 2.16 evtchn_op_t op; 2.17 op.cmd = EVTCHNOP_send;
3.1 --- a/extras/mini-os/include/os.h Thu Dec 08 15:21:36 2005 +0100 3.2 +++ b/extras/mini-os/include/os.h Thu Dec 08 15:24:02 2005 +0100 3.3 @@ -131,9 +131,11 @@ do { \ 3.4 #if defined(__i386__) 3.5 #define mb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory") 3.6 #define rmb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory") 3.7 +#define wmb() __asm__ __volatile__ ("": : :"memory") 3.8 #elif defined(__x86_64__) 3.9 #define mb() __asm__ __volatile__ ("mfence":::"memory") 3.10 #define rmb() __asm__ __volatile__ ("lfence":::"memory") 3.11 +#define wmb() __asm__ __volatile__ ("sfence" ::: "memory") /* From CONFIG_UNORDERED_IO (linux) */ 3.12 #endif 3.13 3.14
4.1 --- a/extras/mini-os/include/semaphore.h Thu Dec 08 15:21:36 2005 +0100 4.2 +++ b/extras/mini-os/include/semaphore.h Thu Dec 08 15:24:02 2005 +0100 4.3 @@ -2,6 +2,7 @@ 4.4 #define _SEMAPHORE_H_ 4.5 4.6 #include <wait.h> 4.7 +#include <spinlock.h> 4.8 4.9 /* 4.10 * Implementation of semaphore in Mini-os is simple, because 4.11 @@ -14,6 +15,15 @@ struct semaphore 4.12 struct wait_queue_head wait; 4.13 }; 4.14 4.15 +/* 4.16 + * the semaphore definition 4.17 + */ 4.18 +struct rw_semaphore { 4.19 + signed long count; 4.20 + spinlock_t wait_lock; 4.21 + struct list_head wait_list; 4.22 + int debug; 4.23 +}; 4.24 4.25 #define __SEMAPHORE_INITIALIZER(name, n) \ 4.26 { \ 4.27 @@ -31,6 +41,12 @@ struct semaphore 4.28 4.29 #define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0) 4.30 4.31 +static inline void init_MUTEX(struct semaphore *sem) 4.32 +{ 4.33 + sem->count = 1; 4.34 + init_waitqueue_head(&sem->wait); 4.35 +} 4.36 + 4.37 static void inline down(struct semaphore *sem) 4.38 { 4.39 wait_event(sem->wait, sem->count > 0); 4.40 @@ -43,4 +59,27 @@ static void inline up(struct semaphore * 4.41 wake_up(&sem->wait); 4.42 } 4.43 4.44 +/* FIXME! Thre read/write semaphores are unimplemented! */ 4.45 +static inline void init_rwsem(struct rw_semaphore *sem) 4.46 +{ 4.47 + sem->count = 1; 4.48 +} 4.49 + 4.50 +static inline void down_read(struct rw_semaphore *sem) 4.51 +{ 4.52 +} 4.53 + 4.54 + 4.55 +static inline void up_read(struct rw_semaphore *sem) 4.56 +{ 4.57 +} 4.58 + 4.59 +static inline void up_write(struct rw_semaphore *sem) 4.60 +{ 4.61 +} 4.62 + 4.63 +static inline void down_write(struct rw_semaphore *sem) 4.64 +{ 4.65 +} 4.66 + 4.67 #endif /* _SEMAPHORE_H */
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/extras/mini-os/include/spinlock.h Thu Dec 08 15:24:02 2005 +0100 5.3 @@ -0,0 +1,121 @@ 5.4 +#ifndef __ASM_SPINLOCK_H 5.5 +#define __ASM_SPINLOCK_H 5.6 + 5.7 +#include <lib.h> 5.8 + 5.9 +/* 5.10 + * Your basic SMP spinlocks, allowing only a single CPU anywhere 5.11 + */ 5.12 + 5.13 +typedef struct { 5.14 + volatile unsigned int slock; 5.15 +} spinlock_t; 5.16 + 5.17 +#define SPINLOCK_MAGIC 0xdead4ead 5.18 + 5.19 +#define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 } 5.20 + 5.21 +#define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while(0) 5.22 + 5.23 +/* 5.24 + * Simple spin lock operations. There are two variants, one clears IRQ's 5.25 + * on the local processor, one does not. 5.26 + * 5.27 + * We make no fairness assumptions. They have a cost. 5.28 + */ 5.29 + 5.30 +#define spin_is_locked(x) (*(volatile signed char *)(&(x)->slock) <= 0) 5.31 +#define spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x)) 5.32 + 5.33 +#define spin_lock_string \ 5.34 + "1:\n" \ 5.35 + LOCK \ 5.36 + "decb %0\n\t" \ 5.37 + "jns 3f\n" \ 5.38 + "2:\t" \ 5.39 + "rep;nop\n\t" \ 5.40 + "cmpb $0,%0\n\t" \ 5.41 + "jle 2b\n\t" \ 5.42 + "jmp 1b\n" \ 5.43 + "3:\n\t" 5.44 + 5.45 +#define spin_lock_string_flags \ 5.46 + "1:\n" \ 5.47 + LOCK \ 5.48 + "decb %0\n\t" \ 5.49 + "jns 4f\n\t" \ 5.50 + "2:\t" \ 5.51 + "testl $0x200, %1\n\t" \ 5.52 + "jz 3f\n\t" \ 5.53 + "#sti\n\t" \ 5.54 + "3:\t" \ 5.55 + "rep;nop\n\t" \ 5.56 + "cmpb $0, %0\n\t" \ 5.57 + "jle 3b\n\t" \ 5.58 + "#cli\n\t" \ 5.59 + "jmp 1b\n" \ 5.60 + "4:\n\t" 5.61 + 5.62 +/* 5.63 + * This works. Despite all the confusion. 5.64 + * (except on PPro SMP or if we are using OOSTORE) 5.65 + * (PPro errata 66, 92) 5.66 + */ 5.67 + 5.68 +#define spin_unlock_string \ 5.69 + "xchgb %b0, %1" \ 5.70 + :"=q" (oldval), "=m" (lock->slock) \ 5.71 + :"0" (oldval) : "memory" 5.72 + 5.73 +static inline void _raw_spin_unlock(spinlock_t *lock) 5.74 +{ 5.75 + char oldval = 1; 5.76 + __asm__ __volatile__( 5.77 + spin_unlock_string 5.78 + ); 5.79 +} 5.80 + 5.81 +static inline int _raw_spin_trylock(spinlock_t *lock) 5.82 +{ 5.83 + char oldval; 5.84 + __asm__ __volatile__( 5.85 + "xchgb %b0,%1\n" 5.86 + :"=q" (oldval), "=m" (lock->slock) 5.87 + :"0" (0) : "memory"); 5.88 + return oldval > 0; 5.89 +} 5.90 + 5.91 +static inline void _raw_spin_lock(spinlock_t *lock) 5.92 +{ 5.93 + __asm__ __volatile__( 5.94 + spin_lock_string 5.95 + :"=m" (lock->slock) : : "memory"); 5.96 +} 5.97 + 5.98 +static inline void _raw_spin_lock_flags (spinlock_t *lock, unsigned long flags) 5.99 +{ 5.100 + __asm__ __volatile__( 5.101 + spin_lock_string_flags 5.102 + :"=m" (lock->slock) : "r" (flags) : "memory"); 5.103 +} 5.104 + 5.105 +#define _spin_trylock(lock) ({_raw_spin_trylock(lock) ? \ 5.106 + 1 : ({ 0;});}) 5.107 + 5.108 +#define _spin_lock(lock) \ 5.109 +do { \ 5.110 + _raw_spin_lock(lock); \ 5.111 +} while(0) 5.112 + 5.113 +#define _spin_unlock(lock) \ 5.114 +do { \ 5.115 + _raw_spin_unlock(lock); \ 5.116 +} while (0) 5.117 + 5.118 + 5.119 +#define spin_lock(lock) _spin_lock(lock) 5.120 +#define spin_unlock(lock) _spin_unlock(lock) 5.121 + 5.122 +#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED 5.123 + 5.124 +#endif
6.1 --- a/extras/mini-os/include/wait.h Thu Dec 08 15:21:36 2005 +0100 6.2 +++ b/extras/mini-os/include/wait.h Thu Dec 08 15:24:02 2005 +0100 6.3 @@ -33,6 +33,10 @@ struct wait_queue name = { 6.4 } 6.5 6.6 6.7 +static inline void init_waitqueue_head(struct wait_queue_head *h) 6.8 +{ 6.9 + INIT_LIST_HEAD(&h->thread_list); 6.10 +} 6.11 6.12 static inline void init_waitqueue_entry(struct wait_queue *q, struct thread *thread) 6.13 {
7.1 --- a/extras/mini-os/include/xenbus.h Thu Dec 08 15:21:36 2005 +0100 7.2 +++ b/extras/mini-os/include/xenbus.h Thu Dec 08 15:24:02 2005 +0100 7.3 @@ -4,6 +4,7 @@ 7.4 * Talks to Xen Store to figure out what devices we have. 7.5 * 7.6 * Copyright (C) 2005 Rusty Russell, IBM Corporation 7.7 + * Copyright (C) 2005 XenSource Ltd. 7.8 * 7.9 * This file may be distributed separately from the Linux kernel, or 7.10 * incorporated into other software packages, subject to the following license: 7.11 @@ -30,45 +31,98 @@ 7.12 #ifndef _ASM_XEN_XENBUS_H 7.13 #define _ASM_XEN_XENBUS_H 7.14 7.15 - 7.16 -/* Caller must hold this lock to call these functions: it's also held 7.17 - * across watch callbacks. */ 7.18 -// TODO 7.19 -//extern struct semaphore xenbus_lock; 7.20 - 7.21 -char **xenbus_directory(const char *dir, const char *node, unsigned int *num); 7.22 -void *xenbus_read(const char *dir, const char *node, unsigned int *len); 7.23 -int xenbus_write(const char *dir, const char *node, 7.24 - const char *string, int createflags); 7.25 -int xenbus_mkdir(const char *dir, const char *node); 7.26 -int xenbus_exists(const char *dir, const char *node); 7.27 -int xenbus_rm(const char *dir, const char *node); 7.28 -int xenbus_transaction_start(const char *subtree); 7.29 -int xenbus_transaction_end(int abort); 7.30 - 7.31 -/* Single read and scanf: returns -errno or num scanned if > 0. */ 7.32 -int xenbus_scanf(const char *dir, const char *node, const char *fmt, ...) 7.33 - __attribute__((format(scanf, 3, 4))); 7.34 - 7.35 -/* Single printf and write: returns -errno or 0. */ 7.36 -int xenbus_printf(const char *dir, const char *node, const char *fmt, ...) 7.37 - __attribute__((format(printf, 3, 4))); 7.38 - 7.39 -/* Generic read function: NULL-terminated triples of name, 7.40 - * sprintf-style type string, and pointer. Returns 0 or errno.*/ 7.41 -int xenbus_gather(const char *dir, ...); 7.42 +#include <errno.h> 7.43 +#include <xen/io/xenbus.h> 7.44 +#include <xen/io/xs_wire.h> 7.45 7.46 /* Register callback to watch this node. */ 7.47 struct xenbus_watch 7.48 { 7.49 struct list_head list; 7.50 - char *node; 7.51 - void (*callback)(struct xenbus_watch *, const char *node); 7.52 + 7.53 + /* Path being watched. */ 7.54 + const char *node; 7.55 + 7.56 + /* Callback (executed in a process context with no locks held). */ 7.57 + void (*callback)(struct xenbus_watch *, 7.58 + const char **vec, unsigned int len); 7.59 +}; 7.60 + 7.61 + 7.62 +/* A xenbus device. */ 7.63 +struct xenbus_device { 7.64 + const char *devicetype; 7.65 + const char *nodename; 7.66 + const char *otherend; 7.67 + int otherend_id; 7.68 + struct xenbus_watch otherend_watch; 7.69 + int has_error; 7.70 + void *data; 7.71 +}; 7.72 + 7.73 +struct xenbus_device_id 7.74 +{ 7.75 + /* .../device/<device_type>/<identifier> */ 7.76 + char devicetype[32]; /* General class of device. */ 7.77 }; 7.78 7.79 +/* A xenbus driver. */ 7.80 +struct xenbus_driver { 7.81 + char *name; 7.82 + struct module *owner; 7.83 + const struct xenbus_device_id *ids; 7.84 + int (*probe)(struct xenbus_device *dev, 7.85 + const struct xenbus_device_id *id); 7.86 + void (*otherend_changed)(struct xenbus_device *dev, 7.87 + XenbusState backend_state); 7.88 + int (*remove)(struct xenbus_device *dev); 7.89 + int (*suspend)(struct xenbus_device *dev); 7.90 + int (*resume)(struct xenbus_device *dev); 7.91 + int (*hotplug)(struct xenbus_device *, char **, int, char *, int); 7.92 + int (*read_otherend_details)(struct xenbus_device *dev); 7.93 +}; 7.94 + 7.95 +int xenbus_register_frontend(struct xenbus_driver *drv); 7.96 +int xenbus_register_backend(struct xenbus_driver *drv); 7.97 +void xenbus_unregister_driver(struct xenbus_driver *drv); 7.98 + 7.99 +struct xenbus_transaction; 7.100 + 7.101 +char **xenbus_directory(struct xenbus_transaction *t, 7.102 + const char *dir, const char *node, unsigned int *num); 7.103 +void *xenbus_read(struct xenbus_transaction *t, 7.104 + const char *dir, const char *node, unsigned int *len); 7.105 +int xenbus_write(struct xenbus_transaction *t, 7.106 + const char *dir, const char *node, const char *string); 7.107 +int xenbus_mkdir(struct xenbus_transaction *t, 7.108 + const char *dir, const char *node); 7.109 +int xenbus_exists(struct xenbus_transaction *t, 7.110 + const char *dir, const char *node); 7.111 +int xenbus_rm(struct xenbus_transaction *t, const char *dir, const char *node); 7.112 +struct xenbus_transaction *xenbus_transaction_start(void); 7.113 +int xenbus_transaction_end(struct xenbus_transaction *t, int abort); 7.114 + 7.115 +/* Single read and scanf: returns -errno or num scanned if > 0. */ 7.116 +int xenbus_scanf(struct xenbus_transaction *t, 7.117 + const char *dir, const char *node, const char *fmt, ...) 7.118 + __attribute__((format(scanf, 4, 5))); 7.119 + 7.120 +/* Single printf and write: returns -errno or 0. */ 7.121 +int xenbus_printf(struct xenbus_transaction *t, 7.122 + const char *dir, const char *node, const char *fmt, ...) 7.123 + __attribute__((format(printf, 4, 5))); 7.124 + 7.125 +/* Generic read function: NULL-terminated triples of name, 7.126 + * sprintf-style type string, and pointer. Returns 0 or errno.*/ 7.127 +int xenbus_gather(struct xenbus_transaction *t, const char *dir, ...); 7.128 + 7.129 int register_xenbus_watch(struct xenbus_watch *watch); 7.130 void unregister_xenbus_watch(struct xenbus_watch *watch); 7.131 -void reregister_xenbus_watches(void); 7.132 +void xs_suspend(void); 7.133 +void xs_resume(void); 7.134 + 7.135 +/* Used by xenbus_dev to borrow kernel's store connection. */ 7.136 +void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg); 7.137 7.138 /* Called from xen core code. */ 7.139 void xenbus_suspend(void); 7.140 @@ -84,6 +138,87 @@ void xenbus_resume(void); 7.141 7.142 #define XENBUS_EXIST_ERR(err) ((err) == -ENOENT || (err) == -ERANGE) 7.143 7.144 -int xs_init(void); 7.145 + 7.146 +/** 7.147 + * Register a watch on the given path, using the given xenbus_watch structure 7.148 + * for storage, and the given callback function as the callback. Return 0 on 7.149 + * success, or -errno on error. On success, the given path will be saved as 7.150 + * watch->node, and remains the caller's to free. On error, watch->node will 7.151 + * be NULL, the device will switch to XenbusStateClosing, and the error will 7.152 + * be saved in the store. 7.153 + */ 7.154 +int xenbus_watch_path(struct xenbus_device *dev, const char *path, 7.155 + struct xenbus_watch *watch, 7.156 + void (*callback)(struct xenbus_watch *, 7.157 + const char **, unsigned int)); 7.158 + 7.159 + 7.160 +/** 7.161 + * Register a watch on the given path/path2, using the given xenbus_watch 7.162 + * structure for storage, and the given callback function as the callback. 7.163 + * Return 0 on success, or -errno on error. On success, the watched path 7.164 + * (path/path2) will be saved as watch->node, and becomes the caller's to 7.165 + * kfree(). On error, watch->node will be NULL, so the caller has nothing to 7.166 + * free, the device will switch to XenbusStateClosing, and the error will be 7.167 + * saved in the store. 7.168 + */ 7.169 +int xenbus_watch_path2(struct xenbus_device *dev, const char *path, 7.170 + const char *path2, struct xenbus_watch *watch, 7.171 + void (*callback)(struct xenbus_watch *, 7.172 + const char **, unsigned int)); 7.173 + 7.174 + 7.175 +/** 7.176 + * Advertise in the store a change of the given driver to the given new_state. 7.177 + * Perform the change inside the given transaction xbt. xbt may be NULL, in 7.178 + * which case this is performed inside its own transaction. Return 0 on 7.179 + * success, or -errno on error. On error, the device will switch to 7.180 + * XenbusStateClosing, and the error will be saved in the store. 7.181 + */ 7.182 +int xenbus_switch_state(struct xenbus_device *dev, 7.183 + struct xenbus_transaction *xbt, 7.184 + XenbusState new_state); 7.185 + 7.186 + 7.187 +/** 7.188 + * Grant access to the given ring_mfn to the peer of the given device. Return 7.189 + * 0 on success, or -errno on error. On error, the device will switch to 7.190 + * XenbusStateClosing, and the error will be saved in the store. 7.191 + */ 7.192 +int xenbus_grant_ring(struct xenbus_device *dev, unsigned long ring_mfn); 7.193 + 7.194 + 7.195 +/** 7.196 + * Allocate an event channel for the given xenbus_device, assigning the newly 7.197 + * created local port to *port. Return 0 on success, or -errno on error. On 7.198 + * error, the device will switch to XenbusStateClosing, and the error will be 7.199 + * saved in the store. 7.200 + */ 7.201 +int xenbus_alloc_evtchn(struct xenbus_device *dev, int *port); 7.202 + 7.203 + 7.204 +/** 7.205 + * Return the state of the driver rooted at the given store path, or 7.206 + * XenbusStateClosed if no state can be read. 7.207 + */ 7.208 +XenbusState xenbus_read_driver_state(const char *path); 7.209 + 7.210 + 7.211 +/*** 7.212 + * Report the given negative errno into the store, along with the given 7.213 + * formatted message. 7.214 + */ 7.215 +void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, 7.216 + ...); 7.217 + 7.218 + 7.219 +/*** 7.220 + * Equivalent to xenbus_dev_error(dev, err, fmt, args), followed by 7.221 + * xenbus_switch_state(dev, NULL, XenbusStateClosing) to schedule an orderly 7.222 + * closedown of this driver and its peer. 7.223 + */ 7.224 +void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt, 7.225 + ...); 7.226 + 7.227 7.228 #endif /* _ASM_XEN_XENBUS_H */
8.1 --- a/extras/mini-os/include/xmalloc.h Thu Dec 08 15:21:36 2005 +0100 8.2 +++ b/extras/mini-os/include/xmalloc.h Thu Dec 08 15:24:02 2005 +0100 8.3 @@ -7,6 +7,9 @@ 8.4 /* Allocate space for array of typed objects. */ 8.5 #define xmalloc_array(_type, _num) ((_type *)_xmalloc_array(sizeof(_type), __alignof__(_type), _num)) 8.6 8.7 +#define malloc(size) _xmalloc(size, 4) 8.8 +#define free(ptr) xfree(ptr) 8.9 + 8.10 /* Free any of the above. */ 8.11 extern void xfree(const void *); 8.12
9.1 --- a/extras/mini-os/kernel.c Thu Dec 08 15:21:36 2005 +0100 9.2 +++ b/extras/mini-os/kernel.c Thu Dec 08 15:24:02 2005 +0100 9.3 @@ -35,6 +35,7 @@ 9.4 #include <lib.h> 9.5 #include <sched.h> 9.6 #include <xenbus.h> 9.7 +#include "xenbus/xenbus_comms.h" 9.8 9.9 /* 9.10 * Shared page for communicating with the hypervisor.
10.1 --- a/extras/mini-os/xenbus/xenbus_comms.c Thu Dec 08 15:21:36 2005 +0100 10.2 +++ b/extras/mini-os/xenbus/xenbus_comms.c Thu Dec 08 15:24:02 2005 +0100 10.3 @@ -33,199 +33,152 @@ 10.4 #include <events.h> 10.5 #include <os.h> 10.6 #include <lib.h> 10.7 - 10.8 - 10.9 -#ifdef XENBUS_COMMS_DEBUG 10.10 -#define DEBUG(_f, _a...) \ 10.11 - printk("MINI_OS(file=xenbus_comms.c, line=%d) " _f "\n", __LINE__, ## _a) 10.12 -#else 10.13 -#define DEBUG(_f, _a...) ((void)0) 10.14 -#endif 10.15 +#include <xenbus.h> 10.16 +#include "xenbus_comms.h" 10.17 10.18 +static int xenbus_irq; 10.19 10.20 -#define RINGBUF_DATASIZE ((PAGE_SIZE / 2) - sizeof(struct ringbuf_head)) 10.21 -struct ringbuf_head 10.22 -{ 10.23 - u32 write; /* Next place to write to */ 10.24 - u32 read; /* Next place to read from */ 10.25 - u8 flags; 10.26 - char buf[0]; 10.27 -} __attribute__((packed)); 10.28 +extern void xenbus_probe(void *); 10.29 +extern int xenstored_ready; 10.30 10.31 DECLARE_WAIT_QUEUE_HEAD(xb_waitq); 10.32 10.33 -static inline struct ringbuf_head *outbuf(void) 10.34 +static inline struct xenstore_domain_interface *xenstore_domain_interface(void) 10.35 { 10.36 return mfn_to_virt(start_info.store_mfn); 10.37 } 10.38 10.39 -static inline struct ringbuf_head *inbuf(void) 10.40 -{ 10.41 - return (struct ringbuf_head *)((char *)mfn_to_virt(start_info.store_mfn) + PAGE_SIZE/2); 10.42 -} 10.43 - 10.44 static void wake_waiting(int port, struct pt_regs *regs) 10.45 { 10.46 wake_up(&xb_waitq); 10.47 } 10.48 10.49 -static int check_buffer(const struct ringbuf_head *h) 10.50 -{ 10.51 - return (h->write < RINGBUF_DATASIZE && h->read < RINGBUF_DATASIZE); 10.52 -} 10.53 - 10.54 -/* We can't fill last byte: would look like empty buffer. */ 10.55 -static void *get_output_chunk(const struct ringbuf_head *h, 10.56 - void *buf, u32 *len) 10.57 +static int check_indexes(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod) 10.58 { 10.59 - u32 read_mark; 10.60 - 10.61 - if (h->read == 0) 10.62 - read_mark = RINGBUF_DATASIZE - 1; 10.63 - else 10.64 - read_mark = h->read - 1; 10.65 - 10.66 - /* Here to the end of buffer, unless they haven't read some out. */ 10.67 - *len = RINGBUF_DATASIZE - h->write; 10.68 - if (read_mark >= h->write) 10.69 - *len = read_mark - h->write; 10.70 - return (void *)((char *)buf + h->write); 10.71 + return ((prod - cons) <= XENSTORE_RING_SIZE); 10.72 } 10.73 10.74 -static const void *get_input_chunk(const struct ringbuf_head *h, 10.75 - const void *buf, u32 *len) 10.76 +static void *get_output_chunk(XENSTORE_RING_IDX cons, 10.77 + XENSTORE_RING_IDX prod, 10.78 + char *buf, uint32_t *len) 10.79 { 10.80 - /* Here to the end of buffer, unless they haven't written some. */ 10.81 - *len = RINGBUF_DATASIZE - h->read; 10.82 - if (h->write >= h->read) 10.83 - *len = h->write - h->read; 10.84 - return (void *)((char *)buf + h->read); 10.85 + *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod); 10.86 + if ((XENSTORE_RING_SIZE - (prod - cons)) < *len) 10.87 + *len = XENSTORE_RING_SIZE - (prod - cons); 10.88 + return buf + MASK_XENSTORE_IDX(prod); 10.89 } 10.90 10.91 -static void update_output_chunk(struct ringbuf_head *h, u32 len) 10.92 -{ 10.93 - h->write += len; 10.94 - if (h->write == RINGBUF_DATASIZE) 10.95 - h->write = 0; 10.96 -} 10.97 - 10.98 -static void update_input_chunk(struct ringbuf_head *h, u32 len) 10.99 +static const void *get_input_chunk(XENSTORE_RING_IDX cons, 10.100 + XENSTORE_RING_IDX prod, 10.101 + const char *buf, uint32_t *len) 10.102 { 10.103 - h->read += len; 10.104 - if (h->read == RINGBUF_DATASIZE) 10.105 - h->read = 0; 10.106 -} 10.107 - 10.108 -static int output_avail(struct ringbuf_head *out) 10.109 -{ 10.110 - unsigned int avail; 10.111 - 10.112 - get_output_chunk(out, out->buf, &avail); 10.113 - return avail != 0; 10.114 + *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons); 10.115 + if ((prod - cons) < *len) 10.116 + *len = prod - cons; 10.117 + return buf + MASK_XENSTORE_IDX(cons); 10.118 } 10.119 10.120 int xb_write(const void *data, unsigned len) 10.121 { 10.122 - struct ringbuf_head h; 10.123 - struct ringbuf_head *out = outbuf(); 10.124 + struct xenstore_domain_interface *intf = xenstore_domain_interface(); 10.125 + XENSTORE_RING_IDX cons, prod; 10.126 10.127 - do { 10.128 + while (len != 0) { 10.129 void *dst; 10.130 unsigned int avail; 10.131 10.132 - wait_event(xb_waitq, output_avail(out)); 10.133 + wait_event(xb_waitq, (intf->req_prod - intf->req_cons) != 10.134 + XENSTORE_RING_SIZE); 10.135 10.136 - /* Read, then check: not that we don't trust store. 10.137 - * Hell, some of my best friends are daemons. But, 10.138 - * in this post-911 world... */ 10.139 - h = *out; 10.140 + /* Read indexes, then verify. */ 10.141 + cons = intf->req_cons; 10.142 + prod = intf->req_prod; 10.143 mb(); 10.144 - if (!check_buffer(&h)) { 10.145 - return -1; /* ETERRORIST! */ 10.146 - } 10.147 + if (!check_indexes(cons, prod)) 10.148 + return -EIO; 10.149 10.150 - dst = get_output_chunk(&h, out->buf, &avail); 10.151 + dst = get_output_chunk(cons, prod, intf->req, &avail); 10.152 + if (avail == 0) 10.153 + continue; 10.154 if (avail > len) 10.155 avail = len; 10.156 + 10.157 memcpy(dst, data, avail); 10.158 - data = (void *)((char *)data + avail); 10.159 + data = (void*) ( (unsigned long)data + avail ); 10.160 len -= avail; 10.161 - update_output_chunk(out, avail); 10.162 - notify_via_evtchn(start_info.store_evtchn); 10.163 - } while (len != 0); 10.164 + 10.165 + /* Other side must not see new header until data is there. */ 10.166 + wmb(); 10.167 + intf->req_prod += avail; 10.168 + 10.169 + /* This implies mb() before other side sees interrupt. */ 10.170 + notify_remote_via_evtchn(start_info.store_evtchn); 10.171 + } 10.172 10.173 return 0; 10.174 } 10.175 10.176 -int xs_input_avail(void) 10.177 -{ 10.178 - unsigned int avail; 10.179 - struct ringbuf_head *in = inbuf(); 10.180 - 10.181 - get_input_chunk(in, in->buf, &avail); 10.182 - return avail != 0; 10.183 -} 10.184 - 10.185 int xb_read(void *data, unsigned len) 10.186 { 10.187 - struct ringbuf_head h; 10.188 - struct ringbuf_head *in = inbuf(); 10.189 - int was_full; 10.190 + struct xenstore_domain_interface *intf = xenstore_domain_interface(); 10.191 + XENSTORE_RING_IDX cons, prod; 10.192 10.193 while (len != 0) { 10.194 unsigned int avail; 10.195 const char *src; 10.196 10.197 - wait_event(xb_waitq, xs_input_avail()); 10.198 - h = *in; 10.199 + wait_event(xb_waitq, 10.200 + intf->rsp_cons != intf->rsp_prod); 10.201 + 10.202 + /* Read indexes, then verify. */ 10.203 + cons = intf->rsp_cons; 10.204 + prod = intf->rsp_prod; 10.205 mb(); 10.206 - if (!check_buffer(&h)) { 10.207 - return -1; 10.208 - } 10.209 + if (!check_indexes(cons, prod)) 10.210 + return -EIO; 10.211 10.212 - src = get_input_chunk(&h, in->buf, &avail); 10.213 + src = get_input_chunk(cons, prod, intf->rsp, &avail); 10.214 + if (avail == 0) 10.215 + continue; 10.216 if (avail > len) 10.217 avail = len; 10.218 - was_full = !output_avail(&h); 10.219 + 10.220 + /* We must read header before we read data. */ 10.221 + rmb(); 10.222 10.223 memcpy(data, src, avail); 10.224 - data = (void *)((char *)data + avail); 10.225 + data = (void*) ( (unsigned long)data + avail ); 10.226 len -= avail; 10.227 - update_input_chunk(in, avail); 10.228 - DEBUG("Finished read of %i bytes (%i to go)\n", avail, len); 10.229 - /* If it was full, tell them we've taken some. */ 10.230 - if (was_full) 10.231 - notify_via_evtchn(start_info.store_evtchn); 10.232 + 10.233 + /* Other side must not see free space until we've copied out */ 10.234 + mb(); 10.235 + intf->rsp_cons += avail; 10.236 + 10.237 + printk("Finished read of %i bytes (%i to go)\n", avail, len); 10.238 + 10.239 + /* Implies mb(): they will see new header. */ 10.240 + notify_remote_via_evtchn(start_info.store_evtchn); 10.241 } 10.242 10.243 - /* If we left something, wake watch thread to deal with it. */ 10.244 - if (xs_input_avail()) 10.245 - wake_up(&xb_waitq); 10.246 - 10.247 return 0; 10.248 } 10.249 10.250 /* Set up interrupt handler off store event channel. */ 10.251 int xb_init_comms(void) 10.252 { 10.253 - printk("Init xenbus comms, store event channel %d\n", start_info.store_evtchn); 10.254 - if (!start_info.store_evtchn) 10.255 - return 0; 10.256 - printk("Binding virq\n"); 10.257 - bind_evtchn(start_info.store_evtchn, &wake_waiting); 10.258 + int err; 10.259 + 10.260 + if (xenbus_irq) 10.261 + unbind_evtchn(xenbus_irq); 10.262 10.263 - /* FIXME zero out page -- domain builder should probably do this*/ 10.264 - memset(mfn_to_virt(start_info.store_mfn), 0, PAGE_SIZE); 10.265 - notify_via_evtchn(start_info.store_evtchn); 10.266 + err = bind_evtchn( 10.267 + start_info.store_evtchn, wake_waiting); 10.268 + if (err <= 0) { 10.269 + printk("XENBUS request irq failed %i\n", err); 10.270 + return err; 10.271 + } 10.272 + 10.273 + xenbus_irq = err; 10.274 + 10.275 return 0; 10.276 } 10.277 - 10.278 -void xb_suspend_comms(void) 10.279 -{ 10.280 - 10.281 - if (!start_info.store_evtchn) 10.282 - return; 10.283 - 10.284 - // TODO 10.285 - //unbind_evtchn_from_irqhandler(xen_start_info.store_evtchn, &xb_waitq); 10.286 -}
11.1 --- a/extras/mini-os/xenbus/xenbus_comms.h Thu Dec 08 15:21:36 2005 +0100 11.2 +++ b/extras/mini-os/xenbus/xenbus_comms.h Thu Dec 08 15:24:02 2005 +0100 11.3 @@ -28,8 +28,8 @@ 11.4 #ifndef _XENBUS_COMMS_H 11.5 #define _XENBUS_COMMS_H 11.6 11.7 +int xs_init(void); 11.8 int xb_init_comms(void); 11.9 -void xb_suspend_comms(void); 11.10 11.11 /* Low level routines. */ 11.12 int xb_write(const void *data, unsigned len);
12.1 --- a/extras/mini-os/xenbus/xenbus_xs.c Thu Dec 08 15:21:36 2005 +0100 12.2 +++ b/extras/mini-os/xenbus/xenbus_xs.c Thu Dec 08 15:24:02 2005 +0100 12.3 @@ -39,15 +39,63 @@ 12.4 #include <wait.h> 12.5 #include <sched.h> 12.6 #include <semaphore.h> 12.7 +#include <spinlock.h> 12.8 #include <xen/io/xs_wire.h> 12.9 #include "xenbus_comms.h" 12.10 12.11 #define streq(a, b) (strcmp((a), (b)) == 0) 12.12 12.13 -static char printf_buffer[4096]; 12.14 +struct xs_stored_msg { 12.15 + struct list_head list; 12.16 + 12.17 + struct xsd_sockmsg hdr; 12.18 + 12.19 + union { 12.20 + /* Queued replies. */ 12.21 + struct { 12.22 + char *body; 12.23 + } reply; 12.24 + 12.25 + /* Queued watch events. */ 12.26 + struct { 12.27 + struct xenbus_watch *handle; 12.28 + char **vec; 12.29 + unsigned int vec_size; 12.30 + } watch; 12.31 + } u; 12.32 +}; 12.33 + 12.34 +struct xs_handle { 12.35 + /* A list of replies. Currently only one will ever be outstanding. */ 12.36 + struct list_head reply_list; 12.37 + spinlock_t reply_lock; 12.38 + struct wait_queue_head reply_waitq; 12.39 + 12.40 + /* One request at a time. */ 12.41 + struct semaphore request_mutex; 12.42 + 12.43 + /* Protect transactions against save/restore. */ 12.44 + struct rw_semaphore suspend_mutex; 12.45 +}; 12.46 + 12.47 +static struct xs_handle xs_state; 12.48 + 12.49 +/* List of registered watches, and a lock to protect it. */ 12.50 static LIST_HEAD(watches); 12.51 -//TODO 12.52 -DECLARE_MUTEX(xenbus_lock); 12.53 +static DEFINE_SPINLOCK(watches_lock); 12.54 + 12.55 +/* List of pending watch callback events, and a lock to protect it. */ 12.56 +static LIST_HEAD(watch_events); 12.57 +static DEFINE_SPINLOCK(watch_events_lock); 12.58 + 12.59 +/* 12.60 + * Details of the xenwatch callback kernel thread. The thread waits on the 12.61 + * watch_events_waitq for work to do (queued on watch_events list). When it 12.62 + * wakes up it acquires the xenwatch_mutex before reading the list and 12.63 + * carrying out work. 12.64 + */ 12.65 +/* static */ DECLARE_MUTEX(xenwatch_mutex); 12.66 +static DECLARE_WAIT_QUEUE_HEAD(watch_events_waitq); 12.67 12.68 static int get_error(const char *errorstring) 12.69 { 12.70 @@ -65,47 +113,82 @@ static int get_error(const char *errorst 12.71 12.72 static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len) 12.73 { 12.74 - struct xsd_sockmsg msg; 12.75 - void *ret; 12.76 - int err; 12.77 + struct xs_stored_msg *msg; 12.78 + char *body; 12.79 + 12.80 + spin_lock(&xs_state.reply_lock); 12.81 12.82 - err = xb_read(&msg, sizeof(msg)); 12.83 - if (err) 12.84 - return ERR_PTR(err); 12.85 - 12.86 - ret = xmalloc_array(char, msg.len + 1); 12.87 - if (!ret) 12.88 - return ERR_PTR(-ENOMEM); 12.89 + while (list_empty(&xs_state.reply_list)) { 12.90 + spin_unlock(&xs_state.reply_lock); 12.91 + wait_event(xs_state.reply_waitq, 12.92 + !list_empty(&xs_state.reply_list)); 12.93 + spin_lock(&xs_state.reply_lock); 12.94 + } 12.95 12.96 - err = xb_read(ret, msg.len); 12.97 - if (err) { 12.98 - xfree(ret); 12.99 - return ERR_PTR(err); 12.100 - } 12.101 - ((char*)ret)[msg.len] = '\0'; 12.102 + msg = list_entry(xs_state.reply_list.next, 12.103 + struct xs_stored_msg, list); 12.104 + list_del(&msg->list); 12.105 + 12.106 + spin_unlock(&xs_state.reply_lock); 12.107 12.108 - *type = msg.type; 12.109 + *type = msg->hdr.type; 12.110 if (len) 12.111 - *len = msg.len; 12.112 - return ret; 12.113 + *len = msg->hdr.len; 12.114 + body = msg->u.reply.body; 12.115 + 12.116 + free(msg); 12.117 + 12.118 + return body; 12.119 } 12.120 12.121 /* Emergency write. */ 12.122 void xenbus_debug_write(const char *str, unsigned int count) 12.123 { 12.124 - struct xsd_sockmsg msg; 12.125 + struct xsd_sockmsg msg = { 0 }; 12.126 12.127 msg.type = XS_DEBUG; 12.128 msg.len = sizeof("print") + count + 1; 12.129 12.130 + down(&xs_state.request_mutex); 12.131 xb_write(&msg, sizeof(msg)); 12.132 xb_write("print", sizeof("print")); 12.133 xb_write(str, count); 12.134 xb_write("", 1); 12.135 + up(&xs_state.request_mutex); 12.136 +} 12.137 + 12.138 +void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg) 12.139 +{ 12.140 + void *ret; 12.141 + struct xsd_sockmsg req_msg = *msg; 12.142 + int err; 12.143 + 12.144 + if (req_msg.type == XS_TRANSACTION_START) 12.145 + down_read(&xs_state.suspend_mutex); 12.146 + 12.147 + down(&xs_state.request_mutex); 12.148 + 12.149 + err = xb_write(msg, sizeof(*msg) + msg->len); 12.150 + if (err) { 12.151 + msg->type = XS_ERROR; 12.152 + ret = ERR_PTR(err); 12.153 + } else { 12.154 + ret = read_reply(&msg->type, &msg->len); 12.155 + } 12.156 + 12.157 + up(&xs_state.request_mutex); 12.158 + 12.159 + if ((msg->type == XS_TRANSACTION_END) || 12.160 + ((req_msg.type == XS_TRANSACTION_START) && 12.161 + (msg->type == XS_ERROR))) 12.162 + up_read(&xs_state.suspend_mutex); 12.163 + 12.164 + return ret; 12.165 } 12.166 12.167 /* Send message to xs, get kmalloc'ed reply. ERR_PTR() on error. */ 12.168 -static void *xs_talkv(enum xsd_sockmsg_type type, 12.169 +static void *xs_talkv(struct xenbus_transaction *t, 12.170 + enum xsd_sockmsg_type type, 12.171 const struct kvec *iovec, 12.172 unsigned int num_vecs, 12.173 unsigned int *len) 12.174 @@ -115,51 +198,57 @@ static void *xs_talkv(enum xsd_sockmsg_t 12.175 unsigned int i; 12.176 int err; 12.177 12.178 - //WARN_ON(down_trylock(&xenbus_lock) == 0); 12.179 - 12.180 + msg.tx_id = (u32)(unsigned long)t; 12.181 + msg.req_id = 0; 12.182 msg.type = type; 12.183 msg.len = 0; 12.184 for (i = 0; i < num_vecs; i++) 12.185 msg.len += iovec[i].iov_len; 12.186 12.187 + down(&xs_state.request_mutex); 12.188 + 12.189 err = xb_write(&msg, sizeof(msg)); 12.190 - if (err) 12.191 + if (err) { 12.192 + up(&xs_state.request_mutex); 12.193 return ERR_PTR(err); 12.194 + } 12.195 12.196 for (i = 0; i < num_vecs; i++) { 12.197 - err = xb_write(iovec[i].iov_base, iovec[i].iov_len); 12.198 - if (err) 12.199 + err = xb_write(iovec[i].iov_base, iovec[i].iov_len);; 12.200 + if (err) { 12.201 + up(&xs_state.request_mutex); 12.202 return ERR_PTR(err); 12.203 + } 12.204 } 12.205 12.206 - /* Watches can have fired before reply comes: daemon detects 12.207 - * and re-transmits, so we can ignore this. */ 12.208 - do { 12.209 - xfree(ret); 12.210 - ret = read_reply(&msg.type, len); 12.211 - if (IS_ERR(ret)) 12.212 - return ret; 12.213 - } while (msg.type == XS_WATCH_EVENT); 12.214 + ret = read_reply(&msg.type, len); 12.215 + 12.216 + up(&xs_state.request_mutex); 12.217 + 12.218 + if (IS_ERR(ret)) 12.219 + return ret; 12.220 12.221 if (msg.type == XS_ERROR) { 12.222 err = get_error(ret); 12.223 - xfree(ret); 12.224 + free(ret); 12.225 return ERR_PTR(-err); 12.226 } 12.227 12.228 - //BUG_ON(msg.type != type); 12.229 + // BUG_ON(msg.type != type); 12.230 return ret; 12.231 } 12.232 12.233 /* Simplified version of xs_talkv: single message. */ 12.234 -static void *xs_single(enum xsd_sockmsg_type type, 12.235 - const char *string, unsigned int *len) 12.236 +static void *xs_single(struct xenbus_transaction *t, 12.237 + enum xsd_sockmsg_type type, 12.238 + const char *string, 12.239 + unsigned int *len) 12.240 { 12.241 struct kvec iovec; 12.242 12.243 iovec.iov_base = (void *)string; 12.244 iovec.iov_len = strlen(string) + 1; 12.245 - return xs_talkv(type, &iovec, 1, len); 12.246 + return xs_talkv(t, type, &iovec, 1, len); 12.247 } 12.248 12.249 /* Many commands only need an ack, don't care what it says. */ 12.250 @@ -167,7 +256,7 @@ static int xs_error(char *reply) 12.251 { 12.252 if (IS_ERR(reply)) 12.253 return PTR_ERR(reply); 12.254 - xfree(reply); 12.255 + free(reply); 12.256 return 0; 12.257 } 12.258 12.259 @@ -182,60 +271,76 @@ static unsigned int count_strings(const 12.260 return num; 12.261 } 12.262 12.263 -/* Return the path to dir with /name appended. */ 12.264 +/* Return the path to dir with /name appended. Buffer must be kfree()'ed. */ 12.265 static char *join(const char *dir, const char *name) 12.266 { 12.267 - static char buffer[4096]; 12.268 + char *buffer; 12.269 12.270 - //BUG_ON(down_trylock(&xenbus_lock) == 0); 12.271 - /* XXX FIXME: might not be correct if name == "" */ 12.272 - //BUG_ON(strlen(dir) + strlen("/") + strlen(name) + 1 > sizeof(buffer)); 12.273 + buffer = malloc(strlen(dir) + strlen("/") + strlen(name) + 1); 12.274 + if (buffer == NULL) 12.275 + return ERR_PTR(-ENOMEM); 12.276 12.277 strcpy(buffer, dir); 12.278 if (!streq(name, "")) { 12.279 strcat(buffer, "/"); 12.280 strcat(buffer, name); 12.281 } 12.282 + 12.283 return buffer; 12.284 } 12.285 12.286 -char **xenbus_directory(const char *dir, const char *node, unsigned int *num) 12.287 +static char **split(char *strings, unsigned int len, unsigned int *num) 12.288 { 12.289 - char *strings, *p, **ret; 12.290 - unsigned int len; 12.291 - 12.292 - strings = xs_single(XS_DIRECTORY, join(dir, node), &len); 12.293 - if (IS_ERR(strings)) 12.294 - return (char **)strings; 12.295 + char *p, **ret; 12.296 12.297 /* Count the strings. */ 12.298 *num = count_strings(strings, len); 12.299 12.300 /* Transfer to one big alloc for easy freeing. */ 12.301 - ret = (char **)xmalloc_array(char, *num * sizeof(char *) + len); 12.302 + ret = malloc(*num * sizeof(char *) + len); 12.303 if (!ret) { 12.304 - xfree(strings); 12.305 + free(strings); 12.306 return ERR_PTR(-ENOMEM); 12.307 } 12.308 memcpy(&ret[*num], strings, len); 12.309 - xfree(strings); 12.310 + free(strings); 12.311 12.312 strings = (char *)&ret[*num]; 12.313 for (p = strings, *num = 0; p < strings + len; p += strlen(p) + 1) 12.314 ret[(*num)++] = p; 12.315 + 12.316 return ret; 12.317 } 12.318 12.319 +char **xenbus_directory(struct xenbus_transaction *t, 12.320 + const char *dir, const char *node, unsigned int *num) 12.321 +{ 12.322 + char *strings, *path; 12.323 + unsigned int len; 12.324 + 12.325 + path = join(dir, node); 12.326 + if (IS_ERR(path)) 12.327 + return (char **)path; 12.328 + 12.329 + strings = xs_single(t, XS_DIRECTORY, path, &len); 12.330 + free(path); 12.331 + if (IS_ERR(strings)) 12.332 + return (char **)strings; 12.333 + 12.334 + return split(strings, len, num); 12.335 +} 12.336 + 12.337 /* Check if a path exists. Return 1 if it does. */ 12.338 -int xenbus_exists(const char *dir, const char *node) 12.339 +int xenbus_exists(struct xenbus_transaction *t, 12.340 + const char *dir, const char *node) 12.341 { 12.342 char **d; 12.343 int dir_n; 12.344 12.345 - d = xenbus_directory(dir, node, &dir_n); 12.346 + d = xenbus_directory(t, dir, node, &dir_n); 12.347 if (IS_ERR(d)) 12.348 return 0; 12.349 - xfree(d); 12.350 + free(d); 12.351 return 1; 12.352 } 12.353 12.354 @@ -243,92 +348,134 @@ int xenbus_exists(const char *dir, const 12.355 * Returns a kmalloced value: call free() on it after use. 12.356 * len indicates length in bytes. 12.357 */ 12.358 -void *xenbus_read(const char *dir, const char *node, unsigned int *len) 12.359 +void *xenbus_read(struct xenbus_transaction *t, 12.360 + const char *dir, const char *node, unsigned int *len) 12.361 { 12.362 - return xs_single(XS_READ, join(dir, node), len); 12.363 + char *path; 12.364 + void *ret; 12.365 + 12.366 + path = join(dir, node); 12.367 + if (IS_ERR(path)) 12.368 + return (void *)path; 12.369 + 12.370 + ret = xs_single(t, XS_READ, path, len); 12.371 + free(path); 12.372 + return ret; 12.373 } 12.374 12.375 /* Write the value of a single file. 12.376 - * Returns -err on failure. createflags can be 0, O_CREAT, or O_CREAT|O_EXCL. 12.377 + * Returns -err on failure. 12.378 */ 12.379 -int xenbus_write(const char *dir, const char *node, 12.380 - const char *string, int createflags) 12.381 +int xenbus_write(struct xenbus_transaction *t, 12.382 + const char *dir, const char *node, const char *string) 12.383 { 12.384 - const char *flags, *path; 12.385 - struct kvec iovec[3]; 12.386 + const char *path; 12.387 + struct kvec iovec[2]; 12.388 + int ret; 12.389 12.390 path = join(dir, node); 12.391 - /* Format: Flags (as string), path, data. */ 12.392 - if (createflags == 0) 12.393 - flags = XS_WRITE_NONE; 12.394 - else if (createflags == O_CREAT) 12.395 - flags = XS_WRITE_CREATE; 12.396 - else if (createflags == (O_CREAT|O_EXCL)) 12.397 - flags = XS_WRITE_CREATE_EXCL; 12.398 - else 12.399 - return -EINVAL; 12.400 + if (IS_ERR(path)) 12.401 + return PTR_ERR(path); 12.402 12.403 iovec[0].iov_base = (void *)path; 12.404 iovec[0].iov_len = strlen(path) + 1; 12.405 - iovec[1].iov_base = (void *)flags; 12.406 - iovec[1].iov_len = strlen(flags) + 1; 12.407 - iovec[2].iov_base = (void *)string; 12.408 - iovec[2].iov_len = strlen(string); 12.409 + iovec[1].iov_base = (void *)string; 12.410 + iovec[1].iov_len = strlen(string); 12.411 12.412 - return xs_error(xs_talkv(XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL)); 12.413 + ret = xs_error(xs_talkv(t, XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL)); 12.414 + free(path); 12.415 + return ret; 12.416 } 12.417 12.418 /* Create a new directory. */ 12.419 -int xenbus_mkdir(const char *dir, const char *node) 12.420 +int xenbus_mkdir(struct xenbus_transaction *t, 12.421 + const char *dir, const char *node) 12.422 { 12.423 - return xs_error(xs_single(XS_MKDIR, join(dir, node), NULL)); 12.424 + char *path; 12.425 + int ret; 12.426 + 12.427 + path = join(dir, node); 12.428 + if (IS_ERR(path)) 12.429 + return PTR_ERR(path); 12.430 + 12.431 + ret = xs_error(xs_single(t, XS_MKDIR, path, NULL)); 12.432 + free(path); 12.433 + return ret; 12.434 } 12.435 12.436 /* Destroy a file or directory (directories must be empty). */ 12.437 -int xenbus_rm(const char *dir, const char *node) 12.438 +int xenbus_rm(struct xenbus_transaction *t, const char *dir, const char *node) 12.439 { 12.440 - return xs_error(xs_single(XS_RM, join(dir, node), NULL)); 12.441 + char *path; 12.442 + int ret; 12.443 + 12.444 + path = join(dir, node); 12.445 + if (IS_ERR(path)) 12.446 + return PTR_ERR(path); 12.447 + 12.448 + ret = xs_error(xs_single(t, XS_RM, path, NULL)); 12.449 + free(path); 12.450 + return ret; 12.451 } 12.452 12.453 /* Start a transaction: changes by others will not be seen during this 12.454 * transaction, and changes will not be visible to others until end. 12.455 - * Transaction only applies to the given subtree. 12.456 - * You can only have one transaction at any time. 12.457 */ 12.458 -int xenbus_transaction_start(const char *subtree) 12.459 +struct xenbus_transaction *xenbus_transaction_start(void) 12.460 { 12.461 - return xs_error(xs_single(XS_TRANSACTION_START, subtree, NULL)); 12.462 + char *id_str; 12.463 + unsigned long id; 12.464 + 12.465 + down_read(&xs_state.suspend_mutex); 12.466 + 12.467 + id_str = xs_single(NULL, XS_TRANSACTION_START, "", NULL); 12.468 + if (IS_ERR(id_str)) { 12.469 + up_read(&xs_state.suspend_mutex); 12.470 + return (struct xenbus_transaction *)id_str; 12.471 + } 12.472 + 12.473 + id = simple_strtoul(id_str, NULL, 0); 12.474 + free(id_str); 12.475 + 12.476 + return (struct xenbus_transaction *)id; 12.477 } 12.478 12.479 /* End a transaction. 12.480 * If abandon is true, transaction is discarded instead of committed. 12.481 */ 12.482 -int xenbus_transaction_end(int abort) 12.483 +int xenbus_transaction_end(struct xenbus_transaction *t, int abort) 12.484 { 12.485 char abortstr[2]; 12.486 + int err; 12.487 12.488 if (abort) 12.489 strcpy(abortstr, "F"); 12.490 else 12.491 strcpy(abortstr, "T"); 12.492 - return xs_error(xs_single(XS_TRANSACTION_END, abortstr, NULL)); 12.493 + 12.494 + err = xs_error(xs_single(t, XS_TRANSACTION_END, abortstr, NULL)); 12.495 + 12.496 + up_read(&xs_state.suspend_mutex); 12.497 + 12.498 + return err; 12.499 } 12.500 12.501 /* Single read and scanf: returns -errno or num scanned. */ 12.502 -int xenbus_scanf(const char *dir, const char *node, const char *fmt, ...) 12.503 +int xenbus_scanf(struct xenbus_transaction *t, 12.504 + const char *dir, const char *node, const char *fmt, ...) 12.505 { 12.506 va_list ap; 12.507 int ret; 12.508 char *val; 12.509 12.510 - val = xenbus_read(dir, node, NULL); 12.511 + val = xenbus_read(t, dir, node, NULL); 12.512 if (IS_ERR(val)) 12.513 return PTR_ERR(val); 12.514 12.515 va_start(ap, fmt); 12.516 ret = vsscanf(val, fmt, ap); 12.517 va_end(ap); 12.518 - xfree(val); 12.519 + free(val); 12.520 /* Distinctive errno. */ 12.521 if (ret == 0) 12.522 return -ERANGE; 12.523 @@ -336,23 +483,32 @@ int xenbus_scanf(const char *dir, const 12.524 } 12.525 12.526 /* Single printf and write: returns -errno or 0. */ 12.527 -int xenbus_printf(const char *dir, const char *node, const char *fmt, ...) 12.528 +int xenbus_printf(struct xenbus_transaction *t, 12.529 + const char *dir, const char *node, const char *fmt, ...) 12.530 { 12.531 va_list ap; 12.532 int ret; 12.533 +#define PRINTF_BUFFER_SIZE 4096 12.534 + char *printf_buffer; 12.535 12.536 - //BUG_ON(down_trylock(&xenbus_lock) == 0); 12.537 + printf_buffer = malloc(PRINTF_BUFFER_SIZE); 12.538 + if (printf_buffer == NULL) 12.539 + return -ENOMEM; 12.540 + 12.541 va_start(ap, fmt); 12.542 - ret = vsnprintf(printf_buffer, sizeof(printf_buffer), fmt, ap); 12.543 + ret = vsnprintf(printf_buffer, PRINTF_BUFFER_SIZE, fmt, ap); 12.544 va_end(ap); 12.545 12.546 - //BUG_ON(ret > sizeof(printf_buffer)-1); 12.547 - return xenbus_write(dir, node, printf_buffer, O_CREAT); 12.548 + // BUG_ON(ret > PRINTF_BUFFER_SIZE-1); 12.549 + ret = xenbus_write(t, dir, node, printf_buffer); 12.550 + 12.551 + free(printf_buffer); 12.552 + 12.553 + return ret; 12.554 } 12.555 12.556 - 12.557 /* Takes tuples of names, scanf-style args, and void **, NULL terminated. */ 12.558 -int xenbus_gather(const char *dir, ...) 12.559 +int xenbus_gather(struct xenbus_transaction *t, const char *dir, ...) 12.560 { 12.561 va_list ap; 12.562 const char *name; 12.563 @@ -364,7 +520,7 @@ int xenbus_gather(const char *dir, ...) 12.564 void *result = va_arg(ap, void *); 12.565 char *p; 12.566 12.567 - p = xenbus_read(dir, name, NULL); 12.568 + p = xenbus_read(t, dir, name, NULL); 12.569 if (IS_ERR(p)) { 12.570 ret = PTR_ERR(p); 12.571 break; 12.572 @@ -372,7 +528,7 @@ int xenbus_gather(const char *dir, ...) 12.573 if (fmt) { 12.574 if (sscanf(p, fmt, result) == 0) 12.575 ret = -EINVAL; 12.576 - xfree(p); 12.577 + free(p); 12.578 } else 12.579 *(char **)result = p; 12.580 } 12.581 @@ -389,31 +545,8 @@ static int xs_watch(const char *path, co 12.582 iov[1].iov_base = (void *)token; 12.583 iov[1].iov_len = strlen(token) + 1; 12.584 12.585 - return xs_error(xs_talkv(XS_WATCH, iov, ARRAY_SIZE(iov), NULL)); 12.586 -} 12.587 - 12.588 -static char *xs_read_watch(char **token) 12.589 -{ 12.590 - enum xsd_sockmsg_type type; 12.591 - char *ret; 12.592 - 12.593 - ret = read_reply(&type, NULL); 12.594 - if (IS_ERR(ret)) 12.595 - return ret; 12.596 - 12.597 - //BUG_ON(type != XS_WATCH_EVENT); 12.598 - *token = ret + strlen(ret) + 1; 12.599 - return ret; 12.600 -} 12.601 - 12.602 -static int xs_acknowledge_watch(const char *token) 12.603 -{ 12.604 -#if 0 12.605 - return xs_error(xs_single(XS_WATCH_ACK, token, NULL)); 12.606 -#else 12.607 - /* XS_WATCH_ACK is no longer available */ 12.608 - return 0; 12.609 -#endif 12.610 + return xs_error(xs_talkv(NULL, XS_WATCH, iov, 12.611 + ARRAY_SIZE(iov), NULL)); 12.612 } 12.613 12.614 static int xs_unwatch(const char *path, const char *token) 12.615 @@ -425,10 +558,10 @@ static int xs_unwatch(const char *path, 12.616 iov[1].iov_base = (char *)token; 12.617 iov[1].iov_len = strlen(token) + 1; 12.618 12.619 - return xs_error(xs_talkv(XS_UNWATCH, iov, ARRAY_SIZE(iov), NULL)); 12.620 + return xs_error(xs_talkv(NULL, XS_UNWATCH, iov, 12.621 + ARRAY_SIZE(iov), NULL)); 12.622 } 12.623 12.624 -/* A little paranoia: we don't just trust token. */ 12.625 static struct xenbus_watch *find_watch(const char *token) 12.626 { 12.627 struct xenbus_watch *i, *cmp; 12.628 @@ -438,6 +571,7 @@ static struct xenbus_watch *find_watch(c 12.629 list_for_each_entry(i, &watches, list) 12.630 if (i == cmp) 12.631 return i; 12.632 + 12.633 return NULL; 12.634 } 12.635 12.636 @@ -449,111 +583,214 @@ int register_xenbus_watch(struct xenbus_ 12.637 int err; 12.638 12.639 sprintf(token, "%lX", (long)watch); 12.640 - //BUG_ON(find_watch(token)); 12.641 -printk("Registered watch for: %s\n", token); 12.642 + 12.643 + down_read(&xs_state.suspend_mutex); 12.644 + 12.645 + spin_lock(&watches_lock); 12.646 + // BUG_ON(find_watch(token)); 12.647 + list_add(&watch->list, &watches); 12.648 + spin_unlock(&watches_lock); 12.649 + 12.650 err = xs_watch(watch->node, token); 12.651 - if (!err) 12.652 - list_add(&watch->list, &watches); 12.653 + 12.654 + /* Ignore errors due to multiple registration. */ 12.655 + if ((err != 0) && (err != -EEXIST)) { 12.656 + spin_lock(&watches_lock); 12.657 + list_del(&watch->list); 12.658 + spin_unlock(&watches_lock); 12.659 + } 12.660 + 12.661 + up_read(&xs_state.suspend_mutex); 12.662 + 12.663 return err; 12.664 } 12.665 12.666 void unregister_xenbus_watch(struct xenbus_watch *watch) 12.667 { 12.668 + struct xs_stored_msg *msg, *tmp; 12.669 char token[sizeof(watch) * 2 + 1]; 12.670 int err; 12.671 12.672 sprintf(token, "%lX", (long)watch); 12.673 - //BUG_ON(!find_watch(token)); 12.674 + 12.675 + down_read(&xs_state.suspend_mutex); 12.676 + 12.677 + spin_lock(&watches_lock); 12.678 + // BUG_ON(!find_watch(token)); 12.679 + list_del(&watch->list); 12.680 + spin_unlock(&watches_lock); 12.681 12.682 err = xs_unwatch(watch->node, token); 12.683 - list_del(&watch->list); 12.684 - 12.685 if (err) 12.686 printk("XENBUS Failed to release watch %s: %i\n", 12.687 watch->node, err); 12.688 + 12.689 + up_read(&xs_state.suspend_mutex); 12.690 + 12.691 + /* Cancel pending watch events. */ 12.692 + spin_lock(&watch_events_lock); 12.693 + list_for_each_entry_safe(msg, tmp, &watch_events, list) { 12.694 + if (msg->u.watch.handle != watch) 12.695 + continue; 12.696 + list_del(&msg->list); 12.697 + free(msg->u.watch.vec); 12.698 + free(msg); 12.699 + } 12.700 + spin_unlock(&watch_events_lock); 12.701 } 12.702 12.703 -/* Re-register callbacks to all watches. */ 12.704 -void reregister_xenbus_watches(void) 12.705 +void xs_suspend(void) 12.706 +{ 12.707 + down_write(&xs_state.suspend_mutex); 12.708 + down(&xs_state.request_mutex); 12.709 +} 12.710 + 12.711 +void xs_resume(void) 12.712 { 12.713 struct xenbus_watch *watch; 12.714 char token[sizeof(watch) * 2 + 1]; 12.715 12.716 + up(&xs_state.request_mutex); 12.717 + 12.718 + /* No need for watches_lock: the suspend_mutex is sufficient. */ 12.719 list_for_each_entry(watch, &watches, list) { 12.720 sprintf(token, "%lX", (long)watch); 12.721 xs_watch(watch->node, token); 12.722 } 12.723 + 12.724 + up_write(&xs_state.suspend_mutex); 12.725 } 12.726 12.727 -void watch_thread(void *unused) 12.728 +static void xenwatch_thread(void *unused) 12.729 { 12.730 + struct list_head *ent; 12.731 + struct xs_stored_msg *msg; 12.732 + 12.733 for (;;) { 12.734 - char *token; 12.735 - char *node = NULL; 12.736 + wait_event(watch_events_waitq, 12.737 + !list_empty(&watch_events)); 12.738 12.739 - wait_event(xb_waitq, xs_input_avail()); 12.740 + down(&xenwatch_mutex); 12.741 12.742 - /* If this is a spurious wakeup caused by someone 12.743 - * doing an op, they'll hold the lock and the buffer 12.744 - * will be empty by the time we get there. 12.745 - */ 12.746 - down(&xenbus_lock); 12.747 - if (xs_input_avail()) 12.748 - node = xs_read_watch(&token); 12.749 + spin_lock(&watch_events_lock); 12.750 + ent = watch_events.next; 12.751 + if (ent != &watch_events) 12.752 + list_del(ent); 12.753 + spin_unlock(&watch_events_lock); 12.754 12.755 - if (node && !IS_ERR(node)) { 12.756 - struct xenbus_watch *w; 12.757 - int err; 12.758 + if (ent != &watch_events) { 12.759 + msg = list_entry(ent, struct xs_stored_msg, list); 12.760 + msg->u.watch.handle->callback( 12.761 + msg->u.watch.handle, 12.762 + (const char **)msg->u.watch.vec, 12.763 + msg->u.watch.vec_size); 12.764 + free(msg->u.watch.vec); 12.765 + free(msg); 12.766 + } 12.767 12.768 - err = xs_acknowledge_watch(token); 12.769 - if (err) 12.770 - printk("XENBUS ack %s fail %i\n", node, err); 12.771 - w = find_watch(token); 12.772 - //BUG_ON(!w); 12.773 - w->callback(w, node); 12.774 - xfree(node); 12.775 - } else 12.776 - printk("XENBUS xs_read_watch: %li\n", PTR_ERR(node)); 12.777 - up(&xenbus_lock); 12.778 + up(&xenwatch_mutex); 12.779 } 12.780 } 12.781 12.782 - 12.783 -static void ballon_changed(struct xenbus_watch *watch, const char *node) 12.784 +static int process_msg(void) 12.785 { 12.786 - unsigned long new_target; 12.787 - int err; 12.788 - err = xenbus_scanf("memory", "target", "%lu", &new_target); 12.789 + struct xs_stored_msg *msg; 12.790 + char *body; 12.791 + int err; 12.792 + 12.793 + msg = malloc(sizeof(*msg)); 12.794 + if (msg == NULL) 12.795 + return -ENOMEM; 12.796 + 12.797 + err = xb_read(&msg->hdr, sizeof(msg->hdr)); 12.798 + if (err) { 12.799 + free(msg); 12.800 + return err; 12.801 + } 12.802 + 12.803 + body = malloc(msg->hdr.len + 1); 12.804 + if (body == NULL) { 12.805 + free(msg); 12.806 + return -ENOMEM; 12.807 + } 12.808 + 12.809 + err = xb_read(body, msg->hdr.len); 12.810 + if (err) { 12.811 + free(body); 12.812 + free(msg); 12.813 + return err; 12.814 + } 12.815 + body[msg->hdr.len] = '\0'; 12.816 12.817 - if(err != 1) 12.818 - { 12.819 - printk("Unable to read memory/target\n"); 12.820 - return; 12.821 - } 12.822 + if (msg->hdr.type == XS_WATCH_EVENT) { 12.823 + msg->u.watch.vec = split(body, msg->hdr.len, 12.824 + &msg->u.watch.vec_size); 12.825 + if (IS_ERR(msg->u.watch.vec)) { 12.826 + free(msg); 12.827 + return PTR_ERR(msg->u.watch.vec); 12.828 + } 12.829 12.830 - printk("Memory target changed to: %ld bytes, ignoring.\n", new_target); 12.831 + spin_lock(&watches_lock); 12.832 + msg->u.watch.handle = find_watch( 12.833 + msg->u.watch.vec[XS_WATCH_TOKEN]); 12.834 + if (msg->u.watch.handle != NULL) { 12.835 + spin_lock(&watch_events_lock); 12.836 + list_add_tail(&msg->list, &watch_events); 12.837 + wake_up(&watch_events_waitq); 12.838 + spin_unlock(&watch_events_lock); 12.839 + } else { 12.840 + free(msg->u.watch.vec); 12.841 + free(msg); 12.842 + } 12.843 + spin_unlock(&watches_lock); 12.844 + } else { 12.845 + msg->u.reply.body = body; 12.846 + spin_lock(&xs_state.reply_lock); 12.847 + list_add_tail(&msg->list, &xs_state.reply_list); 12.848 + spin_unlock(&xs_state.reply_lock); 12.849 + wake_up(&xs_state.reply_waitq); 12.850 + } 12.851 + 12.852 + return 0; 12.853 } 12.854 12.855 +static void xenbus_thread(void *unused) 12.856 +{ 12.857 + int err; 12.858 12.859 -static struct xenbus_watch ballon_watch = { 12.860 - .node = "memory/target", 12.861 - .callback = ballon_changed, 12.862 -}; 12.863 - 12.864 - 12.865 + for (;;) { 12.866 + err = process_msg(); 12.867 + if (err) 12.868 + printk("XENBUS error %d while reading " 12.869 + "message\n", err); 12.870 + } 12.871 +} 12.872 12.873 int xs_init(void) 12.874 { 12.875 int err; 12.876 - struct thread *watcher; 12.877 - printk("xb_init_comms\n"); 12.878 + struct thread *kxwatcher_thread; 12.879 + struct thread *kxenbus_thread; 12.880 + 12.881 + INIT_LIST_HEAD(&xs_state.reply_list); 12.882 + spin_lock_init(&xs_state.reply_lock); 12.883 + init_waitqueue_head(&xs_state.reply_waitq); 12.884 + 12.885 + init_MUTEX(&xs_state.request_mutex); 12.886 + init_rwsem(&xs_state.suspend_mutex); 12.887 + 12.888 + /* Initialize the shared memory rings to talk to xenstored */ 12.889 err = xb_init_comms(); 12.890 if (err) 12.891 return err; 12.892 - 12.893 - watcher = create_thread("kxwatch", watch_thread, NULL); 12.894 - down(&xenbus_lock); 12.895 - register_xenbus_watch(&ballon_watch); 12.896 - up(&xenbus_lock); 12.897 + 12.898 + kxwatcher_thread = create_thread("kxwatch", xenwatch_thread, NULL); 12.899 + if (IS_ERR(kxwatcher_thread)) 12.900 + return PTR_ERR(kxwatcher_thread); 12.901 + 12.902 + kxenbus_thread = create_thread("kxenbus", xenbus_thread, NULL); 12.903 + if (IS_ERR(kxenbus_thread)) 12.904 + return PTR_ERR(kxenbus_thread); 12.905 + 12.906 return 0; 12.907 }