[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] merge
# HG changeset patch # User awilliam@xxxxxxxxxxx # Node ID c4ac21dc3f16d7be84d480f8795e1902da99c230 # Parent ede16886f979dde3991f2a13c7eef71820a60cca # Parent e8fb817c4c1530b9f763b8a726aa00d805173a56 merge diff -r ede16886f979 -r c4ac21dc3f16 .hgignore --- a/.hgignore Mon Mar 6 16:09:18 2006 +++ b/.hgignore Mon Mar 6 17:21:35 2006 @@ -166,6 +166,7 @@ ^tools/xenstore/xenstore-read$ ^tools/xenstore/xenstore-rm$ ^tools/xenstore/xenstore-write$ +^tools/xenstore/xenstore-control$ ^tools/xenstore/xenstore-ls$ ^tools/xenstore/xenstored$ ^tools/xenstore/xenstored_test$ diff -r ede16886f979 -r c4ac21dc3f16 docs/src/interface.tex --- a/docs/src/interface.tex Mon Mar 6 16:09:18 2006 +++ b/docs/src/interface.tex Mon Mar 6 17:21:35 2006 @@ -1059,6 +1059,21 @@ \item[domain] the name of the frontend \end{description} \end{description} + + \item[vtpm/] a directory containin vtpm backends + \begin{description} + \item[$<$domid$>$/] a directory containing vtpm's for domid + \begin{description} + \item[$<$vtpm number$>$/] a directory for each vtpm + \item[frontend-id] the domain id of the frontend + \item[frontend] the path to the frontend + \item[instance] the instance of the virtual TPM that is used + \item[pref{\textunderscore}instance] the instance number as given in the VM configuration file; + may be different from {\bf instance} + \item[domain] the name of the domain of the frontend + \end{description} + \end{description} + \end{description} \item[device/] a directory containing the frontend devices for the @@ -1094,6 +1109,18 @@ \item[event-channel] the event channel used for the two ring queues \end{description} \end{description} + + \item[vtpm/] a directory containing the vtpm frontend device for the + domain + \begin{description} + \item[$<$id$>$] a directory for vtpm id frontend device for the domain + \begin{description} + \item[backend-id] the backend domain id + \item[backend] a path to the backend's store entry + \item[ring-ref] the grant table reference for the tx/rx ring + \item[event-channel] the event channel used for the ring + \end{description} + \end{description} \item[device-misc/] miscellanous information for devices \begin{description} @@ -1450,6 +1477,76 @@ value of {\tt first\_sect}. \end{description} +\section{Virtual TPM} + +Virtual TPM (VTPM) support provides TPM functionality to each virtual +machine that requests this functionality in its configuration file. +The interface enables domains to access therr own private TPM like it +was a hardware TPM built into the machine. + +The virtual TPM interface is implemented as a split driver, +similar to the network and block interfaces described above. +The user domain hosting the frontend exports a character device /dev/tpm0 +to user-level applications for communicating with the virtual TPM. +This is the same device interface that is also offered if a hardware TPM +is available in the system. The backend provides a single interface +/dev/vtpm where the virtual TPM is waiting for commands from all domains +that have located their backend in a given domain. + +\subsection{Data Transfer} + +A single shared memory ring is used between the frontend and backend +drivers. TPM requests and responses are sent in pages where a pointer +to those pages and other information is placed into the ring such that +the backend can map the pages into its memory space using the grant +table mechanism. + +The backend driver has been implemented to only accept well-formed +TPM requests. To meet this requirement, the length inidicator in the +TPM request must correctly indicate the length of the request. +Otherwise an error message is automatically sent back by the device driver. + +The virtual TPM implementation listenes for TPM request on /dev/vtpm. Since +it must be able to apply the TPM request packet to the virtual TPM instance +associated with the virtual machine, a 4-byte virtual TPM instance +identifier is prepended to each packet by the backend driver (in network +byte order) for internal routing of the request. + +\subsection{Virtual TPM ring interface} + +The TPM protocol is a strict request/response protocol and therefore +only one ring is used to send requests from the frontend to the backend +and responses on the reverse path. + +The request/response structure is defined as follows: + +\scriptsize +\begin{verbatim} +typedef struct { + unsigned long addr; /* Machine address of packet. */ + grant_ref_t ref; /* grant table access reference. */ + uint16_t unused; /* unused */ + uint16_t size; /* Packet size in bytes. */ +} tpmif_tx_request_t; +\end{verbatim} +\normalsize + +The fields are as follows: + +\begin{description} +\item[addr] The machine address of the page asscoiated with the TPM + request/response; a request/response may span multiple + pages +\item[ref] The grant table reference associated with the address. +\item[size] The size of the remaining packet; up to + PAGE{\textunderscore}SIZE bytes can be found in the + page referenced by 'addr' +\end{description} + +The frontend initially allocates several pages whose addresses +are stored in the ring. Only these pages are used for exchange of +requests and responses. + \chapter{Further Information} diff -r ede16886f979 -r c4ac21dc3f16 install.sh --- a/install.sh Mon Mar 6 16:09:18 2006 +++ b/install.sh Mon Mar 6 17:21:35 2006 @@ -22,19 +22,29 @@ exit 1 fi +tmp="`mktemp -d`" + echo "Installing Xen from '$src' to '$dst'..." -(cd $src; tar -cf - --exclude etc/init.d --exclude etc/hotplug --exclude etc/udev * ) | tar -C $dst -xf - -cp -fdRL $src/etc/init.d/* $dst/etc/init.d/ -echo "All done." +(cd $src; tar -cf - * ) | tar -C "$tmp" -xf - [ -x "$(which udevinfo)" ] && \ UDEV_VERSION=$(udevinfo -V | sed -e 's/^[^0-9]* \([0-9]\{1,\}\)[^0-9]\{0,\}/\1/') if [ -n "$UDEV_VERSION" ] && [ $UDEV_VERSION -ge 059 ]; then - cp -f $src/etc/udev/rules.d/*.rules $dst/etc/udev/rules.d/ + echo " - installing for udev-based system" + rm -rf "$tmp/etc/hotplug" else - cp -f $src/etc/hotplug/*.agent $dst/etc/hotplug/ + echo " - installing for hotplug-based system" + rm -rf "$tmp/etc/udev" fi + +echo " - modifying permissions" +chmod -R a+rX "$tmp" + +(cd $tmp; tar -cf - *) | tar --no-same-owner -C "$dst" -xf - +rm -rf "$tmp" + +echo "All done." echo "Checking to see whether prerequisite tools are installed..." cd $src/../check diff -r ede16886f979 -r c4ac21dc3f16 linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c --- a/linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c Mon Mar 6 16:09:18 2006 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c Mon Mar 6 17:21:35 2006 @@ -61,8 +61,8 @@ int ret; op.cmd = PHYSDEVOP_APIC_READ; - op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid; - op.u.apic_op.offset = reg; + op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr; + op.u.apic_op.reg = reg; ret = HYPERVISOR_physdev_op(&op); if (ret) return ret; @@ -74,8 +74,8 @@ physdev_op_t op; op.cmd = PHYSDEVOP_APIC_WRITE; - op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid; - op.u.apic_op.offset = reg; + op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr; + op.u.apic_op.reg = reg; op.u.apic_op.value = value; HYPERVISOR_physdev_op(&op); } diff -r ede16886f979 -r c4ac21dc3f16 linux-2.6-xen-sparse/arch/x86_64/kernel/io_apic-xen.c --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/io_apic-xen.c Mon Mar 6 16:09:18 2006 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/io_apic-xen.c Mon Mar 6 17:21:35 2006 @@ -108,8 +108,8 @@ int ret; op.cmd = PHYSDEVOP_APIC_READ; - op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid; - op.u.apic_op.offset = reg; + op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr; + op.u.apic_op.reg = reg; ret = HYPERVISOR_physdev_op(&op); if (ret) return ret; @@ -121,8 +121,8 @@ physdev_op_t op; op.cmd = PHYSDEVOP_APIC_WRITE; - op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid; - op.u.apic_op.offset = reg; + op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr; + op.u.apic_op.reg = reg; op.u.apic_op.value = value; HYPERVISOR_physdev_op(&op); } diff -r ede16886f979 -r c4ac21dc3f16 linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c Mon Mar 6 16:09:18 2006 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c Mon Mar 6 17:21:35 2006 @@ -82,6 +82,8 @@ extern unsigned long start_pfn; extern struct edid_info edid_info; +extern void machine_specific_modify_cpu_capabilities(struct cpuinfo_x86 *c); + shared_info_t *HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page; EXPORT_SYMBOL(HYPERVISOR_shared_info); @@ -1405,6 +1407,8 @@ select_idle_routine(c); detect_ht(c); + machine_specific_modify_cpu_capabilities(c); + /* * On SMP, boot_cpu_data holds the common feature set between * all CPUs; so make sure that we indicate which features are diff -r ede16886f979 -r c4ac21dc3f16 linux-2.6-xen-sparse/arch/x86_64/kernel/x8664_ksyms-xen.c --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/x8664_ksyms-xen.c Mon Mar 6 16:09:18 2006 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/x8664_ksyms-xen.c Mon Mar 6 17:21:35 2006 @@ -32,8 +32,6 @@ #include <asm/tlbflush.h> #include <asm/kdebug.h> -extern spinlock_t rtc_lock; - #ifdef CONFIG_SMP extern void __write_lock_failed(rwlock_t *rw); extern void __read_lock_failed(rwlock_t *rw); @@ -42,9 +40,6 @@ /* platform dependent support */ EXPORT_SYMBOL(boot_cpu_data); //EXPORT_SYMBOL(dump_fpu); -EXPORT_SYMBOL(__ioremap); -EXPORT_SYMBOL(ioremap_nocache); -EXPORT_SYMBOL(iounmap); EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(pm_idle); EXPORT_SYMBOL(pm_power_off); @@ -101,8 +96,6 @@ #endif EXPORT_SYMBOL(get_wchan); - -EXPORT_SYMBOL(rtc_lock); #ifdef CONFIG_X86_LOCAL_APIC EXPORT_SYMBOL_GPL(set_nmi_callback); @@ -166,7 +159,5 @@ EXPORT_SYMBOL(flush_tlb_page); #endif -EXPORT_SYMBOL(cpu_khz); - EXPORT_SYMBOL(load_gs_index); diff -r ede16886f979 -r c4ac21dc3f16 linux-2.6-xen-sparse/drivers/xen/char/mem.c --- a/linux-2.6-xen-sparse/drivers/xen/char/mem.c Mon Mar 6 16:09:18 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/char/mem.c Mon Mar 6 17:21:35 2006 @@ -43,49 +43,85 @@ static ssize_t read_mem(struct file * file, char __user * buf, size_t count, loff_t *ppos) { - unsigned long i, p = *ppos; - ssize_t read = -EFAULT; + unsigned long p = *ppos, ignored; + ssize_t read = 0, sz; void __iomem *v; - if ((v = ioremap(p, count)) == NULL) { + while (count > 0) { /* - * Some programs (e.g., dmidecode) groove off into weird RAM - * areas where no table scan possibly exist (because Xen will - * have stomped on them!). These programs get rather upset if - * we let them know that Xen failed their access, so we fake - * out a read of all zeroes. :-) + * Handle first page in case it's not aligned */ - for (i = 0; i < count; i++) - if (put_user(0, buf+i)) + if (-p & (PAGE_SIZE - 1)) + sz = -p & (PAGE_SIZE - 1); + else + sz = PAGE_SIZE; + + sz = min_t(unsigned long, sz, count); + + if ((v = ioremap(p, sz)) == NULL) { + /* + * Some programs (e.g., dmidecode) groove off into weird RAM + * areas where no tables can possibly exist (because Xen will + * have stomped on them!). These programs get rather upset if + * we let them know that Xen failed their access, so we fake + * out a read of all zeroes. :-) + */ + if (clear_user(buf, count)) return -EFAULT; - return count; + read += count; + break; + } + + ignored = copy_to_user(buf, v, sz); + iounmap(v); + if (ignored) + return -EFAULT; + buf += sz; + p += sz; + count -= sz; + read += sz; } - if (copy_to_user(buf, v, count)) - goto out; - read = count; *ppos += read; -out: - iounmap(v); return read; } static ssize_t write_mem(struct file * file, const char __user * buf, size_t count, loff_t *ppos) { - unsigned long p = *ppos; - ssize_t written = -EFAULT; + unsigned long p = *ppos, ignored; + ssize_t written = 0, sz; void __iomem *v; - if ((v = ioremap(p, count)) == NULL) - return -EFAULT; - if (copy_from_user(v, buf, count)) - goto out; + while (count > 0) { + /* + * Handle first page in case it's not aligned + */ + if (-p & (PAGE_SIZE - 1)) + sz = -p & (PAGE_SIZE - 1); + else + sz = PAGE_SIZE; - written = count; + sz = min_t(unsigned long, sz, count); + + if ((v = ioremap(p, sz)) == NULL) + break; + + ignored = copy_from_user(v, buf, sz); + iounmap(v); + if (ignored) { + written += sz - ignored; + if (written) + break; + return -EFAULT; + } + buf += sz; + p += sz; + count -= sz; + written += sz; + } + *ppos += written; -out: - iounmap(v); return written; } diff -r ede16886f979 -r c4ac21dc3f16 linux-2.6-xen-sparse/drivers/xen/core/gnttab.c --- a/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c Mon Mar 6 16:09:18 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c Mon Mar 6 17:21:35 2006 @@ -35,7 +35,6 @@ #include <xen/interface/xen.h> #include <asm/fixmap.h> #include <asm/uaccess.h> -#include <xen/public/privcmd.h> #include <xen/gnttab.h> #include <asm/synch_bitops.h> diff -r ede16886f979 -r c4ac21dc3f16 linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c Mon Mar 6 16:09:18 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c Mon Mar 6 17:21:35 2006 @@ -19,8 +19,7 @@ LIST_HEAD(tpmif_list); -tpmif_t * -alloc_tpmif(domid_t domid, long int instance) +static tpmif_t *alloc_tpmif(domid_t domid, long int instance) { struct page *page; tpmif_t *tpmif; @@ -45,16 +44,14 @@ return tpmif; } -void -free_tpmif(tpmif_t * tpmif) +static void free_tpmif(tpmif_t * tpmif) { num_frontends--; list_del(&tpmif->tpmif_list); kmem_cache_free(tpmif_cachep, tpmif); } -tpmif_t * -tpmif_find(domid_t domid, long int instance) +tpmif_t *tpmif_find(domid_t domid, long int instance) { tpmif_t *tpmif; @@ -72,8 +69,7 @@ return alloc_tpmif(domid, instance); } -static int -map_frontend_page(tpmif_t *tpmif, unsigned long shared_page) +static int map_frontend_page(tpmif_t *tpmif, unsigned long shared_page) { int ret; struct gnttab_map_grant_ref op = { @@ -99,8 +95,7 @@ return 0; } -static void -unmap_frontend_page(tpmif_t *tpmif) +static void unmap_frontend_page(tpmif_t *tpmif) { struct gnttab_unmap_grant_ref op; int ret; @@ -115,14 +110,14 @@ BUG_ON(ret); } -int -tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn) +int tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn) { int err; evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain, .u.bind_interdomain.remote_dom = tpmif->domid, - .u.bind_interdomain.remote_port = evtchn }; + .u.bind_interdomain.remote_port = evtchn, + }; if (tpmif->irq) { return 0; @@ -156,8 +151,7 @@ return 0; } -static void -__tpmif_disconnect_complete(void *arg) +static void __tpmif_disconnect_complete(void *arg) { tpmif_t *tpmif = (tpmif_t *) arg; @@ -172,22 +166,19 @@ free_tpmif(tpmif); } -void -tpmif_disconnect_complete(tpmif_t * tpmif) +void tpmif_disconnect_complete(tpmif_t * tpmif) { INIT_WORK(&tpmif->work, __tpmif_disconnect_complete, (void *)tpmif); schedule_work(&tpmif->work); } -void __init -tpmif_interface_init(void) +void __init tpmif_interface_init(void) { tpmif_cachep = kmem_cache_create("tpmif_cache", sizeof (tpmif_t), 0, 0, NULL, NULL); } -void __init -tpmif_interface_exit(void) +void __init tpmif_interface_exit(void) { kmem_cache_destroy(tpmif_cachep); } diff -r ede16886f979 -r c4ac21dc3f16 linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c Mon Mar 6 16:09:18 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c Mon Mar 6 17:21:35 2006 @@ -22,16 +22,22 @@ #include <xen/xenbus.h> #include <xen/interface/grant_table.h> - /* local data structures */ struct data_exchange { struct list_head pending_pak; struct list_head current_pak; unsigned int copied_so_far; u8 has_opener; - rwlock_t pak_lock; // protects all of the previous fields + rwlock_t pak_lock; // protects all of the previous fields wait_queue_head_t wait_queue; }; + +struct vtpm_resp_hdr { + uint32_t instance_no; + uint16_t tag_no; + uint32_t len_no; + uint32_t ordinal_no; +} __attribute__ ((packed)); struct packet { struct list_head next; @@ -50,36 +56,30 @@ PACKET_FLAG_CHECK_RESPONSESTATUS = 2, }; +/* local variables */ static struct data_exchange dataex; /* local function prototypes */ +static int _packet_write(struct packet *pak, + const char *data, size_t size, int userbuffer); +static void processing_timeout(unsigned long ptr); +static int packet_read_shmem(struct packet *pak, + tpmif_t * tpmif, + u32 offset, + char *buffer, int isuserbuffer, u32 left); static int vtpm_queue_packet(struct packet *pak); -static int _packet_write(struct packet *pak, - const char *data, size_t size, - int userbuffer); -static void processing_timeout(unsigned long ptr); -static int packet_read_shmem(struct packet *pak, - tpmif_t *tpmif, - u32 offset, - char *buffer, - int isuserbuffer, - u32 left); - #define MIN(x,y) (x) < (y) ? (x) : (y) - /*************************************************************** - Buffer copying + Buffer copying fo user and kernel space buffes. ***************************************************************/ -static inline int -copy_from_buffer(void *to, - const void *from, - unsigned long size, - int userbuffer) -{ - if (userbuffer) { - if (copy_from_user(to, from, size)) +static inline int copy_from_buffer(void *to, + const void *from, unsigned long size, + int isuserbuffer) +{ + if (isuserbuffer) { + if (copy_from_user(to, (void __user *)from, size)) return -EFAULT; } else { memcpy(to, from, size); @@ -87,21 +87,36 @@ return 0; } +static inline int copy_to_buffer(void *to, + const void *from, unsigned long size, + int isuserbuffer) +{ + if (isuserbuffer) { + if (copy_to_user((void __user *)to, from, size)) + return -EFAULT; + } else { + memcpy(to, from, size); + } + return 0; +} + /*************************************************************** Packet-related functions ***************************************************************/ -static struct packet * -packet_find_instance(struct list_head *head, u32 tpm_instance) +static struct packet *packet_find_instance(struct list_head *head, + u32 tpm_instance) { struct packet *pak; struct list_head *p; + /* * traverse the list of packets and return the first * one with the given instance number */ list_for_each(p, head) { pak = list_entry(p, struct packet, next); + if (pak->tpm_instance == tpm_instance) { return pak; } @@ -109,17 +124,18 @@ return NULL; } -static struct packet * -packet_find_packet(struct list_head *head, void *packet) +static struct packet *packet_find_packet(struct list_head *head, void *packet) { struct packet *pak; struct list_head *p; + /* * traverse the list of packets and return the first * one with the given instance number */ list_for_each(p, head) { pak = list_entry(p, struct packet, next); + if (pak == packet) { return pak; } @@ -127,22 +143,20 @@ return NULL; } -static struct packet * -packet_alloc(tpmif_t *tpmif, u32 size, u8 req_tag, u8 flags) +static struct packet *packet_alloc(tpmif_t * tpmif, + u32 size, u8 req_tag, u8 flags) { struct packet *pak = NULL; - pak = kmalloc(sizeof(struct packet), - GFP_KERNEL); + pak = kzalloc(sizeof (struct packet), GFP_KERNEL); if (NULL != pak) { - memset(pak, 0x0, sizeof(*pak)); if (tpmif) { pak->tpmif = tpmif; pak->tpm_instance = tpmif->tpm_instance; } - pak->data_len = size; - pak->req_tag = req_tag; + pak->data_len = size; + pak->req_tag = req_tag; pak->last_read = 0; - pak->flags = flags; + pak->flags = flags; /* * cannot do tpmif_get(tpmif); bad things happen @@ -155,16 +169,16 @@ return pak; } -static void inline -packet_reset(struct packet *pak) +static void inline packet_reset(struct packet *pak) { pak->last_read = 0; } -static void inline -packet_free(struct packet *pak) -{ - del_singleshot_timer_sync(&pak->processing_timer); +static void packet_free(struct packet *pak) +{ + if (timer_pending(&pak->processing_timer)) { + BUG(); + } kfree(pak->data_buffer); /* * cannot do tpmif_put(pak->tpmif); bad things happen @@ -173,13 +187,13 @@ kfree(pak); } -static int -packet_set(struct packet *pak, - const unsigned char *buffer, u32 size) +static int packet_set(struct packet *pak, + const unsigned char *buffer, u32 size) { int rc = 0; unsigned char *buf = kmalloc(size, GFP_KERNEL); - if (NULL != buf) { + + if (buf) { pak->data_buffer = buf; memcpy(buf, buffer, size); pak->data_len = size; @@ -189,27 +203,21 @@ return rc; } - /* * Write data to the shared memory and send it to the FE. */ -static int -packet_write(struct packet *pak, - const char *data, size_t size, - int userbuffer) +static int packet_write(struct packet *pak, + const char *data, size_t size, int isuserbuffer) { int rc = 0; - DPRINTK("Supposed to send %d bytes to front-end!\n", - size); - - if (0 != (pak->flags & PACKET_FLAG_CHECK_RESPONSESTATUS)) { + if ((pak->flags & PACKET_FLAG_CHECK_RESPONSESTATUS)) { #ifdef CONFIG_XEN_TPMDEV_CLOSE_IF_VTPM_FAILS u32 res; + if (copy_from_buffer(&res, - &data[2+4], - sizeof(res), - userbuffer)) { + &data[2 + 4], sizeof (res), + isuserbuffer)) { return -EFAULT; } @@ -230,17 +238,14 @@ /* Don't send a respone to this packet. Just acknowledge it. */ rc = size; } else { - rc = _packet_write(pak, data, size, userbuffer); + rc = _packet_write(pak, data, size, isuserbuffer); } return rc; } - -static int -_packet_write(struct packet *pak, - const char *data, size_t size, - int userbuffer) +int _packet_write(struct packet *pak, + const char *data, size_t size, int isuserbuffer) { /* * Write into the shared memory pages directly @@ -254,7 +259,7 @@ if (tpmif == NULL) { return -EFAULT; - } + } if (tpmif->status == DISCONNECTED) { return size; @@ -273,16 +278,13 @@ return 0; } - map_op.host_addr = MMAP_VADDR(tpmif, i); - map_op.flags = GNTMAP_host_map; - map_op.ref = tx->ref; - map_op.dom = tpmif->domid; - - if(unlikely( - HYPERVISOR_grant_table_op( - GNTTABOP_map_grant_ref, - &map_op, - 1))) { + map_op.host_addr = MMAP_VADDR(tpmif, i); + map_op.flags = GNTMAP_host_map; + map_op.ref = tx->ref; + map_op.dom = tpmif->domid; + + if (unlikely(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, + &map_op, 1))) { BUG(); } @@ -292,28 +294,27 @@ DPRINTK(" Grant table operation failure !\n"); return 0; } - set_phys_to_machine(__pa(MMAP_VADDR(tpmif,i)) >> PAGE_SHIFT, - FOREIGN_FRAME(map_op.dev_bus_addr >> PAGE_SHIFT)); + set_phys_to_machine(__pa(MMAP_VADDR(tpmif, i)) >> PAGE_SHIFT, + FOREIGN_FRAME(map_op. + dev_bus_addr >> PAGE_SHIFT)); tocopy = MIN(size - offset, PAGE_SIZE); - if (copy_from_buffer((void *)(MMAP_VADDR(tpmif,i)| - (tx->addr & ~PAGE_MASK)), - &data[offset], - tocopy, - userbuffer)) { + if (copy_from_buffer((void *)(MMAP_VADDR(tpmif, i) | + (tx->addr & ~PAGE_MASK)), + &data[offset], tocopy, isuserbuffer)) { tpmif_put(tpmif); return -EFAULT; } tx->size = tocopy; - unmap_op.host_addr = MMAP_VADDR(tpmif, i); - unmap_op.handle = handle; + unmap_op.host_addr = MMAP_VADDR(tpmif, i); + unmap_op.handle = handle; unmap_op.dev_bus_addr = 0; - if(unlikely(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, - &unmap_op, - 1))) { + if (unlikely + (HYPERVISOR_grant_table_op + (GNTTABOP_unmap_grant_ref, &unmap_op, 1))) { BUG(); } @@ -322,8 +323,7 @@ } rc = offset; - DPRINTK("Notifying frontend via irq %d\n", - tpmif->irq); + DPRINTK("Notifying frontend via irq %d\n", tpmif->irq); notify_remote_via_irq(tpmif->irq); return rc; @@ -334,26 +334,19 @@ * provided buffer. Advance the read_last indicator which tells * how many bytes have already been read. */ -static int -packet_read(struct packet *pak, size_t numbytes, - char *buffer, size_t buffersize, - int userbuffer) +static int packet_read(struct packet *pak, size_t numbytes, + char *buffer, size_t buffersize, int isuserbuffer) { tpmif_t *tpmif = pak->tpmif; - /* - * I am supposed to read 'numbytes' of data from the - * buffer. - * The first 4 bytes that are read are the instance number in - * network byte order, after that comes the data from the - * shared memory buffer. + + /* + * Read 'numbytes' of data from the buffer. The first 4 + * bytes are the instance number in network byte order, + * after that come the data from the shared memory buffer. */ u32 to_copy; u32 offset = 0; u32 room_left = buffersize; - /* - * Ensure that we see the request when we copy it. - */ - mb(); if (pak->last_read < 4) { /* @@ -361,18 +354,13 @@ */ u32 instance_no = htonl(pak->tpm_instance); u32 last_read = pak->last_read; + to_copy = MIN(4 - last_read, numbytes); - if (userbuffer) { - if (copy_to_user(&buffer[0], - &(((u8 *)&instance_no)[last_read]), - to_copy)) { - return -EFAULT; - } - } else { - memcpy(&buffer[0], - &(((u8 *)&instance_no)[last_read]), - to_copy); + if (copy_to_buffer(&buffer[0], + &(((u8 *) & instance_no)[last_read]), + to_copy, isuserbuffer)) { + return -EFAULT; } pak->last_read += to_copy; @@ -388,39 +376,30 @@ if (pak->data_buffer) { u32 to_copy = MIN(pak->data_len - offset, room_left); u32 last_read = pak->last_read - 4; - if (userbuffer) { - if (copy_to_user(&buffer[offset], - &pak->data_buffer[last_read], - to_copy)) { - return -EFAULT; - } - } else { - memcpy(&buffer[offset], - &pak->data_buffer[last_read], - to_copy); + + if (copy_to_buffer(&buffer[offset], + &pak->data_buffer[last_read], + to_copy, isuserbuffer)) { + return -EFAULT; } pak->last_read += to_copy; offset += to_copy; } else { offset = packet_read_shmem(pak, - tpmif, - offset, - buffer, - userbuffer, - room_left); + tpmif, + offset, + buffer, + isuserbuffer, room_left); } } return offset; } - -static int -packet_read_shmem(struct packet *pak, - tpmif_t *tpmif, - u32 offset, - char *buffer, - int isuserbuffer, - u32 room_left) { +static int packet_read_shmem(struct packet *pak, + tpmif_t * tpmif, + u32 offset, char *buffer, int isuserbuffer, + u32 room_left) +{ u32 last_read = pak->last_read - 4; u32 i = (last_read / PAGE_SIZE); u32 pg_offset = last_read & (PAGE_SIZE - 1); @@ -428,6 +407,7 @@ grant_handle_t handle; tpmif_tx_request_t *tx; + tx = &tpmif->tx->ring[0].req; /* * Start copying data at the page with index 'index' @@ -443,13 +423,12 @@ tx = &tpmif->tx->ring[i].req; map_op.host_addr = MMAP_VADDR(tpmif, i); - map_op.flags = GNTMAP_host_map; - map_op.ref = tx->ref; - map_op.dom = tpmif->domid; - - if(unlikely(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, - &map_op, - 1))) { + map_op.flags = GNTMAP_host_map; + map_op.ref = tx->ref; + map_op.dom = tpmif->domid; + + if (unlikely(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, + &map_op, 1))) { BUG(); } @@ -462,41 +441,33 @@ if (to_copy > tx->size) { /* - * This is the case when the user wants to read more - * than what we have. So we just give him what we - * have. + * User requests more than what's available */ to_copy = MIN(tx->size, to_copy); } DPRINTK("Copying from mapped memory at %08lx\n", - (unsigned long)(MMAP_VADDR(tpmif,i) | - (tx->addr & ~PAGE_MASK))); - - src = (void *)(MMAP_VADDR(tpmif,i) | ((tx->addr & ~PAGE_MASK) + pg_offset)); - if (isuserbuffer) { - if (copy_to_user(&buffer[offset], - src, - to_copy)) { - return -EFAULT; - } - } else { - memcpy(&buffer[offset], - src, - to_copy); - } - + (unsigned long)(MMAP_VADDR(tpmif, i) | + (tx->addr & ~PAGE_MASK))); + + src = (void *)(MMAP_VADDR(tpmif, i) | + ((tx->addr & ~PAGE_MASK) + pg_offset)); + if (copy_to_buffer(&buffer[offset], + src, to_copy, isuserbuffer)) { + return -EFAULT; + } DPRINTK("Data from TPM-FE of domain %d are %d %d %d %d\n", - tpmif->domid, buffer[offset], buffer[offset+1],buffer[offset+2],buffer[offset+3]); - - unmap_op.host_addr = MMAP_VADDR(tpmif, i); - unmap_op.handle = handle; + tpmif->domid, buffer[offset], buffer[offset + 1], + buffer[offset + 2], buffer[offset + 3]); + + unmap_op.host_addr = MMAP_VADDR(tpmif, i); + unmap_op.handle = handle; unmap_op.dev_bus_addr = 0; - if(unlikely(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, - &unmap_op, - 1))) { + if (unlikely + (HYPERVISOR_grant_table_op + (GNTTABOP_unmap_grant_ref, &unmap_op, 1))) { BUG(); } @@ -507,21 +478,19 @@ to_copy = MIN(PAGE_SIZE, room_left); i++; - } /* while (to_copy > 0) */ + } /* while (to_copy > 0) */ /* * Adjust the last_read pointer */ pak->last_read = last_read + 4; return offset; } - /* ============================================================ * The file layer for reading data from this device * ============================================================ */ -static int -vtpm_op_open(struct inode *inode, struct file *f) +static int vtpm_op_open(struct inode *inode, struct file *f) { int rc = 0; unsigned long flags; @@ -536,9 +505,8 @@ return rc; } -static ssize_t -vtpm_op_read(struct file *file, - char __user * data, size_t size, loff_t * offset) +static ssize_t vtpm_op_read(struct file *file, + char __user * data, size_t size, loff_t * offset) { int ret_size = -ENODATA; struct packet *pak = NULL; @@ -549,7 +517,7 @@ if (list_empty(&dataex.pending_pak)) { write_unlock_irqrestore(&dataex.pak_lock, flags); wait_event_interruptible(dataex.wait_queue, - !list_empty(&dataex.pending_pak)); + !list_empty(&dataex.pending_pak)); write_lock_irqsave(&dataex.pak_lock, flags); } @@ -561,7 +529,7 @@ DPRINTK("size given by app: %d, available: %d\n", size, left); - ret_size = MIN(size,left); + ret_size = MIN(size, left); ret_size = packet_read(pak, ret_size, data, size, 1); if (ret_size < 0) { @@ -574,7 +542,8 @@ DPRINTK("All data from this packet given to app.\n"); /* All data given to app */ - del_singleshot_timer_sync(&pak->processing_timer); + del_singleshot_timer_sync(&pak-> + processing_timer); list_del(&pak->next); list_add_tail(&pak->next, &dataex.current_pak); /* @@ -582,7 +551,7 @@ * the more time we give the TPM to process the request. */ mod_timer(&pak->processing_timer, - jiffies + (num_frontends * 60 * HZ)); + jiffies + (num_frontends * 60 * HZ)); dataex.copied_so_far = 0; } } @@ -597,16 +566,15 @@ /* * Write operation - only works after a previous read operation! */ -static ssize_t -vtpm_op_write(struct file *file, const char __user * data, size_t size, - loff_t * offset) +static ssize_t vtpm_op_write(struct file *file, + const char __user * data, size_t size, + loff_t * offset) { struct packet *pak; int rc = 0; unsigned int off = 4; unsigned long flags; - u32 instance_no = 0; - u32 len_no = 0; + struct vtpm_resp_hdr vrh; /* * Minimum required packet size is: @@ -616,45 +584,38 @@ * 4 bytes for the ordinal * sum: 14 bytes */ - if ( size < off + 10 ) { + if (size < sizeof (vrh)) return -EFAULT; - } - - if (copy_from_user(&instance_no, - (void __user *)&data[0], - 4)) { + + if (copy_from_user(&vrh, data, sizeof (vrh))) return -EFAULT; - } - - if (copy_from_user(&len_no, - (void __user *)&data[off+2], - 4) || - (off + ntohl(len_no) != size)) { + + /* malformed packet? */ + if ((off + ntohl(vrh.len_no)) != size) return -EFAULT; - } write_lock_irqsave(&dataex.pak_lock, flags); - pak = packet_find_instance(&dataex.current_pak, ntohl(instance_no)); + pak = packet_find_instance(&dataex.current_pak, + ntohl(vrh.instance_no)); if (pak == NULL) { write_unlock_irqrestore(&dataex.pak_lock, flags); - printk(KERN_ALERT "No associated packet!\n"); + printk(KERN_ALERT "No associated packet! (inst=%d)\n", + ntohl(vrh.instance_no)); return -EFAULT; - } else { - del_singleshot_timer_sync(&pak->processing_timer); - list_del(&pak->next); - } + } + + del_singleshot_timer_sync(&pak->processing_timer); + list_del(&pak->next); write_unlock_irqrestore(&dataex.pak_lock, flags); /* - * The first 'offset' bytes must be the instance number. - * I will just pull that from the packet. + * The first 'offset' bytes must be the instance number - skip them. */ size -= off; - data = &data[off]; - - rc = packet_write(pak, data, size, 1); + + rc = packet_write(pak, &data[off], size, 1); if (rc > 0) { /* I neglected the first 4 bytes */ @@ -664,10 +625,10 @@ return rc; } -static int -vtpm_op_release(struct inode *inode, struct file *file) +static int vtpm_op_release(struct inode *inode, struct file *file) { unsigned long flags; + vtpm_release_packets(NULL, 1); write_lock_irqsave(&dataex.pak_lock, flags); dataex.has_opener = 0; @@ -675,10 +636,11 @@ return 0; } -static unsigned int -vtpm_op_poll(struct file *file, struct poll_table_struct *pts) +static unsigned int vtpm_op_poll(struct file *file, + struct poll_table_struct *pts) { unsigned int flags = POLLOUT | POLLWRNORM; + poll_wait(file, &dataex.wait_queue, pts); if (!list_empty(&dataex.pending_pak)) { flags |= POLLIN | POLLRDNORM; @@ -696,54 +658,47 @@ .poll = vtpm_op_poll, }; -static struct miscdevice ibmvtpms_miscdevice = { +static struct miscdevice vtpms_miscdevice = { .minor = 225, .name = "vtpm", .fops = &vtpm_ops, }; - /*************************************************************** Virtual TPM functions and data stuctures ***************************************************************/ static u8 create_cmd[] = { - 1,193, /* 0: TPM_TAG_RQU_COMMAMD */ - 0,0,0,19, /* 2: length */ - 0,0,0,0x1, /* 6: VTPM_ORD_OPEN */ - 0, /* 10: VTPM type */ - 0,0,0,0, /* 11: domain id */ - 0,0,0,0 /* 15: instance id */ + 1, 193, /* 0: TPM_TAG_RQU_COMMAMD */ + 0, 0, 0, 19, /* 2: length */ + 0, 0, 0, 0x1, /* 6: VTPM_ORD_OPEN */ + 0, /* 10: VTPM type */ + 0, 0, 0, 0, /* 11: domain id */ + 0, 0, 0, 0 /* 15: instance id */ }; -static u8 destroy_cmd[] = { - 1,193, /* 0: TPM_TAG_RQU_COMMAMD */ - 0,0,0,14, /* 2: length */ - 0,0,0,0x2, /* 6: VTPM_ORD_CLOSE */ - 0,0,0,0 /* 10: instance id */ -}; - -int tpmif_vtpm_open(tpmif_t *tpmif, domid_t domid, u32 instance) +int tpmif_vtpm_open(tpmif_t * tpmif, domid_t domid, u32 instance) { int rc = 0; struct packet *pak; pak = packet_alloc(tpmif, - sizeof(create_cmd), - create_cmd[0], - PACKET_FLAG_DISCARD_RESPONSE| - PACKET_FLAG_CHECK_RESPONSESTATUS); + sizeof (create_cmd), + create_cmd[1], + PACKET_FLAG_DISCARD_RESPONSE | + PACKET_FLAG_CHECK_RESPONSESTATUS); if (pak) { - u8 buf[sizeof(create_cmd)]; - u32 domid_no = htonl((u32)domid); + u8 buf[sizeof (create_cmd)]; + u32 domid_no = htonl((u32) domid); u32 instance_no = htonl(instance); - memcpy(buf, create_cmd, sizeof(create_cmd)); - - memcpy(&buf[11], &domid_no, sizeof(u32)); - memcpy(&buf[15], &instance_no, sizeof(u32)); + + memcpy(buf, create_cmd, sizeof (create_cmd)); + + memcpy(&buf[11], &domid_no, sizeof (u32)); + memcpy(&buf[15], &instance_no, sizeof (u32)); /* copy the buffer into the packet */ - rc = packet_set(pak, buf, sizeof(buf)); + rc = packet_set(pak, buf, sizeof (buf)); if (rc == 0) { pak->tpm_instance = 0; @@ -759,23 +714,30 @@ return rc; } +static u8 destroy_cmd[] = { + 1, 193, /* 0: TPM_TAG_RQU_COMMAMD */ + 0, 0, 0, 14, /* 2: length */ + 0, 0, 0, 0x2, /* 6: VTPM_ORD_CLOSE */ + 0, 0, 0, 0 /* 10: instance id */ +}; + int tpmif_vtpm_close(u32 instid) { int rc = 0; struct packet *pak; pak = packet_alloc(NULL, - sizeof(create_cmd), - create_cmd[0], - PACKET_FLAG_DISCARD_RESPONSE); + sizeof (destroy_cmd), + destroy_cmd[1], PACKET_FLAG_DISCARD_RESPONSE); if (pak) { - u8 buf[sizeof(destroy_cmd)]; + u8 buf[sizeof (destroy_cmd)]; u32 instid_no = htonl(instid); - memcpy(buf, destroy_cmd, sizeof(destroy_cmd)); - memcpy(&buf[10], &instid_no, sizeof(u32)); + + memcpy(buf, destroy_cmd, sizeof (destroy_cmd)); + memcpy(&buf[10], &instid_no, sizeof (u32)); /* copy the buffer into the packet */ - rc = packet_set(pak, buf, sizeof(buf)); + rc = packet_set(pak, buf, sizeof (buf)); if (rc == 0) { pak->tpm_instance = 0; @@ -791,23 +753,22 @@ return rc; } - /*************************************************************** Utility functions ***************************************************************/ -static int -tpm_send_fail_message(struct packet *pak, u8 req_tag) +static int tpm_send_fail_message(struct packet *pak, u8 req_tag) { int rc; static const unsigned char tpm_error_message_fail[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, - 0x00, 0x00, 0x00, 0x09 /* TPM_FAIL */ + 0x00, 0x00, 0x00, 0x09 /* TPM_FAIL */ }; - unsigned char buffer[sizeof(tpm_error_message_fail)]; - - memcpy(buffer, tpm_error_message_fail, sizeof(tpm_error_message_fail)); + unsigned char buffer[sizeof (tpm_error_message_fail)]; + + memcpy(buffer, tpm_error_message_fail, + sizeof (tpm_error_message_fail)); /* * Insert the right response tag depending on the given tag * All response tags are '+3' to the request tag. @@ -817,23 +778,24 @@ /* * Write the data to shared memory and notify the front-end */ - rc = packet_write(pak, buffer, sizeof(buffer), 0); + rc = packet_write(pak, buffer, sizeof (buffer), 0); return rc; } - -static void -_vtpm_release_packets(struct list_head *head, tpmif_t *tpmif, - int send_msgs) +static void _vtpm_release_packets(struct list_head *head, + tpmif_t * tpmif, int send_msgs) { struct packet *pak; - struct list_head *pos, *tmp; + struct list_head *pos, + *tmp; list_for_each_safe(pos, tmp, head) { pak = list_entry(pos, struct packet, next); + if (tpmif == NULL || pak->tpmif == tpmif) { int can_send = 0; + del_singleshot_timer_sync(&pak->processing_timer); list_del(&pak->next); @@ -849,9 +811,7 @@ } } - -int -vtpm_release_packets(tpmif_t *tpmif, int send_msgs) +int vtpm_release_packets(tpmif_t * tpmif, int send_msgs) { unsigned long flags; @@ -860,23 +820,22 @@ _vtpm_release_packets(&dataex.pending_pak, tpmif, send_msgs); _vtpm_release_packets(&dataex.current_pak, tpmif, send_msgs); - write_unlock_irqrestore(&dataex.pak_lock, - flags); + write_unlock_irqrestore(&dataex.pak_lock, flags); return 0; } - static int vtpm_queue_packet(struct packet *pak) { int rc = 0; + if (dataex.has_opener) { unsigned long flags; + write_lock_irqsave(&dataex.pak_lock, flags); list_add_tail(&pak->next, &dataex.pending_pak); /* give the TPM some time to pick up the request */ mod_timer(&pak->processing_timer, jiffies + (30 * HZ)); - write_unlock_irqrestore(&dataex.pak_lock, - flags); + write_unlock_irqrestore(&dataex.pak_lock, flags); wake_up_interruptible(&dataex.wait_queue); } else { @@ -885,24 +844,22 @@ return rc; } - -static int vtpm_receive(tpmif_t *tpmif, u32 size) +static int vtpm_receive(tpmif_t * tpmif, u32 size) { int rc = 0; unsigned char buffer[10]; __be32 *native_size; - - struct packet *pak = packet_alloc(tpmif, size, buffer[4], 0); - if (NULL == pak) { + struct packet *pak = packet_alloc(tpmif, size, 0, 0); + + if (!pak) return -ENOMEM; - } /* * Read 10 bytes from the received buffer to test its * content for validity. */ - if (sizeof(buffer) != packet_read(pak, - sizeof(buffer), buffer, - sizeof(buffer), 0)) { + if (sizeof (buffer) != packet_read(pak, + sizeof (buffer), buffer, + sizeof (buffer), 0)) { goto failexit; } /* @@ -911,7 +868,7 @@ */ packet_reset(pak); - native_size = (__force __be32 *)(&buffer[4+2]); + native_size = (__force __be32 *) (&buffer[4 + 2]); /* * Verify that the size of the packet is correct * as indicated and that there's actually someone reading packets. @@ -920,25 +877,23 @@ */ if (size < 10 || be32_to_cpu(*native_size) != size || - 0 == dataex.has_opener || - tpmif->status != CONNECTED) { - rc = -EINVAL; - goto failexit; + 0 == dataex.has_opener || tpmif->status != CONNECTED) { + rc = -EINVAL; + goto failexit; } else { - if ((rc = vtpm_queue_packet(pak)) < 0) { + rc = vtpm_queue_packet(pak); + if (rc < 0) goto failexit; - } } return 0; -failexit: + failexit: if (pak) { - tpm_send_fail_message(pak, buffer[4+1]); + tpm_send_fail_message(pak, buffer[4 + 1]); packet_free(pak); } return rc; } - /* * Timeout function that gets invoked when a packet has not been processed @@ -951,22 +906,23 @@ { struct packet *pak = (struct packet *)ptr; unsigned long flags; + write_lock_irqsave(&dataex.pak_lock, flags); /* * The packet needs to be searched whether it * is still on the list. */ if (pak == packet_find_packet(&dataex.pending_pak, pak) || - pak == packet_find_packet(&dataex.current_pak, pak) ) { + pak == packet_find_packet(&dataex.current_pak, pak)) { list_del(&pak->next); - tpm_send_fail_message(pak, pak->req_tag); + if ((pak->flags & PACKET_FLAG_DISCARD_RESPONSE) == 0) { + tpm_send_fail_message(pak, pak->req_tag); + } packet_free(pak); } write_unlock_irqrestore(&dataex.pak_lock, flags); } - - static void tpm_tx_action(unsigned long unused); static DECLARE_TASKLET(tpm_tx_tasklet, tpm_tx_action, 0); @@ -974,21 +930,18 @@ static struct list_head tpm_schedule_list; static spinlock_t tpm_schedule_list_lock; -static inline void -maybe_schedule_tx_action(void) +static inline void maybe_schedule_tx_action(void) { smp_mb(); tasklet_schedule(&tpm_tx_tasklet); } -static inline int -__on_tpm_schedule_list(tpmif_t * tpmif) +static inline int __on_tpm_schedule_list(tpmif_t * tpmif) { return tpmif->list.next != NULL; } -static void -remove_from_tpm_schedule_list(tpmif_t * tpmif) +static void remove_from_tpm_schedule_list(tpmif_t * tpmif) { spin_lock_irq(&tpm_schedule_list_lock); if (likely(__on_tpm_schedule_list(tpmif))) { @@ -999,8 +952,7 @@ spin_unlock_irq(&tpm_schedule_list_lock); } -static void -add_to_tpm_schedule_list_tail(tpmif_t * tpmif) +static void add_to_tpm_schedule_list_tail(tpmif_t * tpmif) { if (__on_tpm_schedule_list(tpmif)) return; @@ -1013,22 +965,18 @@ spin_unlock_irq(&tpm_schedule_list_lock); } -void -tpmif_schedule_work(tpmif_t * tpmif) +void tpmif_schedule_work(tpmif_t * tpmif) { add_to_tpm_schedule_list_tail(tpmif); maybe_schedule_tx_action(); } -void -tpmif_deschedule_work(tpmif_t * tpmif) +void tpmif_deschedule_work(tpmif_t * tpmif) { remove_from_tpm_schedule_list(tpmif); } - -static void -tpm_tx_action(unsigned long unused) +static void tpm_tx_action(unsigned long unused) { struct list_head *ent; tpmif_t *tpmif; @@ -1042,10 +990,6 @@ tpmif = list_entry(ent, tpmif_t, list); tpmif_get(tpmif); remove_from_tpm_schedule_list(tpmif); - /* - * Ensure that we see the request when we read from it. - */ - mb(); tx = &tpmif->tx->ring[0].req; @@ -1056,22 +1000,22 @@ } } -irqreturn_t -tpmif_be_int(int irq, void *dev_id, struct pt_regs *regs) -{ - tpmif_t *tpmif = dev_id; +irqreturn_t tpmif_be_int(int irq, void *dev_id, struct pt_regs *regs) +{ + tpmif_t *tpmif = (tpmif_t *) dev_id; + add_to_tpm_schedule_list_tail(tpmif); maybe_schedule_tx_action(); return IRQ_HANDLED; } -static int __init -tpmback_init(void) +static int __init tpmback_init(void) { int rc; - if ((rc = misc_register(&ibmvtpms_miscdevice)) != 0) { - printk(KERN_ALERT "Could not register misc device for TPM BE.\n"); + if ((rc = misc_register(&vtpms_miscdevice)) != 0) { + printk(KERN_ALERT + "Could not register misc device for TPM BE.\n"); return rc; } @@ -1094,13 +1038,11 @@ module_init(tpmback_init); -static void __exit -tpmback_exit(void) -{ - +static void __exit tpmback_exit(void) +{ tpmif_xenbus_exit(); tpmif_interface_exit(); - misc_deregister(&ibmvtpms_miscdevice); + misc_deregister(&vtpms_miscdevice); } module_exit(tpmback_exit); diff -r ede16886f979 -r c4ac21dc3f16 linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Mon Mar 6 16:09:18 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Mon Mar 6 17:21:35 2006 @@ -602,7 +602,6 @@ tx = &tp->tx->ring[i].req; - tx->id = i; tx->addr = virt_to_machine(txb->data); tx->size = txb->len; diff -r ede16886f979 -r c4ac21dc3f16 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c Mon Mar 6 16:09:18 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c Mon Mar 6 17:21:35 2006 @@ -95,18 +95,25 @@ */ int current_state; - - int err = xenbus_scanf(xbt, dev->nodename, "state", "%d", + int err; + + if (state == dev->state) + return 0; + + err = xenbus_scanf(xbt, dev->nodename, "state", "%d", ¤t_state); - if ((err == 1 && (XenbusState)current_state == state) || - err == -ENOENT) + if (err != 1) return 0; err = xenbus_printf(xbt, dev->nodename, "state", "%d", state); if (err) { - xenbus_dev_fatal(dev, err, "writing new state"); + if (state != XenbusStateClosing) /* Avoid looping */ + xenbus_dev_fatal(dev, err, "writing new state"); return err; } + + dev->state = state; + return 0; } EXPORT_SYMBOL(xenbus_switch_state); @@ -138,7 +145,6 @@ ret = vsnprintf(printf_buffer+len, PRINTF_BUFFER_SIZE-len, fmt, ap); BUG_ON(len + ret > PRINTF_BUFFER_SIZE-1); - dev->has_error = 1; dev_err(&dev->dev, "%s\n", printf_buffer); diff -r ede16886f979 -r c4ac21dc3f16 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Mon Mar 6 16:09:18 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Mon Mar 6 17:21:35 2006 @@ -89,14 +89,18 @@ { struct xenstore_domain_interface *intf = xenstore_domain_interface(); XENSTORE_RING_IDX cons, prod; + int rc; while (len != 0) { void *dst; unsigned int avail; - wait_event_interruptible(xb_waitq, - (intf->req_prod - intf->req_cons) != - XENSTORE_RING_SIZE); + rc = wait_event_interruptible( + xb_waitq, + (intf->req_prod - intf->req_cons) != + XENSTORE_RING_SIZE); + if (rc < 0) + return rc; /* Read indexes, then verify. */ cons = intf->req_cons; @@ -130,13 +134,17 @@ { struct xenstore_domain_interface *intf = xenstore_domain_interface(); XENSTORE_RING_IDX cons, prod; + int rc; while (len != 0) { unsigned int avail; const char *src; - wait_event_interruptible(xb_waitq, - intf->rsp_cons != intf->rsp_prod); + rc = wait_event_interruptible( + xb_waitq, + intf->rsp_cons != intf->rsp_prod); + if (rc < 0) + return rc; /* Read indexes, then verify. */ cons = intf->rsp_cons; diff -r ede16886f979 -r c4ac21dc3f16 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Mon Mar 6 16:09:18 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Mon Mar 6 17:21:35 2006 @@ -45,9 +45,7 @@ #include <asm/hypervisor.h> #include <xen/xenbus.h> #include <xen/xen_proc.h> -#include <xen/balloon.h> #include <xen/evtchn.h> -#include <xen/public/evtchn.h> #include "xenbus_comms.h" @@ -886,9 +884,33 @@ EXPORT_SYMBOL(unregister_xenstore_notifier); +static int all_devices_ready_(struct device *dev, void *data) +{ + struct xenbus_device *xendev = to_xenbus_device(dev); + int *result = data; + + if (xendev->state != XenbusStateConnected) { + result = 0; + return 1; + } + + return 0; +} + + +static int all_devices_ready(void) +{ + int ready = 1; + bus_for_each_dev(&xenbus_frontend.bus, NULL, &ready, + all_devices_ready_); + return ready; +} + void xenbus_probe(void *unused) { + int i; + BUG_ON((xenstored_ready <= 0)); /* Enumerate devices in xenstore. */ @@ -901,12 +923,50 @@ /* Notify others that xenstore is up */ notifier_call_chain(&xenstore_chain, 0, NULL); -} - - + + /* On a 10 second timeout, waiting for all devices currently + configured. We need to do this to guarantee that the filesystems + and / or network devices needed for boot are available, before we + can allow the boot to proceed. + + A possible improvement here would be to have the tools add a + per-device flag to the store entry, indicating whether it is needed + at boot time. This would allow people who knew what they were + doing to accelerate their boot slightly, but of course needs tools + or manual intervention to set up those flags correctly. + */ + for (i = 0; i < 10 * HZ; i++) { + if (all_devices_ready()) + return; + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + } + + printk(KERN_WARNING + "XENBUS: Timeout connecting to devices!\n"); +} + + +static struct file_operations xsd_kva_fops; static struct proc_dir_entry *xsd_kva_intf; static struct proc_dir_entry *xsd_port_intf; +static int xsd_kva_mmap(struct file *file, struct vm_area_struct *vma) +{ + size_t size = vma->vm_end - vma->vm_start; + + if ((size > PAGE_SIZE) || (vma->vm_pgoff != 0)) + return -EINVAL; + + vma->vm_pgoff = mfn_to_pfn(xen_start_info->store_mfn); + + if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, + size, vma->vm_page_prot)) + return -EAGAIN; + + return 0; +} static int xsd_kva_read(char *page, char **start, off_t off, int count, int *eof, void *data) @@ -980,9 +1040,14 @@ xen_start_info->store_evtchn = op.u.alloc_unbound.port; /* And finally publish the above info in /proc/xen */ - if((xsd_kva_intf = create_xen_proc_entry("xsd_kva", 0400))) + if ((xsd_kva_intf = create_xen_proc_entry("xsd_kva", 0400))) { + memcpy(&xsd_kva_fops, xsd_kva_intf->proc_fops, + sizeof(xsd_kva_fops)); + xsd_kva_fops.mmap = xsd_kva_mmap; + xsd_kva_intf->proc_fops = &xsd_kva_fops; xsd_kva_intf->read_proc = xsd_kva_read; - if((xsd_port_intf = create_xen_proc_entry("xsd_port", 0400))) + } + if ((xsd_port_intf = create_xen_proc_entry("xsd_port", 0400))) xsd_port_intf->read_proc = xsd_port_read; } diff -r ede16886f979 -r c4ac21dc3f16 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Mon Mar 6 16:09:18 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Mon Mar 6 17:21:35 2006 @@ -123,8 +123,9 @@ while (list_empty(&xs_state.reply_list)) { spin_unlock(&xs_state.reply_lock); - wait_event_interruptible(xs_state.reply_waitq, - !list_empty(&xs_state.reply_list)); + /* XXX FIXME: Avoid synchronous wait for response here. */ + wait_event(xs_state.reply_waitq, + !list_empty(&xs_state.reply_list)); spin_lock(&xs_state.reply_lock); } @@ -685,6 +686,9 @@ wait_event_interruptible(watch_events_waitq, !list_empty(&watch_events)); + if (kthread_should_stop()) + break; + down(&xenwatch_mutex); spin_lock(&watch_events_lock); @@ -705,6 +709,8 @@ up(&xenwatch_mutex); } + + return 0; } static int process_msg(void) @@ -778,7 +784,11 @@ if (err) printk(KERN_WARNING "XENBUS error %d while reading " "message\n", err); - } + if (kthread_should_stop()) + break; + } + + return 0; } int xs_init(void) diff -r ede16886f979 -r c4ac21dc3f16 linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h Mon Mar 6 16:09:18 2006 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h Mon Mar 6 17:21:35 2006 @@ -16,7 +16,7 @@ return "Xen"; } -void __init machine_specific_modify_cpu_capabilities(struct cpuinfo_x86 *c) +void __devinit machine_specific_modify_cpu_capabilities(struct cpuinfo_x86 *c) { clear_bit(X86_FEATURE_VME, c->x86_capability); clear_bit(X86_FEATURE_DE, c->x86_capability); diff -r ede16886f979 -r c4ac21dc3f16 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h Mon Mar 6 16:09:18 2006 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h Mon Mar 6 17:21:35 2006 @@ -1,28 +1,12 @@ /** - * machine_specific_memory_setup - Hook for machine specific memory setup. + * machine_specific_* - Hooks for machine specific setup. * * Description: * This is included late in kernel/setup.c so that it can make * use of all of the static functions. **/ -static char * __init machine_specific_memory_setup(void) -{ - char *who; - unsigned long start_pfn, max_pfn; - - who = "Xen"; - - start_pfn = 0; - max_pfn = xen_start_info->nr_pages; - - e820.nr_map = 0; - add_memory_region(PFN_PHYS(start_pfn), PFN_PHYS(max_pfn) - PFN_PHYS(start_pfn), E820_RAM); - - return who; -} - -void __init machine_specific_modify_cpu_capabilities(struct cpuinfo_x86 *c) +void __cpuinit machine_specific_modify_cpu_capabilities(struct cpuinfo_x86 *c) { clear_bit(X86_FEATURE_VME, c->x86_capability); clear_bit(X86_FEATURE_DE, c->x86_capability); diff -r ede16886f979 -r c4ac21dc3f16 linux-2.6-xen-sparse/include/xen/xenbus.h --- a/linux-2.6-xen-sparse/include/xen/xenbus.h Mon Mar 6 16:09:18 2006 +++ b/linux-2.6-xen-sparse/include/xen/xenbus.h Mon Mar 6 17:21:35 2006 @@ -63,7 +63,7 @@ int otherend_id; struct xenbus_watch otherend_watch; struct device dev; - int has_error; + XenbusState state; void *data; }; diff -r ede16886f979 -r c4ac21dc3f16 tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c --- a/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c Mon Mar 6 16:09:18 2006 +++ b/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c Mon Mar 6 17:21:35 2006 @@ -41,8 +41,6 @@ #define TRACE_ENTER /* printf("enter %s\n", __FUNCTION__) */ -long (*myptrace)(int xc_handle, enum __ptrace_request, uint32_t, long, long); -int (*myxcwait)(int xc_handle, int domain, int *status, int options) ; static int xc_handle; static inline int @@ -170,7 +168,7 @@ add_thread (0, new_process); new_process->stop_expected = 0; - if (myptrace (xc_handle, PTRACE_ATTACH, domid, 0, 0) != 0) { + if (xc_ptrace (xc_handle, PTRACE_ATTACH, domid, 0, isfile) != 0) { fprintf (stderr, "Cannot attach to domain %d: %s (%d)\n", domid, strerror (errno), errno); fflush (stderr); @@ -188,7 +186,7 @@ { struct thread_info *thread = (struct thread_info *) entry; struct process_info *process = get_thread_process (thread); - myptrace (xc_handle, PTRACE_KILL, pid_of (process), 0, 0); + xc_ptrace (xc_handle, PTRACE_KILL, pid_of (process), 0, 0); } @@ -202,7 +200,7 @@ linux_detach_one_process (struct inferior_list_entry *entry) { - myptrace (xc_handle, PTRACE_DETACH, current_domid, 0, 0); + xc_ptrace (xc_handle, PTRACE_DETACH, current_domid, 0, 0); } @@ -228,7 +226,7 @@ linux_wait (char *status) { int w; - if (myxcwait(xc_handle, current_domid, &w, 0)) + if (xc_waitdomain(xc_handle, current_domid, &w, 0)) return -1; linux_set_inferior(); @@ -250,7 +248,7 @@ for_each_inferior(&all_threads, regcache_invalidate_one); if (debug_threads) fprintf(stderr, "step: %d\n", step); - myptrace (xc_handle, step ? PTRACE_SINGLESTEP : PTRACE_CONT, + xc_ptrace (xc_handle, step ? PTRACE_SINGLESTEP : PTRACE_CONT, resume_info->thread, 0, 0); } @@ -275,7 +273,7 @@ } buf = malloc (regset->size); - res = myptrace (xc_handle, regset->get_request, + res = xc_ptrace (xc_handle, regset->get_request, curvcpuid(), 0, (PTRACE_XFER_TYPE)buf); if (res < 0) @@ -329,7 +327,7 @@ buf = malloc (regset->size); regset->fill_function (buf); - res = myptrace (xc_handle, regset->set_request, curvcpuid(), 0, (PTRACE_XFER_TYPE)buf); + res = xc_ptrace (xc_handle, regset->set_request, curvcpuid(), 0, (PTRACE_XFER_TYPE)buf); if (res < 0) { if (errno == EIO) @@ -407,7 +405,7 @@ for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE)) { errno = 0; - buffer[i] = myptrace (xc_handle, PTRACE_PEEKTEXT, curvcpuid(), (PTRACE_ARG3_TYPE) addr, 0); + buffer[i] = xc_ptrace (xc_handle, PTRACE_PEEKTEXT, curvcpuid(), (PTRACE_ARG3_TYPE) addr, 0); if (errno) return errno; } @@ -440,13 +438,13 @@ /* Fill start and end extra bytes of buffer with existing memory data. */ - buffer[0] = myptrace (xc_handle, PTRACE_PEEKTEXT, curvcpuid(), + buffer[0] = xc_ptrace (xc_handle, PTRACE_PEEKTEXT, curvcpuid(), (PTRACE_ARG3_TYPE) addr, 0); if (count > 1) { buffer[count - 1] - = myptrace (xc_handle, PTRACE_PEEKTEXT, curvcpuid(), + = xc_ptrace (xc_handle, PTRACE_PEEKTEXT, curvcpuid(), (PTRACE_ARG3_TYPE) (addr + (count - 1) * sizeof (PTRACE_XFER_TYPE)), 0); @@ -460,7 +458,7 @@ for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE)) { errno = 0; - myptrace (xc_handle, PTRACE_POKETEXT, curvcpuid(), + xc_ptrace (xc_handle, PTRACE_POKETEXT, curvcpuid(), (PTRACE_ARG3_TYPE) addr, buffer[i]); if (errno) return errno; @@ -561,13 +559,6 @@ the_low_target.breakpoint_len); init_registers (); linux_init_signals (); - if (isfile) { - myptrace = xc_ptrace_core; - myxcwait = xc_waitdomain_core; - } else { - myptrace = xc_ptrace; - myxcwait = xc_waitdomain; - } using_threads = thread_db_init (); } diff -r ede16886f979 -r c4ac21dc3f16 tools/debugger/gdb/gdbbuild --- a/tools/debugger/gdb/gdbbuild Mon Mar 6 16:09:18 2006 +++ b/tools/debugger/gdb/gdbbuild Mon Mar 6 17:21:35 2006 @@ -1,7 +1,9 @@ #!/bin/sh +[ "$GDB_MIRROR" ] || GDB_MIRROR="ftp://ftp.gnu.org/gnu/gdb/" + rm -rf gdb-6.2.1 gdb-6.2.1-linux-i386-xen -[ -a gdb-6.2.1.tar.bz2 ] || wget -c ftp://ftp.gnu.org/gnu/gdb/gdb-6.2.1.tar.bz2 +[ -a gdb-6.2.1.tar.bz2 ] || wget -c "$GDB_MIRROR/gdb-6.2.1.tar.bz2" tar xjf gdb-6.2.1.tar.bz2 cd gdb-6.2.1-xen-sparse @@ -12,8 +14,10 @@ cd gdb-6.2.1-linux-i386-xen ../gdb-6.2.1/configure -# some people don't have gmake -if which gmake ; then +# Use $MAKE if set, else use gmake if present, otherwise use make +if [ "$MAKE" ]; then + $MAKE +elif which gmake ; then gmake -j4 else make -j4 diff -r ede16886f979 -r c4ac21dc3f16 tools/examples/block --- a/tools/examples/block Mon Mar 6 16:09:18 2006 +++ b/tools/examples/block Mon Mar 6 17:21:35 2006 @@ -129,7 +129,14 @@ same_vm() { local otherdom="$1" - local othervm=$(xenstore-read "/local/domain/$otherdom/vm") + # Note that othervm can be MISSING here, because Xend will be racing with + # the hotplug scripts -- the entries in /local/domain can be removed by + # Xend before the hotplug scripts have removed the entry in + # /local/domain/0/backend/. In this case, we want to pretend that the + # VM is the same as FRONTEND_UUID, because that way the 'sharing' will be + # allowed. + local othervm=$(xenstore_read_default "/local/domain/$otherdom/vm" \ + "$FRONTEND_UUID") [ "$FRONTEND_UUID" == "$othervm" ] } @@ -314,7 +321,28 @@ fi fi - f=$(readlink -f "$f") + # Canonicalise the filename for the comparison. + + # I have seen this readlink fails because the filename given by + # losetup is only the basename. This cannot happen when the loop + # device is set up through this script, because file is + # canonicalised above, but it may happen when loop devices are set + # up some other way. This readlink may also conceivably fail if + # the file backing this loop device has been removed. + + # For maximum safety, in the case that $f does not resolve, we + # assume that $file and $f are in the same directory. + + # If you create a loopback filesystem, remove it and continue to + # run on it, and then create another file with the same name, then + # this check will block that -- don't do that. + + # If you create loop devices through some other mechanism, use + # relative filenames, and then use the same filename through this + # script, then this check will block that -- don't do that either. + + f=$(readlink -f "$f" || echo $(dirname "$file")/$(basename "$f")) + if [ "$f" == "$file" ] then diff -r ede16886f979 -r c4ac21dc3f16 tools/examples/xen-hotplug-cleanup --- a/tools/examples/xen-hotplug-cleanup Mon Mar 6 16:09:18 2006 +++ b/tools/examples/xen-hotplug-cleanup Mon Mar 6 17:21:35 2006 @@ -12,10 +12,11 @@ claim_lock "block" # remove device frontend store entries -xenstore-rm -t $(xenstore-read "$XENBUS_PATH/frontend") || true +xenstore-rm -t \ + $(xenstore-read "$XENBUS_PATH/frontend" 2>/dev/null) 2>/dev/null || true # remove device backend store entries -xenstore-rm -t "$XENBUS_PATH" || true -xenstore-rm -t "error/$XENBUS_PATH" || true +xenstore-rm -t "$XENBUS_PATH" 2>/dev/null || true +xenstore-rm -t "error/$XENBUS_PATH" 2>/dev/null || true release_lock "block" diff -r ede16886f979 -r c4ac21dc3f16 tools/firmware/hvmloader/Makefile --- a/tools/firmware/hvmloader/Makefile Mon Mar 6 16:09:18 2006 +++ b/tools/firmware/hvmloader/Makefile Mon Mar 6 17:21:35 2006 @@ -17,6 +17,9 @@ # this program; if not, write to the Free Software Foundation, Inc., 59 Temple # Place - Suite 330, Boston, MA 02111-1307 USA. # + +# External CFLAGS can do more harm than good. +CFLAGS := XEN_ROOT = ../../.. include $(XEN_ROOT)/Config.mk diff -r ede16886f979 -r c4ac21dc3f16 tools/firmware/vmxassist/Makefile --- a/tools/firmware/vmxassist/Makefile Mon Mar 6 16:09:18 2006 +++ b/tools/firmware/vmxassist/Makefile Mon Mar 6 17:21:35 2006 @@ -17,6 +17,9 @@ # this program; if not, write to the Free Software Foundation, Inc., 59 Temple # Place - Suite 330, Boston, MA 02111-1307 USA. # + +# External CFLAGS can do more harm than good. +CFLAGS := XEN_ROOT = ../../.. include $(XEN_ROOT)/Config.mk diff -r ede16886f979 -r c4ac21dc3f16 tools/firmware/vmxassist/setup.c --- a/tools/firmware/vmxassist/setup.c Mon Mar 6 16:09:18 2006 +++ b/tools/firmware/vmxassist/setup.c Mon Mar 6 17:21:35 2006 @@ -123,6 +123,8 @@ void setup_gdt(void) { + unsigned long long addr = (unsigned long long) &tss; + /* setup task state segment */ memset(&tss, 0, sizeof(tss)); tss.ss0 = DATA_SELECTOR; @@ -130,8 +132,7 @@ tss.iomap_base = offsetof(struct tss, iomap); /* initialize gdt's tss selector */ - unsigned long long addr = (unsigned long long) &tss; - gdt[TSS_SELECTOR / sizeof(gdt[0])] |= + gdt[TSS_SELECTOR / sizeof(gdt[0])] |= ((addr & 0xFF000000) << (56-24)) | ((addr & 0x00FF0000) << (32-16)) | ((addr & 0x0000FFFF) << (16)) | diff -r ede16886f979 -r c4ac21dc3f16 tools/ioemu/audio/audio.c --- a/tools/ioemu/audio/audio.c Mon Mar 6 16:09:18 2006 +++ b/tools/ioemu/audio/audio.c Mon Mar 6 17:21:35 2006 @@ -713,7 +713,7 @@ delta = now - sw->old_ticks; bytes = (delta * sw->bytes_per_second) / ticks_per_sec; if (delta < 0) { - dolog ("whoops delta(<0)=%lld\n", delta); + dolog ("whoops delta(<0)=%"PRId64"\n", delta); return 0; } diff -r ede16886f979 -r c4ac21dc3f16 tools/ioemu/hw/i8254.c --- a/tools/ioemu/hw/i8254.c Mon Mar 6 16:09:18 2006 +++ b/tools/ioemu/hw/i8254.c Mon Mar 6 17:21:35 2006 @@ -249,7 +249,7 @@ req->u.data |= (irq << 16); req->u.data |= (hvm_channel << 24); req->u.data |= ((s->rw_mode) << 26); - fprintf(logfile, "HVM_PIT:pass info 0x%llx to HV!\n", req->u.data); + fprintf(logfile, "HVM_PIT:pass info 0x%"PRIx64" to HV!\n", req->u.data); } static inline void pit_load_count(PITChannelState *s, int val) diff -r ede16886f979 -r c4ac21dc3f16 tools/ioemu/monitor.c --- a/tools/ioemu/monitor.c Mon Mar 6 16:09:18 2006 +++ b/tools/ioemu/monitor.c Mon Mar 6 17:21:35 2006 @@ -676,19 +676,19 @@ break; case '-': { - int has_option; + long has_option; /* option */ - + c = *typestr++; if (c == '\0') goto bad_type; - while (isspace(*p)) + while (isspace(*p)) p++; has_option = 0; if (*p == '-') { p++; if (*p != c) { - term_printf("%s: unsupported option -%c\n", + term_printf("%s: unsupported option -%c\n", cmdname, *p); goto fail; } diff -r ede16886f979 -r c4ac21dc3f16 tools/ioemu/target-i386-dm/helper2.c --- a/tools/ioemu/target-i386-dm/helper2.c Mon Mar 6 16:09:18 2006 +++ b/tools/ioemu/target-i386-dm/helper2.c Mon Mar 6 17:21:35 2006 @@ -138,11 +138,11 @@ req = &(shared_page->vcpu_iodata[i].vp_ioreq); term_printf("vcpu %d: event port %d\n", i, shared_page->vcpu_iodata[i].vp_eport); - term_printf(" req state: %x, pvalid: %x, addr: %llx, " - "data: %llx, count: %llx, size: %llx\n", + term_printf(" req state: %x, pvalid: %x, addr: %"PRIx64", " + "data: %"PRIx64", count: %"PRIx64", size: %"PRIx64"\n", req->state, req->pdata_valid, req->addr, req->u.data, req->count, req->size); - term_printf(" IO totally occurred on this vcpu: %llx\n", + term_printf(" IO totally occurred on this vcpu: %"PRIx64"\n", req->io_count); } } @@ -158,8 +158,8 @@ return req; fprintf(logfile, "False I/O request ... in-service already: " - "%x, pvalid: %x, port: %llx, " - "data: %llx, count: %llx, size: %llx\n", + "%x, pvalid: %x, port: %"PRIx64", " + "data: %"PRIx64", count: %"PRIx64", size: %"PRIx64"\n", req->state, req->pdata_valid, req->addr, req->u.data, req->count, req->size); return NULL; @@ -460,12 +460,6 @@ FD_ZERO(&wakeup_rfds); FD_SET(evtchn_fd, &wakeup_rfds); -#if __WORDSIZE == 32 -#define ULONGLONG_MAX 0xffffffffffffffffULL -#else -#define ULONGLONG_MAX ULONG_MAX -#endif - tun_receive_handler(&rfds); if ( FD_ISSET(evtchn_fd, &rfds) ) { cpu_handle_ioreq(env); diff -r ede16886f979 -r c4ac21dc3f16 tools/ioemu/vl.c --- a/tools/ioemu/vl.c Mon Mar 6 16:09:18 2006 +++ b/tools/ioemu/vl.c Mon Mar 6 17:21:35 2006 @@ -2672,6 +2672,7 @@ char qemu_dm_logfilename[64]; const char *loadvm = NULL; unsigned long nr_pages, extra_pages, ram_pages, *page_array; + xc_dominfo_t info; extern void *shared_page; extern void *shared_vram; @@ -3132,7 +3133,7 @@ ram_pages = ram_size/PAGE_SIZE; #if defined(__i386__) || defined(__x86_64__) - vgaram_pages = (vga_ram_size -1)/PAGE_SIZE + 1; + vgaram_pages = (vga_ram_size -1) / PAGE_SIZE + 1; free_pages = vgaram_pages / L1_PAGETABLE_ENTRIES; extra_pages = vgaram_pages + free_pages; #else @@ -3142,7 +3143,6 @@ xc_handle = xc_interface_open(); - xc_dominfo_t info; xc_domain_getinfo(xc_handle, domid, 1, &info); nr_pages = info.nr_pages + extra_pages; diff -r ede16886f979 -r c4ac21dc3f16 tools/libxc/xc_core.c --- a/tools/libxc/xc_core.c Mon Mar 6 16:09:18 2006 +++ b/tools/libxc/xc_core.c Mon Mar 6 17:21:35 2006 @@ -61,7 +61,7 @@ nr_pages = info.nr_pages; - header.xch_magic = 0xF00FEBED; + header.xch_magic = XC_CORE_MAGIC; header.xch_nr_vcpus = nr_vcpus; header.xch_nr_pages = nr_pages; header.xch_ctxt_offset = sizeof(struct xc_core_header); @@ -71,8 +71,12 @@ (sizeof(vcpu_guest_context_t) * nr_vcpus) + (nr_pages * sizeof(unsigned long))); - write(dump_fd, &header, sizeof(struct xc_core_header)); - write(dump_fd, &ctxt, sizeof(ctxt[0]) * nr_vcpus); + if (write(dump_fd, &header, sizeof(struct xc_core_header)) < 0 || + write(dump_fd, &ctxt, sizeof(ctxt[0]) * nr_vcpus) < 0) + { + PERROR("write failed"); + goto error_out; + } if ((page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL) { printf("Could not allocate memory\n"); @@ -82,7 +86,11 @@ printf("Could not get the page frame list\n"); goto error_out; } - write(dump_fd, page_array, nr_pages * sizeof(unsigned long)); + if (write(dump_fd, page_array, nr_pages * sizeof(unsigned long)) < 0) + { + PERROR("write failed"); + goto error_out; + } lseek(dump_fd, header.xch_pages_offset, SEEK_SET); for (dump_mem = dump_mem_start, i = 0; i < nr_pages; i++) { copy_from_domain_page(xc_handle, domid, page_array, i, dump_mem); diff -r ede16886f979 -r c4ac21dc3f16 tools/libxc/xc_ptrace.c --- a/tools/libxc/xc_ptrace.c Mon Mar 6 16:09:18 2006 +++ b/tools/libxc/xc_ptrace.c Mon Mar 6 17:21:35 2006 @@ -7,14 +7,13 @@ #include "xc_private.h" #include "xg_private.h" -#include <thread_db.h> #include "xc_ptrace.h" - /* XXX application state */ static long nr_pages = 0; static unsigned long *page_array = NULL; static int current_domid = -1; +static int current_isfile; static cpumap_t online_cpumap; static cpumap_t regs_valid; @@ -32,7 +31,8 @@ if (online) *online = 0; - if ( !(regs_valid & (1 << cpu)) ) { + if ( !(regs_valid & (1 << cpu)) ) + { retval = xc_vcpu_getcontext(xc_handle, current_domid, cpu, &ctxt[cpu]); if ( retval ) @@ -50,9 +50,6 @@ return retval; } -#define FETCH_REGS(cpu) if (fetch_regs(xc_handle, cpu, NULL)) goto error_out; - - static struct thr_ev_handlers { thr_ev_handler_t td_create; thr_ev_handler_t td_death; @@ -95,14 +92,12 @@ *cpumap = 0; for (i = 0; i <= d->max_vcpu_id; i++) { if ((retval = fetch_regs(xc_handle, i, &online))) - goto error_out; + return retval; if (online) *cpumap |= (1 << i); } return 0; - error_out: - return retval; } /* @@ -118,7 +113,8 @@ int index; while ( (index = ffsll(changed_cpumap)) ) { - if ( cpumap & (1 << (index - 1)) ) { + if ( cpumap & (1 << (index - 1)) ) + { if (handlers.td_create) handlers.td_create(index - 1); } else { printf("thread death: %d\n", index - 1); @@ -143,34 +139,32 @@ uint64_t *l3, *l2, *l1; static void *v; - FETCH_REGS(cpu); + if (fetch_regs(xc_handle, cpu, NULL)) + return NULL; l3 = xc_map_foreign_range( xc_handle, current_domid, PAGE_SIZE, PROT_READ, ctxt[cpu].ctrlreg[3] >> PAGE_SHIFT); if ( l3 == NULL ) - goto error_out; + return NULL; l2p = l3[l3_table_offset_pae(va)] >> PAGE_SHIFT; l2 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, PROT_READ, l2p); if ( l2 == NULL ) - goto error_out; + return NULL; l1p = l2[l2_table_offset_pae(va)] >> PAGE_SHIFT; l1 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, perm, l1p); if ( l1 == NULL ) - goto error_out; + return NULL; p = l1[l1_table_offset_pae(va)] >> PAGE_SHIFT; if ( v != NULL ) munmap(v, PAGE_SIZE); v = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, perm, p); if ( v == NULL ) - goto error_out; + return NULL; return (void *)((unsigned long)v | (va & (PAGE_SIZE - 1))); - - error_out: - return NULL; } static void * @@ -215,17 +209,18 @@ if ( (page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL ) { printf("Could not allocate memory\n"); - goto error_out; + return NULL; } if ( xc_get_pfn_list(xc_handle, current_domid, page_array, nr_pages) != nr_pages ) { printf("Could not get the page frame list\n"); - goto error_out; + return NULL; } } - FETCH_REGS(cpu); + if (fetch_regs(xc_handle, cpu, NULL)) + return NULL; if ( ctxt[cpu].ctrlreg[3] != cr3_phys[cpu] ) { @@ -236,10 +231,10 @@ xc_handle, current_domid, PAGE_SIZE, PROT_READ, cr3_phys[cpu] >> PAGE_SHIFT); if ( cr3_virt[cpu] == NULL ) - goto error_out; + return NULL; } if ( (pde = cr3_virt[cpu][vtopdi(va)]) == 0 ) - goto error_out; + return NULL; if ( (ctxt[cpu].flags & VGCF_HVM_GUEST) && paging_enabled(&ctxt[cpu]) ) pde = page_array[pde >> PAGE_SHIFT] << PAGE_SHIFT; if ( pde != pde_phys[cpu] ) @@ -251,10 +246,10 @@ xc_handle, current_domid, PAGE_SIZE, PROT_READ, pde_phys[cpu] >> PAGE_SHIFT); if ( pde_virt[cpu] == NULL ) - goto error_out; + return NULL; } if ( (page = pde_virt[cpu][vtopti(va)]) == 0 ) - goto error_out; + return NULL; if ( (ctxt[cpu].flags & VGCF_HVM_GUEST) && paging_enabled(&ctxt[cpu]) ) page = page_array[page >> PAGE_SHIFT] << PAGE_SHIFT; if ( (page != page_phys[cpu]) || (perm != prev_perm[cpu]) ) @@ -268,19 +263,16 @@ if ( page_virt[cpu] == NULL ) { page_phys[cpu] = 0; - goto error_out; + return NULL; } prev_perm[cpu] = perm; } return (void *)(((unsigned long)page_virt[cpu]) | (va & BSD_PAGE_MASK)); - - error_out: - return NULL; -} - -int -xc_waitdomain( +} + +static int +__xc_waitdomain( int xc_handle, int domain, int *status, @@ -335,7 +327,6 @@ long edata) { DECLARE_DOM0_OP; - int status = 0; struct gdb_regs pt; long retval = 0; unsigned long *guest_va; @@ -350,84 +341,83 @@ { case PTRACE_PEEKTEXT: case PTRACE_PEEKDATA: - guest_va = (unsigned long *)map_domain_va( - xc_handle, cpu, addr, PROT_READ); + if (current_isfile) + guest_va = (unsigned long *)map_domain_va_core(current_domid, + cpu, addr, ctxt); + else + guest_va = (unsigned long *)map_domain_va(xc_handle, + cpu, addr, PROT_READ); if ( guest_va == NULL ) - { - status = EFAULT; - goto error_out; - } + goto out_error; retval = *guest_va; break; case PTRACE_POKETEXT: case PTRACE_POKEDATA: /* XXX assume that all CPUs have the same address space */ - guest_va = (unsigned long *)map_domain_va( - xc_handle, cpu, addr, PROT_READ|PROT_WRITE); - if ( guest_va == NULL ) { - status = EFAULT; - goto error_out; - } + if (current_isfile) + guest_va = (unsigned long *)map_domain_va_core(current_domid, + cpu, addr, ctxt); + else + guest_va = (unsigned long *)map_domain_va(xc_handle, + cpu, addr, PROT_READ|PROT_WRITE); + if ( guest_va == NULL ) + goto out_error; *guest_va = (unsigned long)data; break; case PTRACE_GETREGS: + if (!current_isfile && fetch_regs(xc_handle, cpu, NULL)) + goto out_error; + SET_PT_REGS(pt, ctxt[cpu].user_regs); + memcpy(data, &pt, sizeof(struct gdb_regs)); + break; + case PTRACE_GETFPREGS: case PTRACE_GETFPXREGS: - - FETCH_REGS(cpu); - if ( request == PTRACE_GETREGS ) - { - SET_PT_REGS(pt, ctxt[cpu].user_regs); - memcpy(data, &pt, sizeof(struct gdb_regs)); - } - else if (request == PTRACE_GETFPREGS) - { - memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt)); - } - else /*if (request == PTRACE_GETFPXREGS)*/ - { - memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt)); - } + if (!current_isfile && fetch_regs(xc_handle, cpu, NULL)) + goto out_error; + memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt)); break; case PTRACE_SETREGS: + if (!current_isfile) + goto out_unspported; /* XXX not yet supported */ SET_XC_REGS(((struct gdb_regs *)data), ctxt[cpu].user_regs); - retval = xc_vcpu_setcontext(xc_handle, current_domid, cpu, &ctxt[cpu]); - if (retval) - goto error_out; + if ((retval = xc_vcpu_setcontext(xc_handle, current_domid, cpu, + &ctxt[cpu]))) + goto out_error_dom0; break; case PTRACE_SINGLESTEP: + if (!current_isfile) + goto out_unspported; /* XXX not yet supported */ /* XXX we can still have problems if the user switches threads * during single-stepping - but that just seems retarded */ ctxt[cpu].user_regs.eflags |= PSL_T; - retval = xc_vcpu_setcontext(xc_handle, current_domid, cpu, &ctxt[cpu]); - if ( retval ) - { - perror("dom0 op failed"); - goto error_out; - } + if ((retval = xc_vcpu_setcontext(xc_handle, current_domid, cpu, + &ctxt[cpu]))) + goto out_error_dom0; /* FALLTHROUGH */ case PTRACE_CONT: case PTRACE_DETACH: + if (!current_isfile) + goto out_unspported; /* XXX not yet supported */ if ( request != PTRACE_SINGLESTEP ) { FOREACH_CPU(cpumap, index) { cpu = index - 1; - FETCH_REGS(cpu); + if (fetch_regs(xc_handle, cpu, NULL)) + goto out_error; /* Clear trace flag */ - if ( ctxt[cpu].user_regs.eflags & PSL_T ) { + if ( ctxt[cpu].user_regs.eflags & PSL_T ) + { ctxt[cpu].user_regs.eflags &= ~PSL_T; - retval = xc_vcpu_setcontext(xc_handle, current_domid, - cpu, &ctxt[cpu]); - if ( retval ) { - perror("dom0 op failed"); - goto error_out; - } + if ((retval = xc_vcpu_setcontext(xc_handle, current_domid, + cpu, &ctxt[cpu]))) + goto out_error_dom0; } } } @@ -436,31 +426,34 @@ op.cmd = DOM0_SETDEBUGGING; op.u.setdebugging.domain = current_domid; op.u.setdebugging.enable = 0; - retval = do_dom0_op(xc_handle, &op); + if ((retval = do_dom0_op(xc_handle, &op))) + goto out_error_dom0; } regs_valid = 0; - xc_domain_unpause(xc_handle, current_domid > 0 ? current_domid : -current_domid); + if ((retval = xc_domain_unpause(xc_handle, current_domid > 0 ? + current_domid : -current_domid))) + goto out_error_dom0; break; case PTRACE_ATTACH: current_domid = domid_tid; + current_isfile = (int)edata; + if (current_isfile) + break; op.cmd = DOM0_GETDOMAININFO; op.u.getdomaininfo.domain = current_domid; retval = do_dom0_op(xc_handle, &op); if ( retval || (op.u.getdomaininfo.domain != current_domid) ) - { - perror("dom0 op failed"); - goto error_out; - } + goto out_error_dom0; if ( op.u.getdomaininfo.flags & DOMFLAGS_PAUSED ) - { printf("domain currently paused\n"); - } else - retval = xc_domain_pause(xc_handle, current_domid); + else if ((retval = xc_domain_pause(xc_handle, current_domid))) + goto out_error_dom0; op.cmd = DOM0_SETDEBUGGING; op.u.setdebugging.domain = current_domid; op.u.setdebugging.enable = 1; - retval = do_dom0_op(xc_handle, &op); + if ((retval = do_dom0_op(xc_handle, &op))) + goto out_error_dom0; if (get_online_cpumap(xc_handle, &op.u.getdomaininfo, &cpumap)) printf("get_online_cpumap failed\n"); @@ -474,26 +467,40 @@ case PTRACE_POKEUSER: case PTRACE_SYSCALL: case PTRACE_KILL: -#ifdef DEBUG - printf("unsupported xc_ptrace request %s\n", ptrace_names[request]); -#endif - /* XXX not yet supported */ - status = ENOSYS; - break; + goto out_unspported; /* XXX not yet supported */ case PTRACE_TRACEME: printf("PTRACE_TRACEME is an invalid request under Xen\n"); - status = EINVAL; - } - - if ( status ) - { - errno = status; - retval = -1; - } - - error_out: + goto out_error; + } + return retval; + + out_error_dom0: + perror("dom0 op failed"); + out_error: + errno = EINVAL; + return retval; + + out_unspported: +#ifdef DEBUG + printf("unsupported xc_ptrace request %s\n", ptrace_names[request]); +#endif + errno = ENOSYS; + return -1; + +} + +int +xc_waitdomain( + int xc_handle, + int domain, + int *status, + int options) +{ + if (current_isfile) + return xc_waitdomain_core(xc_handle, domain, status, options, ctxt); + return __xc_waitdomain(xc_handle, domain, status, options); } /* diff -r ede16886f979 -r c4ac21dc3f16 tools/libxc/xc_ptrace.h --- a/tools/libxc/xc_ptrace.h Mon Mar 6 16:09:18 2006 +++ b/tools/libxc/xc_ptrace.h Mon Mar 6 17:21:35 2006 @@ -1,5 +1,7 @@ #ifndef XC_PTRACE_ #define XC_PTRACE_ + +#include <thread_db.h> #ifdef XC_PTRACE_PRIVATE #define X86_CR0_PE 0x00000001 /* Enable Protected Mode (RW) */ @@ -8,33 +10,7 @@ #define PDRSHIFT 22 #define PSL_T 0x00000100 /* trace enable bit */ -char * ptrace_names[] = { - "PTRACE_TRACEME", - "PTRACE_PEEKTEXT", - "PTRACE_PEEKDATA", - "PTRACE_PEEKUSER", - "PTRACE_POKETEXT", - "PTRACE_POKEDATA", - "PTRACE_POKEUSER", - "PTRACE_CONT", - "PTRACE_KILL", - "PTRACE_SINGLESTEP", - "PTRACE_INVALID", - "PTRACE_INVALID", - "PTRACE_GETREGS", - "PTRACE_SETREGS", - "PTRACE_GETFPREGS", - "PTRACE_SETFPREGS", - "PTRACE_ATTACH", - "PTRACE_DETACH", - "PTRACE_GETFPXREGS", - "PTRACE_SETFPXREGS", - "PTRACE_INVALID", - "PTRACE_INVALID", - "PTRACE_INVALID", - "PTRACE_INVALID", - "PTRACE_SYSCALL", -}; +extern const char const * ptrace_names[]; struct gdb_regs { long ebx; /* 0 */ diff -r ede16886f979 -r c4ac21dc3f16 tools/libxc/xc_ptrace_core.c --- a/tools/libxc/xc_ptrace_core.c Mon Mar 6 16:09:18 2006 +++ b/tools/libxc/xc_ptrace_core.c Mon Mar 6 17:21:35 2006 @@ -1,81 +1,10 @@ +#define XC_PTRACE_PRIVATE + #include <sys/ptrace.h> #include <sys/wait.h> #include "xc_private.h" +#include "xc_ptrace.h" #include <time.h> - -#define BSD_PAGE_MASK (PAGE_SIZE-1) -#define PDRSHIFT 22 -#define VCPU 0 /* XXX */ - -/* - * long - * ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data); - */ - -struct gdb_regs { - long ebx; /* 0 */ - long ecx; /* 4 */ - long edx; /* 8 */ - long esi; /* 12 */ - long edi; /* 16 */ - long ebp; /* 20 */ - long eax; /* 24 */ - int xds; /* 28 */ - int xes; /* 32 */ - int xfs; /* 36 */ - int xgs; /* 40 */ - long orig_eax; /* 44 */ - long eip; /* 48 */ - int xcs; /* 52 */ - long eflags; /* 56 */ - long esp; /* 60 */ - int xss; /* 64 */ -}; - -#define printval(x) printf("%s = %lx\n", #x, (long)x); -#define SET_PT_REGS(pt, xc) \ -{ \ - pt.ebx = xc.ebx; \ - pt.ecx = xc.ecx; \ - pt.edx = xc.edx; \ - pt.esi = xc.esi; \ - pt.edi = xc.edi; \ - pt.ebp = xc.ebp; \ - pt.eax = xc.eax; \ - pt.eip = xc.eip; \ - pt.xcs = xc.cs; \ - pt.eflags = xc.eflags; \ - pt.esp = xc.esp; \ - pt.xss = xc.ss; \ - pt.xes = xc.es; \ - pt.xds = xc.ds; \ - pt.xfs = xc.fs; \ - pt.xgs = xc.gs; \ -} - -#define SET_XC_REGS(pt, xc) \ -{ \ - xc.ebx = pt->ebx; \ - xc.ecx = pt->ecx; \ - xc.edx = pt->edx; \ - xc.esi = pt->esi; \ - xc.edi = pt->edi; \ - xc.ebp = pt->ebp; \ - xc.eax = pt->eax; \ - xc.eip = pt->eip; \ - xc.cs = pt->xcs; \ - xc.eflags = pt->eflags; \ - xc.esp = pt->esp; \ - xc.ss = pt->xss; \ - xc.es = pt->xes; \ - xc.ds = pt->xds; \ - xc.fs = pt->xfs; \ - xc.gs = pt->xgs; \ -} - - -#define vtopdi(va) ((va) >> PDRSHIFT) -#define vtopti(va) (((va) >> PAGE_SHIFT) & 0x3ff) /* XXX application state */ @@ -84,7 +13,6 @@ static unsigned long *m2p_array = NULL; static unsigned long pages_offset; static unsigned long cr3[MAX_VIRT_CPUS]; -static vcpu_guest_context_t ctxt[MAX_VIRT_CPUS]; /* --------------------- */ @@ -92,11 +20,13 @@ map_mtop_offset(unsigned long ma) { return pages_offset + (m2p_array[ma >> PAGE_SHIFT] << PAGE_SHIFT); + return 0; } -static void * -map_domain_va(unsigned long domfd, int cpu, void * guest_va) +void * +map_domain_va_core(unsigned long domfd, int cpu, void * guest_va, + vcpu_guest_context_t *ctxt) { unsigned long pde, page; unsigned long va = (unsigned long)guest_va; @@ -120,12 +50,12 @@ if (v == MAP_FAILED) { perror("mmap failed"); - goto error_out; + return NULL; } cr3_virt[cpu] = v; } if ((pde = cr3_virt[cpu][vtopdi(va)]) == 0) /* logical address */ - goto error_out; + return NULL; if (ctxt[cpu].flags & VGCF_HVM_GUEST) pde = p2m_array[pde >> PAGE_SHIFT] << PAGE_SHIFT; if (pde != pde_phys[cpu]) @@ -137,11 +67,11 @@ NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, domfd, map_mtop_offset(pde_phys[cpu])); if (v == MAP_FAILED) - goto error_out; + return NULL; pde_virt[cpu] = v; } if ((page = pde_virt[cpu][vtopti(va)]) == 0) /* logical address */ - goto error_out; + return NULL; if (ctxt[cpu].flags & VGCF_HVM_GUEST) page = p2m_array[page >> PAGE_SHIFT] << PAGE_SHIFT; if (page != page_phys[cpu]) @@ -152,17 +82,15 @@ v = mmap( NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, domfd, map_mtop_offset(page_phys[cpu])); - if (v == MAP_FAILED) { + if (v == MAP_FAILED) + { printf("cr3 %lx pde %lx page %lx pti %lx\n", cr3[cpu], pde, page, vtopti(va)); page_phys[cpu] = 0; - goto error_out; + return NULL; } page_virt[cpu] = v; } return (void *)(((unsigned long)page_virt[cpu]) | (va & BSD_PAGE_MASK)); - - error_out: - return 0; } int @@ -170,17 +98,25 @@ int xc_handle, int domfd, int *status, - int options) + int options, + vcpu_guest_context_t *ctxt) { - int retval = -1; int nr_vcpus; int i; xc_core_header_t header; - if (nr_pages == 0) { + if (nr_pages == 0) + { if (read(domfd, &header, sizeof(header)) != sizeof(header)) return -1; + + if (header.xch_magic != XC_CORE_MAGIC) { + printf("Magic number missmatch: 0x%08x (file) != " + " 0x%08x (code)\n", header.xch_magic, + XC_CORE_MAGIC); + return -1; + } nr_pages = header.xch_nr_pages; nr_vcpus = header.xch_nr_vcpus; @@ -193,17 +129,19 @@ for (i = 0; i < nr_vcpus; i++) { cr3[i] = ctxt[i].ctrlreg[3]; } - if ((p2m_array = malloc(nr_pages * sizeof(unsigned long))) == NULL) { + if ((p2m_array = malloc(nr_pages * sizeof(unsigned long))) == NULL) + { printf("Could not allocate p2m_array\n"); - goto error_out; + return -1; } if (read(domfd, p2m_array, sizeof(unsigned long)*nr_pages) != sizeof(unsigned long)*nr_pages) return -1; - if ((m2p_array = malloc((1<<20) * sizeof(unsigned long))) == NULL) { + if ((m2p_array = malloc((1<<20) * sizeof(unsigned long))) == NULL) + { printf("Could not allocate m2p array\n"); - goto error_out; + return -1; } bzero(m2p_array, sizeof(unsigned long)* 1 << 20); @@ -212,89 +150,7 @@ } } - retval = 0; - error_out: - return retval; - -} - -long -xc_ptrace_core( - int xc_handle, - enum __ptrace_request request, - uint32_t domfd, - long eaddr, - long edata) -{ - int status = 0; - struct gdb_regs pt; - long retval = 0; - unsigned long *guest_va; - int cpu = VCPU; - void *addr = (char *)eaddr; - void *data = (char *)edata; - -#if 0 - printf("%20s %d, %p, %p \n", ptrace_names[request], domid, addr, data); -#endif - switch (request) { - case PTRACE_PEEKTEXT: - case PTRACE_PEEKDATA: - if ((guest_va = (unsigned long *)map_domain_va(domfd, cpu, addr)) == NULL) { - status = EFAULT; - goto error_out; - } - - retval = *guest_va; - break; - case PTRACE_POKETEXT: - case PTRACE_POKEDATA: - if ((guest_va = (unsigned long *)map_domain_va(domfd, cpu, addr)) == NULL) { - status = EFAULT; - goto error_out; - } - *guest_va = (unsigned long)data; - break; - case PTRACE_GETREGS: - case PTRACE_GETFPREGS: - case PTRACE_GETFPXREGS: - if (request == PTRACE_GETREGS) { - SET_PT_REGS(pt, ctxt[cpu].user_regs); - memcpy(data, &pt, sizeof(struct gdb_regs)); - } else if (request == PTRACE_GETFPREGS) - memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt)); - else /*if (request == PTRACE_GETFPXREGS)*/ - memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt)); - break; - case PTRACE_ATTACH: - retval = 0; - break; - case PTRACE_SETREGS: - case PTRACE_SINGLESTEP: - case PTRACE_CONT: - case PTRACE_DETACH: - case PTRACE_SETFPREGS: - case PTRACE_SETFPXREGS: - case PTRACE_PEEKUSER: - case PTRACE_POKEUSER: - case PTRACE_SYSCALL: - case PTRACE_KILL: -#ifdef DEBUG - printf("unsupported xc_ptrace request %s\n", ptrace_names[request]); -#endif - status = ENOSYS; - break; - case PTRACE_TRACEME: - printf("PTRACE_TRACEME is an invalid request under Xen\n"); - status = EINVAL; - } - - if (status) { - errno = status; - retval = -1; - } - error_out: - return retval; + return 0; } /* diff -r ede16886f979 -r c4ac21dc3f16 tools/libxc/xenctrl.h --- a/tools/libxc/xenctrl.h Mon Mar 6 16:09:18 2006 +++ b/tools/libxc/xenctrl.h Mon Mar 6 17:21:35 2006 @@ -92,19 +92,26 @@ unsigned int xch_pages_offset; } xc_core_header_t; +#define XC_CORE_MAGIC 0xF00FEBED long xc_ptrace_core( int xc_handle, enum __ptrace_request request, uint32_t domid, long addr, - long data); - + long data, + vcpu_guest_context_t *ctxt); +void * map_domain_va_core( + unsigned long domfd, + int cpu, + void *guest_va, + vcpu_guest_context_t *ctxt); int xc_waitdomain_core( int xc_handle, int domain, int *status, - int options); + int options, + vcpu_guest_context_t *ctxt); /* * DOMAIN MANAGEMENT FUNCTIONS diff -r ede16886f979 -r c4ac21dc3f16 tools/misc/lomount/lomount.c --- a/tools/misc/lomount/lomount.c Mon Mar 6 16:09:18 2006 +++ b/tools/misc/lomount/lomount.c Mon Mar 6 17:21:35 2006 @@ -24,16 +24,33 @@ * THE SOFTWARE. */ +/* + * Return code: + * + * bit 7 set: lomount wrapper failed + * bit 7 clear: lomount wrapper ok; mount's return code in low 7 bits + * 0 success + */ + +enum +{ + ERR_USAGE = 0x80, // Incorrect usage + ERR_PART_PARSE, // Failed to parse partition table + ERR_NO_PART, // No such partition + ERR_NO_EPART, // No such extended partition + ERR_MOUNT // Other failure of mount command +}; + #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <strings.h> +#include <sys/wait.h> #include <errno.h> #define BUF 4096 -//#define SECSIZE 4096 /* arbitrarilly large (it's probably just 512) */ #define SECSIZE 512 struct pentry @@ -50,30 +67,32 @@ unsigned long no_of_sectors_abs; }; -char * progname; - -int loadptable(const char *argv, struct pentry parttbl[], struct pentry **exttbl) -{ - FILE *fd; - int i, valid, total_known_sectors = 0; +int loadptable(const char *diskimage, struct pentry parttbl[], struct pentry **exttbl, int * valid) +{ + FILE *fd; + size_t size; + int fail = 1; + int i, total_known_sectors = 0; unsigned char *pi; unsigned char data [SECSIZE]; unsigned long extent = 0, old_extent = 0, e_count = 1; struct pentry exttbls[4]; - fd = fopen(argv, "r"); + *valid = 0; + + fd = fopen(diskimage, "r"); if (fd == NULL) { - perror ("lomount"); - return 1; - } - i = fread (&data, 1, sizeof (data), fd); - if (i < SECSIZE) - { - fprintf (stderr, "%s: could not read the entire first sector\n", progname); - return 1; - } - for (i = 0;i < 4;i++) + perror(diskimage); + goto done; + } + size = fread (&data, 1, sizeof(data), fd); + if (size < (size_t)sizeof(data)) + { + fprintf(stderr, "Could not read the entire first sector of %s.\n", diskimage); + goto done; + } + for (i = 0; i < 4; i++) { pi = &data [446 + 16 * i]; parttbl [i].bootable = *pi; @@ -95,7 +114,7 @@ old_extent = extent; } } - valid = (data [510] == 0x55 && data [511] == 0xaa) ? 1 : 0; + *valid = (data [510] == 0x55 && data [511] == 0xaa) ? 1 : 0; for (i = 0; i < 4; i++) { total_known_sectors += parttbl[i].no_of_sectors_abs; @@ -105,7 +124,7 @@ #ifdef DEBUG if (extent != 0) { - printf("extended partition detected at offset %d\n", extent); + printf("extended partition detected at offset %ld\n", extent); } #endif while (extent != 0) @@ -113,14 +132,14 @@ /* according to realloc(3) passing NULL as pointer is same as calling malloc() */ exttbl[0] = realloc(exttbl[0], e_count * sizeof(struct pentry)); fseek(fd, extent, SEEK_SET); - i = fread (&data, 1, sizeof (data), fd); - if (i < SECSIZE) - { - fprintf (stderr, "%s: could not read the entire first sector\n", progname); - return 1; + size = fread (&data, 1, sizeof(data), fd); + if (size < (size_t)sizeof(data)) + { + fprintf(stderr, "Could not read extended partition of %s.", diskimage); + goto done; } /* only first 2 entrys are used in extented partition tables */ - for (i = 0;i < 2;i++) + for (i = 0; i < 2; i++) { pi = &data [446 + 16 * i]; exttbls [i].bootable = *pi; @@ -152,7 +171,7 @@ /* adjust for start of image instead of start of ext partition */ exttbl[0][e_count-1].start_sector_abs += (extent/SECSIZE); #ifdef DEBUG - printf("extent %d start_sector_abs %d\n", extent, exttbl[0][e_count-1].start_sector_abs); + printf("extent %ld start_sector_abs %ld\n", extent, exttbl[0][e_count-1].start_sector_abs); #endif //else if (parttbl[i].system == 0x5) } @@ -165,53 +184,71 @@ } e_count ++; } - //fclose (fd); - //the above segfaults (?!!!) -#ifdef DEBUG - printf("e_count = %d\n", e_count); -#endif - return valid; +#ifdef DEBUG + printf("e_count = %ld\n", e_count); +#endif + fail = 0; + +done: + if (fd) + fclose(fd); + return fail; } +void usage() +{ + fprintf(stderr, "You must specify at least -diskimage and -partition.\n"); + fprintf(stderr, "All other arguments are passed through to 'mount'.\n"); + fprintf(stderr, "ex. lomount -t fs-type -diskimage hda.img -partition 1 /mnt\n"); + exit(ERR_USAGE); +} + int main(int argc, char ** argv) { + int status; struct pentry perttbl [4]; struct pentry *exttbl[1], *parttbl; - char buf[BUF], argv2[BUF], diskimage[BUF]; - int partition = 1, sec, num = 0, pnum = 0, len = BUF, i, f = 0, valid; - progname = argv[0]; + char buf[BUF], argv2[BUF]; + const char * diskimage = 0; + int partition = 0, sec, num = 0, pnum = 0, i, valid; + size_t argv2_len = sizeof(argv2); + argv2[0] = '\0'; exttbl[0] = NULL; + for (i = 1; i < argc; i ++) { - if (strncmp(argv[i], "-diskimage", BUF)==0) - { - strncpy(diskimage, argv[i+1], BUF); - i++; f = 1; - } - else if (strncmp(argv[i], "-partition", BUF)==0) - { - partition = atoi(argv[i+1]); + if (strcmp(argv[i], "-diskimage")==0) + { + if (i == argc-1) + usage(); i++; - if (partition < 1) partition = 1; + diskimage = argv[i]; + } + else if (strcmp(argv[i], "-partition")==0) + { + if (i == argc-1) + usage(); + i++; + partition = atoi(argv[i]); } else { - strncat(argv2, argv[i], len); - strncat(argv2, " ", len-1); - len -= strlen(argv[i]); - len--; - } - } - if (!f) - { - printf("You must specify -diskimage and -partition\n"); - printf("ex. lomount -t fs-type -diskimage hda.img -partition 1 /mnt\n"); - return 0; - } - valid = loadptable(diskimage, perttbl, exttbl); + size_t len = strlen(argv[i]); + if (len >= argv2_len-1) + usage(); + strcat(argv2, argv[i]); + strcat(argv2, " "); + len -= (len+1); + } + } + if (! diskimage || partition < 1) + usage(); + + if (loadptable(diskimage, perttbl, exttbl, &valid)) + return ERR_PART_PARSE; if (!valid) { - printf("Warning: disk image does not appear to describe a valid partition table.\n"); + fprintf(stderr, "Warning: disk image does not appear to describe a valid partition table.\n"); } /* NOTE: need to make sure this always rounds down */ //sec = total_known_sectors / sizeof_diskimage; @@ -228,14 +265,14 @@ { if (exttbl[0] == NULL) { - printf("No extended partitions were found in %s.\n", diskimage); - return 2; + fprintf(stderr, "No extended partitions were found in %s.\n", diskimage); + return ERR_NO_EPART; } parttbl = exttbl[0]; if (parttbl[partition-5].no_of_sectors_abs == 0) { - printf("Partition %d was not found in %s.\n", partition, diskimage); - return 3; + fprintf(stderr, "Partition %d was not found in %s.\n", partition, diskimage); + return ERR_NO_PART; } partition -= 4; } @@ -244,8 +281,8 @@ parttbl = perttbl; if (parttbl[partition-1].no_of_sectors_abs == 0) { - printf("Partition %d was not found in %s.\n", partition, diskimage); - return 3; + fprintf(stderr, "Partition %d was not found in %s.\n", partition, diskimage); + return ERR_NO_PART; } } num = parttbl[partition-1].start_sector_abs; @@ -253,10 +290,14 @@ #ifdef DEBUG printf("offset = %d\n", pnum); #endif - snprintf(buf, BUF, "mount -oloop,offset=%d %s %s", pnum, diskimage, argv2); + snprintf(buf, sizeof(buf), "mount -oloop,offset=%d %s %s", pnum, diskimage, argv2); #ifdef DEBUG printf("%s\n", buf); #endif - system(buf); - return 0; + status = system(buf); + if (WIFEXITED(status)) + status = WEXITSTATUS(status); + else + status = ERR_MOUNT; + return status; } diff -r ede16886f979 -r c4ac21dc3f16 tools/python/xen/xend/XendClient.py --- a/tools/python/xen/xend/XendClient.py Mon Mar 6 16:09:18 2006 +++ b/tools/python/xen/xend/XendClient.py Mon Mar 6 17:21:35 2006 @@ -196,8 +196,9 @@ def xend_domains(self): return self.xendGet(self.domainurl()) - def xend_list_domains(self): - return self.xendGet(self.domainurl(), {'detail': '1'}) + def xend_list_domains(self, detail = True): + return self.xendGet(self.domainurl(), + {'detail': detail and '1' or '0'}) def xend_domain_vcpuinfo(self, dom): return self.xendGet(self.domainurl(dom), {'op': 'vcpuinfo'}) diff -r ede16886f979 -r c4ac21dc3f16 tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Mon Mar 6 16:09:18 2006 +++ b/tools/python/xen/xend/XendDomainInfo.py Mon Mar 6 17:21:35 2006 @@ -13,7 +13,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #============================================================================ # Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx> -# Copyright (C) 2005 XenSource Ltd +# Copyright (C) 2005, 2006 XenSource Ltd #============================================================================ """Representation of a single domain. @@ -82,7 +82,7 @@ STATE_DOM_OK = 1 STATE_DOM_SHUTDOWN = 2 -SHUTDOWN_TIMEOUT = 30 +SHUTDOWN_TIMEOUT = 30.0 ZOMBIE_PREFIX = 'Zombie-' @@ -182,7 +182,7 @@ vm.initDomain() vm.storeVmDetails() vm.storeDomDetails() - vm.registerWatch() + vm.registerWatches() vm.refreshShutdown() return vm except: @@ -238,7 +238,7 @@ vm.storeVmDetails() vm.storeDomDetails() - vm.registerWatch() + vm.registerWatches() vm.refreshShutdown(xeninfo) return vm @@ -443,7 +443,10 @@ self.console_mfn = None self.vmWatch = None - + self.shutdownWatch = None + + self.shutdownStartTime = None + self.state = STATE_DOM_OK self.state_updated = threading.Condition() self.refresh_shutdown_lock = threading.Condition() @@ -648,7 +651,7 @@ self.introduceDomain() self.storeDomDetails() - self.registerWatch() + self.registerWatches() self.refreshShutdown() log.debug("XendDomainInfo.completeRestore done") @@ -711,13 +714,15 @@ ## public: - def registerWatch(self): - """Register a watch on this VM's entries in the store, so that - when they are changed externally, we keep up to date. This should - only be called by {@link #create}, {@link #recreate}, or {@link - #restore}, once the domain's details have been written, but before the - new instance is returned.""" + def registerWatches(self): + """Register a watch on this VM's entries in the store, and the + domain's control/shutdown node, so that when they are changed + externally, we keep up to date. This should only be called by {@link + #create}, {@link #recreate}, or {@link #restore}, once the domain's + details have been written, but before the new instance is returned.""" self.vmWatch = xswatch(self.vmpath, self.storeChanged) + self.shutdownWatch = xswatch(self.dompath + '/control/shutdown', + self.handleShutdownWatch) def getDomid(self): @@ -852,33 +857,49 @@ # Domain is alive. If we are shutting it down, then check # the timeout on that, and destroy it if necessary. - sst = self.readDom('xend/shutdown_start_time') - if sst: - sst = float(sst) - timeout = SHUTDOWN_TIMEOUT - time.time() + sst + if self.shutdownStartTime: + timeout = (SHUTDOWN_TIMEOUT - time.time() + + self.shutdownStartTime) if timeout < 0: log.info( "Domain shutdown timeout expired: name=%s id=%s", self.info['name'], self.domid) self.destroy() - else: - log.debug( - "Scheduling refreshShutdown on domain %d in %ds.", - self.domid, timeout) - threading.Timer(timeout, self.refreshShutdown).start() finally: self.refresh_shutdown_lock.release() if restart_reason: self.maybeRestart(restart_reason) + + + def handleShutdownWatch(self, _): + log.debug('XendDomainInfo.handleShutdownWatch') + + reason = self.readDom('control/shutdown') + + if reason and reason != 'suspend': + sst = self.readDom('xend/shutdown_start_time') + now = time.time() + if sst: + self.shutdownStartTime = float(sst) + timeout = float(sst) + SHUTDOWN_TIMEOUT - now + else: + self.shutdownStartTime = now + self.storeDom('xend/shutdown_start_time', now) + timeout = SHUTDOWN_TIMEOUT + + log.trace( + "Scheduling refreshShutdown on domain %d in %ds.", + self.domid, timeout) + threading.Timer(timeout, self.refreshShutdown).start() + + return 1 def shutdown(self, reason): if not reason in shutdown_reasons.values(): raise XendError('Invalid reason: %s' % reason) self.storeDom("control/shutdown", reason) - if reason != 'suspend': - self.storeDom('xend/shutdown_start_time', time.time()) ## private: @@ -1225,6 +1246,8 @@ """Cleanup domain resources; release devices. Idempotent. Nothrow guarantee.""" + self.unwatchShutdown() + self.release_devices() if self.image: @@ -1274,6 +1297,20 @@ self.vmWatch = None except: log.exception("Unwatching VM path failed.") + + + def unwatchShutdown(self): + """Remove the watch on the domain's control/shutdown node, if any. + Idempotent. Nothrow guarantee.""" + + try: + try: + if self.shutdownWatch: + self.shutdownWatch.unwatch() + finally: + self.shutdownWatch = None + except: + log.exception("Unwatching control/shutdown failed.") ## public: diff -r ede16886f979 -r c4ac21dc3f16 tools/python/xen/xend/image.py --- a/tools/python/xen/xend/image.py Mon Mar 6 16:09:18 2006 +++ b/tools/python/xen/xend/image.py Mon Mar 6 17:21:35 2006 @@ -274,6 +274,10 @@ uname = sxp.child_value(info, 'uname') typedev = sxp.child_value(info, 'dev') (_, vbdparam) = string.split(uname, ':', 1) + + if 'file:' in uname and not os.path.isfile(vbdparam): + raise VmError('Disk image does not exist: %s' % vbdparam) + if 'ioemu:' in typedev: (emtype, vbddev) = string.split(typedev, ':', 1) else: diff -r ede16886f979 -r c4ac21dc3f16 tools/python/xen/xend/server/blkif.py --- a/tools/python/xen/xend/server/blkif.py Mon Mar 6 16:09:18 2006 +++ b/tools/python/xen/xend/server/blkif.py Mon Mar 6 17:21:35 2006 @@ -42,10 +42,6 @@ """@see DevController.getDeviceDetails""" dev = sxp.child_value(config, 'dev') - if 'ioemu:' in dev: - return (None,{},{}) - - devid = blkif.blkdev_name_to_number(dev) (typ, params) = string.split(sxp.child_value(config, 'uname'), ':', 1) back = { 'dev' : dev, @@ -54,7 +50,13 @@ 'mode' : sxp.child_value(config, 'mode', 'r') } - front = { 'virtual-device' : "%i" % devid } + if 'ioemu:' in dev: + (dummy, dev1) = string.split(dev, ':', 1) + devid = blkif.blkdev_name_to_number(dev1) + front = {} + else: + devid = blkif.blkdev_name_to_number(dev) + front = { 'virtual-device' : "%i" % devid } return (devid, back, front) diff -r ede16886f979 -r c4ac21dc3f16 tools/python/xen/xm/main.py --- a/tools/python/xen/xm/main.py Mon Mar 6 16:09:18 2006 +++ b/tools/python/xen/xm/main.py Mon Mar 6 17:21:35 2006 @@ -396,10 +396,8 @@ if args: dominfo = map(server.xend_domain_vcpuinfo, args) else: - doms = server.xend_list_domains() - dominfo = map( - lambda x: server.xend_domain_vcpuinfo(sxp.child_value(x, 'name')), - doms) + doms = server.xend_list_domains(False) + dominfo = map(server.xend_domain_vcpuinfo, doms) print 'Name ID VCPU CPU State Time(s) CPU Affinity' diff -r ede16886f979 -r c4ac21dc3f16 tools/vtpm_manager/manager/dmictl.c --- a/tools/vtpm_manager/manager/dmictl.c Mon Mar 6 16:09:18 2006 +++ b/tools/vtpm_manager/manager/dmictl.c Mon Mar 6 17:21:35 2006 @@ -74,7 +74,13 @@ close(dmi_res->guest_tx_fh); dmi_res->guest_tx_fh = -1; close(dmi_res->vtpm_tx_fh); dmi_res->vtpm_tx_fh = -1; - + vtpm_globals->connected_dmis--; + + if (vtpm_globals->connected_dmis == 0) { + // No more DMI's connected. Close fifo to prevent a broken pipe. + close(vtpm_globals->guest_rx_fh); + vtpm_globals->guest_rx_fh = -1; + } #ifndef MANUAL_DM_LAUNCH if (dmi_res->dmi_id != VTPM_CTL_DM) { if (dmi_res->dmi_pid != 0) { @@ -118,6 +124,7 @@ status = TPM_BAD_PARAMETER; goto abort_egress; } else { + vtpm_globals->connected_dmis++; // Put this here so we don't count Dom0 BSG_UnpackList( param_buf->bytes, 3, BSG_TYPE_BYTE, &type, BSG_TYPE_UINT32, &domain_id, diff -r ede16886f979 -r c4ac21dc3f16 tools/vtpm_manager/manager/securestorage.c --- a/tools/vtpm_manager/manager/securestorage.c Mon Mar 6 16:09:18 2006 +++ b/tools/vtpm_manager/manager/securestorage.c Mon Mar 6 17:21:35 2006 @@ -307,8 +307,8 @@ TPM_RESULT status=TPM_SUCCESS; int fh, dmis=-1; - BYTE *flat_boot_key, *flat_dmis, *flat_enc; - buffer_t clear_flat_global, enc_flat_global; + BYTE *flat_boot_key=NULL, *flat_dmis=NULL, *flat_enc=NULL; + buffer_t clear_flat_global=NULL_BUF, enc_flat_global=NULL_BUF; UINT32 storageKeySize = buffer_len(&vtpm_globals->storageKeyWrap); UINT32 bootKeySize = buffer_len(&vtpm_globals->bootKeyWrap); struct pack_buf_t storage_key_pack = {storageKeySize, vtpm_globals->storageKeyWrap.bytes}; @@ -328,12 +328,9 @@ sizeof(UINT32) +// storagekeysize storageKeySize, NULL) ); // storage key - flat_dmis_size = (hashtable_count(vtpm_globals->dmi_map) - 1) * // num DMIS (-1 for Dom0) - (sizeof(UINT32) + 2*sizeof(TPM_DIGEST)); // Per DMI info flat_boot_key = (BYTE *) malloc( boot_key_size ); flat_enc = (BYTE *) malloc( sizeof(UINT32) ); - flat_dmis = (BYTE *) malloc( flat_dmis_size ); boot_key_size = BSG_PackList(flat_boot_key, 1, BSG_TPM_SIZE32_DATA, &boot_key_pack); @@ -349,8 +346,12 @@ BSG_PackConst(buffer_len(&enc_flat_global), 4, flat_enc); - // Per DMI values to be saved + // Per DMI values to be saved (if any exit) if (hashtable_count(vtpm_globals->dmi_map) > 0) { + + flat_dmis_size = (hashtable_count(vtpm_globals->dmi_map) - 1) * // num DMIS (-1 for Dom0) + (sizeof(UINT32) + 2*sizeof(TPM_DIGEST)); // Per DMI info + flat_dmis = (BYTE *) malloc( flat_dmis_size ); dmi_itr = hashtable_iterator(vtpm_globals->dmi_map); do { diff -r ede16886f979 -r c4ac21dc3f16 tools/vtpm_manager/manager/vtpm_manager.c --- a/tools/vtpm_manager/manager/vtpm_manager.c Mon Mar 6 16:09:18 2006 +++ b/tools/vtpm_manager/manager/vtpm_manager.c Mon Mar 6 17:21:35 2006 @@ -754,6 +754,7 @@ #ifndef VTPM_MULTI_VM vtpm_globals->vtpm_rx_fh = -1; vtpm_globals->guest_rx_fh = -1; + vtpm_globals->connected_dmis = 0; #endif if ((vtpm_globals->dmi_map = create_hashtable(10, hashfunc32, equals32)) == NULL){ status = TPM_FAIL; diff -r ede16886f979 -r c4ac21dc3f16 tools/vtpm_manager/manager/vtpmpriv.h --- a/tools/vtpm_manager/manager/vtpmpriv.h Mon Mar 6 16:09:18 2006 +++ b/tools/vtpm_manager/manager/vtpmpriv.h Mon Mar 6 17:21:35 2006 @@ -98,6 +98,7 @@ #ifndef VTPM_MULTI_VM int vtpm_rx_fh; int guest_rx_fh; + int connected_dmis; // Used to close guest_rx when no dmis are connected pid_t master_pid; #endif diff -r ede16886f979 -r c4ac21dc3f16 tools/xenstore/Makefile --- a/tools/xenstore/Makefile Mon Mar 6 16:09:18 2006 +++ b/tools/xenstore/Makefile Mon Mar 6 17:21:35 2006 @@ -27,21 +27,27 @@ CLIENTS += xenstore-write CLIENTS_OBJS := $(patsubst xenstore-%,xenstore_%.o,$(CLIENTS)) -all: libxenstore.so xenstored $(CLIENTS) xs_tdb_dump xenstore-ls +all: libxenstore.so xenstored $(CLIENTS) xs_tdb_dump xenstore-control xenstore-ls + +test_interleaved_transactions: test_interleaved_transactions.o + $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -L. -lxenstore -o $@ testcode: xs_test xenstored_test xs_random -xenstored: xenstored_core.o xenstored_watch.o xenstored_domain.o xenstored_transaction.o xs_lib.o talloc.o utils.o tdb.o +xenstored: xenstored_core.o xenstored_watch.o xenstored_domain.o xenstored_transaction.o xs_lib.o talloc.o utils.o tdb.o hashtable.o $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -lxenctrl -o $@ $(CLIENTS): xenstore-%: xenstore_%.o libxenstore.so - $(LINK.o) $< $(LOADLIBES) $(LDLIBS) -lxenctrl -L. -lxenstore -o $@ + $(LINK.o) $< $(LOADLIBES) $(LDLIBS) -L. -lxenstore -o $@ $(CLIENTS_OBJS): xenstore_%.o: xenstore_client.c $(COMPILE.c) -DCLIENT_$(*F) -o $@ $< +xenstore-control: xenstore_control.o libxenstore.so + $(LINK.o) $< $(LOADLIBES) $(LDLIBS) -L. -lxenstore -o $@ + xenstore-ls: xsls.o libxenstore.so - $(LINK.o) $< $(LOADLIBES) $(LDLIBS) -lxenctrl -L. -lxenstore -o $@ + $(LINK.o) $< $(LOADLIBES) $(LDLIBS) -L. -lxenstore -o $@ xenstored_test: xenstored_core_test.o xenstored_watch_test.o xenstored_domain_test.o xenstored_transaction_test.o xs_lib.o talloc_test.o fake_libxc.o utils.o tdb.o $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@ @@ -77,7 +83,8 @@ clean: testsuite-clean rm -f *.o *.opic *.so rm -f xenstored xs_random xs_stress xs_crashme - rm -f xs_test xenstored_test xs_tdb_dump xenstore-ls $(CLIENTS) + rm -f xs_test xenstored_test xs_tdb_dump xenstore-control xenstore-ls + rm -f $(CLIENTS) $(RM) $(PROG_DEP) print-dir: @@ -129,7 +136,7 @@ tarball: clean cd .. && tar -c -j -v -h -f xenstore.tar.bz2 xenstore/ -install: libxenstore.so xenstored xenstore-ls $(CLIENTS) +install: all $(INSTALL_DIR) -p $(DESTDIR)/var/run/xenstored $(INSTALL_DIR) -p $(DESTDIR)/var/lib/xenstored $(INSTALL_DIR) -p $(DESTDIR)/usr/bin @@ -137,6 +144,7 @@ $(INSTALL_DIR) -p $(DESTDIR)/usr/include $(INSTALL_PROG) xenstored $(DESTDIR)/usr/sbin $(INSTALL_PROG) $(CLIENTS) $(DESTDIR)/usr/bin + $(INSTALL_PROG) xenstore-control $(DESTDIR)/usr/bin $(INSTALL_PROG) xenstore-ls $(DESTDIR)/usr/bin $(INSTALL_DIR) -p $(DESTDIR)/usr/$(LIBDIR) $(INSTALL_DATA) libxenstore.so $(DESTDIR)/usr/$(LIBDIR) diff -r ede16886f979 -r c4ac21dc3f16 tools/xenstore/xenstored_core.c --- a/tools/xenstore/xenstored_core.c Mon Mar 6 16:09:18 2006 +++ b/tools/xenstore/xenstored_core.c Mon Mar 6 17:21:35 2006 @@ -51,14 +51,31 @@ #include "xenctrl.h" #include "tdb.h" +#include "hashtable.h" + + extern int eventchn_fd; /* in xenstored_domain.c */ -static bool verbose; +static bool verbose = false; LIST_HEAD(connections); static int tracefd = -1; +static bool recovery = true; +static bool remove_local = true; static int reopen_log_pipe[2]; static char *tracefile = NULL; static TDB_CONTEXT *tdb_ctx; + +static void corrupt(struct connection *conn, const char *fmt, ...); +static void check_store(); + +#define log(...) \ + do { \ + char *s = talloc_asprintf(NULL, __VA_ARGS__); \ + trace("%s\n", s); \ + syslog(LOG_ERR, "%s", s); \ + talloc_free(s); \ + } while (0) + #ifdef TESTING static bool failtest = false; @@ -103,33 +120,6 @@ #endif /* TESTING */ #include "xenstored_test.h" - -/* FIXME: Ideally, this should never be called. Some can be eliminated. */ -/* Something is horribly wrong: shutdown immediately. */ -void __attribute__((noreturn)) corrupt(struct connection *conn, - const char *fmt, ...) -{ - va_list arglist; - char *str; - int saved_errno = errno; - - va_start(arglist, fmt); - str = talloc_vasprintf(NULL, fmt, arglist); - va_end(arglist); - - trace("xenstored corruption: connection id %i: err %s: %s", - conn ? (int)conn->id : -1, strerror(saved_errno), str); - eprintf("xenstored corruption: connection id %i: err %s: %s", - conn ? (int)conn->id : -1, strerror(saved_errno), str); -#ifdef TESTING - /* Allow them to attach debugger. */ - sleep(30); -#endif - syslog(LOG_DAEMON, - "xenstored corruption: connection id %i: err %s: %s", - conn ? (int)conn->id : -1, strerror(saved_errno), str); - _exit(2); -} TDB_CONTEXT *tdb_context(struct connection *conn) { @@ -216,8 +206,9 @@ now = time(NULL); tm = localtime(&now); - trace("%s %p %02d:%02d:%02d %s (", prefix, conn, - tm->tm_hour, tm->tm_min, tm->tm_sec, + trace("%s %p %04d%02d%02d %02d:%02d:%02d %s (", prefix, conn, + tm->tm_year + 1900, tm->tm_mon + 1, + tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, sockmsg_string(data->hdr.msg.type)); for (i = 0; i < data->hdr.msg.len; i++) @@ -415,16 +406,19 @@ TDB_DATA key, data; uint32_t *p; struct node *node; + TDB_CONTEXT * context = tdb_context(conn); key.dptr = (void *)name; key.dsize = strlen(name); - data = tdb_fetch(tdb_context(conn), key); + data = tdb_fetch(context, key); if (data.dptr == NULL) { - if (tdb_error(tdb_context(conn)) == TDB_ERR_NOEXIST) + if (tdb_error(context) == TDB_ERR_NOEXIST) errno = ENOENT; - else + else { + log("TDB error on read: %s", tdb_errorstr(context)); errno = EIO; + } return NULL; } @@ -837,8 +831,6 @@ return 0; } -/* Be careful: create heirarchy, put entry in existing parent *last*. - * This helps fsck if we die during this. */ static struct node *create_node(struct connection *conn, const char *name, void *data, unsigned int datalen) @@ -939,8 +931,9 @@ { unsigned int i; - /* Delete self, then delete children. If something goes wrong, - * consistency check will clean up this way. */ + /* Delete self, then delete children. If we crash, then the worst + that can happen is the children will continue to take up space, but + will otherwise be unreachable. */ delete_node_single(conn, node); /* Delete children, too. */ @@ -950,11 +943,17 @@ child = read_node(conn, talloc_asprintf(node, "%s/%s", node->name, node->children + i)); - if (!child) - corrupt(conn, "No child '%s' found", child); - delete_node(conn, child); - } -} + if (child) { + delete_node(conn, child); + } + else { + trace("delete_node: No child '%s/%s' found!\n", + node->name, node->children + i); + /* Skip it, we've already deleted the parent. */ + } + } +} + /* Delete memory using memmove. */ static void memdel(void *mem, unsigned off, unsigned len, unsigned total) @@ -962,6 +961,17 @@ memmove(mem + off, mem + off + len, total - off - len); } + +static bool remove_child_entry(struct connection *conn, struct node *node, + size_t offset) +{ + size_t childlen = strlen(node->children + offset); + memdel(node->children, offset, childlen + 1, node->childlen); + node->childlen -= childlen + 1; + return write_node(conn, node); +} + + static bool delete_child(struct connection *conn, struct node *node, const char *childname) { @@ -969,19 +979,19 @@ for (i = 0; i < node->childlen; i += strlen(node->children+i) + 1) { if (streq(node->children+i, childname)) { - memdel(node->children, i, strlen(childname) + 1, - node->childlen); - node->childlen -= strlen(childname) + 1; - return write_node(conn, node); + return remove_child_entry(conn, node, i); } } corrupt(conn, "Can't find child '%s' in %s", childname, node->name); + return false; } static int _rm(struct connection *conn, struct node *node, const char *name) { - /* Delete from parent first, then if something explodes fsck cleans. */ + /* Delete from parent first, then if we crash, the worst that can + happen is the child will continue to take up space, but will + otherwise be unreachable. */ struct node *parent = read_node(conn, get_parent(name)); if (!parent) { send_error(conn, EINVAL); @@ -1000,10 +1010,12 @@ static void internal_rm(const char *name) { - char *tname = talloc_strdup(talloc_autofree_context(), name); + char *tname = talloc_strdup(NULL, name); struct node *node = read_node(NULL, tname); if (node) _rm(NULL, node, tname); + talloc_free(node); + talloc_free(tname); } @@ -1149,18 +1161,19 @@ case XS_DEBUG: if (streq(in->buffer, "print")) xprintf("debug: %s", in->buffer + get_string(in, 0)); + if (streq(in->buffer, "check")) + check_store(); #ifdef TESTING /* For testing, we allow them to set id. */ if (streq(in->buffer, "setid")) { conn->id = atoi(in->buffer + get_string(in, 0)); - send_ack(conn, XS_DEBUG); } else if (streq(in->buffer, "failtest")) { if (get_string(in, 0) < in->used) srandom(atoi(in->buffer + get_string(in, 0))); - send_ack(conn, XS_DEBUG); failtest = true; } #endif /* TESTING */ + send_ack(conn, XS_DEBUG); break; case XS_WATCH: @@ -1258,7 +1271,7 @@ if (in->hdr.msg.len > PATH_MAX) { #ifndef TESTING - syslog(LOG_DAEMON, "Client tried to feed us %i", + syslog(LOG_ERR, "Client tried to feed us %i", in->hdr.msg.len); #endif goto bad_client; @@ -1425,10 +1438,18 @@ balloon driver will pick up stale entries. In the case of the balloon driver, this can be fatal. */ - char *tlocal = talloc_strdup(talloc_autofree_context(), - "/local"); - internal_rm("/local"); - create_node(NULL, tlocal, NULL, 0); + char *tlocal = talloc_strdup(NULL, "/local"); + + check_store(); + + if (remove_local) { + internal_rm("/local"); + create_node(NULL, tlocal, NULL, 0); + + check_store(); + } + + talloc_free(tlocal); } else { tdb_ctx = tdb_open(tdbname, 7919, TDB_FLAGS, O_RDWR|O_CREAT, @@ -1439,10 +1460,196 @@ manual_node("/", "tool"); manual_node("/tool", "xenstored"); manual_node("/tool/xenstored", NULL); - } - - /* FIXME: Fsck */ -} + + check_store(); + } +} + + +static unsigned int hash_from_key_fn(void *k) +{ + char *str = k; + unsigned int hash = 5381; + char c; + + while ((c = *str++)) + hash = ((hash << 5) + hash) + (unsigned int)c; + + return hash; +} + + +static int keys_equal_fn(void *key1, void *key2) +{ + return 0 == strcmp((char *)key1, (char *)key2); +} + + +static char *child_name(const char *s1, const char *s2) +{ + if (strcmp(s1, "/")) { + return talloc_asprintf(NULL, "%s/%s", s1, s2); + } + else { + return talloc_asprintf(NULL, "/%s", s2); + } +} + + +static void remember_string(struct hashtable *hash, const char *str) +{ + char *k = malloc(strlen(str) + 1); + strcpy(k, str); + hashtable_insert(hash, k, (void *)1); +} + + +/** + * A node has a children field that names the children of the node, separated + * by NULs. We check whether there are entries in there that are duplicated + * (and if so, delete the second one), and whether there are any that do not + * have a corresponding child node (and if so, delete them). Each valid child + * is then recursively checked. + * + * No deleting is performed if the recovery flag is cleared (i.e. -R was + * passed on the command line). + * + * As we go, we record each node in the given reachable hashtable. These + * entries will be used later in clean_store. + */ +static void check_store_(const char *name, struct hashtable *reachable) +{ + struct node *node = read_node(NULL, name); + + if (node) { + size_t i = 0; + + struct hashtable * children = + create_hashtable(16, hash_from_key_fn, keys_equal_fn); + + remember_string(reachable, name); + + while (i < node->childlen) { + size_t childlen = strlen(node->children + i); + char * childname = child_name(node->name, + node->children + i); + struct node *childnode = read_node(NULL, childname); + + if (childnode) { + if (hashtable_search(children, childname)) { + log("check_store: '%s' is duplicated!", + childname); + + if (recovery) { + remove_child_entry(NULL, node, + i); + i -= childlen + 1; + } + } + else { + remember_string(children, childname); + check_store_(childname, reachable); + } + } + else { + log("check_store: No child '%s' found!\n", + childname); + + if (recovery) { + remove_child_entry(NULL, node, i); + i -= childlen + 1; + } + } + + talloc_free(childnode); + talloc_free(childname); + i += childlen + 1; + } + + hashtable_destroy(children, 0 /* Don't free values (they are + all (void *)1) */); + talloc_free(node); + } + else { + /* Impossible, because no database should ever be without the + root, and otherwise, we've just checked in our caller + (which made a recursive call to get here). */ + + log("check_store: No child '%s' found: impossible!", name); + } +} + + +/** + * Helper to clean_store below. + */ +static int clean_store_(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA val, + void *private) +{ + struct hashtable *reachable = private; + char * name = talloc_strndup(NULL, key.dptr, key.dsize); + + if (!hashtable_search(reachable, name)) { + log("clean_store: '%s' is orphaned!", name); + if (recovery) { + tdb_delete(tdb, key); + } + } + + talloc_free(name); + + return 0; +} + + +/** + * Given the list of reachable nodes, iterate over the whole store, and + * remove any that were not reached. + */ +static void clean_store(struct hashtable *reachable) +{ + tdb_traverse(tdb_ctx, &clean_store_, reachable); +} + + +static void check_store() +{ + char * root = talloc_strdup(NULL, "/"); + struct hashtable * reachable = + create_hashtable(16, hash_from_key_fn, keys_equal_fn); + + log("Checking store ..."); + check_store_(root, reachable); + clean_store(reachable); + log("Checking store complete."); + + hashtable_destroy(reachable, 0 /* Don't free values (they are all + (void *)1) */); + talloc_free(root); +} + + +/* Something is horribly wrong: check the store. */ +static void corrupt(struct connection *conn, const char *fmt, ...) +{ + va_list arglist; + char *str; + int saved_errno = errno; + + va_start(arglist, fmt); + str = talloc_vasprintf(NULL, fmt, arglist); + va_end(arglist); + + log("corruption detected by connection %i: err %s: %s", + conn ? (int)conn->id : -1, strerror(saved_errno), str); + +#ifdef TESTING + /* Allow them to attach debugger. */ + sleep(30); +#endif + check_store(); +} + static void write_pidfile(const char *pidfile) { @@ -1506,6 +1713,9 @@ " --no-fork to request that the daemon does not fork,\n" " --output-pid to request that the pid of the daemon is output,\n" " --trace-file <file> giving the file for logging, and\n" +" --no-recovery to request that no recovery should be attempted when\n" +" the store is corrupted (debug only),\n" +" --preserve-local to request that /local is preserved on start-up,\n" " --verbose to request verbose execution.\n"); } @@ -1517,6 +1727,8 @@ { "no-fork", 0, NULL, 'N' }, { "output-pid", 0, NULL, 'P' }, { "trace-file", 1, NULL, 'T' }, + { "no-recovery", 0, NULL, 'R' }, + { "preserve-local", 0, NULL, 'L' }, { "verbose", 0, NULL, 'V' }, { NULL, 0, NULL, 0 } }; @@ -1532,7 +1744,7 @@ bool no_domain_init = false; const char *pidfile = NULL; - while ((opt = getopt_long(argc, argv, "DF:HNPT:V", options, + while ((opt = getopt_long(argc, argv, "DF:HNPT:RLV", options, NULL)) != -1) { switch (opt) { case 'D': @@ -1550,6 +1762,12 @@ case 'P': outputpid = true; break; + case 'R': + recovery = false; + break; + case 'L': + remove_local = false; + break; case 'T': tracefile = optarg; break; diff -r ede16886f979 -r c4ac21dc3f16 tools/xenstore/xenstored_core.h --- a/tools/xenstore/xenstored_core.h Mon Mar 6 16:09:18 2006 +++ b/tools/xenstore/xenstored_core.h Mon Mar 6 17:21:35 2006 @@ -148,10 +148,6 @@ /* Replace the tdb: required for transaction code */ bool replace_tdb(const char *newname, TDB_CONTEXT *newtdb); -/* Fail due to excessive corruption, capitalist pigdogs! */ -void __attribute__((noreturn)) corrupt(struct connection *conn, - const char *fmt, ...); - struct connection *new_connection(connwritefn_t *write, connreadfn_t *read); diff -r ede16886f979 -r c4ac21dc3f16 tools/xenstore/xenstored_domain.c --- a/tools/xenstore/xenstored_domain.c Mon Mar 6 16:09:18 2006 +++ b/tools/xenstore/xenstored_domain.c Mon Mar 6 17:21:35 2006 @@ -27,7 +27,6 @@ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> -#include <paths.h> //#define DEBUG #include "utils.h" @@ -466,21 +465,8 @@ { int rc, fd; evtchn_port_t port; - unsigned long kva; char str[20]; struct domain *dom0; - - fd = open(XENSTORED_PROC_KVA, O_RDONLY); - if (fd == -1) - return -1; - - rc = read(fd, str, sizeof(str)); - if (rc == -1) - goto outfd; - str[rc] = '\0'; - kva = strtoul(str, NULL, 0); - - close(fd); fd = open(XENSTORED_PROC_PORT, O_RDONLY); if (fd == -1) @@ -496,12 +482,12 @@ dom0 = new_domain(NULL, 0, port); - fd = open(_PATH_KMEM, O_RDWR); + fd = open(XENSTORED_PROC_KVA, O_RDWR); if (fd == -1) return -1; dom0->interface = mmap(NULL, getpagesize(), PROT_READ|PROT_WRITE, - MAP_SHARED, fd, kva); + MAP_SHARED, fd, 0); if (dom0->interface == MAP_FAILED) goto outfd; diff -r ede16886f979 -r c4ac21dc3f16 xen/arch/ia64/xen/dom0_ops.c --- a/xen/arch/ia64/xen/dom0_ops.c Mon Mar 6 16:09:18 2006 +++ b/xen/arch/ia64/xen/dom0_ops.c Mon Mar 6 17:21:35 2006 @@ -16,10 +16,11 @@ #include <asm/pdb.h> #include <xen/trace.h> #include <xen/console.h> +#include <xen/guest_access.h> #include <public/sched_ctl.h> #include <asm/vmx.h> -long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op) +long arch_do_dom0_op(dom0_op_t *op, GUEST_HANDLE(dom0_op_t) u_dom0_op) { long ret = 0; @@ -64,7 +65,7 @@ put_domain(d); - copy_to_user(u_dom0_op, op, sizeof(*op)); + copy_to_guest(u_dom0_op, op, 1); } break; @@ -74,7 +75,6 @@ int n,j; int num = op->u.getpageframeinfo2.num; domid_t dom = op->u.getpageframeinfo2.domain; - unsigned long *s_ptr = (unsigned long*) op->u.getpageframeinfo2.array; struct domain *d; unsigned long *l_arr; ret = -ESRCH; @@ -95,7 +95,8 @@ { int k = ((num-n)>GPF2_BATCH)?GPF2_BATCH:(num-n); - if ( copy_from_user(l_arr, &s_ptr[n], k*sizeof(unsigned long)) ) + if ( copy_from_guest_offset(l_arr, op->u.getpageframeinfo2.array, + n, k) ) { ret = -EINVAL; break; @@ -135,7 +136,8 @@ } - if ( copy_to_user(&s_ptr[n], l_arr, k*sizeof(unsigned long)) ) + if ( copy_to_guest_offset(op->u.getpageframeinfo2.array, + n, l_arr, k) ) { ret = -EINVAL; break; @@ -160,7 +162,6 @@ unsigned long start_page = op->u.getmemlist.max_pfns >> 32; unsigned long nr_pages = op->u.getmemlist.max_pfns & 0xffffffff; unsigned long mfn; - unsigned long *buffer = op->u.getmemlist.buffer; ret = -EINVAL; if ( d != NULL ) @@ -180,16 +181,16 @@ { mfn = gmfn_to_mfn_foreign(d, i); - if ( put_user(mfn, buffer) ) + if ( copy_to_guest_offset(op->u.getmemlist.buffer, + i - start_page, &mfn, 1) ) { ret = -EFAULT; break; } - buffer++; } op->u.getmemlist.num_pfns = i - start_page; - copy_to_user(u_dom0_op, op, sizeof(*op)); + copy_to_guest(u_dom0_op, op, 1); put_domain(d); } @@ -211,7 +212,7 @@ memset(pi->hw_cap, 0, sizeof(pi->hw_cap)); //memcpy(pi->hw_cap, boot_cpu_data.x86_capability, NCAPINTS*4); ret = 0; - if ( copy_to_user(u_dom0_op, op, sizeof(*op)) ) + if ( copy_to_guest(u_dom0_op, op, 1) ) ret = -EFAULT; } break; diff -r ede16886f979 -r c4ac21dc3f16 xen/arch/ia64/xen/xensetup.c --- a/xen/arch/ia64/xen/xensetup.c Mon Mar 6 16:09:18 2006 +++ b/xen/arch/ia64/xen/xensetup.c Mon Mar 6 17:21:35 2006 @@ -12,7 +12,7 @@ #include <xen/sched.h> #include <xen/mm.h> #include <public/version.h> -//#include <xen/delay.h> +#include <xen/gdbstub.h> #include <xen/compile.h> #include <xen/console.h> #include <xen/serial.h> @@ -341,6 +341,8 @@ printk("Brought up %ld CPUs\n", (long)num_online_cpus()); smp_cpus_done(max_cpus); #endif + + initialise_gdb(); /* could be moved earlier */ do_initcalls(); printk("About to call sort_main_extable()\n"); diff -r ede16886f979 -r c4ac21dc3f16 xen/arch/x86/boot/mkelf32.c --- a/xen/arch/x86/boot/mkelf32.c Mon Mar 6 16:09:18 2006 +++ b/xen/arch/x86/boot/mkelf32.c Mon Mar 6 17:21:35 2006 @@ -244,8 +244,8 @@ inimage = argv[1]; outimage = argv[2]; - loadbase = strtoull(argv[3], NULL, 16); - final_exec_addr = strtoul(argv[4], NULL, 16); + loadbase = strtoul(argv[3], NULL, 16); + final_exec_addr = strtoull(argv[4], NULL, 16); infd = open(inimage, O_RDONLY); if ( infd == -1 ) diff -r ede16886f979 -r c4ac21dc3f16 xen/arch/x86/dom0_ops.c --- a/xen/arch/x86/dom0_ops.c Mon Mar 6 16:09:18 2006 +++ b/xen/arch/x86/dom0_ops.c Mon Mar 6 17:21:35 2006 @@ -10,6 +10,7 @@ #include <xen/types.h> #include <xen/lib.h> #include <xen/mm.h> +#include <xen/guest_access.h> #include <public/dom0_ops.h> #include <xen/sched.h> #include <xen/event.h> @@ -48,7 +49,7 @@ (void)rdmsr_safe(msr_addr, msr_lo, msr_hi); } -long arch_do_dom0_op(struct dom0_op *op, struct dom0_op *u_dom0_op) +long arch_do_dom0_op(struct dom0_op *op, GUEST_HANDLE(dom0_op_t) u_dom0_op) { long ret = 0; @@ -75,7 +76,7 @@ op->u.msr.out1 = msr_lo; op->u.msr.out2 = msr_hi; - copy_to_user(u_dom0_op, op, sizeof(*op)); + copy_to_guest(u_dom0_op, op, 1); } ret = 0; } @@ -90,7 +91,7 @@ { ret = shadow_mode_control(d, &op->u.shadow_control); put_domain(d); - copy_to_user(u_dom0_op, op, sizeof(*op)); + copy_to_guest(u_dom0_op, op, 1); } } break; @@ -102,10 +103,11 @@ op->u.add_memtype.nr_mfns, op->u.add_memtype.type, 1); - if (ret > 0) - { - (void)__put_user(0, &u_dom0_op->u.add_memtype.handle); - (void)__put_user(ret, &u_dom0_op->u.add_memtype.reg); + if ( ret > 0 ) + { + op->u.add_memtype.handle = 0; + op->u.add_memtype.reg = ret; + (void)copy_to_guest(u_dom0_op, op, 1); ret = 0; } } @@ -136,9 +138,10 @@ if ( op->u.read_memtype.reg < num_var_ranges ) { mtrr_if->get(op->u.read_memtype.reg, &mfn, &nr_mfns, &type); - (void)__put_user(mfn, &u_dom0_op->u.read_memtype.mfn); - (void)__put_user(nr_mfns, &u_dom0_op->u.read_memtype.nr_mfns); - (void)__put_user(type, &u_dom0_op->u.read_memtype.type); + op->u.read_memtype.mfn = mfn; + op->u.read_memtype.nr_mfns = nr_mfns; + op->u.read_memtype.type = type; + (void)copy_to_guest(u_dom0_op, op, 1); ret = 0; } } @@ -147,7 +150,7 @@ case DOM0_MICROCODE: { extern int microcode_update(void *buf, unsigned long len); - ret = microcode_update(op->u.microcode.data, op->u.microcode.length); + ret = microcode_update(op->u.microcode.data.p, op->u.microcode.length); } break; @@ -195,7 +198,7 @@ memset(pi->hw_cap, 0, sizeof(pi->hw_cap)); memcpy(pi->hw_cap, boot_cpu_data.x86_capability, NCAPINTS*4); ret = 0; - if ( copy_to_user(u_dom0_op, op, sizeof(*op)) ) + if ( copy_to_guest(u_dom0_op, op, 1) ) ret = -EFAULT; } break; @@ -245,7 +248,7 @@ put_domain(d); - copy_to_user(u_dom0_op, op, sizeof(*op)); + copy_to_guest(u_dom0_op, op, 1); } break; @@ -255,7 +258,6 @@ int n,j; int num = op->u.getpageframeinfo2.num; domid_t dom = op->u.getpageframeinfo2.domain; - unsigned long *s_ptr = (unsigned long*) op->u.getpageframeinfo2.array; struct domain *d; unsigned long *l_arr; ret = -ESRCH; @@ -277,7 +279,8 @@ { int k = ((num-n)>GPF2_BATCH)?GPF2_BATCH:(num-n); - if ( copy_from_user(l_arr, &s_ptr[n], k*sizeof(unsigned long)) ) + if ( copy_from_guest_offset(l_arr, op->u.getpageframeinfo2.array, + n, k) ) { ret = -EINVAL; break; @@ -320,7 +323,8 @@ } - if ( copy_to_user(&s_ptr[n], l_arr, k*sizeof(unsigned long)) ) + if ( copy_to_guest_offset(op->u.getpageframeinfo2.array, + n, l_arr, k) ) { ret = -EINVAL; break; @@ -341,7 +345,6 @@ struct domain *d = find_domain_by_id(op->u.getmemlist.domain); unsigned long max_pfns = op->u.getmemlist.max_pfns; unsigned long mfn; - unsigned long *buffer = op->u.getmemlist.buffer; struct list_head *list_ent; ret = -EINVAL; @@ -353,19 +356,20 @@ list_ent = d->page_list.next; for ( i = 0; (i < max_pfns) && (list_ent != &d->page_list); i++ ) { - mfn = page_to_mfn(list_entry(list_ent, struct page_info, list)); - if ( put_user(mfn, buffer) ) + mfn = page_to_mfn(list_entry( + list_ent, struct page_info, list)); + if ( copy_to_guest_offset(op->u.getmemlist.buffer, + i, &mfn, 1) ) { ret = -EFAULT; break; } - buffer++; list_ent = mfn_to_page(mfn)->list.next; } spin_unlock(&d->page_alloc_lock); op->u.getmemlist.num_pfns = i; - copy_to_user(u_dom0_op, op, sizeof(*op)); + copy_to_guest(u_dom0_op, op, 1); put_domain(d); } @@ -401,13 +405,12 @@ entry.start = e820.map[i].addr; entry.end = e820.map[i].addr + e820.map[i].size; entry.is_ram = (e820.map[i].type == E820_RAM); - (void)copy_to_user( - &op->u.physical_memory_map.memory_map[i], - &entry, sizeof(entry)); + (void)copy_to_guest_offset( + op->u.physical_memory_map.memory_map, i, &entry, 1); } op->u.physical_memory_map.nr_map_entries = i; - (void)copy_to_user(u_dom0_op, op, sizeof(*op)); + (void)copy_to_guest(u_dom0_op, op, 1); } break; diff -r ede16886f979 -r c4ac21dc3f16 xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Mon Mar 6 16:09:18 2006 +++ b/xen/arch/x86/hvm/svm/svm.c Mon Mar 6 17:21:35 2006 @@ -247,6 +247,7 @@ void svm_restore_msrs(struct vcpu *v) { } +#endif #define IS_CANO_ADDRESS(add) 1 @@ -297,7 +298,7 @@ return 0; } - HVM_DBG_LOG(DBG_LEVEL_2, "mode_do_msr_read: msr_content: %lx\n", + HVM_DBG_LOG(DBG_LEVEL_2, "mode_do_msr_read: msr_content: %"PRIx64"\n", msr_content); regs->eax = msr_content & 0xffffffff; @@ -311,12 +312,14 @@ struct vcpu *vc = current; struct vmcb_struct *vmcb = vc->arch.hvm_svm.vmcb; - HVM_DBG_LOG(DBG_LEVEL_1, "mode_do_msr_write msr %lx msr_content %lx\n", - regs->ecx, msr_content); + HVM_DBG_LOG(DBG_LEVEL_1, "mode_do_msr_write msr %lx " + "msr_content %"PRIx64"\n", + (unsigned long)regs->ecx, msr_content); switch (regs->ecx) { case MSR_EFER: +#ifdef __x86_64__ if ((msr_content & EFER_LME) ^ test_bit(SVM_CPU_STATE_LME_ENABLED, &vc->arch.hvm_svm.cpu_state)) { @@ -337,6 +340,7 @@ if ((msr_content ^ vmcb->efer) & EFER_LME) msr_content &= ~EFER_LME; /* No update for LME/LMA since it have no effect */ +#endif vmcb->efer = msr_content | EFER_SVME; break; @@ -382,18 +386,6 @@ } return 1; } - -#else -static inline int long_mode_do_msr_read(struct cpu_user_regs *regs) -{ - return 0; -} - -static inline int long_mode_do_msr_write(struct cpu_user_regs *regs) -{ - return 0; -} -#endif void svm_store_cpu_guest_ctrl_regs(struct vcpu *v, unsigned long crs[8]) { @@ -752,7 +744,8 @@ /* unmap IO shared page */ struct domain *d = v->domain; if ( d->arch.hvm_domain.shared_page_va ) - unmap_domain_page((void *)d->arch.hvm_domain.shared_page_va); + unmap_domain_page_global( + (void *)d->arch.hvm_domain.shared_page_va); shadow_direct_map_clean(d); } @@ -937,10 +930,8 @@ if (input == 1) { -#ifndef __x86_64__ if ( hvm_apic_support(v->domain) && !vlapic_global_enabled((VLAPIC(v))) ) -#endif clear_bit(X86_FEATURE_APIC, &edx); #if CONFIG_PAGING_LEVELS < 3 diff -r ede16886f979 -r c4ac21dc3f16 xen/arch/x86/hvm/svm/x86_32/exits.S --- a/xen/arch/x86/hvm/svm/x86_32/exits.S Mon Mar 6 16:09:18 2006 +++ b/xen/arch/x86/hvm/svm/x86_32/exits.S Mon Mar 6 17:21:35 2006 @@ -88,9 +88,6 @@ #define STGI .byte 0x0F,0x01,0xDC #define CLGI .byte 0x0F,0x01,0xDD -#define DO_TSC_OFFSET 0 -#define DO_FPUSAVE 0 - ENTRY(svm_asm_do_launch) sti CLGI @@ -100,36 +97,6 @@ movl %eax, VMCB_rax(%ecx) movl VCPU_svm_hsa_pa(%ebx), %eax VMSAVE - -#if DO_FPUSAVE - mov %cr0, %eax - push %eax - clts - lea VCPU_arch_guest_fpu_ctxt(%ebx), %eax - fxrstor (%eax) - pop %eax - mov %eax, %cr0 -#endif - -#if (DO_TSC_OFFSET) - pushl %edx /* eax and edx get trashed by rdtsc */ - pushl %eax - rdtsc - subl VCPU_svm_vmexit_tsc(%ebx),%eax /* tsc's from */ - sbbl VCPU_svm_vmexit_tsc+4(%ebx),%edx /* last #VMEXIT? */ - subl %eax,VMCB_tsc_offset(%ecx) /* subtract from running TSC_OFFSET */ - sbbl %edx,VMCB_tsc_offset+4(%ecx) - subl $20000,VMCB_tsc_offset(%ecx) /* fudge factor for VMXXX calls */ - sbbl $0,VMCB_tsc_offset+4(%ecx) - - /* - * TODO: may need to add a kludge factor to account for all the cycles - * burned in VMLOAD, VMSAVE, VMRUN... - */ - - popl %eax - popl %edx - #endif movl VCPU_svm_vmcb_pa(%ebx), %eax popl %ebx @@ -150,31 +117,7 @@ VMSAVE /* eax is the only register we're allowed to touch here... */ -#if DO_FPUSAVE - mov %cr0, %eax - push %eax - clts GET_CURRENT(%eax) - lea VCPU_arch_guest_fpu_ctxt(%eax), %eax - fxsave (%eax) - fnclex - pop %eax - mov %eax, %cr0 -#endif - - GET_CURRENT(%eax) - -#if (DO_TSC_OFFSET) - pushl %edx - pushl %ebx - movl %eax,%ebx - rdtsc - movl %eax,VCPU_svm_vmexit_tsc(%ebx) - movl %edx,VCPU_svm_vmexit_tsc+4(%ebx) - movl %ebx,%eax - popl %ebx - popl %edx -#endif movl VCPU_svm_hsa_pa(%eax), %eax VMLOAD diff -r ede16886f979 -r c4ac21dc3f16 xen/arch/x86/hvm/vioapic.c --- a/xen/arch/x86/hvm/vioapic.c Mon Mar 6 16:09:18 2006 +++ b/xen/arch/x86/hvm/vioapic.c Mon Mar 6 17:21:35 2006 @@ -52,20 +52,6 @@ s->flags &= ~IOAPIC_ENABLE_FLAG; } -static void ioapic_dump_redir(hvm_vioapic_t *s, uint8_t entry) -{ - RedirStatus redir = s->redirtbl[entry]; - - HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_dump_redir " - "entry %x vector %x deliver_mod %x destmode %x delivestatus %x " - "polarity %x remote_irr %x trigmod %x mask %x dest_id %x\n", - entry, redir.RedirForm.vector, redir.RedirForm.deliver_mode, - redir.RedirForm.destmode, redir.RedirForm.delivestatus, - redir.RedirForm.polarity, redir.RedirForm.remoteirr, - redir.RedirForm.trigmod, redir.RedirForm.mask, - redir.RedirForm.dest_id); -} - #ifdef HVM_DOMAIN_SAVE_RESTORE void ioapic_save(QEMUFile* f, void* opaque) { @@ -534,7 +520,19 @@ if (!IOAPICEnabled(s) || s->redirtbl[irq].RedirForm.mask) return; - ioapic_dump_redir(s, irq); + HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "hvm_vioapic_set_irq entry %x " + "vector %x deliver_mod %x destmode %x delivestatus %x " + "polarity %x remote_irr %x trigmod %x mask %x dest_id %x\n", + irq, + s->redirtbl[irq].RedirForm.vector, + s->redirtbl[irq].RedirForm.deliver_mode, + s->redirtbl[irq].RedirForm.destmode, + s->redirtbl[irq].RedirForm.delivestatus, + s->redirtbl[irq].RedirForm.polarity, + s->redirtbl[irq].RedirForm.remoteirr, + s->redirtbl[irq].RedirForm.trigmod, + s->redirtbl[irq].RedirForm.mask, + s->redirtbl[irq].RedirForm.dest_id); if (irq >= 0 && irq < IOAPIC_NUM_PINS) { uint32_t bit = 1 << irq; diff -r ede16886f979 -r c4ac21dc3f16 xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Mon Mar 6 16:09:18 2006 +++ b/xen/arch/x86/hvm/vmx/vmx.c Mon Mar 6 17:21:35 2006 @@ -172,7 +172,7 @@ switch(regs->ecx){ case MSR_EFER: msr_content = msr->msr_items[VMX_INDEX_MSR_EFER]; - HVM_DBG_LOG(DBG_LEVEL_2, "EFER msr_content %llx\n", (unsigned long long)msr_content); + HVM_DBG_LOG(DBG_LEVEL_2, "EFER msr_content %"PRIx64"\n", msr_content); if (test_bit(VMX_CPU_STATE_LME_ENABLED, &vc->arch.hvm_vmx.cpu_state)) msr_content |= 1 << _EFER_LME; @@ -202,7 +202,8 @@ default: return 0; } - HVM_DBG_LOG(DBG_LEVEL_2, "mode_do_msr_read: msr_content: %lx\n", msr_content); + HVM_DBG_LOG(DBG_LEVEL_2, "mode_do_msr_read: msr_content: %"PRIx64"\n", + msr_content); regs->eax = msr_content & 0xffffffff; regs->edx = msr_content >> 32; return 1; @@ -216,8 +217,9 @@ struct vmx_msr_state * host_state = &percpu_msr[smp_processor_id()]; - HVM_DBG_LOG(DBG_LEVEL_1, " mode_do_msr_write msr %lx msr_content %lx\n", - regs->ecx, msr_content); + HVM_DBG_LOG(DBG_LEVEL_1, " mode_do_msr_write msr %lx " + "msr_content %"PRIx64"\n", + (unsigned long)regs->ecx, msr_content); switch (regs->ecx){ case MSR_EFER: @@ -882,7 +884,7 @@ __vmread(GUEST_RFLAGS, &eflags); vm86 = eflags & X86_EFLAGS_VM ? 1 : 0; - HVM_DBG_LOG(DBG_LEVEL_1, + HVM_DBG_LOG(DBG_LEVEL_IO, "vmx_io_instruction: vm86 %d, eip=%lx:%lx, " "exit_qualification = %lx", vm86, cs, eip, exit_qualification); diff -r ede16886f979 -r c4ac21dc3f16 xen/arch/x86/io_apic.c --- a/xen/arch/x86/io_apic.c Mon Mar 6 16:09:18 2006 +++ b/xen/arch/x86/io_apic.c Mon Mar 6 17:21:35 2006 @@ -1548,8 +1548,9 @@ */ apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); init_8259A(1); - timer_ack = 1; - enable_8259A_irq(0); + /* XEN: Ripped out the legacy missed-tick logic, so below is not needed. */ + /*timer_ack = 1;*/ + /*enable_8259A_irq(0);*/ pin1 = find_isa_irq_pin(0, mp_INT); apic1 = find_isa_irq_apic(0, mp_INT); @@ -1617,7 +1618,7 @@ printk(KERN_INFO "...trying to set up timer as ExtINT IRQ..."); - timer_ack = 0; + /*timer_ack = 0;*/ init_8259A(0); make_8259A_irq(0); apic_write_around(APIC_LVT0, APIC_DM_EXTINT); @@ -1631,16 +1632,6 @@ printk(" failed :(.\n"); panic("IO-APIC + timer doesn't work! Boot with apic=debug and send a " "report. Then try booting with the 'noapic' option"); -} - -#define NR_IOAPIC_BIOSIDS 256 -static u8 ioapic_biosid_to_apic_enum[NR_IOAPIC_BIOSIDS]; -static void store_ioapic_biosid_mapping(void) -{ - u8 apic; - memset(ioapic_biosid_to_apic_enum, ~0, NR_IOAPIC_BIOSIDS); - for ( apic = 0; apic < nr_ioapics; apic++ ) - ioapic_biosid_to_apic_enum[mp_ioapics[apic].mpc_apicid] = apic; } /* @@ -1654,8 +1645,6 @@ void __init setup_IO_APIC(void) { - store_ioapic_biosid_mapping(); - enable_IO_APIC(); if (acpi_ioapic) @@ -1839,50 +1828,45 @@ #endif /*CONFIG_ACPI_BOOT*/ - -int ioapic_guest_read(int apicid, int address, u32 *pval) -{ - u32 val; - int apicenum; - union IO_APIC_reg_00 reg_00; +static int ioapic_physbase_to_id(unsigned long physbase) +{ + int apic; + for ( apic = 0; apic < nr_ioapics; apic++ ) + if ( mp_ioapics[apic].mpc_apicaddr == physbase ) + return apic; + return -EINVAL; +} + +int ioapic_guest_read(unsigned long physbase, unsigned int reg, u32 *pval) +{ + int apic; unsigned long flags; - if ( (apicid >= NR_IOAPIC_BIOSIDS) || - ((apicenum = ioapic_biosid_to_apic_enum[apicid]) >= nr_ioapics) ) - return -EINVAL; + if ( (apic = ioapic_physbase_to_id(physbase)) < 0 ) + return apic; spin_lock_irqsave(&ioapic_lock, flags); - val = io_apic_read(apicenum, address); + *pval = io_apic_read(apic, reg); spin_unlock_irqrestore(&ioapic_lock, flags); - /* Rewrite APIC ID to what the BIOS originally specified. */ - if ( address == 0 ) - { - reg_00.raw = val; - reg_00.bits.ID = apicid; - val = reg_00.raw; - } - - *pval = val; return 0; } -int ioapic_guest_write(int apicid, int address, u32 val) -{ - int apicenum, pin, irq; +int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val) +{ + int apic, pin, irq; struct IO_APIC_route_entry rte = { 0 }; struct irq_pin_list *entry; unsigned long flags; - if ( (apicid >= NR_IOAPIC_BIOSIDS) || - ((apicenum = ioapic_biosid_to_apic_enum[apicid]) >= nr_ioapics) ) - return -EINVAL; + if ( (apic = ioapic_physbase_to_id(physbase)) < 0 ) + return apic; /* Only write to the first half of a route entry. */ - if ( (address < 0x10) || (address & 1) ) + if ( (reg < 0x10) || (reg & 1) ) return 0; - pin = (address - 0x10) >> 1; + pin = (reg - 0x10) >> 1; *(u32 *)&rte = val; rte.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS); @@ -1898,7 +1882,7 @@ if ( rte.delivery_mode > dest_LowestPrio ) { printk("ERROR: Attempt to write weird IOAPIC destination mode!\n"); - printk(" APIC=%d/%d, lo-reg=%x\n", apicid, pin, val); + printk(" APIC=%d/%d, lo-reg=%x\n", apic, pin, val); return -EINVAL; } @@ -1923,19 +1907,19 @@ /* Record the pin<->irq mapping. */ for ( entry = &irq_2_pin[irq]; ; entry = &irq_2_pin[entry->next] ) { - if ( (entry->apic == apicenum) && (entry->pin == pin) ) + if ( (entry->apic == apic) && (entry->pin == pin) ) break; if ( !entry->next ) { - add_pin_to_irq(irq, apicenum, pin); + add_pin_to_irq(irq, apic, pin); break; } } } spin_lock_irqsave(&ioapic_lock, flags); - io_apic_write(apicenum, 0x10 + 2 * pin, *(((int *)&rte) + 0)); - io_apic_write(apicenum, 0x11 + 2 * pin, *(((int *)&rte) + 1)); + io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&rte) + 0)); + io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&rte) + 1)); spin_unlock_irqrestore(&ioapic_lock, flags); return 0; diff -r ede16886f979 -r c4ac21dc3f16 xen/arch/x86/microcode.c --- a/xen/arch/x86/microcode.c Mon Mar 6 16:09:18 2006 +++ b/xen/arch/x86/microcode.c Mon Mar 6 17:21:35 2006 @@ -116,7 +116,7 @@ #define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE) /* serialize access to the physical write to MSR 0x79 */ -static spinlock_t microcode_update_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(microcode_update_lock); /* no concurrent ->write()s are allowed on /dev/cpu/microcode */ static DECLARE_MUTEX(microcode_sem); @@ -166,7 +166,8 @@ } wrmsr(MSR_IA32_UCODE_REV, 0, 0); - __asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx"); + /* see notes above for revision 1.07. Apparent chip bug */ + sync_core(); /* get the current revision from MSR 0x8B */ rdmsr(MSR_IA32_UCODE_REV, val[0], uci->rev); pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n", @@ -366,7 +367,7 @@ struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; if (uci->mc == NULL) { - printk(KERN_INFO "microcode: No suitable data for CPU%d\n", cpu_num); + printk(KERN_INFO "microcode: No new microcode data for CPU%d\n", cpu_num); return; } @@ -379,7 +380,9 @@ (unsigned long) uci->mc->bits >> 16 >> 16); wrmsr(MSR_IA32_UCODE_REV, 0, 0); - __asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx"); + /* see notes above for revision 1.07. Apparent chip bug */ + sync_core(); + /* get the current revision from MSR 0x8B */ rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); diff -r ede16886f979 -r c4ac21dc3f16 xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Mon Mar 6 16:09:18 2006 +++ b/xen/arch/x86/mm.c Mon Mar 6 17:21:35 2006 @@ -506,7 +506,6 @@ vaddr <<= PGT_va_shift; rc = get_page_and_type_from_pagenr( l2e_get_pfn(l2e), PGT_l1_page_table | vaddr, d); - #if CONFIG_PAGING_LEVELS == 2 if ( unlikely(!rc) ) rc = get_linear_pagetable(l2e, pfn, d); @@ -3187,8 +3186,8 @@ ptwr_flush(d, PTWR_PT_INACTIVE); /* Read the PTE that maps the page being updated. */ - if (__copy_from_user(&pte, &linear_pg_table[l1_linear_offset(addr)], - sizeof(pte))) + if ( __copy_from_user(&pte, &linear_pg_table[l1_linear_offset(addr)], + sizeof(pte)) ) { MEM_LOG("ptwr_emulate: Cannot read thru linear_pg_table"); return X86EMUL_UNHANDLEABLE; @@ -3198,15 +3197,10 @@ page = mfn_to_page(pfn); /* We are looking only for read-only mappings of p.t. pages. */ - if ( ((l1e_get_flags(pte) & (_PAGE_RW|_PAGE_PRESENT)) != _PAGE_PRESENT) || - ((page->u.inuse.type_info & PGT_type_mask) != PGT_l1_page_table) || - (page_get_owner(page) != d) ) - { - MEM_LOG("ptwr_emulate: Page is mistyped or bad pte " - "(%lx, %" PRtype_info ")", - l1e_get_pfn(pte), page->u.inuse.type_info); - return X86EMUL_UNHANDLEABLE; - } + ASSERT((l1e_get_flags(pte) & (_PAGE_RW|_PAGE_PRESENT)) == _PAGE_PRESENT); + ASSERT((page->u.inuse.type_info & PGT_type_mask) == PGT_l1_page_table); + ASSERT((page->u.inuse.type_info & PGT_count_mask) != 0); + ASSERT(page_get_owner(page) == d); /* Check the new PTE. */ nl1e = l1e_from_intpte(val); @@ -3266,8 +3260,11 @@ unsigned long new, unsigned long new_hi) { - return ptwr_emulated_update( - addr, ((u64)old_hi << 32) | old, ((u64)new_hi << 32) | new, 8, 1); + if ( CONFIG_PAGING_LEVELS == 2 ) + return X86EMUL_UNHANDLEABLE; + else + return ptwr_emulated_update( + addr, ((u64)old_hi << 32) | old, ((u64)new_hi << 32) | new, 8, 1); } static struct x86_mem_emulator ptwr_mem_emulator = { diff -r ede16886f979 -r c4ac21dc3f16 xen/arch/x86/nmi.c --- a/xen/arch/x86/nmi.c Mon Mar 6 16:09:18 2006 +++ b/xen/arch/x86/nmi.c Mon Mar 6 17:21:35 2006 @@ -322,15 +322,9 @@ case X86_VENDOR_INTEL: switch (boot_cpu_data.x86) { case 6: - if (boot_cpu_data.x86_model > 0xd) - return; - setup_p6_watchdog(); break; case 15: - if (boot_cpu_data.x86_model > 0x4) - return; - if (!setup_p4_watchdog()) return; break; diff -r ede16886f979 -r c4ac21dc3f16 xen/arch/x86/physdev.c --- a/xen/arch/x86/physdev.c Mon Mar 6 16:09:18 2006 +++ b/xen/arch/x86/physdev.c Mon Mar 6 17:21:35 2006 @@ -11,8 +11,12 @@ #include <public/xen.h> #include <public/physdev.h> -extern int ioapic_guest_read(int apicid, int address, u32 *pval); -extern int ioapic_guest_write(int apicid, int address, u32 pval); +extern int +ioapic_guest_read( + unsigned long physbase, unsigned int reg, u32 *pval); +extern int +ioapic_guest_write( + unsigned long physbase, unsigned int reg, u32 pval); /* * Demuxing hypercall. @@ -49,7 +53,9 @@ if ( !IS_PRIV(current->domain) ) break; ret = ioapic_guest_read( - op.u.apic_op.apic, op.u.apic_op.offset, &op.u.apic_op.value); + op.u.apic_op.apic_physbase, + op.u.apic_op.reg, + &op.u.apic_op.value); break; case PHYSDEVOP_APIC_WRITE: @@ -57,7 +63,9 @@ if ( !IS_PRIV(current->domain) ) break; ret = ioapic_guest_write( - op.u.apic_op.apic, op.u.apic_op.offset, op.u.apic_op.value); + op.u.apic_op.apic_physbase, + op.u.apic_op.reg, + op.u.apic_op.value); break; case PHYSDEVOP_ASSIGN_VECTOR: diff -r ede16886f979 -r c4ac21dc3f16 xen/arch/x86/setup.c --- a/xen/arch/x86/setup.c Mon Mar 6 16:09:18 2006 +++ b/xen/arch/x86/setup.c Mon Mar 6 17:21:35 2006 @@ -13,6 +13,7 @@ #include <xen/multiboot.h> #include <xen/domain_page.h> #include <xen/compile.h> +#include <xen/gdbstub.h> #include <public/version.h> #include <asm/bitops.h> #include <asm/smp.h> @@ -479,6 +480,8 @@ printk("Brought up %ld CPUs\n", (long)num_online_cpus()); smp_cpus_done(max_cpus); + initialise_gdb(); /* could be moved earlier */ + do_initcalls(); schedulers_start(); diff -r ede16886f979 -r c4ac21dc3f16 xen/arch/x86/shadow.c --- a/xen/arch/x86/shadow.c Mon Mar 6 16:09:18 2006 +++ b/xen/arch/x86/shadow.c Mon Mar 6 17:21:35 2006 @@ -279,8 +279,8 @@ psh_type == PGT_l4_shadow ) /* allocated for PAE PDP page */ page = alloc_domheap_pages(NULL, 0, ALLOC_DOM_DMA); else if ( d->arch.ops->guest_paging_levels == PAGING_L3 && - psh_type == PGT_l3_shadow ) /* allocated for PAE PDP page */ - page = alloc_domheap_pages(NULL, 0, ALLOC_DOM_DMA); + (psh_type == PGT_l3_shadow || psh_type == PGT_l4_shadow) ) + page = alloc_domheap_pages(NULL, 0, ALLOC_DOM_DMA); /* allocated for PAE PDP page */ else page = alloc_domheap_page(NULL); #endif diff -r ede16886f979 -r c4ac21dc3f16 xen/arch/x86/shadow32.c --- a/xen/arch/x86/shadow32.c Mon Mar 6 16:09:18 2006 +++ b/xen/arch/x86/shadow32.c Mon Mar 6 17:21:35 2006 @@ -29,6 +29,7 @@ #include <xen/event.h> #include <xen/sched.h> #include <xen/trace.h> +#include <xen/guest_access.h> #define MFN_PINNED(_x) (mfn_to_page(_x)->u.inuse.type_info & PGT_pinned) #define va_to_l1mfn(_ed, _va) \ @@ -1508,14 +1509,14 @@ d->arch.shadow_fault_count = 0; d->arch.shadow_dirty_count = 0; - if ( (sc->dirty_bitmap == NULL) || + if ( guest_handle_is_null(sc->dirty_bitmap) || (d->arch.shadow_dirty_bitmap == NULL) ) { rc = -EINVAL; break; } - if(sc->pages > d->arch.shadow_dirty_bitmap_size) + if ( sc->pages > d->arch.shadow_dirty_bitmap_size ) sc->pages = d->arch.shadow_dirty_bitmap_size; #define chunk (8*1024) /* Transfer and clear in 1kB chunks for L1 cache. */ @@ -1524,10 +1525,10 @@ int bytes = ((((sc->pages - i) > chunk) ? chunk : (sc->pages - i)) + 7) / 8; - if (copy_to_user( - sc->dirty_bitmap + (i/(8*sizeof(unsigned long))), - d->arch.shadow_dirty_bitmap +(i/(8*sizeof(unsigned long))), - bytes)) + if ( copy_to_guest_offset( + sc->dirty_bitmap, i/(8*sizeof(unsigned long)), + d->arch.shadow_dirty_bitmap +(i/(8*sizeof(unsigned long))), + (bytes+sizeof(unsigned long)-1) / sizeof(unsigned long)) ) { rc = -EINVAL; break; @@ -1544,18 +1545,20 @@ sc->stats.fault_count = d->arch.shadow_fault_count; sc->stats.dirty_count = d->arch.shadow_dirty_count; - if ( (sc->dirty_bitmap == NULL) || + if ( guest_handle_is_null(sc->dirty_bitmap) || (d->arch.shadow_dirty_bitmap == NULL) ) { rc = -EINVAL; break; } - if(sc->pages > d->arch.shadow_dirty_bitmap_size) + if ( sc->pages > d->arch.shadow_dirty_bitmap_size ) sc->pages = d->arch.shadow_dirty_bitmap_size; - if (copy_to_user(sc->dirty_bitmap, - d->arch.shadow_dirty_bitmap, (sc->pages+7)/8)) + if ( copy_to_guest(sc->dirty_bitmap, + d->arch.shadow_dirty_bitmap, + (((sc->pages+7)/8)+sizeof(unsigned long)-1) / + sizeof(unsigned long)) ) { rc = -EINVAL; break; diff -r ede16886f979 -r c4ac21dc3f16 xen/arch/x86/shadow_public.c --- a/xen/arch/x86/shadow_public.c Mon Mar 6 16:09:18 2006 +++ b/xen/arch/x86/shadow_public.c Mon Mar 6 17:21:35 2006 @@ -29,6 +29,7 @@ #include <xen/event.h> #include <xen/sched.h> #include <xen/trace.h> +#include <xen/guest_access.h> #include <asm/shadow_64.h> static int alloc_p2m_table(struct domain *d); @@ -413,7 +414,8 @@ (l3e_get_flags(mpl3e[i]) & _PAGE_PRESENT) ? l2e_from_pfn(l3e_get_pfn(mpl3e[i]), __PAGE_HYPERVISOR) : l2e_empty(); - mpl2e[l2_table_offset(RO_MPT_VIRT_START)] = l2e_empty(); + for ( i = 0; i < (MACHPHYS_MBYTES >> (L2_PAGETABLE_SHIFT - 20)); i++ ) + mpl2e[l2_table_offset(RO_MPT_VIRT_START) + i] = l2e_empty(); v->arch.monitor_table = mk_pagetable(m3mfn << PAGE_SHIFT); /* < 4GB */ v->arch.monitor_vtable = (l2_pgentry_t *) mpl3e; @@ -1266,14 +1268,14 @@ d->arch.shadow_fault_count = 0; d->arch.shadow_dirty_count = 0; - if ( (sc->dirty_bitmap == NULL) || + if ( guest_handle_is_null(sc->dirty_bitmap) || (d->arch.shadow_dirty_bitmap == NULL) ) { rc = -EINVAL; break; } - if(sc->pages > d->arch.shadow_dirty_bitmap_size) + if ( sc->pages > d->arch.shadow_dirty_bitmap_size ) sc->pages = d->arch.shadow_dirty_bitmap_size; #define chunk (8*1024) /* Transfer and clear in 1kB chunks for L1 cache. */ @@ -1282,10 +1284,10 @@ int bytes = ((((sc->pages - i) > chunk) ? chunk : (sc->pages - i)) + 7) / 8; - if (copy_to_user( - sc->dirty_bitmap + (i/(8*sizeof(unsigned long))), + if ( copy_to_guest_offset( + sc->dirty_bitmap, i/(8*sizeof(unsigned long)), d->arch.shadow_dirty_bitmap +(i/(8*sizeof(unsigned long))), - bytes)) + (bytes+sizeof(unsigned long)-1) / sizeof(unsigned long)) ) { rc = -EINVAL; break; @@ -1301,18 +1303,20 @@ sc->stats.fault_count = d->arch.shadow_fault_count; sc->stats.dirty_count = d->arch.shadow_dirty_count; - if ( (sc->dirty_bitmap == NULL) || + if ( guest_handle_is_null(sc->dirty_bitmap) || (d->arch.shadow_dirty_bitmap == NULL) ) { rc = -EINVAL; break; } - if(sc->pages > d->arch.shadow_dirty_bitmap_size) + if ( sc->pages > d->arch.shadow_dirty_bitmap_size ) sc->pages = d->arch.shadow_dirty_bitmap_size; - if (copy_to_user(sc->dirty_bitmap, - d->arch.shadow_dirty_bitmap, (sc->pages+7)/8)) + if ( copy_to_guest(sc->dirty_bitmap, + d->arch.shadow_dirty_bitmap, + (((sc->pages+7)/8)+sizeof(unsigned long)-1) / + sizeof(unsigned long)) ) { rc = -EINVAL; break; diff -r ede16886f979 -r c4ac21dc3f16 xen/arch/x86/time.c --- a/xen/arch/x86/time.c Mon Mar 6 16:09:18 2006 +++ b/xen/arch/x86/time.c Mon Mar 6 17:21:35 2006 @@ -41,7 +41,6 @@ unsigned long cpu_khz; /* CPU clock frequency in kHz. */ unsigned long hpet_address; spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; -int timer_ack = 0; unsigned long volatile jiffies; static u32 wc_sec, wc_nsec; /* UTC time at last 'time update'. */ static spinlock_t wc_lock = SPIN_LOCK_UNLOCKED; @@ -148,16 +147,6 @@ { ASSERT(local_irq_is_enabled()); - if ( timer_ack ) - { - extern spinlock_t i8259A_lock; - spin_lock_irq(&i8259A_lock); - outb(0x0c, 0x20); - /* Ack the IRQ; AEOI will end it automatically. */ - inb(0x20); - spin_unlock_irq(&i8259A_lock); - } - /* Update jiffies counter. */ (*(unsigned long *)&jiffies)++; diff -r ede16886f979 -r c4ac21dc3f16 xen/arch/x86/traps.c --- a/xen/arch/x86/traps.c Mon Mar 6 16:09:18 2006 +++ b/xen/arch/x86/traps.c Mon Mar 6 17:21:35 2006 @@ -1410,7 +1410,13 @@ struct trap_info *dst = current->arch.guest_context.trap_ctxt; long rc = 0; - LOCK_BIGLOCK(current->domain); + /* If no table is presented then clear the entire virtual IDT. */ + if ( traps == NULL ) + { + memset(dst, 0, 256 * sizeof(*dst)); + init_int80_direct_trap(current); + return 0; + } for ( ; ; ) { @@ -1439,8 +1445,6 @@ traps++; } - - UNLOCK_BIGLOCK(current->domain); return rc; } diff -r ede16886f979 -r c4ac21dc3f16 xen/arch/x86/x86_32/domain_page.c --- a/xen/arch/x86/x86_32/domain_page.c Mon Mar 6 16:09:18 2006 +++ b/xen/arch/x86/x86_32/domain_page.c Mon Mar 6 17:21:35 2006 @@ -11,15 +11,40 @@ #include <xen/mm.h> #include <xen/perfc.h> #include <xen/domain_page.h> +#include <xen/shadow.h> #include <asm/current.h> #include <asm/flushtlb.h> #include <asm/hardirq.h> +static inline struct vcpu *mapcache_current_vcpu(void) +{ + struct vcpu *v; + + /* In the common case we use the mapcache of the running VCPU. */ + v = current; + + /* + * If guest_table is NULL, and we are running a paravirtualised guest, + * then it means we are running on the idle domain's page table and must + * therefore use its mapcache. + */ + if ( unlikely(!pagetable_get_pfn(v->arch.guest_table)) && !HVM_DOMAIN(v) ) + { + /* If we really are idling, perform lazy context switch now. */ + if ( (v = idle_vcpu[smp_processor_id()]) == current ) + __sync_lazy_execstate(); + /* We must now be running on the idle page table. */ + ASSERT(read_cr3() == __pa(idle_pg_table)); + } + + return v; +} + void *map_domain_page(unsigned long pfn) { unsigned long va; - unsigned int idx, i, vcpu = current->vcpu_id; - struct domain *d; + unsigned int idx, i, vcpu; + struct vcpu *v; struct mapcache *cache; struct vcpu_maphash_entry *hashent; @@ -27,12 +52,10 @@ perfc_incrc(map_domain_page_count); - /* If we are the idle domain, ensure that we run on our own page tables. */ - d = current->domain; - if ( unlikely(is_idle_domain(d)) ) - __sync_lazy_execstate(); - - cache = &d->arch.mapcache; + v = mapcache_current_vcpu(); + + vcpu = v->vcpu_id; + cache = &v->domain->arch.mapcache; hashent = &cache->vcpu_maphash[vcpu].hash[MAPHASH_HASHFN(pfn)]; if ( hashent->pfn == pfn ) @@ -93,7 +116,8 @@ void unmap_domain_page(void *va) { unsigned int idx; - struct mapcache *cache = ¤t->domain->arch.mapcache; + struct vcpu *v; + struct mapcache *cache; unsigned long pfn; struct vcpu_maphash_entry *hashent; @@ -102,9 +126,13 @@ ASSERT((void *)MAPCACHE_VIRT_START <= va); ASSERT(va < (void *)MAPCACHE_VIRT_END); + v = mapcache_current_vcpu(); + + cache = &v->domain->arch.mapcache; + idx = ((unsigned long)va - MAPCACHE_VIRT_START) >> PAGE_SHIFT; pfn = l1e_get_pfn(cache->l1tab[idx]); - hashent = &cache->vcpu_maphash[current->vcpu_id].hash[MAPHASH_HASHFN(pfn)]; + hashent = &cache->vcpu_maphash[v->vcpu_id].hash[MAPHASH_HASHFN(pfn)]; if ( hashent->idx == idx ) { diff -r ede16886f979 -r c4ac21dc3f16 xen/common/dom0_ops.c --- a/xen/common/dom0_ops.c Mon Mar 6 16:09:18 2006 +++ b/xen/common/dom0_ops.c Mon Mar 6 17:21:35 2006 @@ -17,13 +17,14 @@ #include <xen/trace.h> #include <xen/console.h> #include <xen/iocap.h> +#include <xen/guest_access.h> #include <asm/current.h> #include <public/dom0_ops.h> #include <public/sched_ctl.h> #include <acm/acm_hooks.h> extern long arch_do_dom0_op( - struct dom0_op *op, struct dom0_op *u_dom0_op); + struct dom0_op *op, GUEST_HANDLE(dom0_op_t) u_dom0_op); extern void arch_getdomaininfo_ctxt( struct vcpu *, struct vcpu_guest_context *); @@ -89,7 +90,7 @@ memcpy(info->handle, d->handle, sizeof(xen_domain_handle_t)); } -long do_dom0_op(struct dom0_op *u_dom0_op) +long do_dom0_op(GUEST_HANDLE(dom0_op_t) u_dom0_op) { long ret = 0; struct dom0_op curop, *op = &curop; @@ -99,7 +100,7 @@ if ( !IS_PRIV(current->domain) ) return -EPERM; - if ( copy_from_user(op, u_dom0_op, sizeof(*op)) ) + if ( copy_from_guest(op, u_dom0_op, 1) ) return -EFAULT; if ( op->interface_version != DOM0_INTERFACE_VERSION ) @@ -239,7 +240,7 @@ ret = 0; op->u.createdomain.domain = d->domain_id; - if ( copy_to_user(u_dom0_op, op, sizeof(*op)) ) + if ( copy_to_guest(u_dom0_op, op, 1) ) ret = -EFAULT; } break; @@ -357,7 +358,7 @@ case DOM0_SCHEDCTL: { ret = sched_ctl(&op->u.schedctl); - if ( copy_to_user(u_dom0_op, op, sizeof(*op)) ) + if ( copy_to_guest(u_dom0_op, op, 1) ) ret = -EFAULT; } break; @@ -365,7 +366,7 @@ case DOM0_ADJUSTDOM: { ret = sched_adjdom(&op->u.adjustdom); - if ( copy_to_user(u_dom0_op, op, sizeof(*op)) ) + if ( copy_to_guest(u_dom0_op, op, 1) ) ret = -EFAULT; } break; @@ -398,20 +399,17 @@ getdomaininfo(d, &op->u.getdomaininfo); - if ( copy_to_user(u_dom0_op, op, sizeof(*op)) ) + if ( copy_to_guest(u_dom0_op, op, 1) ) ret = -EFAULT; put_domain(d); } break; - - case DOM0_GETDOMAININFOLIST: { struct domain *d; dom0_getdomaininfo_t info; - dom0_getdomaininfo_t *buffer = op->u.getdomaininfolist.buffer; u32 num_domains = 0; read_lock(&domlist_lock); @@ -432,13 +430,13 @@ put_domain(d); - if ( copy_to_user(buffer, &info, sizeof(dom0_getdomaininfo_t)) ) + if ( copy_to_guest_offset(op->u.getdomaininfolist.buffer, + num_domains, &info, 1) ) { ret = -EFAULT; break; } - buffer++; num_domains++; } @@ -449,7 +447,7 @@ op->u.getdomaininfolist.num_domains = num_domains; - if ( copy_to_user(u_dom0_op, op, sizeof(*op)) ) + if ( copy_to_guest(u_dom0_op, op, 1) ) ret = -EFAULT; } break; @@ -489,12 +487,12 @@ if ( v != current ) vcpu_unpause(v); - if ( copy_to_user(op->u.getvcpucontext.ctxt, c, sizeof(*c)) ) + if ( copy_to_guest(op->u.getvcpucontext.ctxt, c, 1) ) ret = -EFAULT; xfree(c); - if ( copy_to_user(u_dom0_op, op, sizeof(*op)) ) + if ( copy_to_guest(u_dom0_op, op, 1) ) ret = -EFAULT; getvcpucontext_out: @@ -534,7 +532,7 @@ (int)sizeof(op->u.getvcpuinfo.cpumap))); ret = 0; - if ( copy_to_user(u_dom0_op, op, sizeof(*op)) ) + if ( copy_to_guest(u_dom0_op, op, 1) ) ret = -EFAULT; getvcpuinfo_out: @@ -554,7 +552,7 @@ case DOM0_TBUFCONTROL: { ret = tb_control(&op->u.tbufcontrol); - if ( copy_to_user(u_dom0_op, op, sizeof(*op)) ) + if ( copy_to_guest(u_dom0_op, op, 1) ) ret = -EFAULT; } break; @@ -562,10 +560,10 @@ case DOM0_READCONSOLE: { ret = read_console_ring( - &op->u.readconsole.buffer, + op->u.readconsole.buffer, &op->u.readconsole.count, op->u.readconsole.clear); - if ( copy_to_user(u_dom0_op, op, sizeof(*op)) ) + if ( copy_to_guest(u_dom0_op, op, 1) ) ret = -EFAULT; } break; @@ -573,7 +571,7 @@ case DOM0_SCHED_ID: { op->u.sched_id.sched_id = sched_id(); - if ( copy_to_user(u_dom0_op, op, sizeof(*op)) ) + if ( copy_to_guest(u_dom0_op, op, 1) ) ret = -EFAULT; else ret = 0; @@ -678,15 +676,15 @@ { extern int perfc_control(dom0_perfccontrol_t *); ret = perfc_control(&op->u.perfccontrol); - if ( copy_to_user(u_dom0_op, op, sizeof(*op)) ) + if ( copy_to_guest(u_dom0_op, op, 1) ) ret = -EFAULT; } break; #endif default: - ret = arch_do_dom0_op(op,u_dom0_op); - + ret = arch_do_dom0_op(op, u_dom0_op); + break; } spin_unlock(&dom0_lock); diff -r ede16886f979 -r c4ac21dc3f16 xen/common/domain.c --- a/xen/common/domain.c Mon Mar 6 16:09:18 2006 +++ b/xen/common/domain.c Mon Mar 6 17:21:35 2006 @@ -17,6 +17,7 @@ #include <xen/softirq.h> #include <xen/domain_page.h> #include <xen/rangeset.h> +#include <xen/guest_access.h> #include <asm/debugger.h> #include <public/dom0_ops.h> #include <public/sched.h> @@ -380,7 +381,7 @@ domain_pause(d); rc = -EFAULT; - if ( copy_from_user(c, setvcpucontext->ctxt, sizeof(*c)) == 0 ) + if ( copy_from_guest(c, setvcpucontext->ctxt, 1) == 0 ) rc = arch_set_info_guest(v, c); domain_unpause(d); diff -r ede16886f979 -r c4ac21dc3f16 xen/common/gdbstub.c --- a/xen/common/gdbstub.c Mon Mar 6 16:09:18 2006 +++ b/xen/common/gdbstub.c Mon Mar 6 17:21:35 2006 @@ -376,7 +376,6 @@ break; case 'g': /* Read registers */ gdb_arch_read_reg_array(regs, ctx); - ASSERT(!local_irq_is_enabled()); break; case 'G': /* Write registers */ gdb_arch_write_reg_array(regs, ctx->in_buf + 1, ctx); @@ -395,7 +394,6 @@ return 0; } gdb_cmd_read_mem(addr, length, ctx); - ASSERT(!local_irq_is_enabled()); break; case 'M': /* Write memory */ addr = simple_strtoul(ctx->in_buf + 1, &ptr, 16); @@ -477,7 +475,7 @@ { int resume = 0; int r; - unsigned flags; + unsigned long flags; if ( gdb_ctx->serhnd < 0 ) { @@ -506,7 +504,7 @@ if ( !gdb_ctx->connected ) { - printk("GDB connection activated\n"); + printk("GDB connection activated.\n"); gdb_arch_print_state(regs); gdb_ctx->connected = 1; } @@ -522,7 +520,7 @@ /* Shouldn't really do this, but otherwise we stop for no obvious reason, which is Bad */ - printk("Waiting for GDB to attach to Gdb\n"); + printk("Waiting for GDB to attach...\n"); gdb_arch_enter(regs); gdb_ctx->signum = gdb_arch_signal_num(regs, cookie); @@ -535,9 +533,7 @@ while ( resume == 0 ) { - ASSERT(!local_irq_is_enabled()); r = receive_command(gdb_ctx); - ASSERT(!local_irq_is_enabled()); if ( r < 0 ) { dbg_printk("GDB disappeared, trying to resume Xen...\n"); @@ -545,9 +541,7 @@ } else { - ASSERT(!local_irq_is_enabled()); resume = process_command(regs, gdb_ctx); - ASSERT(!local_irq_is_enabled()); } } @@ -561,27 +555,13 @@ return 0; } -/* - * initialization - * XXX TODO - * This should be an explicit call from architecture code. - * initcall is far too late for some early debugging, and only the - * architecture code knows when this call can be made. - */ -static int -initialize_gdb(void) -{ - if ( !strcmp(opt_gdb, "none") ) - return 0; +void +initialise_gdb(void) +{ gdb_ctx->serhnd = serial_parse_handle(opt_gdb); - if ( gdb_ctx->serhnd == -1 ) - panic("Can't parse %s as GDB serial info.\n", opt_gdb); - - printk("Gdb initialised.\n"); - return 0; -} - -__initcall(initialize_gdb); + if ( gdb_ctx->serhnd != -1 ) + printk("GDB stub initialised.\n"); +} /* * Local variables: diff -r ede16886f979 -r c4ac21dc3f16 xen/common/memory.c --- a/xen/common/memory.c Mon Mar 6 16:09:18 2006 +++ b/xen/common/memory.c Mon Mar 6 17:21:35 2006 @@ -31,7 +31,7 @@ static long increase_reservation( struct domain *d, - GUEST_HANDLE(xen_ulong) extent_list, + GUEST_HANDLE(ulong) extent_list, unsigned int nr_extents, unsigned int extent_order, unsigned int flags, @@ -80,7 +80,7 @@ static long populate_physmap( struct domain *d, - GUEST_HANDLE(xen_ulong) extent_list, + GUEST_HANDLE(ulong) extent_list, unsigned int nr_extents, unsigned int extent_order, unsigned int flags, @@ -141,7 +141,7 @@ static long decrease_reservation( struct domain *d, - GUEST_HANDLE(xen_ulong) extent_list, + GUEST_HANDLE(ulong) extent_list, unsigned int nr_extents, unsigned int extent_order, unsigned int flags, diff -r ede16886f979 -r c4ac21dc3f16 xen/common/perfc.c --- a/xen/common/perfc.c Mon Mar 6 16:09:18 2006 +++ b/xen/common/perfc.c Mon Mar 6 17:21:35 2006 @@ -5,9 +5,10 @@ #include <xen/perfc.h> #include <xen/keyhandler.h> #include <xen/spinlock.h> +#include <xen/mm.h> +#include <xen/guest_access.h> #include <public/dom0_ops.h> #include <asm/uaccess.h> -#include <xen/mm.h> #undef PERFCOUNTER #undef PERFCOUNTER_CPU @@ -131,12 +132,12 @@ static dom0_perfc_desc_t perfc_d[NR_PERFCTRS]; static int perfc_init = 0; -static int perfc_copy_info(dom0_perfc_desc_t *desc) +static int perfc_copy_info(GUEST_HANDLE(dom0_perfc_desc_t) desc) { unsigned int i, j; atomic_t *counters = (atomic_t *)&perfcounters; - if ( desc == NULL ) + if ( guest_handle_is_null(desc) ) return 0; /* We only copy the name and array-size information once. */ @@ -196,7 +197,7 @@ } } - return (copy_to_user(desc, perfc_d, NR_PERFCTRS * sizeof(*desc)) ? + return (copy_to_guest(desc, (dom0_perfc_desc_t *)perfc_d, NR_PERFCTRS) ? -EFAULT : 0); } diff -r ede16886f979 -r c4ac21dc3f16 xen/drivers/char/console.c --- a/xen/drivers/char/console.c Mon Mar 6 16:09:18 2006 +++ b/xen/drivers/char/console.c Mon Mar 6 17:21:35 2006 @@ -20,6 +20,7 @@ #include <xen/keyhandler.h> #include <xen/mm.h> #include <xen/delay.h> +#include <xen/guest_access.h> #include <asm/current.h> #include <asm/uaccess.h> #include <asm/debugger.h> @@ -221,9 +222,8 @@ conringc = conringp - CONRING_SIZE; } -long read_console_ring(char **pstr, u32 *pcount, int clear) -{ - char *str = *pstr; +long read_console_ring(GUEST_HANDLE(char) str, u32 *pcount, int clear) +{ unsigned int idx, len, max, sofar, c; unsigned long flags; @@ -239,7 +239,7 @@ len = CONRING_SIZE - idx; if ( (sofar + len) > max ) len = max - sofar; - if ( copy_to_user(str + sofar, &conring[idx], len) ) + if ( copy_to_guest_offset(str, sofar, &conring[idx], len) ) return -EFAULT; sofar += len; c += len; diff -r ede16886f979 -r c4ac21dc3f16 xen/include/asm-x86/hvm/support.h --- a/xen/include/asm-x86/hvm/support.h Mon Mar 6 16:09:18 2006 +++ b/xen/include/asm-x86/hvm/support.h Mon Mar 6 17:21:35 2006 @@ -26,7 +26,11 @@ #include <asm/regs.h> #include <asm/processor.h> +#ifndef NDEBUG #define HVM_DEBUG 1 +#else +#define HVM_DEBUG 0 +#endif #define HVM_DOMAIN(v) ((v)->arch.guest_context.flags & VGCF_HVM_GUEST) @@ -113,7 +117,7 @@ #define DBG_LEVEL_VMMU (1 << 5) #define DBG_LEVEL_VLAPIC (1 << 6) #define DBG_LEVEL_VLAPIC_TIMER (1 << 7) -#define DBG_LEVEL_VLAPIC_INTERRUPT (1 << 7) +#define DBG_LEVEL_VLAPIC_INTERRUPT (1 << 8) #define DBG_LEVEL_IOAPIC (1 << 9) extern unsigned int opt_hvm_debug_level; diff -r ede16886f979 -r c4ac21dc3f16 xen/include/asm-x86/processor.h --- a/xen/include/asm-x86/processor.h Mon Mar 6 16:09:18 2006 +++ b/xen/include/asm-x86/processor.h Mon Mar 6 17:21:35 2006 @@ -352,6 +352,13 @@ outb((reg), 0x22); \ outb((data), 0x23); \ } while (0) + +/* Stop speculative execution */ +static inline void sync_core(void) +{ + int tmp; + asm volatile("cpuid" : "=a" (tmp) : "0" (1) : "ebx","ecx","edx","memory"); +} static always_inline void __monitor(const void *eax, unsigned long ecx, unsigned long edx) diff -r ede16886f979 -r c4ac21dc3f16 xen/include/asm-x86/time.h --- a/xen/include/asm-x86/time.h Mon Mar 6 16:09:18 2006 +++ b/xen/include/asm-x86/time.h Mon Mar 6 17:21:35 2006 @@ -3,8 +3,6 @@ #define __X86_TIME_H__ #include <asm/msr.h> - -extern int timer_ack; extern void calibrate_tsc_bp(void); extern void calibrate_tsc_ap(void); diff -r ede16886f979 -r c4ac21dc3f16 xen/include/public/arch-ia64.h --- a/xen/include/public/arch-ia64.h Mon Mar 6 16:09:18 2006 +++ b/xen/include/public/arch-ia64.h Mon Mar 6 17:21:35 2006 @@ -6,6 +6,28 @@ #ifndef __HYPERVISOR_IF_IA64_H__ #define __HYPERVISOR_IF_IA64_H__ + +#ifdef __XEN__ +#define __DEFINE_GUEST_HANDLE(name, type) \ + typedef struct { type *p; } __guest_handle_ ## name +#else +#define __DEFINE_GUEST_HANDLE(name, type) \ + typedef type * __guest_handle_ ## name +#endif + +#define DEFINE_GUEST_HANDLE(name) __DEFINE_GUEST_HANDLE(name, name) +#define GUEST_HANDLE(name) __guest_handle_ ## name + +#ifndef __ASSEMBLY__ +/* Guest handles for primitive C types. */ +__DEFINE_GUEST_HANDLE(uchar, unsigned char); +__DEFINE_GUEST_HANDLE(uint, unsigned int); +__DEFINE_GUEST_HANDLE(ulong, unsigned long); +DEFINE_GUEST_HANDLE(char); +DEFINE_GUEST_HANDLE(int); +DEFINE_GUEST_HANDLE(long); +DEFINE_GUEST_HANDLE(void); +#endif /* Maximum number of virtual CPUs in multi-processor guests. */ /* WARNING: before changing this, check that shared_info fits on a page */ @@ -298,6 +320,7 @@ arch_initrd_info_t initrd; char cmdline[IA64_COMMAND_LINE_SIZE]; } vcpu_guest_context_t; +DEFINE_GUEST_HANDLE(vcpu_guest_context_t); #endif /* !__ASSEMBLY__ */ diff -r ede16886f979 -r c4ac21dc3f16 xen/include/public/arch-x86_32.h --- a/xen/include/public/arch-x86_32.h Mon Mar 6 16:09:18 2006 +++ b/xen/include/public/arch-x86_32.h Mon Mar 6 17:21:35 2006 @@ -8,6 +8,28 @@ #ifndef __XEN_PUBLIC_ARCH_X86_32_H__ #define __XEN_PUBLIC_ARCH_X86_32_H__ + +#ifdef __XEN__ +#define __DEFINE_GUEST_HANDLE(name, type) \ + typedef struct { type *p; } __guest_handle_ ## name +#else +#define __DEFINE_GUEST_HANDLE(name, type) \ + typedef type * __guest_handle_ ## name +#endif + +#define DEFINE_GUEST_HANDLE(name) __DEFINE_GUEST_HANDLE(name, name) +#define GUEST_HANDLE(name) __guest_handle_ ## name + +#ifndef __ASSEMBLY__ +/* Guest handles for primitive C types. */ +__DEFINE_GUEST_HANDLE(uchar, unsigned char); +__DEFINE_GUEST_HANDLE(uint, unsigned int); +__DEFINE_GUEST_HANDLE(ulong, unsigned long); +DEFINE_GUEST_HANDLE(char); +DEFINE_GUEST_HANDLE(int); +DEFINE_GUEST_HANDLE(long); +DEFINE_GUEST_HANDLE(void); +#endif /* * SEGMENT DESCRIPTOR TABLES @@ -130,6 +152,7 @@ unsigned long failsafe_callback_eip; unsigned long vm_assist; /* VMASST_TYPE_* bitmap */ } vcpu_guest_context_t; +DEFINE_GUEST_HANDLE(vcpu_guest_context_t); typedef struct arch_shared_info { unsigned long max_pfn; /* max pfn that appears in table */ diff -r ede16886f979 -r c4ac21dc3f16 xen/include/public/arch-x86_64.h --- a/xen/include/public/arch-x86_64.h Mon Mar 6 16:09:18 2006 +++ b/xen/include/public/arch-x86_64.h Mon Mar 6 17:21:35 2006 @@ -8,6 +8,28 @@ #ifndef __XEN_PUBLIC_ARCH_X86_64_H__ #define __XEN_PUBLIC_ARCH_X86_64_H__ + +#ifdef __XEN__ +#define __DEFINE_GUEST_HANDLE(name, type) \ + typedef struct { type *p; } __guest_handle_ ## name +#else +#define __DEFINE_GUEST_HANDLE(name, type) \ + typedef type * __guest_handle_ ## name +#endif + +#define DEFINE_GUEST_HANDLE(name) __DEFINE_GUEST_HANDLE(name, name) +#define GUEST_HANDLE(name) __guest_handle_ ## name + +#ifndef __ASSEMBLY__ +/* Guest handles for primitive C types. */ +__DEFINE_GUEST_HANDLE(uchar, unsigned char); +__DEFINE_GUEST_HANDLE(uint, unsigned int); +__DEFINE_GUEST_HANDLE(ulong, unsigned long); +DEFINE_GUEST_HANDLE(char); +DEFINE_GUEST_HANDLE(int); +DEFINE_GUEST_HANDLE(long); +DEFINE_GUEST_HANDLE(void); +#endif /* * SEGMENT DESCRIPTOR TABLES @@ -215,6 +237,7 @@ uint64_t gs_base_kernel; uint64_t gs_base_user; } vcpu_guest_context_t; +DEFINE_GUEST_HANDLE(vcpu_guest_context_t); typedef struct arch_shared_info { unsigned long max_pfn; /* max pfn that appears in table */ diff -r ede16886f979 -r c4ac21dc3f16 xen/include/public/dom0_ops.h --- a/xen/include/public/dom0_ops.h Mon Mar 6 16:09:18 2006 +++ b/xen/include/public/dom0_ops.h Mon Mar 6 17:21:35 2006 @@ -28,18 +28,21 @@ /* IN variables. */ domid_t domain; unsigned long max_pfns; - void *buffer; + GUEST_HANDLE(ulong) buffer; /* OUT variables. */ unsigned long num_pfns; } dom0_getmemlist_t; +DEFINE_GUEST_HANDLE(dom0_getmemlist_t); #define DOM0_SCHEDCTL 6 /* struct sched_ctl_cmd is from sched-ctl.h */ typedef struct sched_ctl_cmd dom0_schedctl_t; +DEFINE_GUEST_HANDLE(dom0_schedctl_t); #define DOM0_ADJUSTDOM 7 /* struct sched_adjdom_cmd is from sched-ctl.h */ typedef struct sched_adjdom_cmd dom0_adjustdom_t; +DEFINE_GUEST_HANDLE(dom0_adjustdom_t); #define DOM0_CREATEDOMAIN 8 typedef struct dom0_createdomain { @@ -50,24 +53,28 @@ /* Identifier for new domain (auto-allocate if zero is specified). */ domid_t domain; } dom0_createdomain_t; +DEFINE_GUEST_HANDLE(dom0_createdomain_t); #define DOM0_DESTROYDOMAIN 9 typedef struct dom0_destroydomain { /* IN variables. */ domid_t domain; } dom0_destroydomain_t; +DEFINE_GUEST_HANDLE(dom0_destroydomain_t); #define DOM0_PAUSEDOMAIN 10 typedef struct dom0_pausedomain { /* IN parameters. */ domid_t domain; } dom0_pausedomain_t; +DEFINE_GUEST_HANDLE(dom0_pausedomain_t); #define DOM0_UNPAUSEDOMAIN 11 typedef struct dom0_unpausedomain { /* IN parameters. */ domid_t domain; } dom0_unpausedomain_t; +DEFINE_GUEST_HANDLE(dom0_unpausedomain_t); #define DOM0_GETDOMAININFO 12 typedef struct dom0_getdomaininfo { @@ -93,6 +100,7 @@ uint32_t ssidref; xen_domain_handle_t handle; } dom0_getdomaininfo_t; +DEFINE_GUEST_HANDLE(dom0_getdomaininfo_t); #define DOM0_SETVCPUCONTEXT 13 typedef struct dom0_setvcpucontext { @@ -100,8 +108,9 @@ domid_t domain; uint32_t vcpu; /* IN/OUT parameters */ - vcpu_guest_context_t *ctxt; + GUEST_HANDLE(vcpu_guest_context_t) ctxt; } dom0_setvcpucontext_t; +DEFINE_GUEST_HANDLE(dom0_setvcpucontext_t); #define DOM0_MSR 15 typedef struct dom0_msr { @@ -115,6 +124,7 @@ uint32_t out1; uint32_t out2; } dom0_msr_t; +DEFINE_GUEST_HANDLE(dom0_msr_t); /* * Set clock such that it would read <secs,nsecs> after 00:00:00 UTC, @@ -127,6 +137,7 @@ uint32_t nsecs; uint64_t system_time; } dom0_settime_t; +DEFINE_GUEST_HANDLE(dom0_settime_t); #define DOM0_GETPAGEFRAMEINFO 18 #define NOTAB 0 /* normal page */ @@ -147,6 +158,7 @@ /* Is the page PINNED to a type? */ uint32_t type; /* see above type defs */ } dom0_getpageframeinfo_t; +DEFINE_GUEST_HANDLE(dom0_getpageframeinfo_t); /* * Read console content from Xen buffer ring. @@ -154,11 +166,12 @@ #define DOM0_READCONSOLE 19 typedef struct dom0_readconsole { /* IN variables. */ - uint32_t clear; /* Non-zero -> clear after reading. */ + uint32_t clear; /* Non-zero -> clear after reading. */ /* IN/OUT variables. */ - char *buffer; /* In: Buffer start; Out: Used buffer start */ - uint32_t count; /* In: Buffer size; Out: Used buffer size */ + GUEST_HANDLE(char) buffer; /* In: Buffer start; Out: Used buffer start */ + uint32_t count; /* In: Buffer size; Out: Used buffer size */ } dom0_readconsole_t; +DEFINE_GUEST_HANDLE(dom0_readconsole_t); /* * Set which physical cpus a vcpu can execute on. @@ -170,6 +183,7 @@ uint32_t vcpu; cpumap_t cpumap; } dom0_setvcpuaffinity_t; +DEFINE_GUEST_HANDLE(dom0_setvcpuaffinity_t); /* Get trace buffers machine base address */ #define DOM0_TBUFCONTROL 21 @@ -189,6 +203,7 @@ unsigned long buffer_mfn; uint32_t size; } dom0_tbufcontrol_t; +DEFINE_GUEST_HANDLE(dom0_tbufcontrol_t); /* * Get physical information about the host machine @@ -204,6 +219,7 @@ unsigned long free_pages; uint32_t hw_cap[8]; } dom0_physinfo_t; +DEFINE_GUEST_HANDLE(dom0_physinfo_t); /* * Get the ID of the current scheduler. @@ -213,6 +229,7 @@ /* OUT variable */ uint32_t sched_id; } dom0_sched_id_t; +DEFINE_GUEST_HANDLE(dom0_sched_id_t); /* * Control shadow pagetables operation @@ -234,17 +251,19 @@ uint32_t dirty_net_count; uint32_t dirty_block_count; } dom0_shadow_control_stats_t; +DEFINE_GUEST_HANDLE(dom0_shadow_control_stats_t); typedef struct dom0_shadow_control { /* IN variables. */ domid_t domain; uint32_t op; - unsigned long *dirty_bitmap; /* pointer to locked buffer */ + GUEST_HANDLE(ulong) dirty_bitmap; /* IN/OUT variables. */ unsigned long pages; /* size of buffer, updated with actual size */ /* OUT variables. */ dom0_shadow_control_stats_t stats; } dom0_shadow_control_t; +DEFINE_GUEST_HANDLE(dom0_shadow_control_t); #define DOM0_SETDOMAINMAXMEM 28 typedef struct dom0_setdomainmaxmem { @@ -252,6 +271,7 @@ domid_t domain; unsigned long max_memkb; } dom0_setdomainmaxmem_t; +DEFINE_GUEST_HANDLE(dom0_setdomainmaxmem_t); #define DOM0_GETPAGEFRAMEINFO2 29 /* batched interface */ typedef struct dom0_getpageframeinfo2 { @@ -259,8 +279,9 @@ domid_t domain; unsigned long num; /* IN/OUT variables. */ - unsigned long *array; + GUEST_HANDLE(ulong) array; } dom0_getpageframeinfo2_t; +DEFINE_GUEST_HANDLE(dom0_getpageframeinfo2_t); /* * Request memory range (@mfn, @mfn+@nr_mfns-1) to have type @type. @@ -279,6 +300,7 @@ uint32_t handle; uint32_t reg; } dom0_add_memtype_t; +DEFINE_GUEST_HANDLE(dom0_add_memtype_t); /* * Tear down an existing memory-range type. If @handle is remembered then it @@ -293,6 +315,7 @@ uint32_t handle; uint32_t reg; } dom0_del_memtype_t; +DEFINE_GUEST_HANDLE(dom0_del_memtype_t); /* Read current type of an MTRR (x86-specific). */ #define DOM0_READ_MEMTYPE 33 @@ -304,6 +327,7 @@ unsigned long nr_mfns; uint32_t type; } dom0_read_memtype_t; +DEFINE_GUEST_HANDLE(dom0_read_memtype_t); /* Interface for controlling Xen software performance counters. */ #define DOM0_PERFCCONTROL 34 @@ -315,20 +339,23 @@ uint32_t nr_vals; /* number of values for this counter */ uint32_t vals[64]; /* array of values */ } dom0_perfc_desc_t; +DEFINE_GUEST_HANDLE(dom0_perfc_desc_t); typedef struct dom0_perfccontrol { /* IN variables. */ uint32_t op; /* DOM0_PERFCCONTROL_OP_??? */ /* OUT variables. */ uint32_t nr_counters; /* number of counters */ - dom0_perfc_desc_t *desc; /* counter information (or NULL) */ + GUEST_HANDLE(dom0_perfc_desc_t) desc; /* counter information (or NULL) */ } dom0_perfccontrol_t; +DEFINE_GUEST_HANDLE(dom0_perfccontrol_t); #define DOM0_MICROCODE 35 typedef struct dom0_microcode { /* IN variables. */ - void *data; /* Pointer to microcode data */ + GUEST_HANDLE(void) data; /* Pointer to microcode data */ uint32_t length; /* Length of microcode data. */ } dom0_microcode_t; +DEFINE_GUEST_HANDLE(dom0_microcode_t); #define DOM0_IOPORT_PERMISSION 36 typedef struct dom0_ioport_permission { @@ -337,6 +364,7 @@ uint32_t nr_ports; /* size of port range */ uint8_t allow_access; /* allow or deny access to range? */ } dom0_ioport_permission_t; +DEFINE_GUEST_HANDLE(dom0_ioport_permission_t); #define DOM0_GETVCPUCONTEXT 37 typedef struct dom0_getvcpucontext { @@ -344,8 +372,9 @@ domid_t domain; /* domain to be affected */ uint32_t vcpu; /* vcpu # */ /* OUT variables. */ - vcpu_guest_context_t *ctxt; + GUEST_HANDLE(vcpu_guest_context_t) ctxt; } dom0_getvcpucontext_t; +DEFINE_GUEST_HANDLE(dom0_getvcpucontext_t); #define DOM0_GETVCPUINFO 43 typedef struct dom0_getvcpuinfo { @@ -360,16 +389,18 @@ uint32_t cpu; /* current mapping */ cpumap_t cpumap; /* allowable mapping */ } dom0_getvcpuinfo_t; +DEFINE_GUEST_HANDLE(dom0_getvcpuinfo_t); #define DOM0_GETDOMAININFOLIST 38 typedef struct dom0_getdomaininfolist { /* IN variables. */ domid_t first_domain; uint32_t max_domains; - dom0_getdomaininfo_t *buffer; + GUEST_HANDLE(dom0_getdomaininfo_t) buffer; /* OUT variables. */ uint32_t num_domains; } dom0_getdomaininfolist_t; +DEFINE_GUEST_HANDLE(dom0_getdomaininfolist_t); #define DOM0_PLATFORM_QUIRK 39 #define QUIRK_NOIRQBALANCING 1 @@ -377,37 +408,44 @@ /* IN variables. */ uint32_t quirk_id; } dom0_platform_quirk_t; +DEFINE_GUEST_HANDLE(dom0_platform_quirk_t); #define DOM0_PHYSICAL_MEMORY_MAP 40 +typedef struct dom0_memory_map_entry { + uint64_t start, end; + uint32_t flags; /* reserved */ + uint8_t is_ram; +} dom0_memory_map_entry_t; +DEFINE_GUEST_HANDLE(dom0_memory_map_entry_t); typedef struct dom0_physical_memory_map { /* IN variables. */ uint32_t max_map_entries; /* OUT variables. */ uint32_t nr_map_entries; - struct dom0_memory_map_entry { - uint64_t start, end; - uint32_t flags; /* reserved */ - uint8_t is_ram; - } *memory_map; + GUEST_HANDLE(dom0_memory_map_entry_t) memory_map; } dom0_physical_memory_map_t; +DEFINE_GUEST_HANDLE(dom0_physical_memory_map_t); #define DOM0_MAX_VCPUS 41 typedef struct dom0_max_vcpus { domid_t domain; /* domain to be affected */ uint32_t max; /* maximum number of vcpus */ } dom0_max_vcpus_t; +DEFINE_GUEST_HANDLE(dom0_max_vcpus_t); #define DOM0_SETDOMAINHANDLE 44 typedef struct dom0_setdomainhandle { domid_t domain; xen_domain_handle_t handle; } dom0_setdomainhandle_t; +DEFINE_GUEST_HANDLE(dom0_setdomainhandle_t); #define DOM0_SETDEBUGGING 45 typedef struct dom0_setdebugging { domid_t domain; uint8_t enable; } dom0_setdebugging_t; +DEFINE_GUEST_HANDLE(dom0_setdebugging_t); #define DOM0_IRQ_PERMISSION 46 typedef struct dom0_irq_permission { @@ -415,6 +453,7 @@ uint8_t pirq; uint8_t allow_access; /* flag to specify enable/disable of IRQ access */ } dom0_irq_permission_t; +DEFINE_GUEST_HANDLE(dom0_irq_permission_t); #define DOM0_IOMEM_PERMISSION 47 typedef struct dom0_iomem_permission { @@ -423,12 +462,14 @@ unsigned long nr_mfns; /* number of pages in range (>0) */ uint8_t allow_access; /* allow (!0) or deny (0) access to range? */ } dom0_iomem_permission_t; +DEFINE_GUEST_HANDLE(dom0_iomem_permission_t); #define DOM0_HYPERCALL_INIT 48 typedef struct dom0_hypercall_init { domid_t domain; /* domain to be affected */ unsigned long mfn; /* machine frame to be initialised */ } dom0_hypercall_init_t; +DEFINE_GUEST_HANDLE(dom0_hypercall_init_t); typedef struct dom0_op { uint32_t cmd; @@ -471,9 +512,10 @@ struct dom0_irq_permission irq_permission; struct dom0_iomem_permission iomem_permission; struct dom0_hypercall_init hypercall_init; - uint8_t pad[128]; + uint8_t pad[128]; } u; } dom0_op_t; +DEFINE_GUEST_HANDLE(dom0_op_t); #endif /* __XEN_PUBLIC_DOM0_OPS_H__ */ diff -r ede16886f979 -r c4ac21dc3f16 xen/include/public/hvm/ioreq.h --- a/xen/include/public/hvm/ioreq.h Mon Mar 6 16:09:18 2006 +++ b/xen/include/public/hvm/ioreq.h Mon Mar 6 17:21:35 2006 @@ -71,8 +71,8 @@ typedef struct { ioreq_t vp_ioreq; /* Event channel port */ - unsigned long vp_eport; /* VMX vcpu uses this to notify DM */ - unsigned long dm_eport; /* DM uses this to notify VMX vcpu */ + unsigned int vp_eport; /* VMX vcpu uses this to notify DM */ + unsigned int dm_eport; /* DM uses this to notify VMX vcpu */ } vcpu_iodata_t; typedef struct { diff -r ede16886f979 -r c4ac21dc3f16 xen/include/public/io/tpmif.h --- a/xen/include/public/io/tpmif.h Mon Mar 6 16:09:18 2006 +++ b/xen/include/public/io/tpmif.h Mon Mar 6 17:21:35 2006 @@ -21,7 +21,7 @@ typedef struct { unsigned long addr; /* Machine address of packet. */ grant_ref_t ref; /* grant table access reference */ - uint16_t id; /* Echoed in response message. */ + uint16_t unused; uint16_t size; /* Packet size in bytes. */ } tpmif_tx_request_t; diff -r ede16886f979 -r c4ac21dc3f16 xen/include/public/memory.h --- a/xen/include/public/memory.h Mon Mar 6 16:09:18 2006 +++ b/xen/include/public/memory.h Mon Mar 6 17:21:35 2006 @@ -29,7 +29,7 @@ * OUT: GMFN bases of extents that were allocated * (NB. This command also updates the mach_to_phys translation table) */ - GUEST_HANDLE(xen_ulong) extent_start; + GUEST_HANDLE(ulong) extent_start; /* Number of extents, and size/alignment of each (2^extent_order pages). */ unsigned long nr_extents; @@ -86,7 +86,7 @@ * any large discontiguities in the machine address space, 2MB gaps in * the machphys table will be represented by an MFN base of zero. */ - GUEST_HANDLE(xen_ulong) extent_start; + GUEST_HANDLE(ulong) extent_start; /* * Number of extents written to the above array. This will be smaller @@ -130,13 +130,13 @@ unsigned long nr_gpfns; /* List of GPFNs to translate. */ - GUEST_HANDLE(xen_ulong) gpfn_list; + GUEST_HANDLE(ulong) gpfn_list; /* * Output list to contain MFN translations. May be the same as the input * list (in which case each input GPFN is overwritten with the output MFN). */ - GUEST_HANDLE(xen_ulong) mfn_list; + GUEST_HANDLE(ulong) mfn_list; } xen_translate_gpfn_list_t; DEFINE_GUEST_HANDLE(xen_translate_gpfn_list_t); diff -r ede16886f979 -r c4ac21dc3f16 xen/include/public/physdev.h --- a/xen/include/public/physdev.h Mon Mar 6 16:09:18 2006 +++ b/xen/include/public/physdev.h Mon Mar 6 17:21:35 2006 @@ -33,8 +33,8 @@ typedef struct physdevop_apic { /* IN */ - uint32_t apic; - uint32_t offset; + unsigned long apic_physbase; + uint32_t reg; /* IN or OUT */ uint32_t value; } physdevop_apic_t; diff -r ede16886f979 -r c4ac21dc3f16 xen/include/public/xen.h --- a/xen/include/public/xen.h Mon Mar 6 16:09:18 2006 +++ b/xen/include/public/xen.h Mon Mar 6 17:21:35 2006 @@ -8,22 +8,6 @@ #ifndef __XEN_PUBLIC_XEN_H__ #define __XEN_PUBLIC_XEN_H__ - -#ifdef __XEN__ -#define DEFINE_GUEST_HANDLE(type) struct __guest_handle_ ## type { type *p; } -#define GUEST_HANDLE(type) struct __guest_handle_ ## type -#else -#define DEFINE_GUEST_HANDLE(type) -#define GUEST_HANDLE(type) type * -#endif - -#ifndef __ASSEMBLY__ -/* Guest handle for unsigned long pointer. Define a name with no whitespace. */ -typedef unsigned long xen_ulong; -DEFINE_GUEST_HANDLE(xen_ulong); -/* Guest handle for arbitrary-type pointer (void *). */ -DEFINE_GUEST_HANDLE(void); -#endif #if defined(__i386__) #include "arch-x86_32.h" @@ -396,8 +380,8 @@ * a. relocated kernel image * b. initial ram disk [mod_start, mod_len] * c. list of allocated page frames [mfn_list, nr_pages] - * d. bootstrap page tables [pt_base, CR3 (x86)] - * e. start_info_t structure [register ESI (x86)] + * d. start_info_t structure [register ESI (x86)] + * e. bootstrap page tables [pt_base, CR3 (x86)] * f. bootstrap stack [register ESP (x86)] * 5. Bootstrap elements are packed together, but each is 4kB-aligned. * 6. The initial ram disk may be omitted. diff -r ede16886f979 -r c4ac21dc3f16 xen/include/xen/console.h --- a/xen/include/xen/console.h Mon Mar 6 16:09:18 2006 +++ b/xen/include/xen/console.h Mon Mar 6 17:21:35 2006 @@ -8,12 +8,13 @@ #define __CONSOLE_H__ #include <xen/spinlock.h> +#include <xen/guest_access.h> extern spinlock_t console_lock; void set_printk_prefix(const char *prefix); -long read_console_ring(char **, u32 *, int); +long read_console_ring(GUEST_HANDLE(char), u32 *, int); void init_console(void); void console_endboot(int disable_vga); diff -r ede16886f979 -r c4ac21dc3f16 xen/include/xen/gdbstub.h --- a/xen/include/xen/gdbstub.h Mon Mar 6 16:09:18 2006 +++ b/xen/include/xen/gdbstub.h Mon Mar 6 17:21:35 2006 @@ -20,6 +20,8 @@ #ifndef __XEN_GDBSTUB_H__ #define __XEN_GDBSTUB_H__ + +#ifdef CRASH_DEBUG /* value <-> char (de)serialzers for arch specific gdb backends */ char hex2char(unsigned long x); @@ -84,6 +86,14 @@ #define SIGALRM 14 #define SIGTERM 15 +void initialise_gdb(void); + +#else + +#define initialise_gdb() ((void)0) + +#endif + #endif /* __XEN_GDBSTUB_H__ */ /* diff -r ede16886f979 -r c4ac21dc3f16 xen/include/xen/guest_access.h --- a/xen/include/xen/guest_access.h Mon Mar 6 16:09:18 2006 +++ b/xen/include/xen/guest_access.h Mon Mar 6 17:21:35 2006 @@ -7,64 +7,17 @@ #ifndef __XEN_GUEST_ACCESS_H__ #define __XEN_GUEST_ACCESS_H__ -#include <asm/uaccess.h> +#include <asm/guest_access.h> -/* Is the guest handle a NULL reference? */ -#define guest_handle_is_null(hnd) ((hnd).p == NULL) - -/* Offset the given guest handle into the array it refers to. */ -#define guest_handle_add_offset(hnd, nr) ((hnd).p += (nr)) - -/* Cast a guest handle to the specified type of handle. */ -#define guest_handle_cast(hnd, type) ({ \ - type *_x = (hnd).p; \ - (GUEST_HANDLE(type)) { _x }; \ -}) - -/* - * Copy an array of objects to guest context via a guest handle. - * Optionally specify an offset into the guest array. - */ -#define copy_to_guest_offset(hnd, off, ptr, nr) ({ \ - const typeof(ptr) _x = (hnd).p; \ - const typeof(ptr) _y = (ptr); \ - copy_to_user(_x+(off), _y, sizeof(*_x)*(nr)); \ -}) #define copy_to_guest(hnd, ptr, nr) \ copy_to_guest_offset(hnd, 0, ptr, nr) -/* - * Copy an array of objects from guest context via a guest handle. - * Optionally specify an offset into the guest array. - */ -#define copy_from_guest_offset(ptr, hnd, off, nr) ({ \ - const typeof(ptr) _x = (hnd).p; \ - const typeof(ptr) _y = (ptr); \ - copy_from_user(_y, _x+(off), sizeof(*_x)*(nr)); \ -}) #define copy_from_guest(ptr, hnd, nr) \ copy_from_guest_offset(ptr, hnd, 0, nr) -/* - * Pre-validate a guest handle. - * Allows use of faster __copy_* functions. - */ -#define guest_handle_okay(hnd, nr) \ - array_access_ok((hnd).p, (nr), sizeof(*(hnd).p)) - -#define __copy_to_guest_offset(hnd, off, ptr, nr) ({ \ - const typeof(ptr) _x = (hnd).p; \ - const typeof(ptr) _y = (ptr); \ - __copy_to_user(_x+(off), _y, sizeof(*_x)*(nr)); \ -}) #define __copy_to_guest(hnd, ptr, nr) \ __copy_to_guest_offset(hnd, 0, ptr, nr) -#define __copy_from_guest_offset(ptr, hnd, off, nr) ({ \ - const typeof(ptr) _x = (hnd).p; \ - const typeof(ptr) _y = (ptr); \ - __copy_from_user(_y, _x+(off), sizeof(*_x)*(nr)); \ -}) #define __copy_from_guest(ptr, hnd, nr) \ __copy_from_guest_offset(ptr, hnd, 0, nr) diff -r ede16886f979 -r c4ac21dc3f16 tools/xenstore/hashtable.c --- /dev/null Mon Mar 6 16:09:18 2006 +++ b/tools/xenstore/hashtable.c Mon Mar 6 17:21:35 2006 @@ -0,0 +1,276 @@ +/* Copyright (C) 2004 Christopher Clark <firstname.lastname@xxxxxxxxxxxx> */ + +#include "hashtable.h" +#include "hashtable_private.h" +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <math.h> +#include <stdint.h> + +/* +Credit for primes table: Aaron Krowne + http://br.endernet.org/~akrowne/ + http://planetmath.org/encyclopedia/GoodHashTablePrimes.html +*/ +static const unsigned int primes[] = { +53, 97, 193, 389, +769, 1543, 3079, 6151, +12289, 24593, 49157, 98317, +196613, 393241, 786433, 1572869, +3145739, 6291469, 12582917, 25165843, +50331653, 100663319, 201326611, 402653189, +805306457, 1610612741 +}; +const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0]); +const unsigned int max_load_factor = 65; /* percentage */ + +/*****************************************************************************/ +struct hashtable * +create_hashtable(unsigned int minsize, + unsigned int (*hashf) (void*), + int (*eqf) (void*,void*)) +{ + struct hashtable *h; + unsigned int pindex, size = primes[0]; + /* Check requested hashtable isn't too large */ + if (minsize > (1u << 30)) return NULL; + /* Enforce size as prime */ + for (pindex=0; pindex < prime_table_length; pindex++) { + if (primes[pindex] > minsize) { size = primes[pindex]; break; } + } + h = (struct hashtable *)malloc(sizeof(struct hashtable)); + if (NULL == h) return NULL; /*oom*/ + h->table = (struct entry **)malloc(sizeof(struct entry*) * size); + if (NULL == h->table) { free(h); return NULL; } /*oom*/ + memset(h->table, 0, size * sizeof(struct entry *)); + h->tablelength = size; + h->primeindex = pindex; + h->entrycount = 0; + h->hashfn = hashf; + h->eqfn = eqf; + h->loadlimit = (unsigned int)(((uint64_t)size * max_load_factor) / 100); + return h; +} + +/*****************************************************************************/ +unsigned int +hash(struct hashtable *h, void *k) +{ + /* Aim to protect against poor hash functions by adding logic here + * - logic taken from java 1.4 hashtable source */ + unsigned int i = h->hashfn(k); + i += ~(i << 9); + i ^= ((i >> 14) | (i << 18)); /* >>> */ + i += (i << 4); + i ^= ((i >> 10) | (i << 22)); /* >>> */ + return i; +} + +/*****************************************************************************/ +static int +hashtable_expand(struct hashtable *h) +{ + /* Double the size of the table to accomodate more entries */ + struct entry **newtable; + struct entry *e; + struct entry **pE; + unsigned int newsize, i, index; + /* Check we're not hitting max capacity */ + if (h->primeindex == (prime_table_length - 1)) return 0; + newsize = primes[++(h->primeindex)]; + + newtable = (struct entry **)malloc(sizeof(struct entry*) * newsize); + if (NULL != newtable) + { + memset(newtable, 0, newsize * sizeof(struct entry *)); + /* This algorithm is not 'stable'. ie. it reverses the list + * when it transfers entries between the tables */ + for (i = 0; i < h->tablelength; i++) { + while (NULL != (e = h->table[i])) { + h->table[i] = e->next; + index = indexFor(newsize,e->h); + e->next = newtable[index]; + newtable[index] = e; + } + } + free(h->table); + h->table = newtable; + } + /* Plan B: realloc instead */ + else + { + newtable = (struct entry **) + realloc(h->table, newsize * sizeof(struct entry *)); + if (NULL == newtable) { (h->primeindex)--; return 0; } + h->table = newtable; + memset(newtable[h->tablelength], 0, newsize - h->tablelength); + for (i = 0; i < h->tablelength; i++) { + for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) { + index = indexFor(newsize,e->h); + if (index == i) + { + pE = &(e->next); + } + else + { + *pE = e->next; + e->next = newtable[index]; + newtable[index] = e; + } + } + } + } + h->tablelength = newsize; + h->loadlimit = (unsigned int) + (((uint64_t)newsize * max_load_factor) / 100); + return -1; +} + +/*****************************************************************************/ +unsigned int +hashtable_count(struct hashtable *h) +{ + return h->entrycount; +} + +/*****************************************************************************/ +int +hashtable_insert(struct hashtable *h, void *k, void *v) +{ + /* This method allows duplicate keys - but they shouldn't be used */ + unsigned int index; + struct entry *e; + if (++(h->entrycount) > h->loadlimit) + { + /* Ignore the return value. If expand fails, we should + * still try cramming just this value into the existing table + * -- we may not have memory for a larger table, but one more + * element may be ok. Next time we insert, we'll try expanding again.*/ + hashtable_expand(h); + } + e = (struct entry *)malloc(sizeof(struct entry)); + if (NULL == e) { --(h->entrycount); return 0; } /*oom*/ + e->h = hash(h,k); + index = indexFor(h->tablelength,e->h); + e->k = k; + e->v = v; + e->next = h->table[index]; + h->table[index] = e; + return -1; +} + +/*****************************************************************************/ +void * /* returns value associated with key */ +hashtable_search(struct hashtable *h, void *k) +{ + struct entry *e; + unsigned int hashvalue, index; + hashvalue = hash(h,k); + index = indexFor(h->tablelength,hashvalue); + e = h->table[index]; + while (NULL != e) + { + /* Check hash value to short circuit heavier comparison */ + if ((hashvalue == e->h) && (h->eqfn(k, e->k))) return e->v; + e = e->next; + } + return NULL; +} + +/*****************************************************************************/ +void * /* returns value associated with key */ +hashtable_remove(struct hashtable *h, void *k) +{ + /* TODO: consider compacting the table when the load factor drops enough, + * or provide a 'compact' method. */ + + struct entry *e; + struct entry **pE; + void *v; + unsigned int hashvalue, index; + + hashvalue = hash(h,k); + index = indexFor(h->tablelength,hash(h,k)); + pE = &(h->table[index]); + e = *pE; + while (NULL != e) + { + /* Check hash value to short circuit heavier comparison */ + if ((hashvalue == e->h) && (h->eqfn(k, e->k))) + { + *pE = e->next; + h->entrycount--; + v = e->v; + freekey(e->k); + free(e); + return v; + } + pE = &(e->next); + e = e->next; + } + return NULL; +} + +/*****************************************************************************/ +/* destroy */ +void +hashtable_destroy(struct hashtable *h, int free_values) +{ + unsigned int i; + struct entry *e, *f; + struct entry **table = h->table; + if (free_values) + { + for (i = 0; i < h->tablelength; i++) + { + e = table[i]; + while (NULL != e) + { f = e; e = e->next; freekey(f->k); free(f->v); free(f); } + } + } + else + { + for (i = 0; i < h->tablelength; i++) + { + e = table[i]; + while (NULL != e) + { f = e; e = e->next; freekey(f->k); free(f); } + } + } + free(h->table); + free(h); +} + +/* + * Copyright (c) 2002, Christopher Clark + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ diff -r ede16886f979 -r c4ac21dc3f16 tools/xenstore/hashtable.h --- /dev/null Mon Mar 6 16:09:18 2006 +++ b/tools/xenstore/hashtable.h Mon Mar 6 17:21:35 2006 @@ -0,0 +1,199 @@ +/* Copyright (C) 2002 Christopher Clark <firstname.lastname@xxxxxxxxxxxx> */ + +#ifndef __HASHTABLE_CWC22_H__ +#define __HASHTABLE_CWC22_H__ + +struct hashtable; + +/* Example of use: + * + * struct hashtable *h; + * struct some_key *k; + * struct some_value *v; + * + * static unsigned int hash_from_key_fn( void *k ); + * static int keys_equal_fn ( void *key1, void *key2 ); + * + * h = create_hashtable(16, hash_from_key_fn, keys_equal_fn); + * k = (struct some_key *) malloc(sizeof(struct some_key)); + * v = (struct some_value *) malloc(sizeof(struct some_value)); + * + * (initialise k and v to suitable values) + * + * if (! hashtable_insert(h,k,v) ) + * { exit(-1); } + * + * if (NULL == (found = hashtable_search(h,k) )) + * { printf("not found!"); } + * + * if (NULL == (found = hashtable_remove(h,k) )) + * { printf("Not found\n"); } + * + */ + +/* Macros may be used to define type-safe(r) hashtable access functions, with + * methods specialized to take known key and value types as parameters. + * + * Example: + * + * Insert this at the start of your file: + * + * DEFINE_HASHTABLE_INSERT(insert_some, struct some_key, struct some_value); + * DEFINE_HASHTABLE_SEARCH(search_some, struct some_key, struct some_value); + * DEFINE_HASHTABLE_REMOVE(remove_some, struct some_key, struct some_value); + * + * This defines the functions 'insert_some', 'search_some' and 'remove_some'. + * These operate just like hashtable_insert etc., with the same parameters, + * but their function signatures have 'struct some_key *' rather than + * 'void *', and hence can generate compile time errors if your program is + * supplying incorrect data as a key (and similarly for value). + * + * Note that the hash and key equality functions passed to create_hashtable + * still take 'void *' parameters instead of 'some key *'. This shouldn't be + * a difficult issue as they're only defined and passed once, and the other + * functions will ensure that only valid keys are supplied to them. + * + * The cost for this checking is increased code size and runtime overhead + * - if performance is important, it may be worth switching back to the + * unsafe methods once your program has been debugged with the safe methods. + * This just requires switching to some simple alternative defines - eg: + * #define insert_some hashtable_insert + * + */ + +/***************************************************************************** + * create_hashtable + + * @name create_hashtable + * @param minsize minimum initial size of hashtable + * @param hashfunction function for hashing keys + * @param key_eq_fn function for determining key equality + * @return newly created hashtable or NULL on failure + */ + +struct hashtable * +create_hashtable(unsigned int minsize, + unsigned int (*hashfunction) (void*), + int (*key_eq_fn) (void*,void*)); + +/***************************************************************************** + * hashtable_insert + + * @name hashtable_insert + * @param h the hashtable to insert into + * @param k the key - hashtable claims ownership and will free on removal + * @param v the value - does not claim ownership + * @return non-zero for successful insertion + * + * This function will cause the table to expand if the insertion would take + * the ratio of entries to table size over the maximum load factor. + * + * This function does not check for repeated insertions with a duplicate key. + * The value returned when using a duplicate key is undefined -- when + * the hashtable changes size, the order of retrieval of duplicate key + * entries is reversed. + * If in doubt, remove before insert. + */ + +int +hashtable_insert(struct hashtable *h, void *k, void *v); + +#define DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \ +int fnname (struct hashtable *h, keytype *k, valuetype *v) \ +{ \ + return hashtable_insert(h,k,v); \ +} + +/***************************************************************************** + * hashtable_search + + * @name hashtable_search + * @param h the hashtable to search + * @param k the key to search for - does not claim ownership + * @return the value associated with the key, or NULL if none found + */ + +void * +hashtable_search(struct hashtable *h, void *k); + +#define DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \ +valuetype * fnname (struct hashtable *h, keytype *k) \ +{ \ + return (valuetype *) (hashtable_search(h,k)); \ +} + +/***************************************************************************** + * hashtable_remove + + * @name hashtable_remove + * @param h the hashtable to remove the item from + * @param k the key to search for - does not claim ownership + * @return the value associated with the key, or NULL if none found + */ + +void * /* returns value */ +hashtable_remove(struct hashtable *h, void *k); + +#define DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \ +valuetype * fnname (struct hashtable *h, keytype *k) \ +{ \ + return (valuetype *) (hashtable_remove(h,k)); \ +} + + +/***************************************************************************** + * hashtable_count + + * @name hashtable_count + * @param h the hashtable + * @return the number of items stored in the hashtable + */ +unsigned int +hashtable_count(struct hashtable *h); + + +/***************************************************************************** + * hashtable_destroy + + * @name hashtable_destroy + * @param h the hashtable + * @param free_values whether to call 'free' on the remaining values + */ + +void +hashtable_destroy(struct hashtable *h, int free_values); + +#endif /* __HASHTABLE_CWC22_H__ */ + +/* + * Copyright (c) 2002, Christopher Clark + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ diff -r ede16886f979 -r c4ac21dc3f16 tools/xenstore/hashtable_private.h --- /dev/null Mon Mar 6 16:09:18 2006 +++ b/tools/xenstore/hashtable_private.h Mon Mar 6 17:21:35 2006 @@ -0,0 +1,85 @@ +/* Copyright (C) 2002, 2004 Christopher Clark <firstname.lastname@xxxxxxxxxxxx> */ + +#ifndef __HASHTABLE_PRIVATE_CWC22_H__ +#define __HASHTABLE_PRIVATE_CWC22_H__ + +#include "hashtable.h" + +/*****************************************************************************/ +struct entry +{ + void *k, *v; + unsigned int h; + struct entry *next; +}; + +struct hashtable { + unsigned int tablelength; + struct entry **table; + unsigned int entrycount; + unsigned int loadlimit; + unsigned int primeindex; + unsigned int (*hashfn) (void *k); + int (*eqfn) (void *k1, void *k2); +}; + +/*****************************************************************************/ +unsigned int +hash(struct hashtable *h, void *k); + +/*****************************************************************************/ +/* indexFor */ +static inline unsigned int +indexFor(unsigned int tablelength, unsigned int hashvalue) { + return (hashvalue % tablelength); +}; + +/* Only works if tablelength == 2^N */ +/*static inline unsigned int +indexFor(unsigned int tablelength, unsigned int hashvalue) +{ + return (hashvalue & (tablelength - 1u)); +} +*/ + +/*****************************************************************************/ +#define freekey(X) free(X) +/*define freekey(X) ; */ + + +/*****************************************************************************/ + +#endif /* __HASHTABLE_PRIVATE_CWC22_H__*/ + +/* + * Copyright (c) 2002, Christopher Clark + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ diff -r ede16886f979 -r c4ac21dc3f16 tools/xenstore/xenstore_control.c --- /dev/null Mon Mar 6 16:09:18 2006 +++ b/tools/xenstore/xenstore_control.c Mon Mar 6 17:21:35 2006 @@ -0,0 +1,35 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "xs.h" + + +int main(int argc, char **argv) +{ + struct xs_handle * xsh; + + if (argc < 2 || + strcmp(argv[1], "check")) + { + fprintf(stderr, + "Usage:\n" + "\n" + " %s check\n" + "\n", argv[0]); + return 2; + } + + xsh = xs_daemon_open(); + + if (xsh == NULL) { + fprintf(stderr, "Failed to contact Xenstored.\n"); + return 1; + } + + xs_debug_command(xsh, argv[1], NULL, 0); + + xs_daemon_close(xsh); + + return 0; +} diff -r ede16886f979 -r c4ac21dc3f16 xen/include/asm-ia64/guest_access.h --- /dev/null Mon Mar 6 16:09:18 2006 +++ b/xen/include/asm-ia64/guest_access.h Mon Mar 6 17:21:35 2006 @@ -0,0 +1,63 @@ +/****************************************************************************** + * guest_access.h + * + * Copyright (c) 2006, K A Fraser + */ + +#ifndef __ASM_IA64_GUEST_ACCESS_H__ +#define __ASM_IA64_GUEST_ACCESS_H__ + +#include <asm/uaccess.h> + +/* Is the guest handle a NULL reference? */ +#define guest_handle_is_null(hnd) ((hnd).p == NULL) + +/* Offset the given guest handle into the array it refers to. */ +#define guest_handle_add_offset(hnd, nr) ((hnd).p += (nr)) + +/* Cast a guest handle to the specified type of handle. */ +#define guest_handle_cast(hnd, type) ({ \ + type *_x = (hnd).p; \ + (GUEST_HANDLE(type)) { _x }; \ +}) + +/* + * Copy an array of objects to guest context via a guest handle, + * specifying an offset into the guest array. + */ +#define copy_to_guest_offset(hnd, off, ptr, nr) ({ \ + const typeof(ptr) _x = (hnd).p; \ + const typeof(ptr) _y = (ptr); \ + copy_to_user(_x+(off), _y, sizeof(*_x)*(nr)); \ +}) + +/* + * Copy an array of objects from guest context via a guest handle, + * specifying an offset into the guest array. + */ +#define copy_from_guest_offset(ptr, hnd, off, nr) ({ \ + const typeof(ptr) _x = (hnd).p; \ + const typeof(ptr) _y = (ptr); \ + copy_from_user(_y, _x+(off), sizeof(*_x)*(nr)); \ +}) + +/* + * Pre-validate a guest handle. + * Allows use of faster __copy_* functions. + */ +#define guest_handle_okay(hnd, nr) \ + array_access_ok((hnd).p, (nr), sizeof(*(hnd).p)) + +#define __copy_to_guest_offset(hnd, off, ptr, nr) ({ \ + const typeof(ptr) _x = (hnd).p; \ + const typeof(ptr) _y = (ptr); \ + __copy_to_user(_x+(off), _y, sizeof(*_x)*(nr)); \ +}) + +#define __copy_from_guest_offset(ptr, hnd, off, nr) ({ \ + const typeof(ptr) _x = (hnd).p; \ + const typeof(ptr) _y = (ptr); \ + __copy_from_user(_y, _x+(off), sizeof(*_x)*(nr)); \ +}) + +#endif /* __ASM_IA64_GUEST_ACCESS_H__ */ diff -r ede16886f979 -r c4ac21dc3f16 xen/include/asm-x86/guest_access.h --- /dev/null Mon Mar 6 16:09:18 2006 +++ b/xen/include/asm-x86/guest_access.h Mon Mar 6 17:21:35 2006 @@ -0,0 +1,63 @@ +/****************************************************************************** + * guest_access.h + * + * Copyright (c) 2006, K A Fraser + */ + +#ifndef __ASM_X86_GUEST_ACCESS_H__ +#define __ASM_X86_GUEST_ACCESS_H__ + +#include <asm/uaccess.h> + +/* Is the guest handle a NULL reference? */ +#define guest_handle_is_null(hnd) ((hnd).p == NULL) + +/* Offset the given guest handle into the array it refers to. */ +#define guest_handle_add_offset(hnd, nr) ((hnd).p += (nr)) + +/* Cast a guest handle to the specified type of handle. */ +#define guest_handle_cast(hnd, type) ({ \ + type *_x = (hnd).p; \ + (GUEST_HANDLE(type)) { _x }; \ +}) + +/* + * Copy an array of objects to guest context via a guest handle, + * specifying an offset into the guest array. + */ +#define copy_to_guest_offset(hnd, off, ptr, nr) ({ \ + const typeof(ptr) _x = (hnd).p; \ + const typeof(ptr) _y = (ptr); \ + copy_to_user(_x+(off), _y, sizeof(*_x)*(nr)); \ +}) + +/* + * Copy an array of objects from guest context via a guest handle, + * specifying an offset into the guest array. + */ +#define copy_from_guest_offset(ptr, hnd, off, nr) ({ \ + const typeof(ptr) _x = (hnd).p; \ + const typeof(ptr) _y = (ptr); \ + copy_from_user(_y, _x+(off), sizeof(*_x)*(nr)); \ +}) + +/* + * Pre-validate a guest handle. + * Allows use of faster __copy_* functions. + */ +#define guest_handle_okay(hnd, nr) \ + array_access_ok((hnd).p, (nr), sizeof(*(hnd).p)) + +#define __copy_to_guest_offset(hnd, off, ptr, nr) ({ \ + const typeof(ptr) _x = (hnd).p; \ + const typeof(ptr) _y = (ptr); \ + __copy_to_user(_x+(off), _y, sizeof(*_x)*(nr)); \ +}) + +#define __copy_from_guest_offset(ptr, hnd, off, nr) ({ \ + const typeof(ptr) _x = (hnd).p; \ + const typeof(ptr) _y = (ptr); \ + __copy_from_user(_y, _x+(off), sizeof(*_x)*(nr)); \ +}) + +#endif /* __ASM_X86_GUEST_ACCESS_H__ */ diff -r ede16886f979 -r c4ac21dc3f16 linux-2.6-xen-sparse/include/xen/public/xenstored.h --- a/linux-2.6-xen-sparse/include/xen/public/xenstored.h Mon Mar 6 16:09:18 2006 +++ /dev/null Mon Mar 6 17:21:35 2006 @@ -1,89 +0,0 @@ -/* - * Simple prototyle Xen Store Daemon providing simple tree-like database. - * 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 _XENSTORED_H -#define _XENSTORED_H - -enum xsd_sockmsg_type -{ - XS_DEBUG, - XS_SHUTDOWN, - XS_DIRECTORY, - XS_READ, - XS_GET_PERMS, - XS_WATCH, - XS_WATCH_ACK, - XS_UNWATCH, - XS_TRANSACTION_START, - XS_TRANSACTION_END, - XS_OP_READ_ONLY = XS_TRANSACTION_END, - XS_INTRODUCE, - XS_RELEASE, - XS_GET_DOMAIN_PATH, - XS_WRITE, - XS_MKDIR, - XS_RM, - XS_SET_PERMS, - XS_WATCH_EVENT, - XS_ERROR, -}; - -#define XS_WRITE_NONE "NONE" -#define XS_WRITE_CREATE "CREATE" -#define XS_WRITE_CREATE_EXCL "CREATE|EXCL" - -/* We hand errors as strings, for portability. */ -struct xsd_errors -{ - int errnum; - const char *errstring; -}; -#define XSD_ERROR(x) { x, #x } -static struct xsd_errors xsd_errors[] __attribute__((unused)) = { - XSD_ERROR(EINVAL), - XSD_ERROR(EACCES), - XSD_ERROR(EEXIST), - XSD_ERROR(EISDIR), - XSD_ERROR(ENOENT), - XSD_ERROR(ENOMEM), - XSD_ERROR(ENOSPC), - XSD_ERROR(EIO), - XSD_ERROR(ENOTEMPTY), - XSD_ERROR(ENOSYS), - XSD_ERROR(EROFS), - XSD_ERROR(EBUSY), - XSD_ERROR(EAGAIN), - XSD_ERROR(EISCONN), -}; -struct xsd_sockmsg -{ - u32 type; - u32 len; /* Length of data following this. */ - - /* Generally followed by nul-terminated string(s). */ -}; - -#endif /* _XENSTORED_H */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |