This commit is contained in:
cl349@firebug.cl.cam.ac.uk committed 2005-09-09 10:20:25 +00:00
commit 4ebbde31e7
33 files changed
+3627 -744

No files matched your search

+7 -4
View File
@@ -31,16 +31,18 @@ TARGET := mini-os
OBJS := $(TARGET_ARCH).o
OBJS += $(patsubst %.c,%.o,$(wildcard *.c))
OBJS += $(patsubst %.c,%.o,$(wildcard lib/*.c))
OBJS += $(patsubst %.c,%.o,$(wildcard xenbus/*.c))
HDRS := $(wildcard include/*.h)
HDRS += $(wildcard include/xen/*.h)
default: $(TARGET)
xen-public:
links:
[ -e include/xen ] || ln -sf ../../../xen/include/public include/xen
$(TARGET): xen-public $(OBJS)
[ -e xenbus/xenstored.h ] || ln -sf ../../../tools/xenstore/xenstored.h xenbus/xenstored.h
$(TARGET): links $(OBJS)
$(LD) -N -T minios-$(TARGET_ARCH).lds $(OBJS) -o $@.elf
gzip -f -9 -c $@.elf >$@.gz
@@ -55,3 +57,4 @@ clean:
%.o: %.S $(HDRS) Makefile
$(CC) $(CFLAGS) -D__ASSEMBLY__ -c $< -o $@
+20 -18
View File
@@ -17,13 +17,13 @@
*/
#include <os.h>
#include <mm.h>
#include <hypervisor.h>
#include <events.h>
#include <lib.h>
#include <xen/event_channel.h>
static ev_action_t ev_actions[NR_EVS];
void default_handler(u32 port, struct pt_regs *regs);
void default_handler(int port, struct pt_regs *regs);
/*
@@ -32,7 +32,6 @@ void default_handler(u32 port, struct pt_regs *regs);
int do_event(u32 port, struct pt_regs *regs)
{
ev_action_t *action;
if (port >= NR_EVS) {
printk("Port number too large: %d\n", port);
return 0;
@@ -57,11 +56,23 @@ int do_event(u32 port, struct pt_regs *regs)
}
void bind_evtchn( u32 port, void (*handler)(int, struct pt_regs *) )
{
if(ev_actions[port].handler)
printk("WARN: Handler for port %d already registered, replacing\n",
port);
ev_actions[port].handler = handler;
ev_actions[port].status &= ~EVS_DISABLED;
/* Finally unmask the port */
unmask_evtchn(port);
}
int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *) )
{
evtchn_op_t op;
int ret = 0;
u32 port;
/* Try to bind the virq to a port */
op.cmd = EVTCHNOP_bind_virq;
@@ -73,22 +84,13 @@ int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *) )
printk("Failed to bind virtual IRQ %d\n", virq);
goto out;
}
port = op.u.bind_virq.port;
if(ev_actions[port].handler)
printk("WARN: Handler for port %d already registered, replacing\n",
port);
ev_actions[port].handler = handler;
ev_actions[port].status &= ~EVS_DISABLED;
/* Finally unmask the port */
unmask_evtchn(port);
bind_evtchn(op.u.bind_virq.port, handler);
out:
return ret;
}
/*
* Initially all events are without a handler and disabled
*/
@@ -100,10 +102,10 @@ void init_events(void)
for ( i = 0; i < NR_EVS; i++ )
{
ev_actions[i].status = EVS_DISABLED;
ev_actions[i].handler = NULL;
ev_actions[i].handler = default_handler;
}
}
void default_handler(u32 port, struct pt_regs *regs) {
void default_handler(int port, struct pt_regs *regs) {
printk("[Port %d] - event received\n", port);
}
+79
View File
@@ -0,0 +1,79 @@
#ifndef _CTYPE_H
#define _CTYPE_H
/*
* NOTE! This ctype does not handle EOF like the standard C
* library is required to.
*/
#define _U 0x01 /* upper */
#define _L 0x02 /* lower */
#define _D 0x04 /* digit */
#define _C 0x08 /* cntrl */
#define _P 0x10 /* punct */
#define _S 0x20 /* white space (space/lf/tab) */
#define _X 0x40 /* hex digit */
#define _SP 0x80 /* hard space (0x20) */
unsigned char _ctype[] = {
_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
#define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0)
#define isalpha(c) ((__ismask(c)&(_U|_L)) != 0)
#define iscntrl(c) ((__ismask(c)&(_C)) != 0)
#define isdigit(c) ((__ismask(c)&(_D)) != 0)
#define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0)
#define islower(c) ((__ismask(c)&(_L)) != 0)
#define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
#define ispunct(c) ((__ismask(c)&(_P)) != 0)
#define isspace(c) ((__ismask(c)&(_S)) != 0)
#define isupper(c) ((__ismask(c)&(_U)) != 0)
#define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0)
#define isascii(c) (((unsigned char)(c))<=0x7f)
#define toascii(c) (((unsigned char)(c))&0x7f)
static inline unsigned char __tolower(unsigned char c)
{
if (isupper(c))
c -= 'A'-'a';
return c;
}
static inline unsigned char __toupper(unsigned char c)
{
if (islower(c))
c -= 'a'-'A';
return c;
}
#define tolower(c) __tolower(c)
#define toupper(c) __toupper(c)
#endif
+31
View File
@@ -0,0 +1,31 @@
#ifndef _ERR_H
#define _ERR_H
#include <errno.h>
/*
* Kernel pointers have redundant information, so we can use a
* scheme where we can return either an error code or a dentry
* pointer with the same return value.
*
* This should be a per-architecture thing, to allow different
* error and pointer decisions.
*/
#define IS_ERR_VALUE(x) ((x) > (unsigned long)-1000L)
static inline void *ERR_PTR(long error)
{
return (void *) error;
}
static inline long PTR_ERR(const void *ptr)
{
return (long) ptr;
}
static inline long IS_ERR(const void *ptr)
{
return IS_ERR_VALUE((unsigned long)ptr);
}
#endif /* _LINUX_ERR_H */
+39
View File
@@ -0,0 +1,39 @@
#ifndef _ERRNO_BASE_H
#define _ERRNO_BASE_H
#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No child processes */
#define EAGAIN 11 /* Try again */
#define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device or resource busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File table overflow */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Not a typewriter */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Math argument out of domain of func */
#define ERANGE 34 /* Math result not representable */
#endif
+109
View File
@@ -0,0 +1,109 @@
#ifndef _ERRNO_H
#define _ERRNO_H
#include <errno-base.h>
#define EDEADLK 35 /* Resource deadlock would occur */
#define ENAMETOOLONG 36 /* File name too long */
#define ENOLCK 37 /* No record locks available */
#define ENOSYS 38 /* Function not implemented */
#define ENOTEMPTY 39 /* Directory not empty */
#define ELOOP 40 /* Too many symbolic links encountered */
#define EWOULDBLOCK EAGAIN /* Operation would block */
#define ENOMSG 42 /* No message of desired type */
#define EIDRM 43 /* Identifier removed */
#define ECHRNG 44 /* Channel number out of range */
#define EL2NSYNC 45 /* Level 2 not synchronized */
#define EL3HLT 46 /* Level 3 halted */
#define EL3RST 47 /* Level 3 reset */
#define ELNRNG 48 /* Link number out of range */
#define EUNATCH 49 /* Protocol driver not attached */
#define ENOCSI 50 /* No CSI structure available */
#define EL2HLT 51 /* Level 2 halted */
#define EBADE 52 /* Invalid exchange */
#define EBADR 53 /* Invalid request descriptor */
#define EXFULL 54 /* Exchange full */
#define ENOANO 55 /* No anode */
#define EBADRQC 56 /* Invalid request code */
#define EBADSLT 57 /* Invalid slot */
#define EDEADLOCK EDEADLK
#define EBFONT 59 /* Bad font file format */
#define ENOSTR 60 /* Device not a stream */
#define ENODATA 61 /* No data available */
#define ETIME 62 /* Timer expired */
#define ENOSR 63 /* Out of streams resources */
#define ENONET 64 /* Machine is not on the network */
#define ENOPKG 65 /* Package not installed */
#define EREMOTE 66 /* Object is remote */
#define ENOLINK 67 /* Link has been severed */
#define EADV 68 /* Advertise error */
#define ESRMNT 69 /* Srmount error */
#define ECOMM 70 /* Communication error on send */
#define EPROTO 71 /* Protocol error */
#define EMULTIHOP 72 /* Multihop attempted */
#define EDOTDOT 73 /* RFS specific error */
#define EBADMSG 74 /* Not a data message */
#define EOVERFLOW 75 /* Value too large for defined data type */
#define ENOTUNIQ 76 /* Name not unique on network */
#define EBADFD 77 /* File descriptor in bad state */
#define EREMCHG 78 /* Remote address changed */
#define ELIBACC 79 /* Can not access a needed shared library */
#define ELIBBAD 80 /* Accessing a corrupted shared library */
#define ELIBSCN 81 /* .lib section in a.out corrupted */
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
#define EILSEQ 84 /* Illegal byte sequence */
#define ERESTART 85 /* Interrupted system call should be restarted */
#define ESTRPIPE 86 /* Streams pipe error */
#define EUSERS 87 /* Too many users */
#define ENOTSOCK 88 /* Socket operation on non-socket */
#define EDESTADDRREQ 89 /* Destination address required */
#define EMSGSIZE 90 /* Message too long */
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
#define ENOPROTOOPT 92 /* Protocol not available */
#define EPROTONOSUPPORT 93 /* Protocol not supported */
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
#define EPFNOSUPPORT 96 /* Protocol family not supported */
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
#define EADDRINUSE 98 /* Address already in use */
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
#define ENETDOWN 100 /* Network is down */
#define ENETUNREACH 101 /* Network is unreachable */
#define ENETRESET 102 /* Network dropped connection because of reset */
#define ECONNABORTED 103 /* Software caused connection abort */
#define ECONNRESET 104 /* Connection reset by peer */
#define ENOBUFS 105 /* No buffer space available */
#define EISCONN 106 /* Transport endpoint is already connected */
#define ENOTCONN 107 /* Transport endpoint is not connected */
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
#define ETIMEDOUT 110 /* Connection timed out */
#define ECONNREFUSED 111 /* Connection refused */
#define EHOSTDOWN 112 /* Host is down */
#define EHOSTUNREACH 113 /* No route to host */
#define EALREADY 114 /* Operation already in progress */
#define EINPROGRESS 115 /* Operation now in progress */
#define ESTALE 116 /* Stale NFS file handle */
#define EUCLEAN 117 /* Structure needs cleaning */
#define ENOTNAM 118 /* Not a XENIX named type file */
#define ENAVAIL 119 /* No XENIX semaphores available */
#define EISNAM 120 /* Is a named type file */
#define EREMOTEIO 121 /* Remote I/O error */
#define EDQUOT 122 /* Quota exceeded */
#define ENOMEDIUM 123 /* No medium found */
#define EMEDIUMTYPE 124 /* Wrong medium type */
#define ECANCELED 125 /* Operation Canceled */
#define ENOKEY 126 /* Required key not available */
#define EKEYEXPIRED 127 /* Key has expired */
#define EKEYREVOKED 128 /* Key has been revoked */
#define EKEYREJECTED 129 /* Key was rejected by service */
/* for robust mutexes */
#define EOWNERDEAD 130 /* Owner died */
#define ENOTRECOVERABLE 131 /* State not recoverable */
#endif
+11
View File
@@ -20,6 +20,7 @@
#define _EVENTS_H_
#include<traps.h>
#include <xen/event_channel.h>
#define NR_EVS 1024
@@ -39,6 +40,16 @@ 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 *) );
void init_events(void);
static inline int notify_via_evtchn(int port)
{
evtchn_op_t op;
op.cmd = EVTCHNOP_send;
op.u.send.local_port = port;
return HYPERVISOR_event_channel_op(&op);
}
#endif /* _EVENTS_H_ */
+89
View File
@@ -0,0 +1,89 @@
#ifndef _I386_FCNTL_H
#define _I386_FCNTL_H
/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
located on an ext2 file system */
#define O_ACCMODE 0003
#define O_RDONLY 00
#define O_WRONLY 01
#define O_RDWR 02
#define O_CREAT 0100 /* not fcntl */
#define O_EXCL 0200 /* not fcntl */
#define O_NOCTTY 0400 /* not fcntl */
#define O_TRUNC 01000 /* not fcntl */
#define O_APPEND 02000
#define O_NONBLOCK 04000
#define O_NDELAY O_NONBLOCK
#define O_SYNC 010000
#define FASYNC 020000 /* fcntl, for BSD compatibility */
#define O_DIRECT 040000 /* direct disk access hint */
#define O_LARGEFILE 0100000
#define O_DIRECTORY 0200000 /* must be a directory */
#define O_NOFOLLOW 0400000 /* don't follow links */
#define O_NOATIME 01000000
#define F_DUPFD 0 /* dup */
#define F_GETFD 1 /* get close_on_exec */
#define F_SETFD 2 /* set/clear close_on_exec */
#define F_GETFL 3 /* get file->f_flags */
#define F_SETFL 4 /* set file->f_flags */
#define F_GETLK 5
#define F_SETLK 6
#define F_SETLKW 7
#define F_SETOWN 8 /* for sockets. */
#define F_GETOWN 9 /* for sockets. */
#define F_SETSIG 10 /* for sockets. */
#define F_GETSIG 11 /* for sockets. */
#define F_GETLK64 12 /* using 'struct flock64' */
#define F_SETLK64 13
#define F_SETLKW64 14
/* for F_[GET|SET]FL */
#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
/* for posix fcntl() and lockf() */
#define F_RDLCK 0
#define F_WRLCK 1
#define F_UNLCK 2
/* for old implementation of bsd flock () */
#define F_EXLCK 4 /* or 3 */
#define F_SHLCK 8 /* or 4 */
/* for leases */
#define F_INPROGRESS 16
/* operations for bsd flock(), also used by the kernel implementation */
#define LOCK_SH 1 /* shared lock */
#define LOCK_EX 2 /* exclusive lock */
#define LOCK_NB 4 /* or'd with one of the above to prevent
blocking */
#define LOCK_UN 8 /* remove lock */
#define LOCK_MAND 32 /* This is a mandatory flock */
#define LOCK_READ 64 /* ... Which allows concurrent read operations */
#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
/*
struct flock {
short l_type;
short l_whence;
off_t l_start;
off_t l_len;
pid_t l_pid;
};
struct flock64 {
short l_type;
short l_whence;
loff_t l_start;
loff_t l_len;
pid_t l_pid;
};
#define F_LINUX_SPECIFIC_BASE 1024
*/
#endif
+611 -94
View File
@@ -13,7 +13,6 @@
#define _HYPERVISOR_H_
#include <types.h>
#include <xen/xen.h>
#include <xen/io/domain_controller.h>
@@ -40,48 +39,26 @@ void clear_evtchn(u32 port);
/*
* Assembler stubs for hyper-calls.
*/
#ifdef __i386__
#define _a1 "b"
#define _a2 "c"
#define _a3 "d"
#define _a4 "S"
#else
#define _a1 "D"
#define _a2 "S"
#define _a3 "d"
#define _a4 "b"
#endif
static __inline__ int HYPERVISOR_event_channel_op(
void *op)
#if defined(__i386__)
static inline int
HYPERVISOR_set_trap_table(
trap_info_t *table)
{
int ret;
unsigned long ignore;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret), "=b" (ignore)
: "0" (__HYPERVISOR_event_channel_op), "1" (op)
: "0" (__HYPERVISOR_set_trap_table), "1" (table)
: "memory" );
return ret;
}
static __inline__ int HYPERVISOR_set_trap_table(trap_info_t *table)
{
int ret;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret) : "0" (__HYPERVISOR_set_trap_table),
_a1 (table) : "memory" );
return ret;
}
static __inline__ int HYPERVISOR_mmu_update(mmu_update_t *req,
int count,
int *success_count,
domid_t domid)
static inline int
HYPERVISOR_mmu_update(
mmu_update_t *req, int count, int *success_count, domid_t domid)
{
int ret;
unsigned long ign1, ign2, ign3, ign4;
@@ -89,18 +66,16 @@ static __inline__ int HYPERVISOR_mmu_update(mmu_update_t *req,
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
: "0" (__HYPERVISOR_mmu_update), "1" (req), "2" (count),
"3" (success_count), "4" (domid)
: "memory" );
: "0" (__HYPERVISOR_mmu_update), "1" (req), "2" (count),
"3" (success_count), "4" (domid)
: "memory" );
return ret;
}
static __inline__ int HYPERVISOR_mmuext_op(struct mmuext_op *op,
int count,
int *success_count,
domid_t domid)
static inline int
HYPERVISOR_mmuext_op(
struct mmuext_op *op, int count, int *success_count, domid_t domid)
{
int ret;
unsigned long ign1, ign2, ign3, ign4;
@@ -108,70 +83,65 @@ static __inline__ int HYPERVISOR_mmuext_op(struct mmuext_op *op,
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
: "0" (__HYPERVISOR_mmuext_op), "1" (op), "2" (count),
"3" (success_count), "4" (domid)
: "memory" );
: "0" (__HYPERVISOR_mmuext_op), "1" (op), "2" (count),
"3" (success_count), "4" (domid)
: "memory" );
return ret;
}
static __inline__ int HYPERVISOR_set_gdt(unsigned long *frame_list, int entries)
static inline int
HYPERVISOR_set_gdt(
unsigned long *frame_list, int entries)
{
int ret;
unsigned long ign1, ign2;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret) : "0" (__HYPERVISOR_set_gdt),
_a1 (frame_list), _a2 (entries) : "memory" );
: "=a" (ret), "=b" (ign1), "=c" (ign2)
: "0" (__HYPERVISOR_set_gdt), "1" (frame_list), "2" (entries)
: "memory" );
return ret;
}
static __inline__ int HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp)
static inline int
HYPERVISOR_stack_switch(
unsigned long ss, unsigned long esp)
{
int ret;
unsigned long ign1, ign2;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret) : "0" (__HYPERVISOR_stack_switch),
_a1 (ss), _a2 (esp) : "memory" );
: "=a" (ret), "=b" (ign1), "=c" (ign2)
: "0" (__HYPERVISOR_stack_switch), "1" (ss), "2" (esp)
: "memory" );
return ret;
}
#ifdef __i386__
static __inline__ int HYPERVISOR_set_callbacks(
static inline int
HYPERVISOR_set_callbacks(
unsigned long event_selector, unsigned long event_address,
unsigned long failsafe_selector, unsigned long failsafe_address)
{
int ret;
unsigned long ign1, ign2, ign3, ign4;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret) : "0" (__HYPERVISOR_set_callbacks),
_a1 (event_selector), _a2 (event_address),
_a3 (failsafe_selector), _a4 (failsafe_address) : "memory" );
: "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
: "0" (__HYPERVISOR_set_callbacks), "1" (event_selector),
"2" (event_address), "3" (failsafe_selector), "4" (failsafe_address)
: "memory" );
return ret;
}
#else
static __inline__ int HYPERVISOR_set_callbacks(
unsigned long event_address,
unsigned long failsafe_address,
unsigned long syscall_address)
{
int ret;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret) : "0" (__HYPERVISOR_set_callbacks),
_a1 (event_address), _a2 (failsafe_address),
_a3 (syscall_address) : "memory" );
return ret;
}
#endif
static __inline__ int
static inline int
HYPERVISOR_fpu_taskswitch(
int set)
{
@@ -187,67 +157,106 @@ HYPERVISOR_fpu_taskswitch(
return ret;
}
static __inline__ int HYPERVISOR_yield(void)
static inline int
HYPERVISOR_yield(
void)
{
int ret;
unsigned long ign;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret) : "0" (__HYPERVISOR_sched_op),
_a1 (SCHEDOP_yield) : "memory" );
: "=a" (ret), "=b" (ign)
: "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_yield)
: "memory", "ecx" );
return ret;
}
static __inline__ int HYPERVISOR_block(void)
static inline int
HYPERVISOR_block(
void)
{
int ret;
unsigned long ign1;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret) : "0" (__HYPERVISOR_sched_op),
_a1 (SCHEDOP_block) : "memory" );
: "=a" (ret), "=b" (ign1)
: "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_block)
: "memory", "ecx" );
return ret;
}
static __inline__ int HYPERVISOR_shutdown(void)
static inline int
HYPERVISOR_shutdown(
void)
{
int ret;
unsigned long ign1;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret) : "0" (__HYPERVISOR_sched_op),
_a1 (SCHEDOP_shutdown | (SHUTDOWN_poweroff << SCHEDOP_reasonshift))
: "memory" );
: "=a" (ret), "=b" (ign1)
: "0" (__HYPERVISOR_sched_op),
"1" (SCHEDOP_shutdown | (SHUTDOWN_poweroff << SCHEDOP_reasonshift))
: "memory", "ecx" );
return ret;
}
static __inline__ int HYPERVISOR_reboot(void)
static inline int
HYPERVISOR_reboot(
void)
{
int ret;
unsigned long ign1;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret) : "0" (__HYPERVISOR_sched_op),
_a1 (SCHEDOP_shutdown | (SHUTDOWN_reboot << SCHEDOP_reasonshift))
: "memory" );
: "=a" (ret), "=b" (ign1)
: "0" (__HYPERVISOR_sched_op),
"1" (SCHEDOP_shutdown | (SHUTDOWN_reboot << SCHEDOP_reasonshift))
: "memory", "ecx" );
return ret;
}
static __inline__ int HYPERVISOR_suspend(unsigned long srec)
static inline int
HYPERVISOR_suspend(
unsigned long srec)
{
int ret;
unsigned long ign1, ign2;
/* NB. On suspend, control software expects a suspend record in %esi. */
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret) : "0" (__HYPERVISOR_sched_op),
_a1 (SCHEDOP_shutdown | (SHUTDOWN_suspend << SCHEDOP_reasonshift)),
"S" (srec) : "memory" );
: "=a" (ret), "=b" (ign1), "=S" (ign2)
: "0" (__HYPERVISOR_sched_op),
"b" (SCHEDOP_shutdown | (SHUTDOWN_suspend << SCHEDOP_reasonshift)),
"S" (srec) : "memory", "ecx");
return ret;
}
#ifdef __i386__
static __inline__ long HYPERVISOR_set_timer_op( u64 timeout )
static inline int
HYPERVISOR_crash(
void)
{
int ret;
unsigned long ign1;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret), "=b" (ign1)
: "0" (__HYPERVISOR_sched_op),
"1" (SCHEDOP_shutdown | (SHUTDOWN_crash << SCHEDOP_reasonshift))
: "memory", "ecx" );
return ret;
}
static inline long
HYPERVISOR_set_timer_op(
u64 timeout)
{
int ret;
unsigned long timeout_hi = (unsigned long)(timeout>>32);
@@ -262,8 +271,516 @@ static __inline__ long HYPERVISOR_set_timer_op( u64 timeout )
return ret;
}
#if 0
static inline int
HYPERVISOR_dom0_op(
dom0_op_t *dom0_op)
{
int ret;
unsigned long ign1;
dom0_op->interface_version = DOM0_INTERFACE_VERSION;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret), "=b" (ign1)
: "0" (__HYPERVISOR_dom0_op), "1" (dom0_op)
: "memory");
return ret;
}
#endif
static inline int
HYPERVISOR_set_debugreg(
int reg, unsigned long value)
{
int ret;
unsigned long ign1, ign2;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret), "=b" (ign1), "=c" (ign2)
: "0" (__HYPERVISOR_set_debugreg), "1" (reg), "2" (value)
: "memory" );
return ret;
}
static inline unsigned long
HYPERVISOR_get_debugreg(
int reg)
{
unsigned long ret;
unsigned long ign;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret), "=b" (ign)
: "0" (__HYPERVISOR_get_debugreg), "1" (reg)
: "memory" );
return ret;
}
static inline int
HYPERVISOR_update_descriptor(
u64 ma, u64 desc)
{
int ret;
unsigned long ign1, ign2, ign3, ign4;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
: "0" (__HYPERVISOR_update_descriptor),
"1" ((unsigned long)ma), "2" ((unsigned long)(ma>>32)),
"3" ((unsigned long)desc), "4" ((unsigned long)(desc>>32))
: "memory" );
return ret;
}
static inline int
HYPERVISOR_dom_mem_op(
unsigned int op, unsigned long *extent_list,
unsigned long nr_extents, unsigned int extent_order)
{
int ret;
unsigned long ign1, ign2, ign3, ign4, ign5;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4),
"=D" (ign5)
: "0" (__HYPERVISOR_dom_mem_op), "1" (op), "2" (extent_list),
"3" (nr_extents), "4" (extent_order), "5" (DOMID_SELF)
: "memory" );
return ret;
}
static inline int
HYPERVISOR_multicall(
void *call_list, int nr_calls)
{
int ret;
unsigned long ign1, ign2;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret), "=b" (ign1), "=c" (ign2)
: "0" (__HYPERVISOR_multicall), "1" (call_list), "2" (nr_calls)
: "memory" );
return ret;
}
static inline int
HYPERVISOR_update_va_mapping(
unsigned long va, pte_t new_val, unsigned long flags)
{
int ret;
unsigned long ign1, ign2, ign3, ign4;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
: "0" (__HYPERVISOR_update_va_mapping),
"1" (va), "2" ((new_val).pte_low),
#ifdef CONFIG_X86_PAE
"3" ((new_val).pte_high),
#else
static __inline__ long HYPERVISOR_set_timer_op( u64 timeout )
"3" (0),
#endif
"4" (flags)
: "memory" );
return ret;
}
static inline int
HYPERVISOR_event_channel_op(
void *op)
{
int ret;
unsigned long ignore;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret), "=b" (ignore)
: "0" (__HYPERVISOR_event_channel_op), "1" (op)
: "memory" );
return ret;
}
static inline int
HYPERVISOR_xen_version(
int cmd)
{
int ret;
unsigned long ignore;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret), "=b" (ignore)
: "0" (__HYPERVISOR_xen_version), "1" (cmd)
: "memory" );
return ret;
}
static inline int
HYPERVISOR_console_io(
int cmd, int count, char *str)
{
int ret;
unsigned long ign1, ign2, ign3;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
: "0" (__HYPERVISOR_console_io), "1" (cmd), "2" (count), "3" (str)
: "memory" );
return ret;
}
static inline int
HYPERVISOR_physdev_op(
void *physdev_op)
{
int ret;
unsigned long ign;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret), "=b" (ign)
: "0" (__HYPERVISOR_physdev_op), "1" (physdev_op)
: "memory" );
return ret;
}
static inline int
HYPERVISOR_grant_table_op(
unsigned int cmd, void *uop, unsigned int count)
{
int ret;
unsigned long ign1, ign2, ign3;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
: "0" (__HYPERVISOR_grant_table_op), "1" (cmd), "2" (uop), "3" (count)
: "memory" );
return ret;
}
static inline int
HYPERVISOR_update_va_mapping_otherdomain(
unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
{
int ret;
unsigned long ign1, ign2, ign3, ign4, ign5;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3),
"=S" (ign4), "=D" (ign5)
: "0" (__HYPERVISOR_update_va_mapping_otherdomain),
"1" (va), "2" ((new_val).pte_low),
#ifdef CONFIG_X86_PAE
"3" ((new_val).pte_high),
#else
"3" (0),
#endif
"4" (flags), "5" (domid) :
"memory" );
return ret;
}
static inline int
HYPERVISOR_vm_assist(
unsigned int cmd, unsigned int type)
{
int ret;
unsigned long ign1, ign2;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret), "=b" (ign1), "=c" (ign2)
: "0" (__HYPERVISOR_vm_assist), "1" (cmd), "2" (type)
: "memory" );
return ret;
}
static inline int
HYPERVISOR_boot_vcpu(
unsigned long vcpu, vcpu_guest_context_t *ctxt)
{
int ret;
unsigned long ign1, ign2;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret), "=b" (ign1), "=c" (ign2)
: "0" (__HYPERVISOR_boot_vcpu), "1" (vcpu), "2" (ctxt)
: "memory");
return ret;
}
static inline int
HYPERVISOR_vcpu_down(
int vcpu)
{
int ret;
unsigned long ign1;
/* Yes, I really do want to clobber edx here: when we resume a
vcpu after unpickling a multi-processor domain, it returns
here, but clobbers all of the call clobbered registers. */
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret), "=b" (ign1)
: "0" (__HYPERVISOR_sched_op),
"1" (SCHEDOP_vcpu_down | (vcpu << SCHEDOP_vcpushift))
: "memory", "ecx", "edx" );
return ret;
}
static inline int
HYPERVISOR_vcpu_up(
int vcpu)
{
int ret;
unsigned long ign1;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret), "=b" (ign1)
: "0" (__HYPERVISOR_sched_op),
"1" (SCHEDOP_vcpu_up | (vcpu << SCHEDOP_vcpushift))
: "memory", "ecx" );
return ret;
}
static inline int
HYPERVISOR_vcpu_pickle(
int vcpu, vcpu_guest_context_t *ctxt)
{
int ret;
unsigned long ign1, ign2;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret), "=b" (ign1), "=c" (ign2)
: "0" (__HYPERVISOR_sched_op),
"1" (SCHEDOP_vcpu_pickle | (vcpu << SCHEDOP_vcpushift)),
"2" (ctxt)
: "memory" );
return ret;
}
#elif defined(__x86_64__)
#define __syscall_clobber "r11","rcx","memory"
/*
* Assembler stubs for hyper-calls.
*/
static inline int
HYPERVISOR_set_trap_table(
trap_info_t *table)
{
int ret;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret)
: "0" ((unsigned long)__HYPERVISOR_set_trap_table), "D" (table)
: __syscall_clobber );
return ret;
}
static inline int
HYPERVISOR_mmu_update(
mmu_update_t *req, int count, int *success_count, domid_t domid)
{
int ret;
__asm__ __volatile__ (
"movq %5, %%r10;" TRAP_INSTR
: "=a" (ret)
: "0" ((unsigned long)__HYPERVISOR_mmu_update), "D" (req), "S" ((long)count),
"d" (success_count), "g" ((unsigned long)domid)
: __syscall_clobber, "r10" );
return ret;
}
static inline int
HYPERVISOR_mmuext_op(
struct mmuext_op *op, int count, int *success_count, domid_t domid)
{
int ret;
__asm__ __volatile__ (
"movq %5, %%r10;" TRAP_INSTR
: "=a" (ret)
: "0" (__HYPERVISOR_mmuext_op), "D" (op), "S" ((long)count),
"d" (success_count), "g" ((unsigned long)domid)
: __syscall_clobber, "r10" );
return ret;
}
static inline int
HYPERVISOR_set_gdt(
unsigned long *frame_list, int entries)
{
int ret;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret)
: "0" ((unsigned long)__HYPERVISOR_set_gdt), "D" (frame_list), "S" ((long)entries)
: __syscall_clobber );
return ret;
}
static inline int
HYPERVISOR_stack_switch(
unsigned long ss, unsigned long esp)
{
int ret;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret)
: "0" ((unsigned long)__HYPERVISOR_stack_switch), "D" (ss), "S" (esp)
: __syscall_clobber );
return ret;
}
static inline int
HYPERVISOR_set_callbacks(
unsigned long event_address, unsigned long failsafe_address,
unsigned long syscall_address)
{
int ret;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret)
: "0" ((unsigned long)__HYPERVISOR_set_callbacks), "D" (event_address),
"S" (failsafe_address), "d" (syscall_address)
: __syscall_clobber );
return ret;
}
static inline int
HYPERVISOR_fpu_taskswitch(
int set)
{
int ret;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret) : "0" ((unsigned long)__HYPERVISOR_fpu_taskswitch),
"D" ((unsigned long) set) : __syscall_clobber );
return ret;
}
static inline int
HYPERVISOR_yield(
void)
{
int ret;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret)
: "0" ((unsigned long)__HYPERVISOR_sched_op), "D" ((unsigned long)SCHEDOP_yield)
: __syscall_clobber );
return ret;
}
static inline int
HYPERVISOR_block(
void)
{
int ret;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret)
: "0" ((unsigned long)__HYPERVISOR_sched_op), "D" ((unsigned long)SCHEDOP_block)
: __syscall_clobber );
return ret;
}
static inline int
HYPERVISOR_shutdown(
void)
{
int ret;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret)
: "0" ((unsigned long)__HYPERVISOR_sched_op),
"D" ((unsigned long)(SCHEDOP_shutdown | (SHUTDOWN_poweroff << SCHEDOP_reasonshift)))
: __syscall_clobber );
return ret;
}
static inline int
HYPERVISOR_reboot(
void)
{
int ret;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret)
: "0" ((unsigned long)__HYPERVISOR_sched_op),
"D" ((unsigned long)(SCHEDOP_shutdown | (SHUTDOWN_reboot << SCHEDOP_reasonshift)))
: __syscall_clobber );
return ret;
}
static inline int
HYPERVISOR_suspend(
unsigned long srec)
{
int ret;
/* NB. On suspend, control software expects a suspend record in %esi. */
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret)
: "0" ((unsigned long)__HYPERVISOR_sched_op),
"D" ((unsigned long)(SCHEDOP_shutdown | (SHUTDOWN_suspend << SCHEDOP_reasonshift))),
"S" (srec)
: __syscall_clobber );
return ret;
}
/*
* We can have the timeout value in a single argument for the hypercall, but
* that will break the common code.
*/
static inline long
HYPERVISOR_set_timer_op(
u64 timeout)
{
int ret;
+26 -4
View File
@@ -60,10 +60,22 @@
/* printing */
#define printk printf
#define kprintf printf
int printf(const char *fmt, ...);
int vprintf(const char *fmt, va_list ap);
int sprintf(char *buf, const char *cfmt, ...);
int vsprintf(char *buf, const char *cfmt, va_list ap);
#define _p(_x) ((void *)(unsigned long)(_x))
void printf(const char *fmt, ...);
int vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
int vscnprintf(char *buf, size_t size, const char *fmt, va_list args);
int snprintf(char * buf, size_t size, const char *fmt, ...);
int scnprintf(char * buf, size_t size, const char *fmt, ...);
int vsprintf(char *buf, const char *fmt, va_list args);
int sprintf(char * buf, const char *fmt, ...);
int vsscanf(const char * buf, const char * fmt, va_list args);
int sscanf(const char * buf, const char * fmt, ...);
long simple_strtol(const char *cp,char **endp,unsigned int base);
unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base);
long long simple_strtoll(const char *cp,char **endp,unsigned int base);
unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base);
/* string and memory manipulation */
int memcmp(const void *cs, const void *ct, size_t count);
@@ -77,6 +89,16 @@ size_t strnlen(const char *s, size_t count);
size_t strlen(const char *s);
char *strchr(const char *s, int c);
char *strstr(const char *s1, const char *s2);
char * strcat(char * dest, const char * src);
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
struct kvec {
void *iov_base;
size_t iov_len;
};
#endif /* _LIB_H_ */
+16 -4
View File
@@ -25,6 +25,15 @@
#ifndef _MM_H_
#define _MM_H_
#ifdef __i386__
#include <xen/arch-x86_32.h>
#endif
#ifdef __x86_64__
#include <xen/arch-x86_64.h>
#endif
#ifdef __x86_64__
#define L1_PAGETABLE_SHIFT 12
@@ -56,6 +65,8 @@
#define L1_PAGETABLE_ENTRIES 1024
#define L2_PAGETABLE_ENTRIES 1024
#elif defined(__x86_64__)
#endif
/* Given a virtual address, get an entry offset into a page table. */
@@ -97,13 +108,15 @@
extern unsigned long *phys_to_machine_mapping;
#define pfn_to_mfn(_pfn) (phys_to_machine_mapping[(_pfn)])
#define mfn_to_pfn(_mfn) (machine_to_phys_mapping[(_mfn)])
static __inline__ unsigned long phys_to_machine(unsigned long phys)
{
unsigned long machine = pfn_to_mfn(phys >> L1_PAGETABLE_SHIFT);
machine = (machine << L1_PAGETABLE_SHIFT) | (phys & ~PAGE_MASK);
return machine;
}
#define mfn_to_pfn(_mfn) (machine_to_phys_mapping[(_mfn)])
static __inline__ unsigned long machine_to_phys(unsigned long machine)
{
unsigned long phys = mfn_to_pfn(machine >> L1_PAGETABLE_SHIFT);
@@ -119,16 +132,15 @@ static __inline__ unsigned long machine_to_phys(unsigned long machine)
#define to_phys(x) ((unsigned long)(x)-VIRT_START)
#define to_virt(x) ((void *)((unsigned long)(x)+VIRT_START))
#define __va to_virt
#define __pa to_phys
#define virt_to_pfn(_virt) (PFN_DOWN(to_phys(_virt)))
#define mach_to_virt(_mach) (to_virt(machine_to_phys(_mach)))
#define mfn_to_virt(_mfn) (mach_to_virt(_mfn << PAGE_SHIFT))
void init_mm(void);
unsigned long alloc_pages(int order);
#define alloc_page() alloc_pages(0);
void free_pages(void *pointer, int order);
//int is_mfn_mapped(unsigned long mfn);
static __inline__ int get_order(unsigned long size)
{
+247 -90
View File
@@ -15,16 +15,17 @@
#define unlikely(x) __builtin_expect((x),0)
#define smp_processor_id() 0
#define preempt_disable() ((void)0)
#define preempt_enable() ((void)0)
#define force_evtchn_callback() ((void)HYPERVISOR_xen_version(0))
#ifndef __ASSEMBLY__
#include <types.h>
#include <hypervisor.h>
#endif
#include <xen/xen.h>
#define force_evtchn_callback() ((void)HYPERVISOR_xen_version(0))
#define __KERNEL_CS FLAT_KERNEL_CS
#define __KERNEL_DS FLAT_KERNEL_DS
#define __KERNEL_SS FLAT_KERNEL_SS
@@ -54,8 +55,6 @@
/* Everything below this point is not included by assembler (.S) files. */
#ifndef __ASSEMBLY__
#define pt_regs xen_regs
void trap_init(void);
/*
@@ -69,10 +68,8 @@ void trap_init(void);
#define __cli() \
do { \
vcpu_info_t *_vcpu; \
preempt_disable(); \
_vcpu = &HYPERVISOR_shared_info->vcpu_data[smp_processor_id()]; \
_vcpu->evtchn_upcall_mask = 1; \
preempt_enable_no_resched(); \
barrier(); \
} while (0)
@@ -80,13 +77,11 @@ do { \
do { \
vcpu_info_t *_vcpu; \
barrier(); \
preempt_disable(); \
_vcpu = &HYPERVISOR_shared_info->vcpu_data[smp_processor_id()]; \
_vcpu->evtchn_upcall_mask = 0; \
barrier(); /* unmask then check (avoid races) */ \
if ( unlikely(_vcpu->evtchn_upcall_pending) ) \
force_evtchn_callback(); \
preempt_enable(); \
} while (0)
#define __save_flags(x) \
@@ -100,15 +95,12 @@ do { \
do { \
vcpu_info_t *_vcpu; \
barrier(); \
preempt_disable(); \
_vcpu = &HYPERVISOR_shared_info->vcpu_data[smp_processor_id()]; \
if ((_vcpu->evtchn_upcall_mask = (x)) == 0) { \
barrier(); /* unmask then check (avoid races) */ \
if ( unlikely(_vcpu->evtchn_upcall_pending) ) \
force_evtchn_callback(); \
preempt_enable(); \
} else \
preempt_enable_no_resched(); \
}\
} while (0)
#define safe_halt() ((void)0)
@@ -116,11 +108,9 @@ do { \
#define __save_and_cli(x) \
do { \
vcpu_info_t *_vcpu; \
preempt_disable(); \
_vcpu = &HYPERVISOR_shared_info->vcpu_data[smp_processor_id()]; \
(x) = _vcpu->evtchn_upcall_mask; \
_vcpu->evtchn_upcall_mask = 1; \
preempt_enable_no_resched(); \
barrier(); \
} while (0)
@@ -136,6 +126,15 @@ do { \
/* This is a barrier for the compiler only, NOT the processor! */
#define barrier() __asm__ __volatile__("": : :"memory")
#if defined(__i386__)
#define mb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
#define rmb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
#elif defined(__x86_64__)
#define mb() __asm__ __volatile__ ("mfence":::"memory")
#define rmb() __asm__ __volatile__ ("lfence":::"memory")
#endif
#define LOCK_PREFIX ""
#define LOCK ""
#define ADDR (*(volatile long *) addr)
@@ -147,39 +146,187 @@ do { \
typedef struct { volatile int counter; } atomic_t;
#define xchg(ptr,v) \
((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
/************************** i386 *******************************/
#if defined (__i386__)
#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
struct __xchg_dummy { unsigned long a[100]; };
#define __xg(x) ((volatile struct __xchg_dummy *)(x))
static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr,
int size)
#define __xg(x) ((struct __xchg_dummy *)(x))
static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
{
switch (size) {
case 1:
__asm__ __volatile__("xchgb %b0,%1"
:"=q" (x)
:"m" (*__xg(ptr)), "0" (x)
:"memory");
break;
case 2:
__asm__ __volatile__("xchgw %w0,%1"
:"=r" (x)
:"m" (*__xg(ptr)), "0" (x)
:"memory");
break;
case 4:
__asm__ __volatile__("xchgl %0,%1"
:"=r" (x)
:"m" (*__xg(ptr)), "0" (x)
:"memory");
break;
}
return x;
switch (size) {
case 1:
__asm__ __volatile__("xchgb %b0,%1"
:"=q" (x)
:"m" (*__xg(ptr)), "0" (x)
:"memory");
break;
case 2:
__asm__ __volatile__("xchgw %w0,%1"
:"=r" (x)
:"m" (*__xg(ptr)), "0" (x)
:"memory");
break;
case 4:
__asm__ __volatile__("xchgl %0,%1"
:"=r" (x)
:"m" (*__xg(ptr)), "0" (x)
:"memory");
break;
}
return x;
}
/**
* test_and_clear_bit - Clear a bit and return its old value
* @nr: Bit to set
* @nr: Bit to clear
* @addr: Address to count from
*
* This operation is atomic and cannot be reordered.
* It can be reorderdered on other architectures other than x86.
* It also implies a memory barrier.
*/
static inline int test_and_clear_bit(int nr, volatile unsigned long * addr)
{
int oldbit;
__asm__ __volatile__( LOCK
"btrl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"=m" (ADDR)
:"Ir" (nr) : "memory");
return oldbit;
}
static inline int constant_test_bit(int nr, const volatile unsigned long *addr)
{
return ((1UL << (nr & 31)) & (addr[nr >> 5])) != 0;
}
static inline int variable_test_bit(int nr, const volatile unsigned long * addr)
{
int oldbit;
__asm__ __volatile__(
"btl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit)
:"m" (ADDR),"Ir" (nr));
return oldbit;
}
#define test_bit(nr,addr) \
(__builtin_constant_p(nr) ? \
constant_test_bit((nr),(addr)) : \
variable_test_bit((nr),(addr)))
/**
* set_bit - Atomically set a bit in memory
* @nr: the bit to set
* @addr: the address to start counting from
*
* This function is atomic and may not be reordered. See __set_bit()
* if you do not require the atomic guarantees.
*
* Note: there are no guarantees that this function will not be reordered
* on non x86 architectures, so if you are writting portable code,
* make sure not to rely on its reordering guarantees.
*
* Note that @nr may be almost arbitrarily large; this function is not
* restricted to acting on a single-word quantity.
*/
static inline void set_bit(int nr, volatile unsigned long * addr)
{
__asm__ __volatile__( LOCK
"btsl %1,%0"
:"=m" (ADDR)
:"Ir" (nr));
}
/**
* clear_bit - Clears a bit in memory
* @nr: Bit to clear
* @addr: Address to start counting from
*
* clear_bit() is atomic and may not be reordered. However, it does
* not contain a memory barrier, so if it is used for locking purposes,
* you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
* in order to ensure changes are visible on other processors.
*/
static inline void clear_bit(int nr, volatile unsigned long * addr)
{
__asm__ __volatile__( LOCK
"btrl %1,%0"
:"=m" (ADDR)
:"Ir" (nr));
}
/**
* __ffs - find first bit in word.
* @word: The word to search
*
* Undefined if no bit exists, so code should check against 0 first.
*/
static inline unsigned long __ffs(unsigned long word)
{
__asm__("bsfl %1,%0"
:"=r" (word)
:"rm" (word));
return word;
}
/*
* These have to be done with inline assembly: that way the bit-setting
* is guaranteed to be atomic. All bit operations return 0 if the bit
* was cleared before the operation and != 0 if it was not.
*
* bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
*/
#define ADDR (*(volatile long *) addr)
#define rdtscll(val) \
__asm__ __volatile__("rdtsc" : "=A" (val))
#elif defined(__x86_64__)/* ifdef __i386__ */
/************************** x86_84 *******************************/
#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
#define __xg(x) ((volatile long *)(x))
static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
{
switch (size) {
case 1:
__asm__ __volatile__("xchgb %b0,%1"
:"=q" (x)
:"m" (*__xg(ptr)), "0" (x)
:"memory");
break;
case 2:
__asm__ __volatile__("xchgw %w0,%1"
:"=r" (x)
:"m" (*__xg(ptr)), "0" (x)
:"memory");
break;
case 4:
__asm__ __volatile__("xchgl %k0,%1"
:"=r" (x)
:"m" (*__xg(ptr)), "0" (x)
:"memory");
break;
case 8:
__asm__ __volatile__("xchgq %0,%1"
:"=r" (x)
:"m" (*__xg(ptr)), "0" (x)
:"memory");
break;
}
return x;
}
/**
* test_and_clear_bit - Clear a bit and return its old value
* @nr: Bit to clear
* @addr: Address to count from
*
* This operation is atomic and cannot be reordered.
@@ -187,29 +334,29 @@ static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr,
*/
static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
{
int oldbit;
int oldbit;
__asm__ __volatile__( LOCK_PREFIX
"btrl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"=m" (ADDR)
:"Ir" (nr) : "memory");
return oldbit;
__asm__ __volatile__( LOCK_PREFIX
"btrl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"=m" (ADDR)
:"dIr" (nr) : "memory");
return oldbit;
}
static __inline__ int constant_test_bit(int nr, const volatile void * addr)
{
return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
}
static __inline__ int variable_test_bit(int nr, volatile void * addr)
static __inline__ int variable_test_bit(int nr, volatile const void * addr)
{
int oldbit;
__asm__ __volatile__(
"btl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit)
:"m" (ADDR),"Ir" (nr));
return oldbit;
int oldbit;
__asm__ __volatile__(
"btl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit)
:"m" (ADDR),"dIr" (nr));
return oldbit;
}
#define test_bit(nr,addr) \
@@ -230,10 +377,10 @@ static __inline__ int variable_test_bit(int nr, volatile void * addr)
*/
static __inline__ void set_bit(int nr, volatile void * addr)
{
__asm__ __volatile__( LOCK_PREFIX
"btsl %1,%0"
:"=m" (ADDR)
:"Ir" (nr));
__asm__ __volatile__( LOCK_PREFIX
"btsl %1,%0"
:"=m" (ADDR)
:"dIr" (nr) : "memory");
}
/**
@@ -248,41 +395,44 @@ static __inline__ void set_bit(int nr, volatile void * addr)
*/
static __inline__ void clear_bit(int nr, volatile void * addr)
{
__asm__ __volatile__( LOCK_PREFIX
"btrl %1,%0"
:"=m" (ADDR)
:"Ir" (nr));
__asm__ __volatile__( LOCK_PREFIX
"btrl %1,%0"
:"=m" (ADDR)
:"dIr" (nr));
}
/**
* atomic_inc - increment atomic variable
* @v: pointer of type atomic_t
*
* Atomically increments @v by 1. Note that the guaranteed
* useful range of an atomic_t is only 24 bits.
*/
static __inline__ void atomic_inc(atomic_t *v)
{
__asm__ __volatile__(
LOCK "incl %0"
:"=m" (v->counter)
:"m" (v->counter));
}
#define rdtscll(val) \
__asm__ __volatile__("rdtsc" : "=A" (val))
* __ffs - find first bit in word.
* @word: The word to search
*
* Undefined if no bit exists, so code should check against 0 first.
*/
static __inline__ unsigned long __ffs(unsigned long word)
{
__asm__("bsfl %1,%0"
:"=r" (word)
:"rm" (word));
return word;
__asm__("bsfq %1,%0"
:"=r" (word)
:"rm" (word));
return word;
}
#define ADDR (*(volatile long *) addr)
#define rdtscll(val) do { \
unsigned int __a,__d; \
asm volatile("rdtsc" : "=a" (__a), "=d" (__d)); \
(val) = ((unsigned long)__a) | (((unsigned long)__d)<<32); \
} while(0)
#else /* ifdef __x86_64__ */
#error "Unsupported architecture"
#endif
/********************* common i386 and x86_64 ****************************/
static __inline__ void synch_set_bit(int nr, volatile void * addr)
{
__asm__ __volatile__ (
@@ -306,6 +456,14 @@ static __inline__ int synch_test_and_set_bit(int nr, volatile void * addr)
return oldbit;
}
static __inline__ int synch_test_and_clear_bit(int nr, volatile void * addr)
{
int oldbit;
__asm__ __volatile__ (
"lock btrl %2,%1\n\tsbbl %0,%0"
: "=r" (oldbit), "=m" (ADDR) : "Ir" (nr) : "memory");
return oldbit;
}
static __inline__ int synch_const_test_bit(int nr, const volatile void * addr)
{
@@ -326,9 +484,8 @@ static __inline__ int synch_var_test_bit(int nr, volatile void * addr)
(__builtin_constant_p(nr) ? \
synch_const_test_bit((nr),(addr)) : \
synch_var_test_bit((nr),(addr)))
#endif /* !__ASSEMBLY__ */
#define rdtsc(low,high) \
__asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
#endif /* not assembly */
#endif /* _OS_H_ */
+38
View File
@@ -0,0 +1,38 @@
#ifndef __SCHED_H__
#define __SCHED_H__
#include <list.h>
struct thread
{
char *name;
char *stack;
unsigned long eps;
unsigned long eip;
struct list_head thread_list;
u32 flags;
};
void init_sched(void);
void run_idle_thread(void);
struct thread* create_thread(char *name, void (*function)(void *), void *data);
void schedule(void);
static inline struct thread* get_current(void)
{
struct thread **current;
#ifdef __i386__
__asm__("andl %%esp,%0; ":"=r" (current) : "r" (~8191UL));
#endif
return *current;
}
#define current get_current()
void wake(struct thread *thread);
void block(struct thread *thread);
#endif /* __SCHED_H__ */
+46
View File
@@ -0,0 +1,46 @@
#ifndef _SEMAPHORE_H_
#define _SEMAPHORE_H_
#include <wait.h>
/*
* Implementation of semaphore in Mini-os is simple, because
* there are no preemptive threads, the atomicity is guaranteed.
*/
struct semaphore
{
int count;
struct wait_queue_head wait;
};
#define __SEMAPHORE_INITIALIZER(name, n) \
{ \
.count = n, \
.wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
}
#define __MUTEX_INITIALIZER(name) \
__SEMAPHORE_INITIALIZER(name,1)
#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
static void inline down(struct semaphore *sem)
{
wait_event(sem->wait, sem->count > 0);
sem->count--;
}
static void inline up(struct semaphore *sem)
{
sem->count++;
wake_up(&sem->wait);
}
#endif /* _SEMAPHORE_H */
+1 -1
View File
@@ -58,6 +58,6 @@ void init_time(void);
s_time_t get_s_time(void);
s_time_t get_v_time(void);
void gettimeofday(struct timeval *tv);
void block(u32 millisecs);
void block_domain(u32 millisecs);
#endif /* _TIME_H_ */
+32
View File
@@ -17,6 +17,7 @@
#ifndef _TRAPS_H_
#define _TRAPS_H_
#ifdef __i386__
struct pt_regs {
long ebx;
long ecx;
@@ -34,7 +35,38 @@ struct pt_regs {
long esp;
int xss;
};
#elif __x86_64__
struct pt_regs {
unsigned long r15;
unsigned long r14;
unsigned long r13;
unsigned long r12;
unsigned long rbp;
unsigned long rbx;
/* arguments: non interrupts/non tracing syscalls only save upto here*/
unsigned long r11;
unsigned long r10;
unsigned long r9;
unsigned long r8;
unsigned long rax;
unsigned long rcx;
unsigned long rdx;
unsigned long rsi;
unsigned long rdi;
unsigned long orig_rax;
/* end of arguments */
/* cpu exception frame or undefined */
unsigned long rip;
unsigned long cs;
unsigned long eflags;
unsigned long rsp;
unsigned long ss;
/* top of stack page */
};
#endif
void dump_regs(struct pt_regs *regs);
+8
View File
@@ -44,11 +44,19 @@ typedef unsigned long u_long;
typedef long long quad_t;
typedef unsigned long long u_quad_t;
typedef unsigned int uintptr_t;
typedef struct { unsigned long pte_low; } pte_t;
#elif defined(__x86_64__)
typedef long quad_t;
typedef unsigned long u_quad_t;
typedef unsigned long uintptr_t;
typedef struct { unsigned long pte; } pte_t;
#endif
#define INT_MAX ((int)(~0U>>1))
#define UINT_MAX (~0U)
#endif /* _TYPES_H_ */
+91
View File
@@ -0,0 +1,91 @@
#ifndef __WAIT_H__
#define __WAIT_H__
#include <sched.h>
#include <list.h>
#include <lib.h>
#include <os.h>
struct wait_queue
{
struct thread *thread;
struct list_head thread_list;
};
struct wait_queue_head
{
/* TODO - lock required? */
struct list_head thread_list;
};
#define DECLARE_WAIT_QUEUE_HEAD(name) \
struct wait_queue_head name = \
{ .thread_list = { &(name).thread_list, &(name).thread_list} }
#define __WAIT_QUEUE_HEAD_INITIALIZER(name) { \
.thread_list = { &(name).thread_list, &(name).thread_list } }
#define DEFINE_WAIT(name) \
struct wait_queue name = { \
.thread = current, \
.thread_list = LIST_HEAD_INIT((name).thread_list), \
}
static inline void init_waitqueue_entry(struct wait_queue *q, struct thread *thread)
{
q->thread = thread;
}
static inline void add_wait_queue(struct wait_queue_head *h, struct wait_queue *q)
{
if (list_empty(&q->thread_list))
list_add(&q->thread_list, &h->thread_list);
}
static inline void remove_wait_queue(struct wait_queue *q)
{
list_del(&q->thread_list);
}
static inline void wake_up(struct wait_queue_head *head)
{
struct list_head *tmp, *next;
list_for_each_safe(tmp, next, &head->thread_list)
{
struct wait_queue *curr;
curr = list_entry(tmp, struct wait_queue, thread_list);
wake(curr->thread);
}
}
#define wait_event(wq, condition) do{ \
unsigned long flags; \
if(condition) \
break; \
DEFINE_WAIT(__wait); \
for(;;) \
{ \
/* protect the list */ \
local_irq_save(flags); \
add_wait_queue(&wq, &__wait); \
block(current); \
local_irq_restore(flags); \
if(condition) \
break; \
schedule(); \
} \
local_irq_save(flags); \
/* need to wake up */ \
wake(current); \
remove_wait_queue(&__wait); \
local_irq_restore(flags); \
} while(0)
#endif /* __WAIT_H__ */
+89
View File
@@ -0,0 +1,89 @@
/******************************************************************************
* xenbus.h
*
* Talks to Xen Store to figure out what devices we have.
*
* Copyright (C) 2005 Rusty Russell, IBM Corporation
*
* This file may be distributed separately from the Linux kernel, or
* incorporated into other software packages, subject to the following license:
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this source file (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#ifndef _ASM_XEN_XENBUS_H
#define _ASM_XEN_XENBUS_H
/* Caller must hold this lock to call these functions: it's also held
* across watch callbacks. */
// TODO
//extern struct semaphore xenbus_lock;
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);
/* 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)));
/* 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)));
/* 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 register_xenbus_watch(struct xenbus_watch *watch);
void unregister_xenbus_watch(struct xenbus_watch *watch);
void reregister_xenbus_watches(void);
/* Called from xen core code. */
void xenbus_suspend(void);
void xenbus_resume(void);
#define XENBUS_IS_ERR_READ(str) ({ \
if (!IS_ERR(str) && strlen(str) == 0) { \
kfree(str); \
str = ERR_PTR(-ERANGE); \
} \
IS_ERR(str); \
})
#define XENBUS_EXIST_ERR(err) ((err) == -ENOENT || (err) == -ERANGE)
int xs_init(void);
#endif /* _ASM_XEN_XENBUS_H */
+13 -12
View File
@@ -33,6 +33,8 @@
#include <time.h>
#include <types.h>
#include <lib.h>
#include <sched.h>
#include <xenbus.h>
/*
* Shared page for communicating with the hypervisor.
@@ -59,10 +61,12 @@ void failsafe_callback(void);
extern char shared_info[PAGE_SIZE];
#define __pte(x) ((pte_t) { (0) } )
static shared_info_t *map_shared_info(unsigned long pa)
{
if ( HYPERVISOR_update_va_mapping(
(unsigned long)shared_info, pa | 7, UVMF_INVLPG) )
(unsigned long)shared_info, __pte(pa | 7), UVMF_INVLPG) )
{
printk("Failed to map shared_info!!\n");
*(int*)0=0;
@@ -77,7 +81,6 @@ static shared_info_t *map_shared_info(unsigned long pa)
void start_kernel(start_info_t *si)
{
static char hello[] = "Bootstrapping...\n";
int i;
(void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(hello), hello);
/* Copy the start_info struct to a globally-accessible area. */
@@ -96,7 +99,6 @@ void start_kernel(start_info_t *si)
(unsigned long)hypervisor_callback,
(unsigned long)failsafe_callback, 0);
#endif
trap_init();
/* ENABLE EVENT DELIVERY. This is disabled at start of day. */
@@ -119,7 +121,6 @@ void start_kernel(start_info_t *si)
* If used for porting another OS, start here to figure out your
* guest os entry point. Otherwise continue below...
*/
/* init memory management */
init_mm();
@@ -127,15 +128,15 @@ void start_kernel(start_info_t *si)
init_events();
/* init time and timers */
init_time();
/* init scheduler */
init_sched();
/* do nothing */
i = 0;
for ( ; ; )
{
// HYPERVISOR_yield();
block(100);
i++;
}
/* init xenbus */
xs_init();
/* Everything initialised, start idle thread */
run_idle_thread();
}
File diff suppressed because it is too large. Load diff
+13
View File
@@ -107,6 +107,19 @@ size_t strnlen(const char * s, size_t count)
return sc - s;
}
char * strcat(char * dest, const char * src)
{
char *tmp = dest;
while (*dest)
dest++;
while ((*dest++ = *src++) != '\0');
return tmp;
}
size_t strlen(const char * s)
{
const char *sc;
+4 -6
View File
@@ -198,7 +198,6 @@ static void print_chunks(void *start, int nr_pages)
#endif
/*
* Initialise allocator, placing addresses [@min,@max] in free pool.
* @min and @max are PHYSICAL addresses.
@@ -486,16 +485,17 @@ void init_mm(void)
phys_to_machine_mapping = (unsigned long *)start_info.mfn_list;
/* First page follows page table pages and 3 more pages (store page etc) */
start_pfn = PFN_UP(__pa(start_info.pt_base)) + start_info.nr_pt_frames + 3;
start_pfn = PFN_UP(to_phys(start_info.pt_base)) + start_info.nr_pt_frames + 3;
max_pfn = start_info.nr_pages;
printk(" start_pfn: %lx\n", start_pfn);
printk(" max_pfn: %lx\n", max_pfn);
build_pagetable(&start_pfn, &max_pfn);
#ifdef __i386__
build_pagetable(&start_pfn, &max_pfn);
#endif
/*
* now we can initialise the page allocator
*/
@@ -503,7 +503,5 @@ void init_mm(void)
(u_long)to_virt(PFN_PHYS(start_pfn)), PFN_PHYS(start_pfn),
(u_long)to_virt(PFN_PHYS(max_pfn)), PFN_PHYS(max_pfn));
init_page_allocator(PFN_PHYS(start_pfn), PFN_PHYS(max_pfn));
#endif
printk("MM: done\n");
}
+300
View File
@@ -0,0 +1,300 @@
/*
****************************************************************************
* (C) 2005 - Grzegorz Milos - Intel Research Cambridge
****************************************************************************
*
* File: sched.c
* Author: Grzegorz Milos
* Changes:
*
* Date: Aug 2005
*
* Environment: Xen Minimal OS
* Description: simple scheduler for Mini-Os
*
* The scheduler is non-preemptive (cooperative), and schedules according
* to Round Robin algorithm.
*
****************************************************************************
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <os.h>
#include <hypervisor.h>
#include <time.h>
#include <mm.h>
#include <types.h>
#include <lib.h>
#include <xmalloc.h>
#include <list.h>
#include <sched.h>
#include <semaphore.h>
#ifdef SCHED_DEBUG
#define DEBUG(_f, _a...) \
printk("MINI_OS(file=sched.c, line=%d) " _f "\n", __LINE__, ## _a)
#else
#define DEBUG(_f, _a...) ((void)0)
#endif
#define RUNNABLE_FLAG 0x00000001
#define is_runnable(_thread) (_thread->flags & RUNNABLE_FLAG)
#define set_runnable(_thread) (_thread->flags |= RUNNABLE_FLAG)
#define clear_runnable(_thread) (_thread->flags &= ~RUNNABLE_FLAG)
struct thread *idle_thread;
LIST_HEAD(exited_threads);
void dump_stack(struct thread *thread)
{
unsigned long *bottom = (unsigned long *)thread->stack + 2048;
unsigned long *pointer = (unsigned long *)thread->eps;
int count;
printk("The stack for \"%s\"\n", thread->name);
for(count = 0; count < 15 && pointer < bottom; count ++)
{
printk("[0x%lx] 0x%lx\n", pointer, *pointer);
pointer++;
}
if(pointer < bottom) printk("Not the whole stack printed\n");
}
#ifdef __i386__
#define switch_threads(prev, next) do { \
unsigned long esi,edi; \
__asm__ __volatile__("pushfl\n\t" \
"pushl %%ebp\n\t" \
"movl %%esp,%0\n\t" /* save ESP */ \
"movl %4,%%esp\n\t" /* restore ESP */ \
"movl $1f,%1\n\t" /* save EIP */ \
"pushl %5\n\t" /* restore EIP */ \
"ret\n\t" \
"1:\t" \
"popl %%ebp\n\t" \
"popfl" \
:"=m" (prev->eps),"=m" (prev->eip), \
"=S" (esi),"=D" (edi) \
:"m" (next->eps),"m" (next->eip), \
"2" (prev), "d" (next)); \
} while (0)
#elif __x86_64__
/* FIXME */
#endif
void inline print_runqueue(void)
{
struct list_head *it;
struct thread *th;
list_for_each(it, &idle_thread->thread_list)
{
th = list_entry(it, struct thread, thread_list);
printk(" Thread \"%s\", runnable=%d\n", th->name, is_runnable(th));
}
printk("\n");
}
void schedule(void)
{
struct thread *prev, *next, *thread;
struct list_head *iterator;
unsigned long flags;
prev = current;
local_irq_save(flags);
list_for_each(iterator, &exited_threads)
{
thread = list_entry(iterator, struct thread, thread_list);
if(thread != prev)
{
list_del(&thread->thread_list);
free_pages(thread->stack, 1);
xfree(thread);
}
}
next = idle_thread;
/* Thread list needs to be protected */
list_for_each(iterator, &idle_thread->thread_list)
{
thread = list_entry(iterator, struct thread, thread_list);
if(is_runnable(thread))
{
next = thread;
/* Put this thread on the end of the list */
list_del(&thread->thread_list);
list_add_tail(&thread->thread_list, &idle_thread->thread_list);
break;
}
}
local_irq_restore(flags);
/* Interrupting the switch is equivalent to having the next thread
inturrupted at the return instruction. And therefore at safe point. */
/* The thread switching only works for i386 at the moment */
#ifdef __i386__
if(prev != next) switch_threads(prev, next);
#endif
}
void exit_thread(struct thread *thread)
{
unsigned long flags;
printk("Thread \"%s\" exited.\n", thread->name);
local_irq_save(flags);
/* Remove from the thread list */
list_del(&thread->thread_list);
clear_runnable(thread);
/* Put onto exited list */
list_add(&thread->thread_list, &exited_threads);
local_irq_restore(flags);
/* Schedule will free the resources */
schedule();
}
struct thread* create_thread(char *name, void (*function)(void *), void *data)
{
struct thread *thread;
unsigned long flags;
thread = xmalloc(struct thread);
/* Allocate 2 pages for stack, stack will be 2pages aligned */
thread->stack = (char *)alloc_pages(1);
thread->name = name;
printk("Thread \"%s\": pointer: 0x%lx, stack: 0x%lx\n", name, thread,
thread->stack);
thread->eps = (unsigned long)thread->stack + 4096 * 2 - 4;
/* Save pointer to the thread on the stack, used by current macro */
*((unsigned long *)thread->stack) = (unsigned long)thread;
*((unsigned long *)thread->eps) = (unsigned long)thread;
thread->eps -= 4;
*((unsigned long *)thread->eps) = (unsigned long)data;
/* No return address */
thread->eps -= 4;
*((unsigned long *)thread->eps) = (unsigned long)exit_thread;
thread->eip = (unsigned long)function;
/* Not runable, not exited */
thread->flags = 0;
set_runnable(thread);
local_irq_save(flags);
if(idle_thread != NULL)
list_add_tail(&thread->thread_list, &idle_thread->thread_list);
local_irq_restore(flags);
return thread;
}
void block(struct thread *thread)
{
clear_runnable(thread);
}
void wake(struct thread *thread)
{
set_runnable(thread);
}
void idle_thread_fn(void *unused)
{
for(;;)
{
schedule();
printk("Blocking the domain\n");
block_domain(10000);
}
}
void run_idle_thread(void)
{
/* Switch stacks and run the thread */
__asm__ __volatile__("mov %0,%%esp\n\t"
"push %1\n\t"
"ret"
:"=m" (idle_thread->eps)
:"m" (idle_thread->eip));
}
DECLARE_MUTEX(mutex);
void th_f1(void *data)
{
struct timeval tv1, tv2;
for(;;)
{
down(&mutex);
printk("Thread \"%s\" got semaphore, runnable %d\n", current->name, is_runnable(current));
schedule();
printk("Thread \"%s\" releases the semaphore\n", current->name);
up(&mutex);
gettimeofday(&tv1);
for(;;)
{
gettimeofday(&tv2);
if(tv2.tv_sec - tv1.tv_sec > 2) break;
}
schedule();
}
}
void th_f2(void *data)
{
for(;;)
{
printk("Thread OTHER executing, data 0x%lx\n", data);
schedule();
}
}
void init_sched(void)
{
printk("Initialising scheduler\n");
idle_thread = create_thread("Idle", idle_thread_fn, NULL);
INIT_LIST_HEAD(&idle_thread->thread_list);
/* create_thread("1", th_f1, (void *)0x1234);
create_thread("2", th_f1, (void *)0x1234);
create_thread("3", th_f1, (void *)0x1234);
create_thread("4", th_f1, (void *)0x1234);
create_thread("5", th_f1, (void *)0x1234);
create_thread("6", th_f1, (void *)0x1234);
create_thread("second", th_f2, NULL);
*/
}
+2 -1
View File
@@ -203,7 +203,7 @@ static void print_current_time(void)
}
void block(u32 millisecs)
void block_domain(u32 millisecs)
{
struct timeval tv;
gettimeofday(&tv);
@@ -232,5 +232,6 @@ static void timer_handler(int ev, struct pt_regs *regs)
void init_time(void)
{
printk("Initialising timer interface\n");
bind_virq(VIRQ_TIMER, &timer_handler);
}
+6 -41
View File
@@ -33,36 +33,7 @@ extern void do_exit(void);
void dump_regs(struct pt_regs *regs)
{
unsigned long esp;
unsigned short ss;
#ifdef __x86_64__
esp = regs->rsp;
ss = regs->xss;
#else
esp = (unsigned long) (&regs->esp);
ss = __KERNEL_DS;
if (regs->xcs & 2) {
printk("CS is true, esp is %x\n", regs->esp);
esp = regs->esp;
ss = regs->xss & 0xffff;
}
#endif
printf("EIP: %04x:[<%p>]\n",
0xffff & regs->xcs , regs->eip);
printf("EFLAGS: %p\n",regs->eflags);
printf("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
regs->eax, regs->ebx, regs->ecx, regs->edx);
printf("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",
regs->esi, regs->edi, regs->ebp, esp);
#ifdef __x86_64__
printf("r8 : %p r9 : %p r10: %p r11: %p\n",
regs->r8, regs->r9, regs->r10, regs->r11);
printf("r12: %p r13: %p r14: %p r15: %p\n",
regs->r12, regs->r13, regs->r14, regs->r15);
#endif
printf("ds: %04x es: %04x ss: %04x\n",
regs->xds & 0xffff, regs->xes & 0xffff, ss);
printk("FIXME: proper register dump (with the stack dump)\n");
}
@@ -105,6 +76,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long error_code,
printk("Page fault at linear address %p\n", addr);
dump_regs(regs);
#ifdef __x86_64__
/* FIXME: _PAGE_PSE */
{
unsigned long *tab = (unsigned long *)start_info.pt_base;
unsigned long page;
@@ -112,23 +84,16 @@ void do_page_fault(struct pt_regs *regs, unsigned long error_code,
printk("Pagetable walk from %p:\n", tab);
page = tab[l4_table_offset(addr)];
tab = __va(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT);
tab = to_virt(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT);
printk(" L4 = %p (%p)\n", page, tab);
if ( !(page & AGERESENT) )
goto out;
page = tab[l3_table_offset(addr)];
tab = __va(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT);
tab = to_virt(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT);
printk(" L3 = %p (%p)\n", page, tab);
if ( !(page & AGERESENT) )
goto out;
page = tab[l2_table_offset(addr)];
tab = __va(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT);
printk(" L2 = %p (%p) %s\n", page, tab,
(page & AGESE) ? "(2MB)" : "");
if ( !(page & AGERESENT) || (page & AGESE) )
goto out;
tab = to_virt(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT);
printk(" L2 = %p (%p)\n", page, tab);
page = tab[l1_table_offset(addr)];
printk(" L1 = %p\n", page);
+9
View File
@@ -0,0 +1,9 @@
all: xenstore.h xenbus_comms.o xenbus_xs.o xenbus_probe.o
xenstore.h:
[ -e xenstored.h ] || ln -sf ../../../tools/xenstore/xenstored.h xenstored.h
clean:
#Taken care of by main Makefile
#rm xenstored.h
#rm *.o
+231
View File
@@ -0,0 +1,231 @@
/******************************************************************************
* xenbus_comms.c
*
* Low level code to talks to Xen Store: ringbuffer and event channel.
*
* Copyright (C) 2005 Rusty Russell, IBM Corporation
*
* This file may be distributed separately from the Linux kernel, or
* incorporated into other software packages, subject to the following license:
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this source file (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <types.h>
#include <wait.h>
#include <mm.h>
#include <hypervisor.h>
#include <events.h>
#include <os.h>
#include <lib.h>
#ifdef XENBUS_COMMS_DEBUG
#define DEBUG(_f, _a...) \
printk("MINI_OS(file=xenbus_comms.c, line=%d) " _f "\n", __LINE__, ## _a)
#else
#define DEBUG(_f, _a...) ((void)0)
#endif
#define RINGBUF_DATASIZE ((PAGE_SIZE / 2) - sizeof(struct ringbuf_head))
struct ringbuf_head
{
u32 write; /* Next place to write to */
u32 read; /* Next place to read from */
u8 flags;
char buf[0];
} __attribute__((packed));
DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
static inline struct ringbuf_head *outbuf(void)
{
return mfn_to_virt(start_info.store_mfn);
}
static inline struct ringbuf_head *inbuf(void)
{
return (struct ringbuf_head *)((char *)mfn_to_virt(start_info.store_mfn) + PAGE_SIZE/2);
}
static void wake_waiting(int port, struct pt_regs *regs)
{
wake_up(&xb_waitq);
}
static int check_buffer(const struct ringbuf_head *h)
{
return (h->write < RINGBUF_DATASIZE && h->read < RINGBUF_DATASIZE);
}
/* We can't fill last byte: would look like empty buffer. */
static void *get_output_chunk(const struct ringbuf_head *h,
void *buf, u32 *len)
{
u32 read_mark;
if (h->read == 0)
read_mark = RINGBUF_DATASIZE - 1;
else
read_mark = h->read - 1;
/* Here to the end of buffer, unless they haven't read some out. */
*len = RINGBUF_DATASIZE - h->write;
if (read_mark >= h->write)
*len = read_mark - h->write;
return (void *)((char *)buf + h->write);
}
static const void *get_input_chunk(const struct ringbuf_head *h,
const void *buf, u32 *len)
{
/* Here to the end of buffer, unless they haven't written some. */
*len = RINGBUF_DATASIZE - h->read;
if (h->write >= h->read)
*len = h->write - h->read;
return (void *)((char *)buf + h->read);
}
static void update_output_chunk(struct ringbuf_head *h, u32 len)
{
h->write += len;
if (h->write == RINGBUF_DATASIZE)
h->write = 0;
}
static void update_input_chunk(struct ringbuf_head *h, u32 len)
{
h->read += len;
if (h->read == RINGBUF_DATASIZE)
h->read = 0;
}
static int output_avail(struct ringbuf_head *out)
{
unsigned int avail;
get_output_chunk(out, out->buf, &avail);
return avail != 0;
}
int xb_write(const void *data, unsigned len)
{
struct ringbuf_head h;
struct ringbuf_head *out = outbuf();
do {
void *dst;
unsigned int avail;
wait_event(xb_waitq, output_avail(out));
/* Read, then check: not that we don't trust store.
* Hell, some of my best friends are daemons. But,
* in this post-911 world... */
h = *out;
mb();
if (!check_buffer(&h)) {
return -1; /* ETERRORIST! */
}
dst = get_output_chunk(&h, out->buf, &avail);
if (avail > len)
avail = len;
memcpy(dst, data, avail);
data = (void *)((char *)data + avail);
len -= avail;
update_output_chunk(out, avail);
notify_via_evtchn(start_info.store_evtchn);
} while (len != 0);
return 0;
}
int xs_input_avail(void)
{
unsigned int avail;
struct ringbuf_head *in = inbuf();
get_input_chunk(in, in->buf, &avail);
return avail != 0;
}
int xb_read(void *data, unsigned len)
{
struct ringbuf_head h;
struct ringbuf_head *in = inbuf();
int was_full;
while (len != 0) {
unsigned int avail;
const char *src;
wait_event(xb_waitq, xs_input_avail());
h = *in;
mb();
if (!check_buffer(&h)) {
return -1;
}
src = get_input_chunk(&h, in->buf, &avail);
if (avail > len)
avail = len;
was_full = !output_avail(&h);
memcpy(data, src, avail);
data = (void *)((char *)data + avail);
len -= avail;
update_input_chunk(in, avail);
DEBUG("Finished read of %i bytes (%i to go)\n", avail, len);
/* If it was full, tell them we've taken some. */
if (was_full)
notify_via_evtchn(start_info.store_evtchn);
}
/* If we left something, wake watch thread to deal with it. */
if (xs_input_avail())
wake_up(&xb_waitq);
return 0;
}
/* Set up interrupt handler off store event channel. */
int xb_init_comms(void)
{
printk("Init xenbus comms, store event channel %d\n", start_info.store_evtchn);
if (!start_info.store_evtchn)
return 0;
printk("Binding virq\n");
bind_evtchn(start_info.store_evtchn, &wake_waiting);
/* FIXME zero out page -- domain builder should probably do this*/
memset(mfn_to_virt(start_info.store_mfn), 0, PAGE_SIZE);
notify_via_evtchn(start_info.store_evtchn);
return 0;
}
void xb_suspend_comms(void)
{
if (!start_info.store_evtchn)
return;
// TODO
//unbind_evtchn_from_irqhandler(xen_start_info.store_evtchn, &xb_waitq);
}
+40
View File
@@ -0,0 +1,40 @@
/*
* Private include for xenbus communications.
*
* Copyright (C) 2005 Rusty Russell, IBM Corporation
*
* This file may be distributed separately from the Linux kernel, or
* incorporated into other software packages, subject to the following license:
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this source file (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#ifndef _XENBUS_COMMS_H
#define _XENBUS_COMMS_H
int xb_init_comms(void);
void xb_suspend_comms(void);
/* Low level routines. */
int xb_write(const void *data, unsigned len);
int xb_read(void *data, unsigned len);
int xs_input_avail(void);
extern struct wait_queue_head xb_waitq;
#endif /* _XENBUS_COMMS_H */
+554
View File
@@ -0,0 +1,554 @@
/******************************************************************************
* xenbus_xs.c
*
* This is the kernel equivalent of the "xs" library. We don't need everything
* and we use xenbus_comms for communication.
*
* Copyright (C) 2005 Rusty Russell, IBM Corporation
*
* This file may be distributed separately from the Linux kernel, or
* incorporated into other software packages, subject to the following license:
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this source file (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <errno.h>
#include <types.h>
#include <list.h>
#include <lib.h>
#include <err.h>
#include <os.h>
#include <xmalloc.h>
#include <fcntl.h>
#include <xenbus.h>
#include <wait.h>
#include <sched.h>
#include <semaphore.h>
#include "xenstored.h"
#include "xenbus_comms.h"
#define streq(a, b) (strcmp((a), (b)) == 0)
static char printf_buffer[4096];
static LIST_HEAD(watches);
//TODO
DECLARE_MUTEX(xenbus_lock);
static int get_error(const char *errorstring)
{
unsigned int i;
for (i = 0; !streq(errorstring, xsd_errors[i].errstring); i++) {
if (i == ARRAY_SIZE(xsd_errors) - 1) {
printk("XENBUS xen store gave: unknown error %s",
errorstring);
return EINVAL;
}
}
return xsd_errors[i].errnum;
}
static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len)
{
struct xsd_sockmsg msg;
void *ret;
int err;
err = xb_read(&msg, sizeof(msg));
if (err)
return ERR_PTR(err);
ret = xmalloc_array(char, msg.len + 1);
if (!ret)
return ERR_PTR(-ENOMEM);
err = xb_read(ret, msg.len);
if (err) {
xfree(ret);
return ERR_PTR(err);
}
((char*)ret)[msg.len] = '\0';
*type = msg.type;
if (len)
*len = msg.len;
return ret;
}
/* Emergency write. */
void xenbus_debug_write(const char *str, unsigned int count)
{
struct xsd_sockmsg msg;
msg.type = XS_DEBUG;
msg.len = sizeof("print") + count + 1;
xb_write(&msg, sizeof(msg));
xb_write("print", sizeof("print"));
xb_write(str, count);
xb_write("", 1);
}
/* Send message to xs, get kmalloc'ed reply. ERR_PTR() on error. */
static void *xs_talkv(enum xsd_sockmsg_type type,
const struct kvec *iovec,
unsigned int num_vecs,
unsigned int *len)
{
struct xsd_sockmsg msg;
void *ret = NULL;
unsigned int i;
int err;
//WARN_ON(down_trylock(&xenbus_lock) == 0);
msg.type = type;
msg.len = 0;
for (i = 0; i < num_vecs; i++)
msg.len += iovec[i].iov_len;
err = xb_write(&msg, sizeof(msg));
if (err)
return ERR_PTR(err);
for (i = 0; i < num_vecs; i++) {
err = xb_write(iovec[i].iov_base, iovec[i].iov_len);;
if (err)
return ERR_PTR(err);
}
/* Watches can have fired before reply comes: daemon detects
* and re-transmits, so we can ignore this. */
do {
xfree(ret);
ret = read_reply(&msg.type, len);
if (IS_ERR(ret))
return ret;
} while (msg.type == XS_WATCH_EVENT);
if (msg.type == XS_ERROR) {
err = get_error(ret);
xfree(ret);
return ERR_PTR(-err);
}
//BUG_ON(msg.type != type);
return ret;
}
/* Simplified version of xs_talkv: single message. */
static void *xs_single(enum xsd_sockmsg_type type,
const char *string, unsigned int *len)
{
struct kvec iovec;
iovec.iov_base = (void *)string;
iovec.iov_len = strlen(string) + 1;
return xs_talkv(type, &iovec, 1, len);
}
/* Many commands only need an ack, don't care what it says. */
static int xs_error(char *reply)
{
if (IS_ERR(reply))
return PTR_ERR(reply);
xfree(reply);
return 0;
}
static unsigned int count_strings(const char *strings, unsigned int len)
{
unsigned int num;
const char *p;
for (p = strings, num = 0; p < strings + len; p += strlen(p) + 1)
num++;
return num;
}
/* Return the path to dir with /name appended. */
static char *join(const char *dir, const char *name)
{
static char buffer[4096];
//BUG_ON(down_trylock(&xenbus_lock) == 0);
/* XXX FIXME: might not be correct if name == "" */
//BUG_ON(strlen(dir) + strlen("/") + strlen(name) + 1 > sizeof(buffer));
strcpy(buffer, dir);
if (!streq(name, "")) {
strcat(buffer, "/");
strcat(buffer, name);
}
return buffer;
}
char **xenbus_directory(const char *dir, const char *node, unsigned int *num)
{
char *strings, *p, **ret;
unsigned int len;
strings = xs_single(XS_DIRECTORY, join(dir, node), &len);
if (IS_ERR(strings))
return (char **)strings;
/* Count the strings. */
*num = count_strings(strings, len);
/* Transfer to one big alloc for easy freeing. */
ret = (char **)xmalloc_array(char, *num * sizeof(char *) + len);
if (!ret) {
xfree(strings);
return ERR_PTR(-ENOMEM);
}
memcpy(&ret[*num], strings, len);
xfree(strings);
strings = (char *)&ret[*num];
for (p = strings, *num = 0; p < strings + len; p += strlen(p) + 1)
ret[(*num)++] = p;
return ret;
}
/* Check if a path exists. Return 1 if it does. */
int xenbus_exists(const char *dir, const char *node)
{
char **d;
int dir_n;
d = xenbus_directory(dir, node, &dir_n);
if (IS_ERR(d))
return 0;
xfree(d);
return 1;
}
/* Get the value of a single file.
* Returns a kmalloced value: call free() on it after use.
* len indicates length in bytes.
*/
void *xenbus_read(const char *dir, const char *node, unsigned int *len)
{
return xs_single(XS_READ, join(dir, node), len);
}
/* Write the value of a single file.
* Returns -err on failure. createflags can be 0, O_CREAT, or O_CREAT|O_EXCL.
*/
int xenbus_write(const char *dir, const char *node,
const char *string, int createflags)
{
const char *flags, *path;
struct kvec iovec[3];
path = join(dir, node);
/* Format: Flags (as string), path, data. */
if (createflags == 0)
flags = XS_WRITE_NONE;
else if (createflags == O_CREAT)
flags = XS_WRITE_CREATE;
else if (createflags == (O_CREAT|O_EXCL))
flags = XS_WRITE_CREATE_EXCL;
else
return -EINVAL;
iovec[0].iov_base = (void *)path;
iovec[0].iov_len = strlen(path) + 1;
iovec[1].iov_base = (void *)flags;
iovec[1].iov_len = strlen(flags) + 1;
iovec[2].iov_base = (void *)string;
iovec[2].iov_len = strlen(string);
return xs_error(xs_talkv(XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL));
}
/* Create a new directory. */
int xenbus_mkdir(const char *dir, const char *node)
{
return xs_error(xs_single(XS_MKDIR, join(dir, node), NULL));
}
/* Destroy a file or directory (directories must be empty). */
int xenbus_rm(const char *dir, const char *node)
{
return xs_error(xs_single(XS_RM, join(dir, node), NULL));
}
/* Start a transaction: changes by others will not be seen during this
* transaction, and changes will not be visible to others until end.
* Transaction only applies to the given subtree.
* You can only have one transaction at any time.
*/
int xenbus_transaction_start(const char *subtree)
{
return xs_error(xs_single(XS_TRANSACTION_START, subtree, NULL));
}
/* End a transaction.
* If abandon is true, transaction is discarded instead of committed.
*/
int xenbus_transaction_end(int abort)
{
char abortstr[2];
if (abort)
strcpy(abortstr, "F");
else
strcpy(abortstr, "T");
return xs_error(xs_single(XS_TRANSACTION_END, abortstr, NULL));
}
/* Single read and scanf: returns -errno or num scanned. */
int xenbus_scanf(const char *dir, const char *node, const char *fmt, ...)
{
va_list ap;
int ret;
char *val;
val = xenbus_read(dir, node, NULL);
if (IS_ERR(val))
return PTR_ERR(val);
va_start(ap, fmt);
ret = vsscanf(val, fmt, ap);
va_end(ap);
xfree(val);
/* Distinctive errno. */
if (ret == 0)
return -ERANGE;
return ret;
}
/* Single printf and write: returns -errno or 0. */
int xenbus_printf(const char *dir, const char *node, const char *fmt, ...)
{
va_list ap;
int ret;
//BUG_ON(down_trylock(&xenbus_lock) == 0);
va_start(ap, fmt);
ret = vsnprintf(printf_buffer, sizeof(printf_buffer), fmt, ap);
va_end(ap);
//BUG_ON(ret > sizeof(printf_buffer)-1);
return xenbus_write(dir, node, printf_buffer, O_CREAT);
}
/* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
int xenbus_gather(const char *dir, ...)
{
va_list ap;
const char *name;
int ret = 0;
va_start(ap, dir);
while (ret == 0 && (name = va_arg(ap, char *)) != NULL) {
const char *fmt = va_arg(ap, char *);
void *result = va_arg(ap, void *);
char *p;
p = xenbus_read(dir, name, NULL);
if (IS_ERR(p)) {
ret = PTR_ERR(p);
break;
}
if (fmt) {
if (sscanf(p, fmt, result) == 0)
ret = -EINVAL;
xfree(p);
} else
*(char **)result = p;
}
va_end(ap);
return ret;
}
static int xs_watch(const char *path, const char *token)
{
struct kvec iov[2];
iov[0].iov_base = (void *)path;
iov[0].iov_len = strlen(path) + 1;
iov[1].iov_base = (void *)token;
iov[1].iov_len = strlen(token) + 1;
return xs_error(xs_talkv(XS_WATCH, iov, ARRAY_SIZE(iov), NULL));
}
static char *xs_read_watch(char **token)
{
enum xsd_sockmsg_type type;
char *ret;
ret = read_reply(&type, NULL);
if (IS_ERR(ret))
return ret;
//BUG_ON(type != XS_WATCH_EVENT);
*token = ret + strlen(ret) + 1;
return ret;
}
static int xs_acknowledge_watch(const char *token)
{
return xs_error(xs_single(XS_WATCH_ACK, token, NULL));
}
static int xs_unwatch(const char *path, const char *token)
{
struct kvec iov[2];
iov[0].iov_base = (char *)path;
iov[0].iov_len = strlen(path) + 1;
iov[1].iov_base = (char *)token;
iov[1].iov_len = strlen(token) + 1;
return xs_error(xs_talkv(XS_UNWATCH, iov, ARRAY_SIZE(iov), NULL));
}
/* A little paranoia: we don't just trust token. */
static struct xenbus_watch *find_watch(const char *token)
{
struct xenbus_watch *i, *cmp;
cmp = (void *)simple_strtoul(token, NULL, 16);
list_for_each_entry(i, &watches, list)
if (i == cmp)
return i;
return NULL;
}
/* Register callback to watch this node. */
int register_xenbus_watch(struct xenbus_watch *watch)
{
/* Pointer in ascii is the token. */
char token[sizeof(watch) * 2 + 1];
int err;
sprintf(token, "%lX", (long)watch);
//BUG_ON(find_watch(token));
printk("Registered watch for: %s\n", token);
err = xs_watch(watch->node, token);
if (!err)
list_add(&watch->list, &watches);
return err;
}
void unregister_xenbus_watch(struct xenbus_watch *watch)
{
char token[sizeof(watch) * 2 + 1];
int err;
sprintf(token, "%lX", (long)watch);
//BUG_ON(!find_watch(token));
err = xs_unwatch(watch->node, token);
list_del(&watch->list);
if (err)
printk("XENBUS Failed to release watch %s: %i\n",
watch->node, err);
}
/* Re-register callbacks to all watches. */
void reregister_xenbus_watches(void)
{
struct xenbus_watch *watch;
char token[sizeof(watch) * 2 + 1];
list_for_each_entry(watch, &watches, list) {
sprintf(token, "%lX", (long)watch);
xs_watch(watch->node, token);
}
}
void watch_thread(void *unused)
{
for (;;) {
char *token;
char *node = NULL;
wait_event(xb_waitq, xs_input_avail());
/* If this is a spurious wakeup caused by someone
* doing an op, they'll hold the lock and the buffer
* will be empty by the time we get there.
*/
down(&xenbus_lock);
if (xs_input_avail())
node = xs_read_watch(&token);
if (node && !IS_ERR(node)) {
struct xenbus_watch *w;
int err;
err = xs_acknowledge_watch(token);
if (err)
printk("XENBUS ack %s fail %i\n", node, err);
w = find_watch(token);
//BUG_ON(!w);
w->callback(w, node);
xfree(node);
} else
printk("XENBUS xs_read_watch: %li\n", PTR_ERR(node));
up(&xenbus_lock);
}
}
static void ballon_changed(struct xenbus_watch *watch, const char *node)
{
unsigned long new_target;
int err;
err = xenbus_scanf("memory", "target", "%lu", &new_target);
if(err != 1)
{
printk("Unable to read memory/target\n");
return;
}
printk("Memory target changed to: %ld bytes, ignoring.\n", new_target);
}
static struct xenbus_watch ballon_watch = {
.node = "memory/target",
.callback = ballon_changed,
};
int xs_init(void)
{
int err;
struct thread *watcher;
printk("xb_init_comms\n");
err = xb_init_comms();
if (err)
return err;
watcher = create_thread("kxwatch", watch_thread, NULL);
down(&xenbus_lock);
register_xenbus_watch(&ballon_watch);
up(&xenbus_lock);
return 0;
}
@@ -776,8 +776,8 @@ static void blkif_completion(struct blk_shadow *s)
{
int i;
for (i = 0; i < s->req.nr_segments; i++)
gnttab_free_grant_reference(
blkif_gref_from_fas(s->req.frame_and_sects[i]));
gnttab_end_foreign_access(
blkif_gref_from_fas(s->req.frame_and_sects[i]), 0);
}
/*
@@ -29,136 +29,163 @@
#include <linux/skbuff.h>
#include <net/dst.h>
static int nloopbacks = 1;
module_param(nloopbacks, int, 0);
MODULE_PARM_DESC(nloopbacks, "Number of netback-loopback devices to create");
struct net_private {
struct net_device *loopback_dev;
struct net_device_stats stats;
struct net_device *loopback_dev;
struct net_device_stats stats;
};
static int loopback_open(struct net_device *dev)
{
struct net_private *np = netdev_priv(dev);
memset(&np->stats, 0, sizeof(np->stats));
netif_start_queue(dev);
return 0;
struct net_private *np = netdev_priv(dev);
memset(&np->stats, 0, sizeof(np->stats));
netif_start_queue(dev);
return 0;
}
static int loopback_close(struct net_device *dev)
{
netif_stop_queue(dev);
return 0;
netif_stop_queue(dev);
return 0;
}
static int loopback_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct net_private *np = netdev_priv(dev);
struct net_private *np = netdev_priv(dev);
dst_release(skb->dst);
skb->dst = NULL;
dst_release(skb->dst);
skb->dst = NULL;
skb_orphan(skb);
skb_orphan(skb);
np->stats.tx_bytes += skb->len;
np->stats.tx_packets++;
np->stats.tx_bytes += skb->len;
np->stats.tx_packets++;
/* Switch to loopback context. */
dev = np->loopback_dev;
np = netdev_priv(dev);
/* Switch to loopback context. */
dev = np->loopback_dev;
np = netdev_priv(dev);
np->stats.rx_bytes += skb->len;
np->stats.rx_packets++;
np->stats.rx_bytes += skb->len;
np->stats.rx_packets++;
if ( skb->ip_summed == CHECKSUM_HW )
{
/* Defer checksum calculation. */
skb->proto_csum_blank = 1;
/* Must be a local packet: assert its integrity. */
skb->proto_csum_valid = 1;
}
if (skb->ip_summed == CHECKSUM_HW) {
/* Defer checksum calculation. */
skb->proto_csum_blank = 1;
/* Must be a local packet: assert its integrity. */
skb->proto_csum_valid = 1;
}
skb->ip_summed = skb->proto_csum_valid ?
CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
skb->ip_summed = skb->proto_csum_valid ?
CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
skb->pkt_type = PACKET_HOST; /* overridden by eth_type_trans() */
skb->protocol = eth_type_trans(skb, dev);
skb->dev = dev;
dev->last_rx = jiffies;
netif_rx(skb);
skb->pkt_type = PACKET_HOST; /* overridden by eth_type_trans() */
skb->protocol = eth_type_trans(skb, dev);
skb->dev = dev;
dev->last_rx = jiffies;
netif_rx(skb);
return 0;
return 0;
}
static struct net_device_stats *loopback_get_stats(struct net_device *dev)
{
struct net_private *np = netdev_priv(dev);
return &np->stats;
struct net_private *np = netdev_priv(dev);
return &np->stats;
}
static void loopback_construct(struct net_device *dev, struct net_device *lo)
{
struct net_private *np = netdev_priv(dev);
struct net_private *np = netdev_priv(dev);
np->loopback_dev = lo;
np->loopback_dev = lo;
dev->open = loopback_open;
dev->stop = loopback_close;
dev->hard_start_xmit = loopback_start_xmit;
dev->get_stats = loopback_get_stats;
dev->open = loopback_open;
dev->stop = loopback_close;
dev->hard_start_xmit = loopback_start_xmit;
dev->get_stats = loopback_get_stats;
dev->tx_queue_len = 0;
dev->tx_queue_len = 0;
dev->features = NETIF_F_HIGHDMA | NETIF_F_LLTX;
dev->features = NETIF_F_HIGHDMA | NETIF_F_LLTX;
/*
* We do not set a jumbo MTU on the interface. Otherwise the network
* stack will try to send large packets that will get dropped by the
* Ethernet bridge (unless the physical Ethernet interface is configured
* to transfer jumbo packets). If a larger MTU is desired then the system
* administrator can specify it using the 'ifconfig' command.
*/
/*dev->mtu = 16*1024;*/
/*
* We do not set a jumbo MTU on the interface. Otherwise the network
* stack will try to send large packets that will get dropped by the
* Ethernet bridge (unless the physical Ethernet interface is
* configured to transfer jumbo packets). If a larger MTU is desired
* then the system administrator can specify it using the 'ifconfig'
* command.
*/
/*dev->mtu = 16*1024;*/
}
static int __init make_loopback(int i)
{
struct net_device *dev1, *dev2;
char dev_name[IFNAMSIZ];
int err = -ENOMEM;
sprintf(dev_name, "vif0.%d", i);
dev1 = alloc_netdev(sizeof(struct net_private), dev_name, ether_setup);
sprintf(dev_name, "veth%d", i);
dev2 = alloc_netdev(sizeof(struct net_private), dev_name, ether_setup);
if ((dev1 == NULL) || (dev2 == NULL))
goto fail;
loopback_construct(dev1, dev2);
loopback_construct(dev2, dev1);
dev1->features |= NETIF_F_NO_CSUM;
dev2->features |= NETIF_F_IP_CSUM;
/*
* Initialise a dummy MAC address for the 'dummy backend' interface. We
* choose the numerically largest non-broadcast address to prevent the
* address getting stolen by an Ethernet bridge for STP purposes.
*/
memset(dev1->dev_addr, 0xFF, ETH_ALEN);
dev1->dev_addr[0] &= ~0x01;
if ((err = register_netdev(dev1)) != 0)
goto fail;
if ((err = register_netdev(dev2)) != 0) {
unregister_netdev(dev1);
goto fail;
}
return 0;
fail:
if (dev1 != NULL)
kfree(dev1);
if (dev2 != NULL)
kfree(dev2);
return err;
}
static int __init loopback_init(void)
{
struct net_device *dev1, *dev2;
int err = -ENOMEM;
int i, err = 0;
dev1 = alloc_netdev(sizeof(struct net_private), "vif0.0", ether_setup);
dev2 = alloc_netdev(sizeof(struct net_private), "veth0", ether_setup);
if ( (dev1 == NULL) || (dev2 == NULL) )
goto fail;
for (i = 0; i < nloopbacks; i++)
if ((err = make_loopback(i)) != 0)
break;
loopback_construct(dev1, dev2);
loopback_construct(dev2, dev1);
dev1->features |= NETIF_F_NO_CSUM;
dev2->features |= NETIF_F_IP_CSUM;
/*
* Initialise a dummy MAC address for the 'dummy backend' interface. We
* choose the numerically largest non-broadcast address to prevent the
* address getting stolen by an Ethernet bridge for STP purposes.
*/
memset(dev1->dev_addr, 0xFF, ETH_ALEN);
dev1->dev_addr[0] &= ~0x01;
if ( (err = register_netdev(dev1)) != 0 )
goto fail;
if ( (err = register_netdev(dev2)) != 0 )
{
unregister_netdev(dev1);
goto fail;
}
return 0;
fail:
if ( dev1 != NULL )
kfree(dev1);
if ( dev2 != NULL )
kfree(dev2);
return err;
return err;
}
module_init(loopback_init);
/*
* Local variables:
* c-file-style: "linux"
* indent-tabs-mode: t
* c-indent-level: 8
* c-basic-offset: 8
* tab-width: 8
* End:
*/
+32
View File
@@ -93,7 +93,9 @@ static PyObject *xspy_read(PyObject *self, PyObject *args, PyObject *kwds)
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
&path))
goto exit;
Py_BEGIN_ALLOW_THREADS
xsval = xs_read(xh, path, &xsval_n);
Py_END_ALLOW_THREADS
if (!xsval) {
val = pyvalue_int(0);
goto exit;
@@ -140,7 +142,9 @@ static PyObject *xspy_write(PyObject *self, PyObject *args, PyObject *kwds)
flags |= O_CREAT;
if (excl)
flags |= O_EXCL;
Py_BEGIN_ALLOW_THREADS
xsval = xs_write(xh, path, data, data_n, flags);
Py_END_ALLOW_THREADS
val = pyvalue_int(xsval);
exit:
return val;
@@ -170,7 +174,9 @@ static PyObject *xspy_ls(PyObject *self, PyObject *args, PyObject *kwds)
goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
goto exit;
Py_BEGIN_ALLOW_THREADS
xsval = xs_directory(xh, path, &xsval_n);
Py_END_ALLOW_THREADS
if (!xsval) {
val = pyvalue_int(0);
goto exit;
@@ -204,7 +210,9 @@ static PyObject *xspy_mkdir(PyObject *self, PyObject *args, PyObject *kwds)
goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
goto exit;
Py_BEGIN_ALLOW_THREADS
xsval = xs_mkdir(xh, path);
Py_END_ALLOW_THREADS
val = pyvalue_int(xsval);
exit:
return val;
@@ -232,7 +240,9 @@ static PyObject *xspy_rm(PyObject *self, PyObject *args, PyObject *kwds)
goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
goto exit;
Py_BEGIN_ALLOW_THREADS
xsval = xs_rm(xh, path);
Py_END_ALLOW_THREADS
val = pyvalue_int(xsval);
exit:
return val;
@@ -263,7 +273,9 @@ static PyObject *xspy_get_permissions(PyObject *self, PyObject *args,
goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
goto exit;
Py_BEGIN_ALLOW_THREADS
perms = xs_get_permissions(xh, path, &perms_n);
Py_END_ALLOW_THREADS
if (!perms) {
PyErr_SetFromErrno(PyExc_RuntimeError);
goto exit;
@@ -339,7 +351,9 @@ static PyObject *xspy_set_permissions(PyObject *self, PyObject *args,
if (p_write)
xsperms[i].perms |= XS_PERM_WRITE;
}
Py_BEGIN_ALLOW_THREADS
xsval = xs_set_permissions(xh, path, xsperms, xsperms_n);
Py_END_ALLOW_THREADS
val = pyvalue_int(xsval);
exit:
Py_XDECREF(tuple0);
@@ -381,7 +395,9 @@ static PyObject *xspy_watch(PyObject *self, PyObject *args, PyObject *kwds)
goto exit;
Py_INCREF(token);
sprintf(token_str, "%li", (unsigned long)token);
Py_BEGIN_ALLOW_THREADS
xsval = xs_watch(xh, path, token_str);
Py_END_ALLOW_THREADS
if (!xsval) {
val = PyErr_SetFromErrno(PyExc_RuntimeError);
Py_DECREF(token);
@@ -429,7 +445,9 @@ static PyObject *xspy_read_watch(PyObject *self, PyObject *args,
goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
goto exit;
Py_BEGIN_ALLOW_THREADS
xsval = xs_read_watch(xh);
Py_END_ALLOW_THREADS
if (!xsval) {
val = PyErr_SetFromErrno(PyExc_RuntimeError);
goto exit;
@@ -479,7 +497,9 @@ static PyObject *xspy_acknowledge_watch(PyObject *self, PyObject *args,
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &token))
goto exit;
sprintf(token_str, "%li", (unsigned long)token);
Py_BEGIN_ALLOW_THREADS
xsval = xs_acknowledge_watch(xh, token_str);
Py_END_ALLOW_THREADS
if (!xsval) {
val = PyErr_SetFromErrno(PyExc_RuntimeError);
goto exit;
@@ -519,7 +539,9 @@ static PyObject *xspy_unwatch(PyObject *self, PyObject *args, PyObject *kwds)
&token))
goto exit;
sprintf(token_str, "%li", (unsigned long)token);
Py_BEGIN_ALLOW_THREADS
xsval = xs_unwatch(xh, path, token_str);
Py_END_ALLOW_THREADS
if (!xsval)
val = PyErr_SetFromErrno(PyExc_RuntimeError);
else {
@@ -561,7 +583,9 @@ static PyObject *xspy_transaction_start(PyObject *self, PyObject *args,
goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
goto exit;
Py_BEGIN_ALLOW_THREADS
xsval = xs_transaction_start(xh, path);
Py_END_ALLOW_THREADS
val = pyvalue_int(xsval);
exit:
return val;
@@ -591,7 +615,9 @@ static PyObject *xspy_transaction_end(PyObject *self, PyObject *args,
goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &abort))
goto exit;
Py_BEGIN_ALLOW_THREADS
xsval = xs_transaction_end(xh, abort);
Py_END_ALLOW_THREADS
val = pyvalue_int(xsval);
exit:
return val;
@@ -627,7 +653,9 @@ static PyObject *xspy_introduce_domain(PyObject *self, PyObject *args,
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
&dom, &page, &port, &path))
goto exit;
Py_BEGIN_ALLOW_THREADS
xsval = xs_introduce_domain(xh, dom, page, port, path);
Py_END_ALLOW_THREADS
val = pyvalue_int(xsval);
exit:
return val;
@@ -658,7 +686,9 @@ static PyObject *xspy_release_domain(PyObject *self, PyObject *args,
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
&dom))
goto exit;
Py_BEGIN_ALLOW_THREADS
xsval = xs_release_domain(xh, dom);
Py_END_ALLOW_THREADS
val = pyvalue_int(xsval);
exit:
return val;
@@ -718,7 +748,9 @@ static PyObject *xspy_shutdown(PyObject *self, PyObject *args, PyObject *kwds)
goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
goto exit;
Py_BEGIN_ALLOW_THREADS
xsval = xs_shutdown(xh);
Py_END_ALLOW_THREADS
val = pyvalue_int(xsval);
exit:
return val;
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.