# HG changeset patch
# User djm@xxxxxxxxxxxxxxx
# Node ID b2f4823b6ff09017e21c0d44f73c58118f50ea46
# Parent 10b1d30d3f66beac5a8275d108461da558c38d1d
# Parent ec4a3f2d060e1dcc137cca136309ca67d46fbb85
Merge (only) xen-ia64-unstable with latest xen-unstable
diff -r 10b1d30d3f66 -r b2f4823b6ff0 .hgignore
--- a/.hgignore Thu Sep 8 15:18:40 2005
+++ b/.hgignore Fri Sep 9 16:30:54 2005
@@ -82,6 +82,7 @@
^tools/blktap/parallax/vdi_validate$
^tools/blktap/parallax/parallax$
^tools/blktap/parallax/blockstored$
+^tools/blktap/ublkback/ublkback$
^tools/blktap/xen/.*$
^tools/check/\..*$
^tools/cmdline/.*$
@@ -141,24 +142,28 @@
^tools/vnet/vnet-module/\.tmp_versions/.*$
^tools/vnet/vnet-module/vnet_module\.mod\..*$
^tools/vnetd/vnetd$
+^tools/vtpm/vtpm*
+^tools/vtpm/tpm_emulator-*
+^tools/vtpm_manager/manager/vtpm_managerd
^tools/web-shutdown\.tap$
^tools/x2d2/minixend$
-^tools/xcs/xcs$
-^tools/xcs/xcsdump$
^tools/xcutils/xc_restore$
^tools/xcutils/xc_save$
^tools/xenstat/xentop/xentop$
^tools/xenstore/testsuite/tmp/.*$
^tools/xenstore/xen$
+^tools/xenstore/xenbus_dev.h$
^tools/xenstore/xenstored$
^tools/xenstore/xenstored_test$
+^tools/xenstore/xenstore-read$
+^tools/xenstore/xenstore-rm$
+^tools/xenstore/xenstore-write$
^tools/xenstore/xs_dom0_test$
^tools/xenstore/xs_random$
^tools/xenstore/xs_stress$
^tools/xenstore/xs_test$
^tools/xenstore/xs_watch_stress$
^tools/xentrace/xentrace$
-^tools/xfrd/xfrd$
^xen/BLOG$
^xen/TAGS$
^xen/arch/x86/asm-offsets\.s$
diff -r 10b1d30d3f66 -r b2f4823b6ff0 Config.mk
--- a/Config.mk Thu Sep 8 15:18:40 2005
+++ b/Config.mk Fri Sep 9 16:30:54 2005
@@ -48,3 +48,4 @@
# Optional components
XENSTAT_XENTOP ?= y
+VTPM_TOOLS ?= n
diff -r 10b1d30d3f66 -r b2f4823b6ff0 Makefile
--- a/Makefile Thu Sep 8 15:18:40 2005
+++ b/Makefile Fri Sep 9 16:30:54 2005
@@ -35,11 +35,11 @@
export pae=y
endif
-.PHONY: all dist install xen tools kernels docs world clean mkpatches
mrproper
+.PHONY: all dist install xen kernels tools docs world clean mkpatches
mrproper
.PHONY: kbuild kdelete kclean
# build and install everything into the standard system directories
-install: install-xen install-tools install-kernels install-docs
+install: install-xen install-kernels install-tools install-docs
build: kernels
$(MAKE) -C xen build
@@ -47,7 +47,7 @@
$(MAKE) -C docs build
# build and install everything into local dist directory
-dist: xen tools kernels docs
+dist: xen kernels tools docs
$(INSTALL_DIR) $(DISTDIR)/check
$(INSTALL_DATA) ./COPYING $(DISTDIR)
$(INSTALL_DATA) ./README $(DISTDIR)
@@ -178,6 +178,8 @@
rm -rf $(D)/usr/share/man/man1/xen*
rm -rf $(D)/usr/share/man/man8/xen*
rm -rf $(D)/usr/lib/xen
+ rm -rf $(D)/etc/hotplug.d/xen-backend
+ rm -rf $(D)/etc/hotplug/xen-backend.agent
# Legacy targets for compatibility
linux24:
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/Makefile
--- a/extras/mini-os/Makefile Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/Makefile Fri Sep 9 16:30:54 2005
@@ -31,16 +31,18 @@
OBJS := $(TARGET_ARCH).o
OBJS += $(patsubst %.c,%.o,$(wildcard *.c))
OBJS += $(patsubst %.c,%.o,$(wildcard lib/*.c))
-
+OBJS += $(patsubst %.c,%.o,$(wildcard xenbus/*.c))
+
HDRS := $(wildcard include/*.h)
HDRS += $(wildcard include/xen/*.h)
default: $(TARGET)
-xen-public:
+links:
[ -e include/xen ] || ln -sf ../../../xen/include/public include/xen
-
-$(TARGET): xen-public $(OBJS)
+ [ -e xenbus/xenstored.h ] || ln -sf ../../../tools/xenstore/xenstored.h
xenbus/xenstored.h
+
+$(TARGET): links $(OBJS)
$(LD) -N -T minios-$(TARGET_ARCH).lds $(OBJS) -o $@.elf
gzip -f -9 -c $@.elf >$@.gz
@@ -55,3 +57,4 @@
%.o: %.S $(HDRS) Makefile
$(CC) $(CFLAGS) -D__ASSEMBLY__ -c $< -o $@
+
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/README
--- a/extras/mini-os/README Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/README Fri Sep 9 16:30:54 2005
@@ -23,13 +23,8 @@
- to build it just type make.
-- copy image.final somewhere where dom0 can access it
+- to start it do the following in domain0 (assuming xend is running)
+ # xm create domain_config
-- in dom0
- # xi_create 16000 test
- <domid>
- # xi_build <domid> image.final 0
- # xi_start <domid>
-
-this prints out a bunch of stuff and then every 1000 timer interrupts the
-system time.
+this starts the kernel and prints out a bunch of stuff and then every
+1000 timer interrupts the system time.
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/events.c
--- a/extras/mini-os/events.c Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/events.c Fri Sep 9 16:30:54 2005
@@ -17,13 +17,13 @@
*/
#include <os.h>
+#include <mm.h>
#include <hypervisor.h>
#include <events.h>
#include <lib.h>
-#include <xen/event_channel.h>
static ev_action_t ev_actions[NR_EVS];
-void default_handler(u32 port, struct pt_regs *regs);
+void default_handler(int port, struct pt_regs *regs);
/*
@@ -32,7 +32,6 @@
int do_event(u32 port, struct pt_regs *regs)
{
ev_action_t *action;
-
if (port >= NR_EVS) {
printk("Port number too large: %d\n", port);
return 0;
@@ -57,11 +56,23 @@
}
+void bind_evtchn( u32 port, void (*handler)(int, struct pt_regs *) )
+{
+ if(ev_actions[port].handler)
+ printk("WARN: Handler for port %d already registered, replacing\n",
+ port);
+
+ ev_actions[port].handler = handler;
+ ev_actions[port].status &= ~EVS_DISABLED;
+
+ /* Finally unmask the port */
+ unmask_evtchn(port);
+}
+
int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *) )
{
evtchn_op_t op;
int ret = 0;
- u32 port;
/* Try to bind the virq to a port */
op.cmd = EVTCHNOP_bind_virq;
@@ -73,21 +84,12 @@
printk("Failed to bind virtual IRQ %d\n", virq);
goto out;
}
-
- port = op.u.bind_virq.port;
-
- if(ev_actions[port].handler)
- printk("WARN: Handler for port %d already registered, replacing\n",
- port);
-
- ev_actions[port].handler = handler;
- ev_actions[port].status &= ~EVS_DISABLED;
-
- /* Finally unmask the port */
- unmask_evtchn(port);
+ bind_evtchn(op.u.bind_virq.port, handler);
out:
return ret;
}
+
+
/*
* Initially all events are without a handler and disabled
@@ -100,10 +102,10 @@
for ( i = 0; i < NR_EVS; i++ )
{
ev_actions[i].status = EVS_DISABLED;
- ev_actions[i].handler = NULL;
+ ev_actions[i].handler = default_handler;
}
}
-void default_handler(u32 port, struct pt_regs *regs) {
+void default_handler(int port, struct pt_regs *regs) {
printk("[Port %d] - event received\n", port);
}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/events.h
--- a/extras/mini-os/include/events.h Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/include/events.h Fri Sep 9 16:30:54 2005
@@ -20,6 +20,7 @@
#define _EVENTS_H_
#include<traps.h>
+#include <xen/event_channel.h>
#define NR_EVS 1024
@@ -39,6 +40,16 @@
/* prototypes */
int do_event(u32 port, struct pt_regs *regs);
int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *) );
+void bind_evtchn( u32 virq, void (*handler)(int, struct pt_regs *) );
void init_events(void);
+static inline int notify_via_evtchn(int port)
+{
+ evtchn_op_t op;
+ op.cmd = EVTCHNOP_send;
+ op.u.send.local_port = port;
+ return HYPERVISOR_event_channel_op(&op);
+}
+
+
#endif /* _EVENTS_H_ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/hypervisor.h
--- a/extras/mini-os/include/hypervisor.h Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/include/hypervisor.h Fri Sep 9 16:30:54 2005
@@ -13,7 +13,6 @@
#define _HYPERVISOR_H_
#include <types.h>
-
#include <xen/xen.h>
#include <xen/io/domain_controller.h>
@@ -40,48 +39,26 @@
/*
* Assembler stubs for hyper-calls.
*/
-
-#ifdef __i386__
-#define _a1 "b"
-#define _a2 "c"
-#define _a3 "d"
-#define _a4 "S"
-#else
-#define _a1 "D"
-#define _a2 "S"
-#define _a3 "d"
-#define _a4 "b"
-#endif
-
-static __inline__ int HYPERVISOR_event_channel_op(
- void *op)
+#if defined(__i386__)
+static inline int
+HYPERVISOR_set_trap_table(
+ trap_info_t *table)
{
int ret;
unsigned long ignore;
+
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret), "=b" (ignore)
- : "0" (__HYPERVISOR_event_channel_op), "1" (op)
- : "memory" );
-
- return ret;
-}
-
-static __inline__ int HYPERVISOR_set_trap_table(trap_info_t *table)
-{
- int ret;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret) : "0" (__HYPERVISOR_set_trap_table),
- _a1 (table) : "memory" );
-
- return ret;
-}
-
-static __inline__ int HYPERVISOR_mmu_update(mmu_update_t *req,
- int count,
- int *success_count,
- domid_t domid)
+ : "0" (__HYPERVISOR_set_trap_table), "1" (table)
+ : "memory" );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_mmu_update(
+ mmu_update_t *req, int count, int *success_count, domid_t domid)
{
int ret;
unsigned long ign1, ign2, ign3, ign4;
@@ -89,18 +66,16 @@
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
- : "0" (__HYPERVISOR_mmu_update), "1" (req), "2" (count),
- "3" (success_count), "4" (domid)
- : "memory" );
-
- return ret;
-}
-
-
-static __inline__ int HYPERVISOR_mmuext_op(struct mmuext_op *op,
- int count,
- int *success_count,
- domid_t domid)
+ : "0" (__HYPERVISOR_mmu_update), "1" (req), "2" (count),
+ "3" (success_count), "4" (domid)
+ : "memory" );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_mmuext_op(
+ struct mmuext_op *op, int count, int *success_count, domid_t domid)
{
int ret;
unsigned long ign1, ign2, ign3, ign4;
@@ -108,70 +83,65 @@
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
- : "0" (__HYPERVISOR_mmuext_op), "1" (op), "2" (count),
- "3" (success_count), "4" (domid)
- : "memory" );
-
- return ret;
-}
-
-
-
-static __inline__ int HYPERVISOR_set_gdt(unsigned long *frame_list, int
entries)
-{
- int ret;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret) : "0" (__HYPERVISOR_set_gdt),
- _a1 (frame_list), _a2 (entries) : "memory" );
-
-
- return ret;
-}
-
-static __inline__ int HYPERVISOR_stack_switch(unsigned long ss, unsigned long
esp)
-{
- int ret;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret) : "0" (__HYPERVISOR_stack_switch),
- _a1 (ss), _a2 (esp) : "memory" );
-
- return ret;
-}
-
-#ifdef __i386__
-static __inline__ int HYPERVISOR_set_callbacks(
+ : "0" (__HYPERVISOR_mmuext_op), "1" (op), "2" (count),
+ "3" (success_count), "4" (domid)
+ : "memory" );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_set_gdt(
+ unsigned long *frame_list, int entries)
+{
+ int ret;
+ unsigned long ign1, ign2;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2)
+ : "0" (__HYPERVISOR_set_gdt), "1" (frame_list), "2" (entries)
+ : "memory" );
+
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_stack_switch(
+ unsigned long ss, unsigned long esp)
+{
+ int ret;
+ unsigned long ign1, ign2;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2)
+ : "0" (__HYPERVISOR_stack_switch), "1" (ss), "2" (esp)
+ : "memory" );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_set_callbacks(
unsigned long event_selector, unsigned long event_address,
unsigned long failsafe_selector, unsigned long failsafe_address)
{
int ret;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret) : "0" (__HYPERVISOR_set_callbacks),
- _a1 (event_selector), _a2 (event_address),
- _a3 (failsafe_selector), _a4 (failsafe_address) : "memory" );
-
- return ret;
-}
-#else
-static __inline__ int HYPERVISOR_set_callbacks(
- unsigned long event_address,
- unsigned long failsafe_address,
- unsigned long syscall_address)
-{
- int ret;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret) : "0" (__HYPERVISOR_set_callbacks),
- _a1 (event_address), _a2 (failsafe_address),
- _a3 (syscall_address) : "memory" );
-
- return ret;
-}
-#endif
-
-static __inline__ int
+ unsigned long ign1, ign2, ign3, ign4;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
+ : "0" (__HYPERVISOR_set_callbacks), "1" (event_selector),
+ "2" (event_address), "3" (failsafe_selector), "4" (failsafe_address)
+ : "memory" );
+
+ return ret;
+}
+
+static inline int
HYPERVISOR_fpu_taskswitch(
int set)
{
@@ -187,67 +157,106 @@
return ret;
}
-static __inline__ int HYPERVISOR_yield(void)
-{
- int ret;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret) : "0" (__HYPERVISOR_sched_op),
- _a1 (SCHEDOP_yield) : "memory" );
-
- return ret;
-}
-
-static __inline__ int HYPERVISOR_block(void)
-{
- int ret;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret) : "0" (__HYPERVISOR_sched_op),
- _a1 (SCHEDOP_block) : "memory" );
-
- return ret;
-}
-
-static __inline__ int HYPERVISOR_shutdown(void)
-{
- int ret;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret) : "0" (__HYPERVISOR_sched_op),
- _a1 (SCHEDOP_shutdown | (SHUTDOWN_poweroff << SCHEDOP_reasonshift))
- : "memory" );
-
- return ret;
-}
-
-static __inline__ int HYPERVISOR_reboot(void)
-{
- int ret;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret) : "0" (__HYPERVISOR_sched_op),
- _a1 (SCHEDOP_shutdown | (SHUTDOWN_reboot << SCHEDOP_reasonshift))
- : "memory" );
-
- return ret;
-}
-
-static __inline__ int HYPERVISOR_suspend(unsigned long srec)
-{
- int ret;
+static inline int
+HYPERVISOR_yield(
+ void)
+{
+ int ret;
+ unsigned long ign;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign)
+ : "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_yield)
+ : "memory", "ecx" );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_block(
+ void)
+{
+ int ret;
+ unsigned long ign1;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1)
+ : "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_block)
+ : "memory", "ecx" );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_shutdown(
+ void)
+{
+ int ret;
+ unsigned long ign1;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1)
+ : "0" (__HYPERVISOR_sched_op),
+ "1" (SCHEDOP_shutdown | (SHUTDOWN_poweroff << SCHEDOP_reasonshift))
+ : "memory", "ecx" );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_reboot(
+ void)
+{
+ int ret;
+ unsigned long ign1;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1)
+ : "0" (__HYPERVISOR_sched_op),
+ "1" (SCHEDOP_shutdown | (SHUTDOWN_reboot << SCHEDOP_reasonshift))
+ : "memory", "ecx" );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_suspend(
+ unsigned long srec)
+{
+ int ret;
+ unsigned long ign1, ign2;
+
/* NB. On suspend, control software expects a suspend record in %esi. */
__asm__ __volatile__ (
TRAP_INSTR
- : "=a" (ret) : "0" (__HYPERVISOR_sched_op),
- _a1 (SCHEDOP_shutdown | (SHUTDOWN_suspend << SCHEDOP_reasonshift)),
- "S" (srec) : "memory" );
-
- return ret;
-}
-
-#ifdef __i386__
-static __inline__ long HYPERVISOR_set_timer_op( u64 timeout )
+ : "=a" (ret), "=b" (ign1), "=S" (ign2)
+ : "0" (__HYPERVISOR_sched_op),
+ "b" (SCHEDOP_shutdown | (SHUTDOWN_suspend << SCHEDOP_reasonshift)),
+ "S" (srec) : "memory", "ecx");
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_crash(
+ void)
+{
+ int ret;
+ unsigned long ign1;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1)
+ : "0" (__HYPERVISOR_sched_op),
+ "1" (SCHEDOP_shutdown | (SHUTDOWN_crash << SCHEDOP_reasonshift))
+ : "memory", "ecx" );
+
+ return ret;
+}
+
+static inline long
+HYPERVISOR_set_timer_op(
+ u64 timeout)
{
int ret;
unsigned long timeout_hi = (unsigned long)(timeout>>32);
@@ -262,8 +271,516 @@
return ret;
}
+
+#if 0
+static inline int
+HYPERVISOR_dom0_op(
+ dom0_op_t *dom0_op)
+{
+ int ret;
+ unsigned long ign1;
+
+ dom0_op->interface_version = DOM0_INTERFACE_VERSION;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1)
+ : "0" (__HYPERVISOR_dom0_op), "1" (dom0_op)
+ : "memory");
+
+ return ret;
+}
+#endif
+
+static inline int
+HYPERVISOR_set_debugreg(
+ int reg, unsigned long value)
+{
+ int ret;
+ unsigned long ign1, ign2;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2)
+ : "0" (__HYPERVISOR_set_debugreg), "1" (reg), "2" (value)
+ : "memory" );
+
+ return ret;
+}
+
+static inline unsigned long
+HYPERVISOR_get_debugreg(
+ int reg)
+{
+ unsigned long ret;
+ unsigned long ign;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign)
+ : "0" (__HYPERVISOR_get_debugreg), "1" (reg)
+ : "memory" );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_update_descriptor(
+ u64 ma, u64 desc)
+{
+ int ret;
+ unsigned long ign1, ign2, ign3, ign4;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
+ : "0" (__HYPERVISOR_update_descriptor),
+ "1" ((unsigned long)ma), "2" ((unsigned long)(ma>>32)),
+ "3" ((unsigned long)desc), "4" ((unsigned long)(desc>>32))
+ : "memory" );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_dom_mem_op(
+ unsigned int op, unsigned long *extent_list,
+ unsigned long nr_extents, unsigned int extent_order)
+{
+ int ret;
+ unsigned long ign1, ign2, ign3, ign4, ign5;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4),
+ "=D" (ign5)
+ : "0" (__HYPERVISOR_dom_mem_op), "1" (op), "2" (extent_list),
+ "3" (nr_extents), "4" (extent_order), "5" (DOMID_SELF)
+ : "memory" );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_multicall(
+ void *call_list, int nr_calls)
+{
+ int ret;
+ unsigned long ign1, ign2;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2)
+ : "0" (__HYPERVISOR_multicall), "1" (call_list), "2" (nr_calls)
+ : "memory" );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_update_va_mapping(
+ unsigned long va, pte_t new_val, unsigned long flags)
+{
+ int ret;
+ unsigned long ign1, ign2, ign3, ign4;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
+ : "0" (__HYPERVISOR_update_va_mapping),
+ "1" (va), "2" ((new_val).pte_low),
+#ifdef CONFIG_X86_PAE
+ "3" ((new_val).pte_high),
#else
-static __inline__ long HYPERVISOR_set_timer_op( u64 timeout )
+ "3" (0),
+#endif
+ "4" (flags)
+ : "memory" );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_event_channel_op(
+ void *op)
+{
+ int ret;
+ unsigned long ignore;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ignore)
+ : "0" (__HYPERVISOR_event_channel_op), "1" (op)
+ : "memory" );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_xen_version(
+ int cmd)
+{
+ int ret;
+ unsigned long ignore;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ignore)
+ : "0" (__HYPERVISOR_xen_version), "1" (cmd)
+ : "memory" );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_console_io(
+ int cmd, int count, char *str)
+{
+ int ret;
+ unsigned long ign1, ign2, ign3;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
+ : "0" (__HYPERVISOR_console_io), "1" (cmd), "2" (count), "3" (str)
+ : "memory" );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_physdev_op(
+ void *physdev_op)
+{
+ int ret;
+ unsigned long ign;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign)
+ : "0" (__HYPERVISOR_physdev_op), "1" (physdev_op)
+ : "memory" );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_grant_table_op(
+ unsigned int cmd, void *uop, unsigned int count)
+{
+ int ret;
+ unsigned long ign1, ign2, ign3;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
+ : "0" (__HYPERVISOR_grant_table_op), "1" (cmd), "2" (uop), "3" (count)
+ : "memory" );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_update_va_mapping_otherdomain(
+ unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
+{
+ int ret;
+ unsigned long ign1, ign2, ign3, ign4, ign5;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3),
+ "=S" (ign4), "=D" (ign5)
+ : "0" (__HYPERVISOR_update_va_mapping_otherdomain),
+ "1" (va), "2" ((new_val).pte_low),
+#ifdef CONFIG_X86_PAE
+ "3" ((new_val).pte_high),
+#else
+ "3" (0),
+#endif
+ "4" (flags), "5" (domid) :
+ "memory" );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_vm_assist(
+ unsigned int cmd, unsigned int type)
+{
+ int ret;
+ unsigned long ign1, ign2;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2)
+ : "0" (__HYPERVISOR_vm_assist), "1" (cmd), "2" (type)
+ : "memory" );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_boot_vcpu(
+ unsigned long vcpu, vcpu_guest_context_t *ctxt)
+{
+ int ret;
+ unsigned long ign1, ign2;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2)
+ : "0" (__HYPERVISOR_boot_vcpu), "1" (vcpu), "2" (ctxt)
+ : "memory");
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_vcpu_down(
+ int vcpu)
+{
+ int ret;
+ unsigned long ign1;
+ /* Yes, I really do want to clobber edx here: when we resume a
+ vcpu after unpickling a multi-processor domain, it returns
+ here, but clobbers all of the call clobbered registers. */
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1)
+ : "0" (__HYPERVISOR_sched_op),
+ "1" (SCHEDOP_vcpu_down | (vcpu << SCHEDOP_vcpushift))
+ : "memory", "ecx", "edx" );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_vcpu_up(
+ int vcpu)
+{
+ int ret;
+ unsigned long ign1;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1)
+ : "0" (__HYPERVISOR_sched_op),
+ "1" (SCHEDOP_vcpu_up | (vcpu << SCHEDOP_vcpushift))
+ : "memory", "ecx" );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_vcpu_pickle(
+ int vcpu, vcpu_guest_context_t *ctxt)
+{
+ int ret;
+ unsigned long ign1, ign2;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2)
+ : "0" (__HYPERVISOR_sched_op),
+ "1" (SCHEDOP_vcpu_pickle | (vcpu << SCHEDOP_vcpushift)),
+ "2" (ctxt)
+ : "memory" );
+
+ return ret;
+}
+#elif defined(__x86_64__)
+
+#define __syscall_clobber "r11","rcx","memory"
+
+/*
+ * Assembler stubs for hyper-calls.
+ */
+static inline int
+HYPERVISOR_set_trap_table(
+ trap_info_t *table)
+{
+ int ret;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret)
+ : "0" ((unsigned long)__HYPERVISOR_set_trap_table), "D" (table)
+ : __syscall_clobber );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_mmu_update(
+ mmu_update_t *req, int count, int *success_count, domid_t domid)
+{
+ int ret;
+
+ __asm__ __volatile__ (
+ "movq %5, %%r10;" TRAP_INSTR
+ : "=a" (ret)
+ : "0" ((unsigned long)__HYPERVISOR_mmu_update), "D" (req), "S"
((long)count),
+ "d" (success_count), "g" ((unsigned long)domid)
+ : __syscall_clobber, "r10" );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_mmuext_op(
+ struct mmuext_op *op, int count, int *success_count, domid_t domid)
+{
+ int ret;
+
+ __asm__ __volatile__ (
+ "movq %5, %%r10;" TRAP_INSTR
+ : "=a" (ret)
+ : "0" (__HYPERVISOR_mmuext_op), "D" (op), "S" ((long)count),
+ "d" (success_count), "g" ((unsigned long)domid)
+ : __syscall_clobber, "r10" );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_set_gdt(
+ unsigned long *frame_list, int entries)
+{
+ int ret;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret)
+ : "0" ((unsigned long)__HYPERVISOR_set_gdt), "D" (frame_list), "S"
((long)entries)
+ : __syscall_clobber );
+
+
+ return ret;
+}
+static inline int
+HYPERVISOR_stack_switch(
+ unsigned long ss, unsigned long esp)
+{
+ int ret;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret)
+ : "0" ((unsigned long)__HYPERVISOR_stack_switch), "D" (ss), "S" (esp)
+ : __syscall_clobber );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_set_callbacks(
+ unsigned long event_address, unsigned long failsafe_address,
+ unsigned long syscall_address)
+{
+ int ret;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret)
+ : "0" ((unsigned long)__HYPERVISOR_set_callbacks), "D" (event_address),
+ "S" (failsafe_address), "d" (syscall_address)
+ : __syscall_clobber );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_fpu_taskswitch(
+ int set)
+{
+ int ret;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret) : "0" ((unsigned long)__HYPERVISOR_fpu_taskswitch),
+ "D" ((unsigned long) set) : __syscall_clobber );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_yield(
+ void)
+{
+ int ret;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret)
+ : "0" ((unsigned long)__HYPERVISOR_sched_op), "D" ((unsigned
long)SCHEDOP_yield)
+ : __syscall_clobber );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_block(
+ void)
+{
+ int ret;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret)
+ : "0" ((unsigned long)__HYPERVISOR_sched_op), "D" ((unsigned
long)SCHEDOP_block)
+ : __syscall_clobber );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_shutdown(
+ void)
+{
+ int ret;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret)
+ : "0" ((unsigned long)__HYPERVISOR_sched_op),
+ "D" ((unsigned long)(SCHEDOP_shutdown | (SHUTDOWN_poweroff <<
SCHEDOP_reasonshift)))
+ : __syscall_clobber );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_reboot(
+ void)
+{
+ int ret;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret)
+ : "0" ((unsigned long)__HYPERVISOR_sched_op),
+ "D" ((unsigned long)(SCHEDOP_shutdown | (SHUTDOWN_reboot <<
SCHEDOP_reasonshift)))
+ : __syscall_clobber );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_suspend(
+ unsigned long srec)
+{
+ int ret;
+
+ /* NB. On suspend, control software expects a suspend record in %esi. */
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret)
+ : "0" ((unsigned long)__HYPERVISOR_sched_op),
+ "D" ((unsigned long)(SCHEDOP_shutdown | (SHUTDOWN_suspend <<
SCHEDOP_reasonshift))),
+ "S" (srec)
+ : __syscall_clobber );
+
+ return ret;
+}
+
+/*
+ * We can have the timeout value in a single argument for the hypercall, but
+ * that will break the common code.
+ */
+static inline long
+HYPERVISOR_set_timer_op(
+ u64 timeout)
{
int ret;
@@ -329,7 +846,7 @@
int ret;
__asm__ __volatile__ (
TRAP_INSTR
- : "=a" (ret) : "0" (__HYPERVISOR_dom_mem_op),
+ : "=a" (ret) : "0" (__HYPERVISOR_memory_op),
_a1 (dom_mem_op) : "memory" );
return ret;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/lib.h
--- a/extras/mini-os/include/lib.h Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/include/lib.h Fri Sep 9 16:30:54 2005
@@ -60,10 +60,22 @@
/* printing */
#define printk printf
#define kprintf printf
-int printf(const char *fmt, ...);
-int vprintf(const char *fmt, va_list ap);
-int sprintf(char *buf, const char *cfmt, ...);
-int vsprintf(char *buf, const char *cfmt, va_list ap);
+#define _p(_x) ((void *)(unsigned long)(_x))
+void printf(const char *fmt, ...);
+int vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
+int vscnprintf(char *buf, size_t size, const char *fmt, va_list args);
+int snprintf(char * buf, size_t size, const char *fmt, ...);
+int scnprintf(char * buf, size_t size, const char *fmt, ...);
+int vsprintf(char *buf, const char *fmt, va_list args);
+int sprintf(char * buf, const char *fmt, ...);
+int vsscanf(const char * buf, const char * fmt, va_list args);
+int sscanf(const char * buf, const char * fmt, ...);
+
+long simple_strtol(const char *cp,char **endp,unsigned int base);
+unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base);
+long long simple_strtoll(const char *cp,char **endp,unsigned int base);
+unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int
base);
+
/* string and memory manipulation */
int memcmp(const void *cs, const void *ct, size_t count);
@@ -77,6 +89,16 @@
size_t strlen(const char *s);
char *strchr(const char *s, int c);
char *strstr(const char *s1, const char *s2);
+char * strcat(char * dest, const char * src);
+
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+struct kvec {
+ void *iov_base;
+ size_t iov_len;
+};
+
#endif /* _LIB_H_ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/mm.h
--- a/extras/mini-os/include/mm.h Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/include/mm.h Fri Sep 9 16:30:54 2005
@@ -24,6 +24,15 @@
#ifndef _MM_H_
#define _MM_H_
+
+#ifdef __i386__
+#include <xen/arch-x86_32.h>
+#endif
+
+#ifdef __x86_64__
+#include <xen/arch-x86_64.h>
+#endif
+
#ifdef __x86_64__
@@ -56,6 +65,8 @@
#define L1_PAGETABLE_ENTRIES 1024
#define L2_PAGETABLE_ENTRIES 1024
+
+#elif defined(__x86_64__)
#endif
/* Given a virtual address, get an entry offset into a page table. */
@@ -97,13 +108,15 @@
extern unsigned long *phys_to_machine_mapping;
#define pfn_to_mfn(_pfn) (phys_to_machine_mapping[(_pfn)])
-#define mfn_to_pfn(_mfn) (machine_to_phys_mapping[(_mfn)])
static __inline__ unsigned long phys_to_machine(unsigned long phys)
{
unsigned long machine = pfn_to_mfn(phys >> L1_PAGETABLE_SHIFT);
machine = (machine << L1_PAGETABLE_SHIFT) | (phys & ~PAGE_MASK);
return machine;
}
+
+
+#define mfn_to_pfn(_mfn) (machine_to_phys_mapping[(_mfn)])
static __inline__ unsigned long machine_to_phys(unsigned long machine)
{
unsigned long phys = mfn_to_pfn(machine >> L1_PAGETABLE_SHIFT);
@@ -119,16 +132,15 @@
#define to_phys(x) ((unsigned long)(x)-VIRT_START)
#define to_virt(x) ((void *)((unsigned long)(x)+VIRT_START))
-#define __va to_virt
-#define __pa to_phys
#define virt_to_pfn(_virt) (PFN_DOWN(to_phys(_virt)))
+#define mach_to_virt(_mach) (to_virt(machine_to_phys(_mach)))
+#define mfn_to_virt(_mfn) (mach_to_virt(_mfn << PAGE_SHIFT))
void init_mm(void);
unsigned long alloc_pages(int order);
#define alloc_page() alloc_pages(0);
void free_pages(void *pointer, int order);
-//int is_mfn_mapped(unsigned long mfn);
static __inline__ int get_order(unsigned long size)
{
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/os.h
--- a/extras/mini-os/include/os.h Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/include/os.h Fri Sep 9 16:30:54 2005
@@ -15,15 +15,16 @@
#define unlikely(x) __builtin_expect((x),0)
#define smp_processor_id() 0
-#define preempt_disable() ((void)0)
-#define preempt_enable() ((void)0)
-
-#define force_evtchn_callback() ((void)HYPERVISOR_xen_version(0))
+
#ifndef __ASSEMBLY__
#include <types.h>
+#include <hypervisor.h>
#endif
#include <xen/xen.h>
+
+
+#define force_evtchn_callback() ((void)HYPERVISOR_xen_version(0))
#define __KERNEL_CS FLAT_KERNEL_CS
#define __KERNEL_DS FLAT_KERNEL_DS
@@ -54,8 +55,6 @@
/* Everything below this point is not included by assembler (.S) files. */
#ifndef __ASSEMBLY__
-#define pt_regs xen_regs
-
void trap_init(void);
/*
@@ -69,10 +68,8 @@
#define __cli()
\
do { \
vcpu_info_t *_vcpu; \
- preempt_disable(); \
_vcpu = &HYPERVISOR_shared_info->vcpu_data[smp_processor_id()]; \
_vcpu->evtchn_upcall_mask = 1; \
- preempt_enable_no_resched(); \
barrier(); \
} while (0)
@@ -80,13 +77,11 @@
do { \
vcpu_info_t *_vcpu; \
barrier(); \
- preempt_disable(); \
_vcpu = &HYPERVISOR_shared_info->vcpu_data[smp_processor_id()]; \
_vcpu->evtchn_upcall_mask = 0; \
barrier(); /* unmask then check (avoid races) */ \
if ( unlikely(_vcpu->evtchn_upcall_pending) ) \
force_evtchn_callback(); \
- preempt_enable(); \
} while (0)
#define __save_flags(x)
\
@@ -100,15 +95,12 @@
do { \
vcpu_info_t *_vcpu; \
barrier(); \
- preempt_disable(); \
_vcpu = &HYPERVISOR_shared_info->vcpu_data[smp_processor_id()]; \
if ((_vcpu->evtchn_upcall_mask = (x)) == 0) { \
barrier(); /* unmask then check (avoid races) */ \
if ( unlikely(_vcpu->evtchn_upcall_pending) ) \
force_evtchn_callback(); \
- preempt_enable(); \
- } else \
- preempt_enable_no_resched(); \
+ }\
} while (0)
#define safe_halt() ((void)0)
@@ -116,11 +108,9 @@
#define __save_and_cli(x) \
do { \
vcpu_info_t *_vcpu; \
- preempt_disable(); \
_vcpu = &HYPERVISOR_shared_info->vcpu_data[smp_processor_id()]; \
(x) = _vcpu->evtchn_upcall_mask; \
_vcpu->evtchn_upcall_mask = 1; \
- preempt_enable_no_resched(); \
barrier(); \
} while (0)
@@ -135,6 +125,15 @@
/* This is a barrier for the compiler only, NOT the processor! */
#define barrier() __asm__ __volatile__("": : :"memory")
+
+#if defined(__i386__)
+#define mb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
+#define rmb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
+#elif defined(__x86_64__)
+#define mb() __asm__ __volatile__ ("mfence":::"memory")
+#define rmb() __asm__ __volatile__ ("lfence":::"memory")
+#endif
+
#define LOCK_PREFIX ""
#define LOCK ""
@@ -147,69 +146,71 @@
typedef struct { volatile int counter; } atomic_t;
-#define xchg(ptr,v) \
- ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
+/************************** i386 *******************************/
+#if defined (__i386__)
+
+#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned
long)(v),(ptr),sizeof(*(ptr))))
struct __xchg_dummy { unsigned long a[100]; };
-#define __xg(x) ((volatile struct __xchg_dummy *)(x))
-static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr,
- int size)
-{
- switch (size) {
- case 1:
- __asm__ __volatile__("xchgb %b0,%1"
- :"=q" (x)
- :"m" (*__xg(ptr)), "0" (x)
- :"memory");
- break;
- case 2:
- __asm__ __volatile__("xchgw %w0,%1"
- :"=r" (x)
- :"m" (*__xg(ptr)), "0" (x)
- :"memory");
- break;
- case 4:
- __asm__ __volatile__("xchgl %0,%1"
- :"=r" (x)
- :"m" (*__xg(ptr)), "0" (x)
- :"memory");
- break;
- }
- return x;
+#define __xg(x) ((struct __xchg_dummy *)(x))
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int
size)
+{
+ switch (size) {
+ case 1:
+ __asm__ __volatile__("xchgb %b0,%1"
+ :"=q" (x)
+ :"m" (*__xg(ptr)), "0" (x)
+ :"memory");
+ break;
+ case 2:
+ __asm__ __volatile__("xchgw %w0,%1"
+ :"=r" (x)
+ :"m" (*__xg(ptr)), "0" (x)
+ :"memory");
+ break;
+ case 4:
+ __asm__ __volatile__("xchgl %0,%1"
+ :"=r" (x)
+ :"m" (*__xg(ptr)), "0" (x)
+ :"memory");
+ break;
+ }
+ return x;
}
/**
* test_and_clear_bit - Clear a bit and return its old value
- * @nr: Bit to set
+ * @nr: Bit to clear
* @addr: Address to count from
*
- * This operation is atomic and cannot be reordered.
+ * This operation is atomic and cannot be reordered.
+ * It can be reorderdered on other architectures other than x86.
* It also implies a memory barrier.
*/
-static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
-{
- int oldbit;
-
- __asm__ __volatile__( LOCK_PREFIX
- "btrl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit),"=m" (ADDR)
- :"Ir" (nr) : "memory");
- return oldbit;
-}
-
-static __inline__ int constant_test_bit(int nr, const volatile void * addr)
-{
- return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >>
5])) != 0;
-}
-
-static __inline__ int variable_test_bit(int nr, volatile void * addr)
-{
- int oldbit;
-
- __asm__ __volatile__(
- "btl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit)
- :"m" (ADDR),"Ir" (nr));
- return oldbit;
+static inline int test_and_clear_bit(int nr, volatile unsigned long * addr)
+{
+ int oldbit;
+
+ __asm__ __volatile__( LOCK
+ "btrl %2,%1\n\tsbbl %0,%0"
+ :"=r" (oldbit),"=m" (ADDR)
+ :"Ir" (nr) : "memory");
+ return oldbit;
+}
+
+static inline int constant_test_bit(int nr, const volatile unsigned long *addr)
+{
+ return ((1UL << (nr & 31)) & (addr[nr >> 5])) != 0;
+}
+
+static inline int variable_test_bit(int nr, const volatile unsigned long *
addr)
+{
+ int oldbit;
+
+ __asm__ __volatile__(
+ "btl %2,%1\n\tsbbl %0,%0"
+ :"=r" (oldbit)
+ :"m" (ADDR),"Ir" (nr));
+ return oldbit;
}
#define test_bit(nr,addr) \
@@ -217,6 +218,152 @@
constant_test_bit((nr),(addr)) : \
variable_test_bit((nr),(addr)))
+/**
+ * set_bit - Atomically set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * This function is atomic and may not be reordered. See __set_bit()
+ * if you do not require the atomic guarantees.
+ *
+ * Note: there are no guarantees that this function will not be reordered
+ * on non x86 architectures, so if you are writting portable code,
+ * make sure not to rely on its reordering guarantees.
+ *
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ */
+static inline void set_bit(int nr, volatile unsigned long * addr)
+{
+ __asm__ __volatile__( LOCK
+ "btsl %1,%0"
+ :"=m" (ADDR)
+ :"Ir" (nr));
+}
+
+/**
+ * clear_bit - Clears a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * clear_bit() is atomic and may not be reordered. However, it does
+ * not contain a memory barrier, so if it is used for locking purposes,
+ * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
+ * in order to ensure changes are visible on other processors.
+ */
+static inline void clear_bit(int nr, volatile unsigned long * addr)
+{
+ __asm__ __volatile__( LOCK
+ "btrl %1,%0"
+ :"=m" (ADDR)
+ :"Ir" (nr));
+}
+
+/**
+ * __ffs - find first bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
+static inline unsigned long __ffs(unsigned long word)
+{
+ __asm__("bsfl %1,%0"
+ :"=r" (word)
+ :"rm" (word));
+ return word;
+}
+
+
+/*
+ * These have to be done with inline assembly: that way the bit-setting
+ * is guaranteed to be atomic. All bit operations return 0 if the bit
+ * was cleared before the operation and != 0 if it was not.
+ *
+ * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
+ */
+#define ADDR (*(volatile long *) addr)
+
+#define rdtscll(val) \
+ __asm__ __volatile__("rdtsc" : "=A" (val))
+
+
+
+#elif defined(__x86_64__)/* ifdef __i386__ */
+/************************** x86_84 *******************************/
+
+#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned
long)(v),(ptr),sizeof(*(ptr))))
+#define __xg(x) ((volatile long *)(x))
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int
size)
+{
+ switch (size) {
+ case 1:
+ __asm__ __volatile__("xchgb %b0,%1"
+ :"=q" (x)
+ :"m" (*__xg(ptr)), "0" (x)
+ :"memory");
+ break;
+ case 2:
+ __asm__ __volatile__("xchgw %w0,%1"
+ :"=r" (x)
+ :"m" (*__xg(ptr)), "0" (x)
+ :"memory");
+ break;
+ case 4:
+ __asm__ __volatile__("xchgl %k0,%1"
+ :"=r" (x)
+ :"m" (*__xg(ptr)), "0" (x)
+ :"memory");
+ break;
+ case 8:
+ __asm__ __volatile__("xchgq %0,%1"
+ :"=r" (x)
+ :"m" (*__xg(ptr)), "0" (x)
+ :"memory");
+ break;
+ }
+ return x;
+}
+
+/**
+ * test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to clear
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.
+ * It also implies a memory barrier.
+ */
+static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
+{
+ int oldbit;
+
+ __asm__ __volatile__( LOCK_PREFIX
+ "btrl %2,%1\n\tsbbl %0,%0"
+ :"=r" (oldbit),"=m" (ADDR)
+ :"dIr" (nr) : "memory");
+ return oldbit;
+}
+
+static __inline__ int constant_test_bit(int nr, const volatile void * addr)
+{
+ return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr
>> 5])) != 0;
+}
+
+static __inline__ int variable_test_bit(int nr, volatile const void * addr)
+{
+ int oldbit;
+
+ __asm__ __volatile__(
+ "btl %2,%1\n\tsbbl %0,%0"
+ :"=r" (oldbit)
+ :"m" (ADDR),"dIr" (nr));
+ return oldbit;
+}
+
+#define test_bit(nr,addr) \
+(__builtin_constant_p(nr) ? \
+ constant_test_bit((nr),(addr)) : \
+ variable_test_bit((nr),(addr)))
+
/**
* set_bit - Atomically set a bit in memory
@@ -230,10 +377,10 @@
*/
static __inline__ void set_bit(int nr, volatile void * addr)
{
- __asm__ __volatile__( LOCK_PREFIX
- "btsl %1,%0"
- :"=m" (ADDR)
- :"Ir" (nr));
+ __asm__ __volatile__( LOCK_PREFIX
+ "btsl %1,%0"
+ :"=m" (ADDR)
+ :"dIr" (nr) : "memory");
}
/**
@@ -248,40 +395,43 @@
*/
static __inline__ void clear_bit(int nr, volatile void * addr)
{
- __asm__ __volatile__( LOCK_PREFIX
- "btrl %1,%0"
- :"=m" (ADDR)
- :"Ir" (nr));
-}
-
-/**
- * atomic_inc - increment atomic variable
- * @v: pointer of type atomic_t
- *
- * Atomically increments @v by 1. Note that the guaranteed
- * useful range of an atomic_t is only 24 bits.
- */
-static __inline__ void atomic_inc(atomic_t *v)
-{
- __asm__ __volatile__(
- LOCK "incl %0"
- :"=m" (v->counter)
- :"m" (v->counter));
-}
-
-
-#define rdtscll(val) \
- __asm__ __volatile__("rdtsc" : "=A" (val))
-
+ __asm__ __volatile__( LOCK_PREFIX
+ "btrl %1,%0"
+ :"=m" (ADDR)
+ :"dIr" (nr));
+}
+
+/**
+ * __ffs - find first bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
static __inline__ unsigned long __ffs(unsigned long word)
{
- __asm__("bsfl %1,%0"
- :"=r" (word)
- :"rm" (word));
- return word;
+ __asm__("bsfq %1,%0"
+ :"=r" (word)
+ :"rm" (word));
+ return word;
}
#define ADDR (*(volatile long *) addr)
+
+#define rdtscll(val) do { \
+ unsigned int __a,__d; \
+ asm volatile("rdtsc" : "=a" (__a), "=d" (__d)); \
+ (val) = ((unsigned long)__a) | (((unsigned long)__d)<<32); \
+} while(0)
+
+
+#else /* ifdef __x86_64__ */
+#error "Unsupported architecture"
+#endif
+
+
+/********************* common i386 and x86_64 ****************************/
+
+
static __inline__ void synch_set_bit(int nr, volatile void * addr)
{
@@ -306,6 +456,14 @@
return oldbit;
}
+static __inline__ int synch_test_and_clear_bit(int nr, volatile void * addr)
+{
+ int oldbit;
+ __asm__ __volatile__ (
+ "lock btrl %2,%1\n\tsbbl %0,%0"
+ : "=r" (oldbit), "=m" (ADDR) : "Ir" (nr) : "memory");
+ return oldbit;
+}
static __inline__ int synch_const_test_bit(int nr, const volatile void * addr)
{
@@ -326,9 +484,8 @@
(__builtin_constant_p(nr) ? \
synch_const_test_bit((nr),(addr)) : \
synch_var_test_bit((nr),(addr)))
-#endif /* !__ASSEMBLY__ */
-
-#define rdtsc(low,high) \
- __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
-
+
+
+
+#endif /* not assembly */
#endif /* _OS_H_ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/time.h
--- a/extras/mini-os/include/time.h Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/include/time.h Fri Sep 9 16:30:54 2005
@@ -58,6 +58,6 @@
s_time_t get_s_time(void);
s_time_t get_v_time(void);
void gettimeofday(struct timeval *tv);
-void block(u32 millisecs);
+void block_domain(u32 millisecs);
#endif /* _TIME_H_ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/traps.h
--- a/extras/mini-os/include/traps.h Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/include/traps.h Fri Sep 9 16:30:54 2005
@@ -17,6 +17,7 @@
#ifndef _TRAPS_H_
#define _TRAPS_H_
+#ifdef __i386__
struct pt_regs {
long ebx;
long ecx;
@@ -34,7 +35,38 @@
long esp;
int xss;
};
+#elif __x86_64__
+struct pt_regs {
+ unsigned long r15;
+ unsigned long r14;
+ unsigned long r13;
+ unsigned long r12;
+ unsigned long rbp;
+ unsigned long rbx;
+/* arguments: non interrupts/non tracing syscalls only save upto here*/
+ unsigned long r11;
+ unsigned long r10;
+ unsigned long r9;
+ unsigned long r8;
+ unsigned long rax;
+ unsigned long rcx;
+ unsigned long rdx;
+ unsigned long rsi;
+ unsigned long rdi;
+ unsigned long orig_rax;
+/* end of arguments */
+/* cpu exception frame or undefined */
+ unsigned long rip;
+ unsigned long cs;
+ unsigned long eflags;
+ unsigned long rsp;
+ unsigned long ss;
+/* top of stack page */
+};
+
+
+#endif
void dump_regs(struct pt_regs *regs);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/types.h
--- a/extras/mini-os/include/types.h Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/include/types.h Fri Sep 9 16:30:54 2005
@@ -44,11 +44,19 @@
typedef long long quad_t;
typedef unsigned long long u_quad_t;
typedef unsigned int uintptr_t;
+
+typedef struct { unsigned long pte_low; } pte_t;
#elif defined(__x86_64__)
typedef long quad_t;
typedef unsigned long u_quad_t;
typedef unsigned long uintptr_t;
+
+typedef struct { unsigned long pte; } pte_t;
#endif
+
+
+
+#define INT_MAX ((int)(~0U>>1))
#define UINT_MAX (~0U)
#endif /* _TYPES_H_ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/kernel.c
--- a/extras/mini-os/kernel.c Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/kernel.c Fri Sep 9 16:30:54 2005
@@ -33,6 +33,8 @@
#include <time.h>
#include <types.h>
#include <lib.h>
+#include <sched.h>
+#include <xenbus.h>
/*
* Shared page for communicating with the hypervisor.
@@ -59,10 +61,12 @@
extern char shared_info[PAGE_SIZE];
+#define __pte(x) ((pte_t) { (0) } )
+
static shared_info_t *map_shared_info(unsigned long pa)
{
if ( HYPERVISOR_update_va_mapping(
- (unsigned long)shared_info, pa | 7, UVMF_INVLPG) )
+ (unsigned long)shared_info, __pte(pa | 7), UVMF_INVLPG) )
{
printk("Failed to map shared_info!!\n");
*(int*)0=0;
@@ -77,7 +81,6 @@
void start_kernel(start_info_t *si)
{
static char hello[] = "Bootstrapping...\n";
- int i;
(void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(hello), hello);
/* Copy the start_info struct to a globally-accessible area. */
@@ -96,7 +99,6 @@
(unsigned long)hypervisor_callback,
(unsigned long)failsafe_callback, 0);
#endif
-
trap_init();
/* ENABLE EVENT DELIVERY. This is disabled at start of day. */
@@ -119,7 +121,6 @@
* If used for porting another OS, start here to figure out your
* guest os entry point. Otherwise continue below...
*/
-
/* init memory management */
init_mm();
@@ -127,15 +128,15 @@
init_events();
/* init time and timers */
init_time();
+
+ /* init scheduler */
+ init_sched();
- /* do nothing */
- i = 0;
- for ( ; ; )
- {
-// HYPERVISOR_yield();
- block(100);
- i++;
- }
+ /* init xenbus */
+ xs_init();
+
+ /* Everything initialised, start idle thread */
+ run_idle_thread();
}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/lib/printf.c
--- a/extras/mini-os/lib/printf.c Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/lib/printf.c Fri Sep 9 16:30:54 2005
@@ -1,20 +1,18 @@
-/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
+/*
****************************************************************************
* (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
****************************************************************************
*
* File: printf.c
* Author: Rolf Neugebauer (neugebar@xxxxxxxxxxxxx)
- * Changes:
+ * Changes: Grzegorz Milos (gm281@xxxxxxxxx)
*
- * Date: Aug 2003
+ * Date: Aug 2003, Aug 2005
*
* Environment: Xen Minimal OS
* Description: Library functions for printing
* (freebsd port, mainly sys/subr_prf.c)
*
- ****************************************************************************
- * $Id: c-insert.c,v 1.7 2002/11/08 16:04:34 rn Exp $
****************************************************************************
*
*-
@@ -60,409 +58,748 @@
#include <types.h>
#include <hypervisor.h>
#include <lib.h>
-
-/****************************************************************************
- * RN: printf family of routines
- * taken mainly from sys/subr_prf.c
- ****************************************************************************/
-char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
-#define hex2ascii(hex) (hex2ascii_data[hex])
-#define NBBY 8 /* number of bits in a byte */
-#define MAXNBUF (sizeof(quad_t) * NBBY + 1)
-
-static int kvprintf(char const *fmt, void *arg, int radix, va_list ap);
-
-
-int
-printf(const char *fmt, ...)
-{
- va_list ap;
- int retval;
- static char printk_buf[1024];
-
- va_start(ap, fmt);
- retval = kvprintf(fmt, printk_buf, 10, ap);
- printk_buf[retval] = '\0';
- va_end(ap);
- (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(printk_buf),
- printk_buf);
- return retval;
-}
-
-int
-vprintf(const char *fmt, va_list ap)
-{
- int retval;
- static char printk_buf[1024];
- retval = kvprintf(fmt, printk_buf, 10, ap);
- printk_buf[retval] = '\0';
- (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(printk_buf),
- printk_buf);
- return retval;
-}
-
-int
-sprintf(char *buf, const char *cfmt, ...)
-{
- int retval;
- va_list ap;
-
- va_start(ap, cfmt);
- retval = kvprintf(cfmt, (void *)buf, 10, ap);
- buf[retval] = '\0';
- va_end(ap);
- return retval;
-}
-
-int
-vsprintf(char *buf, const char *cfmt, va_list ap)
-{
- int retval;
-
- retval = kvprintf(cfmt, (void *)buf, 10, ap);
- buf[retval] = '\0';
- return retval;
-}
-
-
-/*
- * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
- * order; return an optional length and a pointer to the last character
- * written in the buffer (i.e., the first character of the string).
- * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
- */
-static char *
-ksprintn(char *nbuf, u_long ul, int base, int *lenp)
-{
- char *p;
-
- p = nbuf;
- *p = '\0';
- do {
- *++p = hex2ascii(ul % base);
- } while (ul /= base);
- if (lenp)
- *lenp = p - nbuf;
- return (p);
-}
-/* ksprintn, but for a quad_t. */
-static char *
-ksprintqn(char *nbuf, u_quad_t uq, int base, int *lenp)
-{
- char *p;
-
- p = nbuf;
- *p = '\0';
- do {
- *++p = hex2ascii(uq % base);
- } while (uq /= base);
- if (lenp)
- *lenp = p - nbuf;
- return (p);
-}
-
-/*
- * Scaled down version of printf(3).
+#include <mm.h>
+#include <ctype.h>
+
+/**
+ * simple_strtoul - convert a string to an unsigned long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
+{
+ unsigned long result = 0,value;
+
+ if (!base) {
+ base = 10;
+ if (*cp == '0') {
+ base = 8;
+ cp++;
+ if ((*cp == 'x') && isxdigit(cp[1])) {
+ cp++;
+ base = 16;
+ }
+ }
+ }
+ while (isxdigit(*cp) &&
+ (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
+ result = result*base + value;
+ cp++;
+ }
+ if (endp)
+ *endp = (char *)cp;
+ return result;
+}
+
+/**
+ * simple_strtol - convert a string to a signed long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+long simple_strtol(const char *cp,char **endp,unsigned int base)
+{
+ if(*cp=='-')
+ return -simple_strtoul(cp+1,endp,base);
+ return simple_strtoul(cp,endp,base);
+}
+
+/**
+ * simple_strtoull - convert a string to an unsigned long long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int
base)
+{
+ unsigned long long result = 0,value;
+
+ if (!base) {
+ base = 10;
+ if (*cp == '0') {
+ base = 8;
+ cp++;
+ if ((*cp == 'x') && isxdigit(cp[1])) {
+ cp++;
+ base = 16;
+ }
+ }
+ }
+ while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
+ ? toupper(*cp)
: *cp)-'A'+10) < base) {
+ result = result*base + value;
+ cp++;
+ }
+ if (endp)
+ *endp = (char *)cp;
+ return result;
+}
+
+/**
+ * simple_strtoll - convert a string to a signed long long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+long long simple_strtoll(const char *cp,char **endp,unsigned int base)
+{
+ if(*cp=='-')
+ return -simple_strtoull(cp+1,endp,base);
+ return simple_strtoull(cp,endp,base);
+}
+
+static int skip_atoi(const char **s)
+{
+ int i=0;
+
+ while (isdigit(**s))
+ i = i*10 + *((*s)++) - '0';
+ return i;
+}
+
+#define ZEROPAD 1 /* pad with zero */
+#define SIGN 2 /* unsigned/signed long */
+#define PLUS 4 /* show plus */
+#define SPACE 8 /* space if plus */
+#define LEFT 16 /* left justified */
+#define SPECIAL 32 /* 0x */
+#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
+
+static char * number(char * buf, char * end, long long num, int base, int
size, int precision, int type)
+{
+ char c,sign,tmp[66];
+ const char *digits;
+ const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+ const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ int i;
+
+ digits = (type & LARGE) ? large_digits : small_digits;
+ if (type & LEFT)
+ type &= ~ZEROPAD;
+ if (base < 2 || base > 36)
+ return buf;
+ c = (type & ZEROPAD) ? '0' : ' ';
+ sign = 0;
+ if (type & SIGN) {
+ if (num < 0) {
+ sign = '-';
+ num = -num;
+ size--;
+ } else if (type & PLUS) {
+ sign = '+';
+ size--;
+ } else if (type & SPACE) {
+ sign = ' ';
+ size--;
+ }
+ }
+ if (type & SPECIAL) {
+ if (base == 16)
+ size -= 2;
+ else if (base == 8)
+ size--;
+ }
+ i = 0;
+ if (num == 0)
+ tmp[i++]='0';
+ else
+ {
+ /* XXX KAF: force unsigned mod and div. */
+ unsigned long long num2=(unsigned long long)num;
+ unsigned int base2=(unsigned int)base;
+ while (num2 != 0) { tmp[i++] = digits[num2%base2]; num2 /= base2; }
+ }
+ if (i > precision)
+ precision = i;
+ size -= precision;
+ if (!(type&(ZEROPAD+LEFT))) {
+ while(size-->0) {
+ if (buf <= end)
+ *buf = ' ';
+ ++buf;
+ }
+ }
+ if (sign) {
+ if (buf <= end)
+ *buf = sign;
+ ++buf;
+ }
+ if (type & SPECIAL) {
+ if (base==8) {
+ if (buf <= end)
+ *buf = '0';
+ ++buf;
+ } else if (base==16) {
+ if (buf <= end)
+ *buf = '0';
+ ++buf;
+ if (buf <= end)
+ *buf = digits[33];
+ ++buf;
+ }
+ }
+ if (!(type & LEFT)) {
+ while (size-- > 0) {
+ if (buf <= end)
+ *buf = c;
+ ++buf;
+ }
+ }
+ while (i < precision--) {
+ if (buf <= end)
+ *buf = '0';
+ ++buf;
+ }
+ while (i-- > 0) {
+ if (buf <= end)
+ *buf = tmp[i];
+ ++buf;
+ }
+ while (size-- > 0) {
+ if (buf <= end)
+ *buf = ' ';
+ ++buf;
+ }
+ return buf;
+}
+
+/**
+* vsnprintf - Format a string and place it in a buffer
+* @buf: The buffer to place the result into
+* @size: The size of the buffer, including the trailing null space
+* @fmt: The format string to use
+* @args: Arguments for the format string
+*
+* Call this function if you are already dealing with a va_list.
+* You probably want snprintf instead.
+ */
+int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
+{
+ int len;
+ unsigned long long num;
+ int i, base;
+ char *str, *end, c;
+ const char *s;
+
+ int flags; /* flags to number() */
+
+ int field_width; /* width of output field */
+ int precision; /* min. # of digits for integers; max
+ number of chars for from string */
+ int qualifier; /* 'h', 'l', or 'L' for integer fields */
+ /* 'z' support added 23/7/1999 S.H. */
+ /* 'z' changed to 'Z' --davidm 1/25/99 */
+
+ str = buf;
+ end = buf + size - 1;
+
+ if (end < buf - 1) {
+ end = ((void *) -1);
+ size = end - buf + 1;
+ }
+
+ for (; *fmt ; ++fmt) {
+ if (*fmt != '%') {
+ if (str <= end)
+ *str = *fmt;
+ ++str;
+ continue;
+ }
+
+ /* process flags */
+ flags = 0;
+ repeat:
+ ++fmt; /* this also skips first '%' */
+ switch (*fmt) {
+ case '-': flags |= LEFT; goto repeat;
+ case '+': flags |= PLUS; goto repeat;
+ case ' ': flags |= SPACE; goto repeat;
+ case '#': flags |= SPECIAL; goto repeat;
+ case '0': flags |= ZEROPAD; goto repeat;
+ }
+
+ /* get field width */
+ field_width = -1;
+ if (isdigit(*fmt))
+ field_width = skip_atoi(&fmt);
+ else if (*fmt == '*') {
+ ++fmt;
+ /* it's the next argument */
+ field_width = va_arg(args, int);
+ if (field_width < 0) {
+ field_width = -field_width;
+ flags |= LEFT;
+ }
+ }
+
+ /* get the precision */
+ precision = -1;
+ if (*fmt == '.') {
+ ++fmt;
+ if (isdigit(*fmt))
+ precision = skip_atoi(&fmt);
+ else if (*fmt == '*') {
+ ++fmt;
+ /* it's the next argument */
+ precision = va_arg(args, int);
+ }
+ if (precision < 0)
+ precision = 0;
+ }
+
+ /* get the conversion qualifier */
+ qualifier = -1;
+ if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
+ qualifier = *fmt;
+ ++fmt;
+ if (qualifier == 'l' && *fmt == 'l') {
+ qualifier = 'L';
+ ++fmt;
+ }
+ }
+ if (*fmt == 'q') {
+ qualifier = 'L';
+ ++fmt;
+ }
+
+ /* default base */
+ base = 10;
+
+ switch (*fmt) {
+ case 'c':
+ if (!(flags & LEFT)) {
+ while (--field_width > 0) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
+ }
+ c = (unsigned char) va_arg(args, int);
+ if (str <= end)
+ *str = c;
+ ++str;
+ while (--field_width > 0) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
+ continue;
+
+ case 's':
+ s = va_arg(args, char *);
+ if (!s)
+ s = "<NULL>";
+
+ len = strnlen(s, precision);
+
+ if (!(flags & LEFT)) {
+ while (len < field_width--) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
+ }
+ for (i = 0; i < len; ++i) {
+ if (str <= end)
+ *str = *s;
+ ++str; ++s;
+ }
+ while (len < field_width--) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
+ continue;
+
+ case 'p':
+ if (field_width == -1) {
+ field_width = 2*sizeof(void *);
+ flags |= ZEROPAD;
+ }
+ str = number(str, end,
+ (unsigned long) va_arg(args, void *),
+ 16, field_width, precision, flags);
+ continue;
+
+
+ case 'n':
+ /* FIXME:
+ * What does C99 say about the overflow case here? */
+ if (qualifier == 'l') {
+ long * ip = va_arg(args, long *);
+ *ip = (str - buf);
+ } else if (qualifier == 'Z') {
+ size_t * ip = va_arg(args, size_t *);
+ *ip = (str - buf);
+ } else {
+ int * ip = va_arg(args, int *);
+ *ip = (str - buf);
+ }
+ continue;
+
+ case '%':
+ if (str <= end)
+ *str = '%';
+ ++str;
+ continue;
+
+ /* integer number formats - set up the flags and
"break" */
+ case 'o':
+ base = 8;
+ break;
+
+ case 'X':
+ flags |= LARGE;
+ case 'x':
+ base = 16;
+ break;
+
+ case 'd':
+ case 'i':
+ flags |= SIGN;
+ case 'u':
+ break;
+
+ default:
+ if (str <= end)
+ *str = '%';
+ ++str;
+ if (*fmt) {
+ if (str <= end)
+ *str = *fmt;
+ ++str;
+ } else {
+ --fmt;
+ }
+ continue;
+ }
+ if (qualifier == 'L')
+ num = va_arg(args, long long);
+ else if (qualifier == 'l') {
+ num = va_arg(args, unsigned long);
+ if (flags & SIGN)
+ num = (signed long) num;
+ } else if (qualifier == 'Z') {
+ num = va_arg(args, size_t);
+ } else if (qualifier == 'h') {
+ num = (unsigned short) va_arg(args, int);
+ if (flags & SIGN)
+ num = (signed short) num;
+ } else {
+ num = va_arg(args, unsigned int);
+ if (flags & SIGN)
+ num = (signed int) num;
+ }
+
+ str = number(str, end, num, base,
+ field_width, precision, flags);
+ }
+ if (str <= end)
+ *str = '\0';
+ else if (size > 0)
+ /* don't write out a null byte if the buf size is zero */
+ *end = '\0';
+ /* the trailing null byte doesn't count towards the total
+ * ++str;
+ */
+ return str-buf;
+}
+
+/**
+ * snprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @size: The size of the buffer, including the trailing null space
+ * @fmt: The format string to use
+ * @...: Arguments for the format string
+ */
+int snprintf(char * buf, size_t size, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i=vsnprintf(buf,size,fmt,args);
+ va_end(args);
+ return i;
+}
+
+/**
+ * vsprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @fmt: The format string to use
+ * @args: Arguments for the format string
*
- * Two additional formats:
- *
- * The format %b is supported to decode error registers.
- * Its usage is:
- *
- * printf("reg=%b\n", regval, "<base><arg>*");
- *
- * where <base> is the output base expressed as a control character, e.g.
- * \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
- * the first of which gives the bit number to be inspected (origin 1), and
- * the next characters (up to a control character, i.e. a character <= 32),
- * give the name of the register. Thus:
- *
- * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
- *
- * would produce output:
- *
- * reg=3<BITTWO,BITONE>
- *
- * XXX: %D -- Hexdump, takes pointer and separator string:
- * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
- * ("%*D", len, ptr, " " -> XX XX XX XX ...
- */
-
-/* RN: This normally takes a function for output.
- * we always print to a string and the use HYPERCALL for write to console */
-static int
-kvprintf(char const *fmt, void *arg, int radix, va_list ap)
-{
-
-#define PCHAR(c) {int cc=(c); *d++ = cc; retval++; }
-
- char nbuf[MAXNBUF];
- char *p, *q, *d;
- u_char *up;
- int ch, n;
- u_long ul;
- u_quad_t uq;
- int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
- int dwidth;
- char padc;
- int retval = 0;
-
- ul = 0;
- uq = 0;
- d = (char *) arg;
-
- if (fmt == NULL)
- fmt = "(fmt null)\n";
-
- if (radix < 2 || radix > 36)
- radix = 10;
-
- for (;;) {
- padc = ' ';
- width = 0;
- while ((ch = (u_char)*fmt++) != '%') {
- if (ch == '\0')
- return retval;
- PCHAR(ch);
- }
- qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
- sign = 0; dot = 0; dwidth = 0;
-reswitch: switch (ch = (u_char)*fmt++) {
- case '.':
- dot = 1;
- goto reswitch;
- case '#':
- sharpflag = 1;
- goto reswitch;
- case '+':
- sign = 1;
- goto reswitch;
- case '-':
- ladjust = 1;
- goto reswitch;
- case '%':
- PCHAR(ch);
- break;
- case '*':
- if (!dot) {
- width = va_arg(ap, int);
- if (width < 0) {
- ladjust = !ladjust;
- width = -width;
+ * Call this function if you are already dealing with a va_list.
+ * You probably want sprintf instead.
+ */
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+ return vsnprintf(buf, 0xFFFFFFFFUL, fmt, args);
+}
+
+
+/**
+ * sprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @fmt: The format string to use
+ * @...: Arguments for the format string
+ */
+int sprintf(char * buf, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i=vsprintf(buf,fmt,args);
+ va_end(args);
+ return i;
+}
+
+
+void printf(const char *fmt, ...)
+{
+ static char buf[1024];
+ va_list args;
+
+ va_start(args, fmt);
+ (void)vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(buf), buf);
+}
+
+/**
+ * vsscanf - Unformat a buffer into a list of arguments
+ * @buf: input buffer
+ * @fmt: format of buffer
+ * @args: arguments
+ */
+int vsscanf(const char * buf, const char * fmt, va_list args)
+{
+ const char *str = buf;
+ char *next;
+ char digit;
+ int num = 0;
+ int qualifier;
+ int base;
+ int field_width;
+ int is_sign = 0;
+
+ while(*fmt && *str) {
+ /* skip any white space in format */
+ /* white space in format matchs any amount of
+ * white space, including none, in the input.
+ */
+ if (isspace(*fmt)) {
+ while (isspace(*fmt))
+ ++fmt;
+ while (isspace(*str))
+ ++str;
+ }
+
+ /* anything that is not a conversion must match exactly */
+ if (*fmt != '%' && *fmt) {
+ if (*fmt++ != *str++)
+ break;
+ continue;
+ }
+
+ if (!*fmt)
+ break;
+ ++fmt;
+
+ /* skip this conversion.
+ * advance both strings to next white space
+ */
+ if (*fmt == '*') {
+ while (!isspace(*fmt) && *fmt)
+ fmt++;
+ while (!isspace(*str) && *str)
+ str++;
+ continue;
+ }
+
+ /* get field width */
+ field_width = -1;
+ if (isdigit(*fmt))
+ field_width = skip_atoi(&fmt);
+
+ /* get conversion qualifier */
+ qualifier = -1;
+ if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
+ *fmt == 'Z' || *fmt == 'z') {
+ qualifier = *fmt++;
+ if (unlikely(qualifier == *fmt)) {
+ if (qualifier == 'h') {
+ qualifier = 'H';
+ fmt++;
+ } else if (qualifier == 'l') {
+ qualifier = 'L';
+ fmt++;
}
- } else {
- dwidth = va_arg(ap, int);
}
- goto reswitch;
- case '0':
- if (!dot) {
- padc = '0';
- goto reswitch;
+ }
+ base = 10;
+ is_sign = 0;
+
+ if (!*fmt || !*str)
+ break;
+
+ switch(*fmt++) {
+ case 'c':
+ {
+ char *s = (char *) va_arg(args,char*);
+ if (field_width == -1)
+ field_width = 1;
+ do {
+ *s++ = *str++;
+ } while (--field_width > 0 && *str);
+ num++;
+ }
+ continue;
+ case 's':
+ {
+ char *s = (char *) va_arg(args, char *);
+ if(field_width == -1)
+ field_width = INT_MAX;
+ /* first, skip leading white space in buffer */
+ while (isspace(*str))
+ str++;
+
+ /* now copy until next white space */
+ while (*str && !isspace(*str) && field_width--) {
+ *s++ = *str++;
}
- case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- for (n = 0;; ++fmt) {
- n = n * 10 + ch - '0';
- ch = *fmt;
- if (ch < '0' || ch > '9')
- break;
- }
- if (dot)
- dwidth = n;
- else
- width = n;
- goto reswitch;
- case 'b':
- ul = va_arg(ap, int);
- p = va_arg(ap, char *);
- for (q = ksprintn(nbuf, ul, *p++, NULL); *q;)
- PCHAR(*q--);
-
- if (!ul)
- break;
-
- for (tmp = 0; *p;) {
- n = *p++;
- if (ul & (1 << (n - 1))) {
- PCHAR(tmp ? ',' : '<');
- for (; (n = *p) > ' '; ++p)
- PCHAR(n);
- tmp = 1;
- } else
- for (; *p > ' '; ++p)
- continue;
- }
- if (tmp)
- PCHAR('>');
- break;
- case 'c':
- PCHAR(va_arg(ap, int));
- break;
- case 'D':
- up = va_arg(ap, u_char *);
- p = va_arg(ap, char *);
- if (!width)
- width = 16;
- while(width--) {
- PCHAR(hex2ascii(*up >> 4));
- PCHAR(hex2ascii(*up & 0x0f));
- up++;
- if (width)
- for (q=p;*q;q++)
- PCHAR(*q);
- }
- break;
- case 'd':
- if (qflag)
- uq = va_arg(ap, quad_t);
- else if (lflag)
- ul = va_arg(ap, long);
- else
- ul = va_arg(ap, int);
- sign = 1;
- base = 10;
- goto number;
- case 'l':
- if (lflag) {
- lflag = 0;
- qflag = 1;
- } else
- lflag = 1;
- goto reswitch;
+ *s = '\0';
+ num++;
+ }
+ continue;
+ case 'n':
+ /* return number of characters read so far */
+ {
+ int *i = (int *)va_arg(args,int*);
+ *i = str - buf;
+ }
+ continue;
case 'o':
- if (qflag)
- uq = va_arg(ap, u_quad_t);
- else if (lflag)
- ul = va_arg(ap, u_long);
- else
- ul = va_arg(ap, u_int);
base = 8;
- goto nosign;
- case 'p':
- ul = (uintptr_t)va_arg(ap, void *);
- base = 16;
- sharpflag = 0;
- padc = '0';
- width = sizeof(uintptr_t)*2;
- goto nosign;
- case 'q':
- qflag = 1;
- goto reswitch;
- case 'n':
- case 'r':
- if (qflag)
- uq = va_arg(ap, u_quad_t);
- else if (lflag)
- ul = va_arg(ap, u_long);
- else
- ul = sign ?
- (u_long)va_arg(ap, int) : va_arg(ap, u_int);
- base = radix;
- goto number;
- case 's':
- p = va_arg(ap, char *);
- if (p == NULL)
- p = "(null)";
- if (!dot)
- n = strlen (p);
- else
- for (n = 0; n < dwidth && p[n]; n++)
- continue;
-
- width -= n;
-
- if (!ladjust && width > 0)
- while (width--)
- PCHAR(padc);
- while (n--)
- PCHAR(*p++);
- if (ladjust && width > 0)
- while (width--)
- PCHAR(padc);
- break;
- case 'u':
- if (qflag)
- uq = va_arg(ap, u_quad_t);
- else if (lflag)
- ul = va_arg(ap, u_long);
- else
- ul = va_arg(ap, u_int);
- base = 10;
- goto nosign;
+ break;
case 'x':
case 'X':
- if (qflag)
- uq = va_arg(ap, u_quad_t);
- else if (lflag)
- ul = va_arg(ap, u_long);
- else
- ul = va_arg(ap, u_int);
base = 16;
- goto nosign;
+ break;
+ case 'i':
+ base = 0;
+ case 'd':
+ is_sign = 1;
+ case 'u':
+ break;
+ case '%':
+ /* looking for '%' in str */
+ if (*str++ != '%')
+ return num;
+ continue;
+ default:
+ /* invalid format; stop here */
+ return num;
+ }
+
+ /* have some sort of integer conversion.
+ * first, skip white space in buffer.
+ */
+ while (isspace(*str))
+ str++;
+
+ digit = *str;
+ if (is_sign && digit == '-')
+ digit = *(str + 1);
+
+ if (!digit
+ || (base == 16 && !isxdigit(digit))
+ || (base == 10 && !isdigit(digit))
+ || (base == 8 && (!isdigit(digit) || digit > '7'))
+ || (base == 0 && !isdigit(digit)))
+ break;
+
+ switch(qualifier) {
+ case 'H': /* that's 'hh' in format */
+ if (is_sign) {
+ signed char *s = (signed char *)
va_arg(args,signed char *);
+ *s = (signed char)
simple_strtol(str,&next,base);
+ } else {
+ unsigned char *s = (unsigned char *)
va_arg(args, unsigned char *);
+ *s = (unsigned char) simple_strtoul(str, &next,
base);
+ }
+ break;
+ case 'h':
+ if (is_sign) {
+ short *s = (short *) va_arg(args,short *);
+ *s = (short) simple_strtol(str,&next,base);
+ } else {
+ unsigned short *s = (unsigned short *)
va_arg(args, unsigned short *);
+ *s = (unsigned short) simple_strtoul(str,
&next, base);
+ }
+ break;
+ case 'l':
+ if (is_sign) {
+ long *l = (long *) va_arg(args,long *);
+ *l = simple_strtol(str,&next,base);
+ } else {
+ unsigned long *l = (unsigned long*)
va_arg(args,unsigned long*);
+ *l = simple_strtoul(str,&next,base);
+ }
+ break;
+ case 'L':
+ if (is_sign) {
+ long long *l = (long long*) va_arg(args,long
long *);
+ *l = simple_strtoll(str,&next,base);
+ } else {
+ unsigned long long *l = (unsigned long long*)
va_arg(args,unsigned long long*);
+ *l = simple_strtoull(str,&next,base);
+ }
+ break;
+ case 'Z':
case 'z':
- if (qflag)
- uq = va_arg(ap, u_quad_t);
- else if (lflag)
- ul = va_arg(ap, u_long);
- else
- ul = sign ?
- (u_long)va_arg(ap, int) : va_arg(ap, u_int);
- base = 16;
- goto number;
-nosign: sign = 0;
-number:
- if (qflag) {
- if (sign && (quad_t)uq < 0) {
- neg = 1;
- uq = -(quad_t)uq;
- }
- p = ksprintqn(nbuf, uq, base, &tmp);
+ {
+ size_t *s = (size_t*) va_arg(args,size_t*);
+ *s = (size_t) simple_strtoul(str,&next,base);
+ }
+ break;
+ default:
+ if (is_sign) {
+ int *i = (int *) va_arg(args, int*);
+ *i = (int) simple_strtol(str,&next,base);
} else {
- if (sign && (long)ul < 0) {
- neg = 1;
- ul = -(long)ul;
- }
- p = ksprintn(nbuf, ul, base, &tmp);
+ unsigned int *i = (unsigned int*) va_arg(args,
unsigned int*);
+ *i = (unsigned int)
simple_strtoul(str,&next,base);
}
- if (sharpflag && (qflag ? uq != 0 : ul != 0)) {
- if (base == 8)
- tmp++;
- else if (base == 16)
- tmp += 2;
- }
- if (neg)
- tmp++;
-
- if (!ladjust && width && (width -= tmp) > 0)
- while (width--)
- PCHAR(padc);
- if (neg)
- PCHAR('-');
- if (sharpflag && (qflag ? uq != 0 : ul != 0)) {
- if (base == 8) {
- PCHAR('0');
- } else if (base == 16) {
- PCHAR('0');
- PCHAR('x');
- }
- }
-
- while (*p)
- PCHAR(*p--);
-
- if (ladjust && width && (width -= tmp) > 0)
- while (width--)
- PCHAR(padc);
-
- break;
- default:
- PCHAR('%');
- if (lflag)
- PCHAR('l');
- PCHAR(ch);
- break;
- }
+ break;
+ }
+ num++;
+
+ if (!next)
+ break;
+ str = next;
}
-#undef PCHAR
-}
-
+ return num;
+}
+
+/**
+ * sscanf - Unformat a buffer into a list of arguments
+ * @buf: input buffer
+ * @fmt: formatting of buffer
+ * @...: resulting arguments
+ */
+int sscanf(const char * buf, const char * fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args,fmt);
+ i = vsscanf(buf,fmt,args);
+ va_end(args);
+ return i;
+}
+
+
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/lib/string.c
--- a/extras/mini-os/lib/string.c Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/lib/string.c Fri Sep 9 16:30:54 2005
@@ -107,6 +107,19 @@
return sc - s;
}
+
+char * strcat(char * dest, const char * src)
+{
+ char *tmp = dest;
+
+ while (*dest)
+ dest++;
+
+ while ((*dest++ = *src++) != '\0');
+
+ return tmp;
+}
+
size_t strlen(const char * s)
{
const char *sc;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/mm.c
--- a/extras/mini-os/mm.c Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/mm.c Fri Sep 9 16:30:54 2005
@@ -198,7 +198,6 @@
#endif
-
/*
* Initialise allocator, placing addresses [@min,@max] in free pool.
* @min and @max are PHYSICAL addresses.
@@ -486,16 +485,17 @@
phys_to_machine_mapping = (unsigned long *)start_info.mfn_list;
/* First page follows page table pages and 3 more pages (store page etc) */
- start_pfn = PFN_UP(__pa(start_info.pt_base)) + start_info.nr_pt_frames + 3;
+ start_pfn = PFN_UP(to_phys(start_info.pt_base)) + start_info.nr_pt_frames
+ 3;
max_pfn = start_info.nr_pages;
printk(" start_pfn: %lx\n", start_pfn);
printk(" max_pfn: %lx\n", max_pfn);
+#ifdef __i386__
build_pagetable(&start_pfn, &max_pfn);
-
-#ifdef __i386__
+#endif
+
/*
* now we can initialise the page allocator
*/
@@ -503,7 +503,5 @@
(u_long)to_virt(PFN_PHYS(start_pfn)), PFN_PHYS(start_pfn),
(u_long)to_virt(PFN_PHYS(max_pfn)), PFN_PHYS(max_pfn));
init_page_allocator(PFN_PHYS(start_pfn), PFN_PHYS(max_pfn));
-#endif
-
printk("MM: done\n");
}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/time.c
--- a/extras/mini-os/time.c Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/time.c Fri Sep 9 16:30:54 2005
@@ -203,7 +203,7 @@
}
-void block(u32 millisecs)
+void block_domain(u32 millisecs)
{
struct timeval tv;
gettimeofday(&tv);
@@ -232,5 +232,6 @@
void init_time(void)
{
+ printk("Initialising timer interface\n");
bind_virq(VIRQ_TIMER, &timer_handler);
}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/traps.c
--- a/extras/mini-os/traps.c Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/traps.c Fri Sep 9 16:30:54 2005
@@ -33,36 +33,7 @@
void dump_regs(struct pt_regs *regs)
{
- unsigned long esp;
- unsigned short ss;
-
-#ifdef __x86_64__
- esp = regs->rsp;
- ss = regs->xss;
-#else
- esp = (unsigned long) (®s->esp);
- ss = __KERNEL_DS;
- if (regs->xcs & 2) {
-printk("CS is true, esp is %x\n", regs->esp);
- esp = regs->esp;
- ss = regs->xss & 0xffff;
- }
-#endif
- printf("EIP: %04x:[<%p>]\n",
- 0xffff & regs->xcs , regs->eip);
- printf("EFLAGS: %p\n",regs->eflags);
- printf("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
- regs->eax, regs->ebx, regs->ecx, regs->edx);
- printf("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",
- regs->esi, regs->edi, regs->ebp, esp);
-#ifdef __x86_64__
- printf("r8 : %p r9 : %p r10: %p r11: %p\n",
- regs->r8, regs->r9, regs->r10, regs->r11);
- printf("r12: %p r13: %p r14: %p r15: %p\n",
- regs->r12, regs->r13, regs->r14, regs->r15);
-#endif
- printf("ds: %04x es: %04x ss: %04x\n",
- regs->xds & 0xffff, regs->xes & 0xffff, ss);
+ printk("FIXME: proper register dump (with the stack dump)\n");
}
@@ -105,6 +76,7 @@
printk("Page fault at linear address %p\n", addr);
dump_regs(regs);
#ifdef __x86_64__
+ /* FIXME: _PAGE_PSE */
{
unsigned long *tab = (unsigned long *)start_info.pt_base;
unsigned long page;
@@ -112,23 +84,16 @@
printk("Pagetable walk from %p:\n", tab);
page = tab[l4_table_offset(addr)];
- tab = __va(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT);
+ tab = to_virt(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT);
printk(" L4 = %p (%p)\n", page, tab);
- if ( !(page & AGERESENT) )
- goto out;
page = tab[l3_table_offset(addr)];
- tab = __va(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT);
+ tab = to_virt(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT);
printk(" L3 = %p (%p)\n", page, tab);
- if ( !(page & AGERESENT) )
- goto out;
page = tab[l2_table_offset(addr)];
- tab = __va(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT);
- printk(" L2 = %p (%p) %s\n", page, tab,
- (page & AGESE) ? "(2MB)" : "");
- if ( !(page & AGERESENT) || (page & AGESE) )
- goto out;
+ tab = to_virt(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT);
+ printk(" L2 = %p (%p)\n", page, tab);
page = tab[l1_table_offset(addr)];
printk(" L1 = %p\n", page);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 linux-2.4-xen-sparse/mkbuildtree
--- a/linux-2.4-xen-sparse/mkbuildtree Thu Sep 8 15:18:40 2005
+++ b/linux-2.4-xen-sparse/mkbuildtree Fri Sep 9 16:30:54 2005
@@ -102,9 +102,9 @@
relative_lndir ${RS}
rm -f mkbuildtree
-set ${RS}/../linux-2.6-xen-sparse
-[ "$1" == "${RS}/../linux-2.6-xen-sparse" ] && { echo "no Linux 2.6 sparse
tree at ${RS}/../linux-2.6-xen-sparse"; exit 1; }
-LINUX_26="$1"
+LINUX_26=${RS}/../linux-2.6-xen-sparse
+[ -d $LINUX_26 ] || { echo "no Linux 2.6 sparse tree at
${RS}/../linux-2.6-xen-sparse"; exit 1; }
+
# Create links to the shared definitions of the Xen interfaces.
rm -rf ${AD}/include/asm-xen/xen-public
diff -r 10b1d30d3f66 -r b2f4823b6ff0 linux-2.6-xen-sparse/arch/xen/Kconfig
--- a/linux-2.6-xen-sparse/arch/xen/Kconfig Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/Kconfig Fri Sep 9 16:30:54 2005
@@ -70,6 +70,27 @@
network devices to other guests via a high-performance shared-memory
interface.
+config XEN_TPMDEV_FRONTEND
+ bool "TPM-device frontend driver"
+ default n
+ help
+ The TPM-device frontend driver.
+
+config XEN_TPMDEV_BACKEND
+ bool "TPM-device backend driver"
+ default n
+ help
+ The TPM-device backend driver
+
+config XEN_TPMDEV_CLOSE_IF_VTPM_FAILS
+ bool "TPM backend closes upon vTPM failure"
+ depends on XEN_TPMDEV_BACKEND
+ default n
+ help
+ The TPM backend closes the channel if the vTPM in userspace indicates
+ a failure. The corresponding domain's channel will be closed.
+ Say Y if you want this feature.
+
config XEN_BLKDEV_FRONTEND
bool "Block-device frontend driver"
default y
@@ -88,15 +109,8 @@
dedicated device-driver domain, or your master control domain
(domain 0), then you almost certainly want to say Y here.
-config XEN_NETDEV_GRANT_TX
- bool "Grant table substrate for net drivers tx path (DANGEROUS)"
- default n
- help
- This introduces the use of grant tables as a data exhange mechanism
- between the frontend and backend network drivers.
-
-config XEN_NETDEV_GRANT_RX
- bool "Grant table substrate for net drivers rx path (DANGEROUS)"
+config XEN_NETDEV_GRANT
+ bool "Grant table substrate for network drivers (DANGEROUS)"
default n
help
This introduces the use of grant tables as a data exhange mechanism
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/Kconfig.drivers
--- a/linux-2.6-xen-sparse/arch/xen/Kconfig.drivers Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/Kconfig.drivers Fri Sep 9 16:30:54 2005
@@ -49,6 +49,10 @@
endif
if !XEN_PHYSDEV_ACCESS
+source "drivers/char/tpm/Kconfig.domU"
+endif
+
+if !XEN_PHYSDEV_ACCESS
menu "Character devices"
diff -r 10b1d30d3f66 -r b2f4823b6ff0 linux-2.6-xen-sparse/arch/xen/Makefile
--- a/linux-2.6-xen-sparse/arch/xen/Makefile Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/Makefile Fri Sep 9 16:30:54 2005
@@ -65,6 +65,7 @@
XINSTALL_NAME ?= $(KERNELRELEASE)
install: vmlinuz
+install kernel_install:
mkdir -p $(INSTALL_PATH)/boot
ln -f -s vmlinuz-$(XINSTALL_NAME)$(INSTALL_SUFFIX)
$(INSTALL_PATH)/boot/vmlinuz-$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(XENGUEST)$(INSTALL_SUFFIX)
rm -f $(INSTALL_PATH)/boot/vmlinuz-$(XINSTALL_NAME)$(INSTALL_SUFFIX)
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32
--- a/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32 Thu Sep
8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32 Fri Sep
9 16:30:54 2005
@@ -15,10 +15,11 @@
CONFIG_XEN_BLKDEV_BACKEND=y
# CONFIG_XEN_BLKDEV_TAP_BE is not set
CONFIG_XEN_NETDEV_BACKEND=y
+# CONFIG_XEN_TPMDEV_FRONTEND is not set
+# CONFIG_XEN_TPMDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
-CONFIG_XEN_NETDEV_GRANT_TX=y
-CONFIG_XEN_NETDEV_GRANT_RX=y
+CONFIG_XEN_NETDEV_GRANT=y
# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
# CONFIG_XEN_BLKDEV_TAP is not set
# CONFIG_XEN_SHADOW_MODE is not set
@@ -1122,7 +1123,7 @@
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
+CONFIG_CRAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64
--- a/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64 Thu Sep
8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64 Fri Sep
9 16:30:54 2005
@@ -15,10 +15,11 @@
CONFIG_XEN_BLKDEV_BACKEND=y
# CONFIG_XEN_BLKDEV_TAP_BE is not set
CONFIG_XEN_NETDEV_BACKEND=y
+# CONFIG_XEN_TPMDEV_FRONTEND is not set
+# CONFIG_XEN_TPMDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
-CONFIG_XEN_NETDEV_GRANT_TX=y
-CONFIG_XEN_NETDEV_GRANT_RX=y
+CONFIG_XEN_NETDEV_GRANT=y
# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
# CONFIG_XEN_BLKDEV_TAP is not set
# CONFIG_XEN_SHADOW_MODE is not set
@@ -195,6 +196,7 @@
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=16384
@@ -1030,7 +1032,7 @@
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
+CONFIG_CRAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32
--- a/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32 Thu Sep
8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32 Fri Sep
9 16:30:54 2005
@@ -12,10 +12,11 @@
#
# CONFIG_XEN_PRIVILEGED_GUEST is not set
# CONFIG_XEN_PHYSDEV_ACCESS is not set
+# CONFIG_XEN_TPMDEV_FRONTEND is not set
+# CONFIG_XEN_TPMDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
-CONFIG_XEN_NETDEV_GRANT_TX=y
-CONFIG_XEN_NETDEV_GRANT_RX=y
+CONFIG_XEN_NETDEV_GRANT=y
# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
# CONFIG_XEN_BLKDEV_TAP is not set
# CONFIG_XEN_SHADOW_MODE is not set
@@ -336,6 +337,7 @@
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_TCG_TPM is not set
#
# Character devices
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_64
--- a/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_64 Thu Sep
8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_64 Fri Sep
9 16:30:54 2005
@@ -12,10 +12,11 @@
#
# CONFIG_XEN_PRIVILEGED_GUEST is not set
# CONFIG_XEN_PHYSDEV_ACCESS is not set
+# CONFIG_XEN_TPMDEV_FRONTEND is not set
+# CONFIG_XEN_TPMDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
-CONFIG_XEN_NETDEV_GRANT_TX=y
-CONFIG_XEN_NETDEV_GRANT_RX=y
+CONFIG_XEN_NETDEV_GRANT=y
# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
# CONFIG_XEN_BLKDEV_TAP is not set
# CONFIG_XEN_SHADOW_MODE is not set
@@ -662,6 +663,7 @@
CONFIG_INPUT=m
CONFIG_UNIX98_PTYS=y
# CONFIG_LEGACY_PTYS is not set
+# CONFIG_TCG_TPM is not set
#
# Character devices
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32
--- a/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32 Thu Sep
8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32 Fri Sep
9 16:30:54 2005
@@ -15,10 +15,11 @@
CONFIG_XEN_BLKDEV_BACKEND=y
# CONFIG_XEN_BLKDEV_TAP_BE is not set
CONFIG_XEN_NETDEV_BACKEND=y
+# CONFIG_XEN_TPMDEV_FRONTEND is not set
+# CONFIG_XEN_TPMDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
-CONFIG_XEN_NETDEV_GRANT_TX=y
-CONFIG_XEN_NETDEV_GRANT_RX=y
+CONFIG_XEN_NETDEV_GRANT=y
# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
# CONFIG_XEN_BLKDEV_TAP is not set
# CONFIG_XEN_SHADOW_MODE is not set
@@ -1855,9 +1856,7 @@
#
# TPM devices
#
-CONFIG_TCG_TPM=m
-CONFIG_TCG_NSC=m
-CONFIG_TCG_ATMEL=m
+# CONFIG_TCG_TPM is not set
#
# I2C support
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64
--- a/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64 Thu Sep
8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64 Fri Sep
9 16:30:54 2005
@@ -15,10 +15,11 @@
CONFIG_XEN_BLKDEV_BACKEND=y
# CONFIG_XEN_BLKDEV_TAP_BE is not set
CONFIG_XEN_NETDEV_BACKEND=y
+# CONFIG_XEN_TPMDEV_FRONTEND is not set
+# CONFIG_XEN_TPMDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
-CONFIG_XEN_NETDEV_GRANT_TX=y
-CONFIG_XEN_NETDEV_GRANT_RX=y
+CONFIG_XEN_NETDEV_GRANT=y
# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
# CONFIG_XEN_BLKDEV_TAP is not set
# CONFIG_XEN_SHADOW_MODE is not set
@@ -2201,7 +2202,7 @@
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
+CONFIG_DEVFS_FS=y
CONFIG_DEVPTS_FS_XATTR=y
CONFIG_DEVPTS_FS_SECURITY=y
CONFIG_TMPFS=y
@@ -2231,7 +2232,7 @@
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
-CONFIG_CRAMFS=m
+CONFIG_CRAMFS=y
CONFIG_VXFS_FS=m
# CONFIG_HPFS_FS is not set
CONFIG_QNX4FS_FS=m
diff -r 10b1d30d3f66 -r b2f4823b6ff0 linux-2.6-xen-sparse/arch/xen/i386/Kconfig
--- a/linux-2.6-xen-sparse/arch/xen/i386/Kconfig Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/Kconfig Fri Sep 9 16:30:54 2005
@@ -379,18 +379,18 @@
If you don't know what to do here, say N.
config SMP_ALTERNATIVES
- bool "SMP alternatives support (EXPERIMENTAL)"
- depends on SMP && EXPERIMENTAL
- help
- Try to reduce the overhead of running an SMP kernel on a uniprocessor
- host slightly by replacing certain key instruction sequences
- according to whether we currently have more than one CPU available.
- This should provide a noticeable boost to performance when
- running SMP kernels on UP machines, and have negligible impact
- when running on an true SMP host.
+ bool "SMP alternatives support (EXPERIMENTAL)"
+ depends on SMP && EXPERIMENTAL
+ help
+ Try to reduce the overhead of running an SMP kernel on a uniprocessor
+ host slightly by replacing certain key instruction sequences
+ according to whether we currently have more than one CPU available.
+ This should provide a noticeable boost to performance when
+ running SMP kernels on UP machines, and have negligible impact
+ when running on an true SMP host.
If unsure, say N.
-
+
config NR_CPUS
int "Maximum number of CPUs (2-255)"
range 2 255
@@ -807,8 +807,8 @@
direct access method and falls back to the BIOS if that doesn't
work. If unsure, go with the default, which is "Any".
-config PCI_GOBIOS
- bool "BIOS"
+#config PCI_GOBIOS
+# bool "BIOS"
config PCI_GOMMCONFIG
bool "MMConfig"
@@ -821,10 +821,10 @@
endchoice
-config PCI_BIOS
- bool
- depends on !X86_VISWS && PCI && (PCI_GOBIOS || PCI_GOANY)
- default y
+#config PCI_BIOS
+# bool
+# depends on !X86_VISWS && PCI && (PCI_GOBIOS || PCI_GOANY)
+# default y
config PCI_DIRECT
bool
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/i386/kernel/Makefile
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/Makefile Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/Makefile Fri Sep 9
16:30:54 2005
@@ -5,6 +5,7 @@
XENARCH := $(subst ",,$(CONFIG_XENARCH))
CFLAGS += -Iarch/$(XENARCH)/kernel
+AFLAGS += -Iarch/$(XENARCH)/kernel
extra-y := head.o init_task.o
@@ -32,7 +33,7 @@
obj-$(CONFIG_X86_LOCAL_APIC) += apic.o
c-obj-$(CONFIG_X86_LOCAL_APIC) += nmi.o
obj-$(CONFIG_X86_IO_APIC) += io_apic.o
-c-obj-$(CONFIG_X86_REBOOTFIXUPS)+= reboot_fixups.o
+c-obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups.o
c-obj-$(CONFIG_X86_NUMAQ) += numaq.o
c-obj-$(CONFIG_X86_SUMMIT_NUMA) += summit.o
c-obj-$(CONFIG_MODULES) += module.o
@@ -69,7 +70,7 @@
$(obj)/vsyscall-int80.so $(obj)/vsyscall-sysenter.so: \
$(obj)/vsyscall-%.so: $(src)/vsyscall.lds \
- $(obj)/vsyscall-%.o FORCE
+ $(obj)/vsyscall-%.o $(obj)/vsyscall-note.o FORCE
$(call if_changed,syscall)
# We also create a special relocatable object that should mirror the symbol
@@ -81,20 +82,17 @@
SYSCFLAGS_vsyscall-syms.o = -r
$(obj)/vsyscall-syms.o: $(src)/vsyscall.lds \
- $(obj)/vsyscall-sysenter.o FORCE
+ $(obj)/vsyscall-sysenter.o $(obj)/vsyscall-note.o FORCE
$(call if_changed,syscall)
c-link :=
-s-link := vsyscall-int80.o vsyscall-sysenter.o vsyscall-sigreturn.o
vsyscall.lds.o syscall_table.o
+s-link := vsyscall-int80.o vsyscall-sysenter.o vsyscall-sigreturn.o
vsyscall.lds.o vsyscall-note.o
$(patsubst %.o,$(obj)/%.c,$(c-obj-y) $(c-obj-m) $(c-link)) $(patsubst
%.o,$(obj)/%.S,$(s-obj-y) $(s-link)):
@ln -fsn $(srctree)/arch/i386/kernel/$(notdir $@) $@
$(obj)/vsyscall-int80.S: $(obj)/vsyscall-sigreturn.S
-EXTRA_AFLAGS += -I$(obj)
-$(obj)/entry.o: $(src)/entry.S $(src)/syscall_table.S
-
obj-y += $(c-obj-y) $(s-obj-y)
obj-m += $(c-obj-m)
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/i386/kernel/acpi/boot.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/acpi/boot.c Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/acpi/boot.c Fri Sep 9
16:30:54 2005
@@ -469,6 +469,18 @@
unsigned int irq;
unsigned int plat_gsi = gsi;
+#ifdef CONFIG_PCI
+ /*
+ * Make sure all (legacy) PCI IRQs are set as level-triggered.
+ */
+ if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) {
+ extern void eisa_set_level_irq(unsigned int irq);
+
+ if (edge_level == ACPI_LEVEL_SENSITIVE)
+ eisa_set_level_irq(gsi);
+ }
+#endif
+
#ifdef CONFIG_X86_IO_APIC
if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) {
plat_gsi = mp_register_gsi(gsi, edge_level, active_high_low);
@@ -610,7 +622,7 @@
acpi_fadt.force_apic_physical_destination_mode =
fadt->force_apic_physical_destination_mode;
#endif
-#ifdef CONFIG_X86_PM_TIMER
+#if defined(CONFIG_X86_PM_TIMER) && !defined(CONFIG_XEN)
/* detect the location of the ACPI PM Timer */
if (fadt->revision >= FADT2_REVISION_ID) {
/* FADT rev. 2 */
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/main.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/main.c Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/main.c Fri Sep 9
16:30:54 2005
@@ -147,7 +147,7 @@
{
struct cpuinfo_x86 *c = &boot_cpu_data;
- if (!(xen_start_info.flags & SIF_PRIVILEGED))
+ if (!(xen_start_info->flags & SIF_PRIVILEGED))
return -ENODEV;
if ((!cpu_has(c, X86_FEATURE_MTRR)) &&
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/i386/kernel/entry.S
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/entry.S Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/entry.S Fri Sep 9 16:30:54 2005
@@ -47,6 +47,7 @@
#include <asm/segment.h>
#include <asm/smp.h>
#include <asm/page.h>
+#include <asm/desc.h>
#include "irq_vectors.h"
#include <asm-xen/xen-public/xen.h>
@@ -112,7 +113,7 @@
XEN_BLOCK_EVENTS(%esi)
#else
#define preempt_stop
-#define resume_kernel restore_all
+#define resume_kernel restore_nocheck
#endif
#define SAVE_ALL \
@@ -161,11 +162,9 @@
addl $4, %esp; \
1: iret; \
.section .fixup,"ax"; \
-2: movl $(__USER_DS), %edx; \
- movl %edx, %ds; \
- movl %edx, %es; \
- movl $11,%eax; \
- call do_exit; \
+2: pushl $0; \
+ pushl $do_iret_error; \
+ jmp error_code; \
.previous; \
.section __ex_table,"a";\
.align 4; \
@@ -196,7 +195,7 @@
movl EFLAGS(%esp), %eax # mix EFLAGS and CS
movb CS(%esp), %al
testl $(VM_MASK | 2), %eax
- jz resume_kernel # returning to kernel or vm86-space
+ jz resume_kernel
ENTRY(resume_userspace)
XEN_BLOCK_EVENTS(%esi) # make sure we don't miss an interrupt
# setting need_resched or sigpending
@@ -211,7 +210,7 @@
ENTRY(resume_kernel)
XEN_BLOCK_EVENTS(%esi)
cmpl $0,TI_preempt_count(%ebp) # non-zero preempt_count ?
- jnz restore_all
+ jnz restore_nocheck
need_resched:
movl TI_flags(%ebp), %ecx # need_resched set ?
testb $_TIF_NEED_RESCHED, %cl
@@ -252,7 +251,8 @@
SAVE_ALL
GET_THREAD_INFO(%ebp)
- testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
+ /* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not
testb */
+ testw
$(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),TI_flags(%ebp)
jnz syscall_trace_entry
cmpl $(nr_syscalls), %eax
jae syscall_badsys
@@ -276,7 +276,8 @@
SAVE_ALL
GET_THREAD_INFO(%ebp)
# system call tracing in operation
- testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
+ /* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not
testb */
+ testw
$(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),TI_flags(%ebp)
jnz syscall_trace_entry
cmpl $(nr_syscalls), %eax
jae syscall_badsys
@@ -290,7 +291,20 @@
movl TI_flags(%ebp), %ecx
testw $_TIF_ALLWORK_MASK, %cx # current->work
jne syscall_exit_work
+
restore_all:
+#if 0 /* XEN */
+ movl EFLAGS(%esp), %eax # mix EFLAGS, SS and CS
+ # Warning: OLDSS(%esp) contains the wrong/random values if we
+ # are returning to the kernel.
+ # See comments in process.c:copy_thread() for details.
+ movb OLDSS(%esp), %ah
+ movb CS(%esp), %al
+ andl $(VM_MASK | (4 << 8) | 3), %eax
+ cmpl $((4 << 8) | 3), %eax
+ je ldt_ss # returning to user-space with LDT SS
+#endif /* XEN */
+restore_nocheck:
testl $VM_MASK, EFLAGS(%esp)
jnz resume_vm86
movb EVENT_MASK(%esp), %al
@@ -300,7 +314,19 @@
andb $1,%al # %al == mask & ~saved_mask
jnz restore_all_enable_events # != 0 => reenable event delivery
XEN_PUT_VCPU_INFO(%esi)
- RESTORE_ALL
+ RESTORE_REGS
+ addl $4, %esp
+1: iret
+.section .fixup,"ax"
+iret_exc:
+ pushl $0 # no error code
+ pushl $do_iret_error
+ jmp error_code
+.previous
+.section __ex_table,"a"
+ .align 4
+ .long 1b,iret_exc
+.previous
resume_vm86:
XEN_UNBLOCK_EVENTS(%esi)
@@ -309,6 +335,33 @@
movl $__HYPERVISOR_switch_vm86,%eax
int $0x82
ud2
+
+#if 0 /* XEN */
+ldt_ss:
+ larl OLDSS(%esp), %eax
+ jnz restore_nocheck
+ testl $0x00400000, %eax # returning to 32bit stack?
+ jnz restore_nocheck # allright, normal return
+ /* If returning to userspace with 16bit stack,
+ * try to fix the higher word of ESP, as the CPU
+ * won't restore it.
+ * This is an "official" bug of all the x86-compatible
+ * CPUs, which we can try to work around to make
+ * dosemu and wine happy. */
+ subl $8, %esp # reserve space for switch16 pointer
+ cli
+ movl %esp, %eax
+ /* Set up the 16bit stack frame with switch32 pointer on top,
+ * and a switch16 pointer on top of the current frame. */
+ call setup_x86_bogus_stack
+ RESTORE_REGS
+ lss 20+4(%esp), %esp # switch to 16bit stack
+1: iret
+.section __ex_table,"a"
+ .align 4
+ .long 1b,iret_exc
+.previous
+#endif /* XEN */
# perform work that needs to be done immediately before resumption
ALIGN
@@ -385,6 +438,27 @@
jmp resume_userspace
#if 0 /* XEN */
+#define FIXUP_ESPFIX_STACK \
+ movl %esp, %eax; \
+ /* switch to 32bit stack using the pointer on top of 16bit stack */ \
+ lss %ss:CPU_16BIT_STACK_SIZE-8, %esp; \
+ /* copy data from 16bit stack to 32bit stack */ \
+ call fixup_x86_bogus_stack; \
+ /* put ESP to the proper location */ \
+ movl %eax, %esp;
+#define UNWIND_ESPFIX_STACK \
+ pushl %eax; \
+ movl %ss, %eax; \
+ /* see if on 16bit stack */ \
+ cmpw $__ESPFIX_SS, %ax; \
+ jne 28f; \
+ movl $__KERNEL_DS, %edx; \
+ movl %edx, %ds; \
+ movl %edx, %es; \
+ /* switch to 32bit stack */ \
+ FIXUP_ESPFIX_STACK \
+28: popl %eax;
+
/*
* Build the entry stubs and pointer table with
* some assembler magic.
@@ -440,7 +514,9 @@
pushl %ecx
pushl %ebx
cld
- movl %es, %ecx
+ pushl %es
+# UNWIND_ESPFIX_STACK
+ popl %ecx
movl ES(%esp), %edi # get the function address
movl ORIG_EAX(%esp), %edx # get the error code
movl %eax, ORIG_EAX(%esp)
@@ -625,6 +701,11 @@
* fault happened on the sysenter path.
*/
ENTRY(nmi)
+ pushl %eax
+ movl %ss, %eax
+ cmpw $__ESPFIX_SS, %ax
+ popl %eax
+ je nmi_16bit_stack
cmpl $sysenter_entry,(%esp)
je nmi_stack_fixup
pushl %eax
@@ -644,7 +725,7 @@
xorl %edx,%edx # zero error code
movl %esp,%eax # pt_regs pointer
call do_nmi
- RESTORE_ALL
+ jmp restore_all
nmi_stack_fixup:
FIX_STACK(12,nmi_stack_correct, 1)
@@ -659,6 +740,29 @@
nmi_debug_stack_fixup:
FIX_STACK(24,nmi_stack_correct, 1)
jmp nmi_stack_correct
+
+nmi_16bit_stack:
+ /* create the pointer to lss back */
+ pushl %ss
+ pushl %esp
+ movzwl %sp, %esp
+ addw $4, (%esp)
+ /* copy the iret frame of 12 bytes */
+ .rept 3
+ pushl 16(%esp)
+ .endr
+ pushl %eax
+ SAVE_ALL
+ FIXUP_ESPFIX_STACK # %eax == %esp
+ xorl %edx,%edx # zero error code
+ call do_nmi
+ RESTORE_REGS
+ lss 12+4(%esp), %esp # back to 16bit stack
+1: iret
+.section __ex_table,"a"
+ .align 4
+ .long 1b,iret_exc
+.previous
#endif /* XEN */
ENTRY(int3)
@@ -725,7 +829,9 @@
pushl %ecx
pushl %ebx
cld
- movl %es,%edi
+ pushl %es
+# UNWIND_ESPFIX_STACK
+ popl %edi
movl ES(%esp), %ecx /* get the faulting address */
movl ORIG_EAX(%esp), %edx /* get the error code */
movl %eax, ORIG_EAX(%esp)
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/i386/kernel/head.S
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/head.S Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/head.S Fri Sep 9 16:30:54 2005
@@ -38,17 +38,13 @@
#define X86_VENDOR_ID new_cpu_data+CPUINFO_x86_vendor_id
ENTRY(startup_32)
- cld
-
- /* Copy the necessary stuff from xen_start_info structure. */
- mov $xen_start_info_union,%edi
- mov $512,%ecx
- rep movsl
+ movl %esi,xen_start_info
#ifdef CONFIG_SMP
ENTRY(startup_32_smp)
+#endif /* CONFIG_SMP */
+
cld
-#endif /* CONFIG_SMP */
/* Set up the stack pointer */
lss stack_start,%esp
@@ -179,7 +175,7 @@
.quad 0x0000000000000000 /* 0xc0 APM CS 16 code (16 bit) */
.quad 0x0000000000000000 /* 0xc8 APM DS data */
- .quad 0x0000000000000000 /* 0xd0 - unused */
+ .quad 0x0000000000000000 /* 0xd0 - ESPFIX 16-bit SS */
.quad 0x0000000000000000 /* 0xd8 - unused */
.quad 0x0000000000000000 /* 0xe0 - unused */
.quad 0x0000000000000000 /* 0xe8 - unused */
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/i386/kernel/irq.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/irq.c Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/irq.c Fri Sep 9 16:30:54 2005
@@ -242,12 +242,12 @@
} else if (i == NR_IRQS) {
seq_printf(p, "NMI: ");
for_each_cpu(j)
- seq_printf(p, "%10u ", nmi_count(j));
+ seq_printf(p, "%10u ", nmi_count(j));
seq_putc(p, '\n');
#ifdef CONFIG_X86_LOCAL_APIC
seq_printf(p, "LOC: ");
for_each_cpu(j)
- seq_printf(p, "%10u ", per_cpu(irq_stat,
j).apic_timer_irqs);
+ seq_printf(p, "%10u ",
per_cpu(irq_stat,j).apic_timer_irqs);
seq_putc(p, '\n');
#endif
seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
@@ -263,6 +263,7 @@
void fixup_irqs(cpumask_t map)
{
unsigned int irq;
+ static int warned;
for (irq = 0; irq < NR_IRQS; irq++) {
cpumask_t mask;
@@ -276,7 +277,7 @@
}
if (irq_desc[irq].handler->set_affinity)
irq_desc[irq].handler->set_affinity(irq, mask);
- else if (irq_desc[irq].action)
+ else if (irq_desc[irq].action && !(warned++))
printk("Cannot set affinity for irq %i\n", irq);
}
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/i386/kernel/pci-dma.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/pci-dma.c Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/pci-dma.c Fri Sep 9
16:30:54 2005
@@ -115,9 +115,9 @@
if (swiotlb)
return swiotlb_dma_supported(dev, mask);
/*
- * By default we'll BUG when an infeasible DMA is requested, and
- * request swiotlb=force (see IOMMU_BUG_ON).
- */
+ * By default we'll BUG when an infeasible DMA is requested, and
+ * request swiotlb=force (see IOMMU_BUG_ON).
+ */
return 1;
}
EXPORT_SYMBOL(dma_supported);
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c Fri Sep 9
16:30:54 2005
@@ -135,6 +135,10 @@
* low exit latency (ie sit in a loop waiting for
* somebody to say that they'd like to reschedule)
*/
+#ifdef CONFIG_SMP
+extern void smp_suspend(void);
+extern void smp_resume(void);
+#endif
void cpu_idle (void)
{
int cpu = _smp_processor_id();
@@ -149,6 +153,9 @@
if (cpu_is_offline(cpu)) {
local_irq_disable();
+#ifdef CONFIG_SMP
+ smp_suspend();
+#endif
#if defined(CONFIG_XEN) && defined(CONFIG_HOTPLUG_CPU)
/* Ack it. From this point on until
we get woken up, we're not allowed
@@ -159,6 +166,9 @@
HYPERVISOR_vcpu_down(cpu);
#endif
play_dead();
+#ifdef CONFIG_SMP
+ smp_resume();
+#endif
local_irq_enable();
}
@@ -456,7 +466,6 @@
boot_option_idle_override = 1;
return 1;
}
-
/*
* switch_to(x,yn) should switch tasks from x to y.
@@ -789,10 +798,3 @@
sp -= get_random_int() % 8192;
return sp & ~0xf;
}
-
-
-#ifndef CONFIG_X86_SMP
-void _restore_vcpu(void)
-{
-}
-#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/i386/kernel/setup.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/setup.c Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/setup.c Fri Sep 9 16:30:54 2005
@@ -55,6 +55,7 @@
#include <asm/io.h>
#include <asm-xen/hypervisor.h>
#include <asm-xen/xen-public/physdev.h>
+#include <asm-xen/xen-public/memory.h>
#include "setup_arch_pre.h"
#include <bios_ebda.h>
@@ -288,7 +289,7 @@
int i;
/* Nothing to do if not running in dom0. */
- if (!(xen_start_info.flags & SIF_INITDOMAIN))
+ if (!(xen_start_info->flags & SIF_INITDOMAIN))
return;
/* video rom */
@@ -358,11 +359,12 @@
shared_info_t *HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
EXPORT_SYMBOL(HYPERVISOR_shared_info);
-unsigned int *phys_to_machine_mapping, *pfn_to_mfn_frame_list;
+unsigned long *phys_to_machine_mapping;
+unsigned long *pfn_to_mfn_frame_list_list, *pfn_to_mfn_frame_list[16];
EXPORT_SYMBOL(phys_to_machine_mapping);
/* Raw start-of-day parameters from the hypervisor. */
-union xen_start_info_union xen_start_info_union;
+start_info_t *xen_start_info;
static void __init limit_regions(unsigned long long size)
{
@@ -702,7 +704,7 @@
if ((max_cmdline = MAX_GUEST_CMDLINE) > COMMAND_LINE_SIZE)
max_cmdline = COMMAND_LINE_SIZE;
- memcpy(saved_command_line, xen_start_info.cmd_line, max_cmdline);
+ memcpy(saved_command_line, xen_start_info->cmd_line, max_cmdline);
/* Save unparsed command line copy for /proc/cmdline */
saved_command_line[max_cmdline-1] = '\0';
@@ -933,8 +935,8 @@
/* We don't use the fake e820 because we need to respond to user override. */
void __init find_max_pfn(void)
{
- if ( xen_override_max_pfn < xen_start_info.nr_pages )
- xen_override_max_pfn = xen_start_info.nr_pages;
+ if ( xen_override_max_pfn < xen_start_info->nr_pages )
+ xen_override_max_pfn = xen_start_info->nr_pages;
max_pfn = xen_override_max_pfn;
}
#endif /* XEN */
@@ -1077,12 +1079,12 @@
void __init setup_bootmem_allocator(void);
static unsigned long __init setup_memory(void)
{
-
/*
* partially used pages are not usable - thus
* we are rounding upwards:
*/
- min_low_pfn = PFN_UP(__pa(xen_start_info.pt_base)) +
xen_start_info.nr_pt_frames;
+ min_low_pfn = PFN_UP(__pa(xen_start_info->pt_base)) +
+ xen_start_info->nr_pt_frames;
find_max_pfn();
@@ -1188,7 +1190,7 @@
#endif /* !CONFIG_XEN */
#ifdef CONFIG_BLK_DEV_INITRD
- if (xen_start_info.mod_start) {
+ if (xen_start_info->mod_start) {
if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
/*reserve_bootmem(INITRD_START, INITRD_SIZE);*/
initrd_start = INITRD_START + PAGE_OFFSET;
@@ -1205,7 +1207,7 @@
}
#endif
- phys_to_machine_mapping = (unsigned int *)xen_start_info.mfn_list;
+ phys_to_machine_mapping = (unsigned long *)xen_start_info->mfn_list;
}
/*
@@ -1234,10 +1236,64 @@
legacy_init_iomem_resources(struct resource *code_resource, struct resource
*data_resource)
{
int i;
+#ifdef CONFIG_XEN
+ dom0_op_t op;
+ struct dom0_memory_map_entry *map;
+ unsigned long gapstart, gapsize;
+ unsigned long long last;
+#endif
#ifdef CONFIG_XEN_PRIVILEGED_GUEST
probe_roms();
#endif
+
+#ifdef CONFIG_XEN
+ map = alloc_bootmem_low_pages(PAGE_SIZE);
+ op.cmd = DOM0_PHYSICAL_MEMORY_MAP;
+ op.u.physical_memory_map.memory_map = map;
+ op.u.physical_memory_map.max_map_entries =
+ PAGE_SIZE / sizeof(struct dom0_memory_map_entry);
+ BUG_ON(HYPERVISOR_dom0_op(&op));
+
+ last = 0x100000000ULL;
+ gapstart = 0x10000000;
+ gapsize = 0x400000;
+
+ for (i = op.u.physical_memory_map.nr_map_entries - 1; i >= 0; i--) {
+ struct resource *res;
+
+ if ((last > map[i].end) && ((last - map[i].end) > gapsize)) {
+ gapsize = last - map[i].end;
+ gapstart = map[i].end;
+ }
+ if (map[i].start < last)
+ last = map[i].start;
+
+ if (map[i].end > 0x100000000ULL)
+ continue;
+ res = alloc_bootmem_low(sizeof(struct resource));
+ res->name = map[i].is_ram ? "System RAM" : "reserved";
+ res->start = map[i].start;
+ res->end = map[i].end - 1;
+ res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+ request_resource(&iomem_resource, res);
+ }
+
+ free_bootmem(__pa(map), PAGE_SIZE);
+
+ /*
+ * Start allocating dynamic PCI memory a bit into the gap,
+ * aligned up to the nearest megabyte.
+ *
+ * Question: should we try to pad it up a bit (do something
+ * like " + (gapsize >> 3)" in there too?). We now have the
+ * technology.
+ */
+ pci_mem_start = (gapstart + 0xfffff) & ~0xfffff;
+
+ printk("Allocating PCI resources starting at %08lx (gap:
%08lx:%08lx)\n",
+ pci_mem_start, gapstart, gapsize);
+#else
for (i = 0; i < e820.nr_map; i++) {
struct resource *res;
if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL)
@@ -1263,6 +1319,7 @@
request_resource(res, data_resource);
}
}
+#endif
}
/*
@@ -1270,23 +1327,29 @@
*/
static void __init register_memory(void)
{
+#ifndef CONFIG_XEN
unsigned long gapstart, gapsize;
unsigned long long last;
+#endif
int i;
+
+ /* Nothing to do if not running in dom0. */
+ if (!(xen_start_info->flags & SIF_INITDOMAIN))
+ return;
if (efi_enabled)
efi_initialize_iomem_resources(&code_resource, &data_resource);
else
legacy_init_iomem_resources(&code_resource, &data_resource);
- if (xen_start_info.flags & SIF_INITDOMAIN)
- /* EFI systems may still have VGA */
- request_resource(&iomem_resource, &video_ram_resource);
+ /* EFI systems may still have VGA */
+ request_resource(&iomem_resource, &video_ram_resource);
/* request I/O space for devices used on all i[345]86 PCs */
for (i = 0; i < STANDARD_IO_RESOURCES; i++)
request_resource(&ioport_resource, &standard_io_resources[i]);
+#ifndef CONFIG_XEN
/*
* Search for the bigest gap in the low 32 bits of the e820
* memory space.
@@ -1327,6 +1390,7 @@
printk("Allocating PCI resources starting at %08lx (gap:
%08lx:%08lx)\n",
pci_mem_start, gapstart, gapsize);
+#endif
}
/* Use inline assembly to define this because the nops are defined
@@ -1456,7 +1520,7 @@
*/
void __init setup_arch(char **cmdline_p)
{
- int i, j;
+ int i, j, k, fpp;
physdev_op_t op;
unsigned long max_low_pfn;
@@ -1535,8 +1599,8 @@
init_mm.start_code = (unsigned long) _text;
init_mm.end_code = (unsigned long) _etext;
init_mm.end_data = (unsigned long) _edata;
- init_mm.brk = (PFN_UP(__pa(xen_start_info.pt_base)) +
- xen_start_info.nr_pt_frames) << PAGE_SHIFT;
+ init_mm.brk = (PFN_UP(__pa(xen_start_info->pt_base)) +
+ xen_start_info->nr_pt_frames) << PAGE_SHIFT;
/* XEN: This is nonsense: kernel may not even be contiguous in RAM. */
/*code_resource.start = virt_to_phys(_text);*/
@@ -1573,42 +1637,64 @@
#endif
/* Make sure we have a correctly sized P->M table. */
- if (max_pfn != xen_start_info.nr_pages) {
+ if (max_pfn != xen_start_info->nr_pages) {
phys_to_machine_mapping = alloc_bootmem_low_pages(
- max_pfn * sizeof(unsigned int));
-
- if (max_pfn > xen_start_info.nr_pages) {
+ max_pfn * sizeof(unsigned long));
+
+ if (max_pfn > xen_start_info->nr_pages) {
/* set to INVALID_P2M_ENTRY */
memset(phys_to_machine_mapping, ~0,
- max_pfn * sizeof(unsigned int));
+ max_pfn * sizeof(unsigned long));
memcpy(phys_to_machine_mapping,
- (unsigned int *)xen_start_info.mfn_list,
- xen_start_info.nr_pages * sizeof(unsigned int));
+ (unsigned long *)xen_start_info->mfn_list,
+ xen_start_info->nr_pages * sizeof(unsigned
long));
} else {
+ struct xen_memory_reservation reservation = {
+ .extent_start = (unsigned long
*)xen_start_info->mfn_list + max_pfn,
+ .nr_extents = xen_start_info->nr_pages -
max_pfn,
+ .extent_order = 0,
+ .domid = DOMID_SELF
+ };
+
memcpy(phys_to_machine_mapping,
- (unsigned int *)xen_start_info.mfn_list,
- max_pfn * sizeof(unsigned int));
- /* N.B. below relies on sizeof(int) == sizeof(long). */
- if (HYPERVISOR_dom_mem_op(
- MEMOP_decrease_reservation,
- (unsigned long *)xen_start_info.mfn_list +
max_pfn,
- xen_start_info.nr_pages - max_pfn, 0) !=
- (xen_start_info.nr_pages - max_pfn)) BUG();
+ (unsigned long *)xen_start_info->mfn_list,
+ max_pfn * sizeof(unsigned long));
+ BUG_ON(HYPERVISOR_memory_op(
+ XENMEM_decrease_reservation,
+ &reservation) !=
+ (xen_start_info->nr_pages - max_pfn));
}
free_bootmem(
- __pa(xen_start_info.mfn_list),
- PFN_PHYS(PFN_UP(xen_start_info.nr_pages *
- sizeof(unsigned int))));
- }
-
- pfn_to_mfn_frame_list = alloc_bootmem_low_pages(PAGE_SIZE);
- for ( i=0, j=0; i < max_pfn; i+=(PAGE_SIZE/sizeof(unsigned int)), j++ )
- {
- pfn_to_mfn_frame_list[j] =
- virt_to_mfn(&phys_to_machine_mapping[i]);
- }
- HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list =
- virt_to_mfn(pfn_to_mfn_frame_list);
+ __pa(xen_start_info->mfn_list),
+ PFN_PHYS(PFN_UP(xen_start_info->nr_pages *
+ sizeof(unsigned long))));
+ }
+
+
+ /*
+ * Initialise the list of the frames that specify the list of
+ * frames that make up the p2m table. Used by save/restore
+ */
+ pfn_to_mfn_frame_list_list = alloc_bootmem_low_pages(PAGE_SIZE);
+ HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
+ virt_to_mfn(pfn_to_mfn_frame_list_list);
+
+ fpp = PAGE_SIZE/sizeof(unsigned long);
+ for ( i=0, j=0, k=-1; i< max_pfn; i+=fpp, j++ )
+ {
+ if ( (j % fpp) == 0 )
+ {
+ k++;
+ BUG_ON(k>=16);
+ pfn_to_mfn_frame_list[k] = alloc_bootmem_low_pages(PAGE_SIZE);
+ pfn_to_mfn_frame_list_list[k] =
+ virt_to_mfn(pfn_to_mfn_frame_list[k]);
+ j=0;
+ }
+ pfn_to_mfn_frame_list[k][j] =
+ virt_to_mfn(&phys_to_machine_mapping[i]);
+ }
+ HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
/*
* NOTE: at this point the bootmem allocator is fully available.
@@ -1626,8 +1712,8 @@
}
#endif
-
- dmi_scan_machine();
+ if (xen_start_info->flags & SIF_INITDOMAIN)
+ dmi_scan_machine();
#ifdef CONFIG_X86_GENERICARCH
generic_apic_probe(*cmdline_p);
@@ -1640,7 +1726,7 @@
HYPERVISOR_physdev_op(&op);
#ifdef CONFIG_ACPI_BOOT
- if (!(xen_start_info.flags & SIF_INITDOMAIN)) {
+ if (!(xen_start_info->flags & SIF_INITDOMAIN)) {
printk(KERN_INFO "ACPI in unprivileged domain disabled\n");
acpi_disabled = 1;
acpi_ht = 0;
@@ -1666,8 +1752,8 @@
register_memory();
- if (xen_start_info.flags & SIF_INITDOMAIN) {
- if (!(xen_start_info.flags & SIF_PRIVILEGED))
+ if (xen_start_info->flags & SIF_INITDOMAIN) {
+ if (!(xen_start_info->flags & SIF_PRIVILEGED))
panic("Xen granted us console access "
"but not privileged status");
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c Fri Sep 9
16:30:54 2005
@@ -856,9 +856,6 @@
cpu_gdt_descr[cpu].address = __get_free_page(GFP_KERNEL|__GFP_ZERO);
BUG_ON(cpu_gdt_descr[0].size > PAGE_SIZE);
cpu_gdt_descr[cpu].size = cpu_gdt_descr[0].size;
- printk("GDT: copying %d bytes from %lx to %lx\n",
- cpu_gdt_descr[0].size, cpu_gdt_descr[0].address,
- cpu_gdt_descr[cpu].address);
memcpy((void *)cpu_gdt_descr[cpu].address,
(void *)cpu_gdt_descr[0].address, cpu_gdt_descr[0].size);
@@ -1274,6 +1271,7 @@
printk(KERN_WARNING "WARNING: %d siblings found for
CPU%d, should be %d\n", siblings, cpu, smp_num_siblings);
smp_num_siblings = siblings;
}
+
if (c->x86_num_cores > 1) {
for (i = 0; i < NR_CPUS; i++) {
if (!cpu_isset(i, cpu_callout_map))
@@ -1601,32 +1599,71 @@
void smp_suspend(void)
{
- /* XXX todo: take down time and ipi's on all cpus */
local_teardown_timer_irq();
smp_intr_exit();
}
void smp_resume(void)
{
- /* XXX todo: restore time and ipi's on all cpus */
smp_intr_init();
local_setup_timer_irq();
}
-DECLARE_PER_CPU(int, timer_irq);
-
-void _restore_vcpu(void)
-{
- int cpu = smp_processor_id();
- extern atomic_t vcpus_rebooting;
-
- /* We are the first thing the vcpu runs when it comes back,
- and we are supposed to restore the IPIs and timer
- interrupts etc. When we return, the vcpu's idle loop will
- start up again. */
- _bind_virq_to_irq(VIRQ_TIMER, cpu, per_cpu(timer_irq, cpu));
- _bind_virq_to_irq(VIRQ_DEBUG, cpu, per_cpu(ldebug_irq, cpu));
- _bind_ipi_to_irq(RESCHEDULE_VECTOR, cpu, per_cpu(resched_irq, cpu) );
- _bind_ipi_to_irq(CALL_FUNCTION_VECTOR, cpu, per_cpu(callfunc_irq, cpu)
);
+static atomic_t vcpus_rebooting;
+
+static void restore_vcpu_ready(void)
+{
+
atomic_dec(&vcpus_rebooting);
}
+
+void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt)
+{
+ int r;
+ int gdt_pages;
+ r = HYPERVISOR_vcpu_pickle(vcpu, ctxt);
+ if (r != 0)
+ panic("pickling vcpu %d -> %d!\n", vcpu, r);
+
+ /* Translate from machine to physical addresses where necessary,
+ so that they can be translated to our new machine address space
+ after resume. libxc is responsible for doing this to vcpu0,
+ but we do it to the others. */
+ gdt_pages = (ctxt->gdt_ents + 511) / 512;
+ ctxt->ctrlreg[3] = machine_to_phys(ctxt->ctrlreg[3]);
+ for (r = 0; r < gdt_pages; r++)
+ ctxt->gdt_frames[r] = mfn_to_pfn(ctxt->gdt_frames[r]);
+}
+
+int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt)
+{
+ int r;
+ int gdt_pages = (ctxt->gdt_ents + 511) / 512;
+
+ /* This is kind of a hack, and implicitly relies on the fact that
+ the vcpu stops in a place where all of the call clobbered
+ registers are already dead. */
+ ctxt->user_regs.esp -= 4;
+ ((unsigned long *)ctxt->user_regs.esp)[0] = ctxt->user_regs.eip;
+ ctxt->user_regs.eip = (unsigned long)restore_vcpu_ready;
+
+ /* De-canonicalise. libxc handles this for vcpu 0, but we need
+ to do it for the other vcpus. */
+ ctxt->ctrlreg[3] = phys_to_machine(ctxt->ctrlreg[3]);
+ for (r = 0; r < gdt_pages; r++)
+ ctxt->gdt_frames[r] = pfn_to_mfn(ctxt->gdt_frames[r]);
+
+ atomic_set(&vcpus_rebooting, 1);
+ r = HYPERVISOR_boot_vcpu(vcpu, ctxt);
+ if (r != 0) {
+ printk(KERN_EMERG "Failed to reboot vcpu %d (%d)\n", vcpu, r);
+ return -1;
+ }
+
+ /* Make sure we wait for the new vcpu to come up before trying to do
+ anything with it or starting the next one. */
+ while (atomic_read(&vcpus_rebooting))
+ barrier();
+
+ return 0;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c Fri Sep 9
16:30:54 2005
@@ -51,7 +51,7 @@
* swiotlb_sync_single_*, to see if the memory was in fact allocated by this
* API.
*/
-static dma_addr_t iotlb_bus_start, iotlb_bus_mask;
+static dma_addr_t iotlb_bus_start, iotlb_bus_end, iotlb_bus_mask;
/* Does the given dma address reside within the swiotlb aperture? */
#define in_swiotlb_aperture(a) (!(((a) ^ iotlb_bus_start) & iotlb_bus_mask))
@@ -157,6 +157,7 @@
io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow);
iotlb_bus_start = virt_to_bus(iotlb_virt_start);
+ iotlb_bus_end = iotlb_bus_start + bytes;
iotlb_bus_mask = ~(dma_addr_t)(bytes - 1);
printk(KERN_INFO "Software IO TLB enabled: \n"
@@ -165,7 +166,7 @@
" Kernel range: 0x%016lx - 0x%016lx\n",
bytes >> 20,
(unsigned long)iotlb_bus_start,
- (unsigned long)iotlb_bus_start + bytes,
+ (unsigned long)iotlb_bus_end,
(unsigned long)iotlb_virt_start,
(unsigned long)iotlb_virt_start + bytes);
}
@@ -181,7 +182,7 @@
* Otherwise, enable for domain 0 if the machine has 'lots of memory',
* which we take to mean more than 2GB.
*/
- if (xen_start_info.flags & SIF_INITDOMAIN) {
+ if (xen_start_info->flags & SIF_INITDOMAIN) {
dom0_op_t op;
op.cmd = DOM0_PHYSINFO;
if ((HYPERVISOR_dom0_op(&op) == 0) &&
@@ -191,6 +192,8 @@
if (swiotlb)
swiotlb_init_with_default_size(64 * (1<<20));
+ else
+ printk(KERN_INFO "Software IO TLB disabled\n");
}
static void
@@ -424,13 +427,6 @@
}
dev_addr = virt_to_bus(map);
-
- /*
- * Ensure that the address returned is DMA'ble
- */
- if (address_needs_mapping(hwdev, dev_addr))
- panic("map_single: bounce buffer is not DMA'ble");
-
return dev_addr;
}
@@ -632,7 +628,7 @@
int
swiotlb_dma_supported (struct device *hwdev, u64 mask)
{
- return (mask >= 0xffffffffUL);
+ return (mask >= (iotlb_bus_end - 1));
}
EXPORT_SYMBOL(swiotlb_init);
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c Fri Sep 9 16:30:54 2005
@@ -445,7 +445,7 @@
sec = tv->tv_sec;
__normalize_time(&sec, &nsec);
- if ((xen_start_info.flags & SIF_INITDOMAIN) &&
+ if ((xen_start_info->flags & SIF_INITDOMAIN) &&
!independent_wallclock) {
op.cmd = DOM0_SETTIME;
op.u.settime.secs = sec;
@@ -476,7 +476,7 @@
WARN_ON(irqs_disabled());
- if (!(xen_start_info.flags & SIF_INITDOMAIN))
+ if (!(xen_start_info->flags & SIF_INITDOMAIN))
return 0;
/* gets recalled with irq locally disabled */
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c Fri Sep 9 16:30:54 2005
@@ -449,10 +449,10 @@
DO_ERROR(11, SIGBUS, "segment not present", segment_not_present)
DO_ERROR(12, SIGBUS, "stack segment", stack_segment)
DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
-DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0)
#ifdef CONFIG_X86_MCE
DO_ERROR(18, SIGBUS, "machine check", machine_check)
#endif
+DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0)
fastcall void do_general_protection(struct pt_regs * regs, long error_code)
{
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/i386/mm/fault.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/mm/fault.c Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/fault.c Fri Sep 9 16:30:54 2005
@@ -588,7 +588,15 @@
pmd_k = pmd_offset(pud_k, address);
if (!pmd_present(*pmd_k))
goto no_context;
+#ifndef CONFIG_XEN
set_pmd(pmd, *pmd_k);
+#else
+ /*
+ * When running on Xen we must launder *pmd_k through
+ * pmd_val() to ensure that _PAGE_PRESENT is correctly set.
+ */
+ set_pmd(pmd, __pmd(pmd_val(*pmd_k)));
+#endif
pte_k = pte_offset_kernel(pmd_k, address);
if (!pte_present(*pte_k))
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c Fri Sep 9
16:30:54 2005
@@ -35,6 +35,7 @@
#include <asm/pgtable.h>
#include <asm-xen/hypervisor.h>
#include <asm-xen/balloon.h>
+#include <asm-xen/xen-public/memory.h>
#include <linux/module.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
#include <linux/percpu.h>
@@ -105,7 +106,7 @@
void xen_machphys_update(unsigned long mfn, unsigned long pfn)
{
mmu_update_t u;
- u.ptr = (mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
+ u.ptr = ((unsigned long long)mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
u.val = pfn;
BUG_ON(HYPERVISOR_mmu_update(&u, 1, NULL, DOMID_SELF) < 0);
}
@@ -320,6 +321,12 @@
pmd_t *pmd;
pte_t *pte;
unsigned long mfn, i, flags;
+ struct xen_memory_reservation reservation = {
+ .extent_start = &mfn,
+ .nr_extents = 1,
+ .extent_order = 0,
+ .domid = DOMID_SELF
+ };
scrub_pages(vstart, 1 << order);
@@ -336,13 +343,15 @@
vstart + (i*PAGE_SIZE), __pte_ma(0), 0));
phys_to_machine_mapping[(__pa(vstart)>>PAGE_SHIFT)+i] =
INVALID_P2M_ENTRY;
- BUG_ON(HYPERVISOR_dom_mem_op(
- MEMOP_decrease_reservation, &mfn, 1, 0) != 1);
+ BUG_ON(HYPERVISOR_memory_op(
+ XENMEM_decrease_reservation, &reservation) != 1);
}
/* 2. Get a new contiguous memory extent. */
- BUG_ON(HYPERVISOR_dom_mem_op(
- MEMOP_increase_reservation, &mfn, 1, order | (32<<8)) != 1);
+ reservation.extent_order = order;
+ reservation.address_bits = 31; /* aacraid limitation */
+ BUG_ON(HYPERVISOR_memory_op(
+ XENMEM_increase_reservation, &reservation) != 1);
/* 3. Map the new extent in place of old pages. */
for (i = 0; i < (1<<order); i++) {
@@ -367,6 +376,12 @@
pmd_t *pmd;
pte_t *pte;
unsigned long mfn, i, flags;
+ struct xen_memory_reservation reservation = {
+ .extent_start = &mfn,
+ .nr_extents = 1,
+ .extent_order = 0,
+ .domid = DOMID_SELF
+ };
scrub_pages(vstart, 1 << order);
@@ -385,14 +400,14 @@
vstart + (i*PAGE_SIZE), __pte_ma(0), 0));
phys_to_machine_mapping[(__pa(vstart)>>PAGE_SHIFT)+i] =
INVALID_P2M_ENTRY;
- BUG_ON(HYPERVISOR_dom_mem_op(
- MEMOP_decrease_reservation, &mfn, 1, 0) != 1);
+ BUG_ON(HYPERVISOR_memory_op(
+ XENMEM_decrease_reservation, &reservation) != 1);
}
/* 2. Map new pages in place of old pages. */
for (i = 0; i < (1<<order); i++) {
- BUG_ON(HYPERVISOR_dom_mem_op(
- MEMOP_increase_reservation, &mfn, 1, 0) != 1);
+ BUG_ON(HYPERVISOR_memory_op(
+ XENMEM_increase_reservation, &reservation) != 1);
BUG_ON(HYPERVISOR_update_va_mapping(
vstart + (i*PAGE_SIZE),
pfn_pte_ma(mfn, PAGE_KERNEL), 0));
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/i386/mm/init.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/mm/init.c Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/init.c Fri Sep 9 16:30:54 2005
@@ -159,7 +159,7 @@
pte_t *pte;
int pgd_idx, pmd_idx, pte_ofs;
- unsigned long max_ram_pfn = xen_start_info.nr_pages;
+ unsigned long max_ram_pfn = xen_start_info->nr_pages;
if (max_ram_pfn > max_low_pfn)
max_ram_pfn = max_low_pfn;
@@ -219,6 +219,8 @@
}
}
+#ifndef CONFIG_XEN
+
static inline int page_kills_ppro(unsigned long pagenr)
{
if (pagenr >= 0x70000 && pagenr <= 0x7003F)
@@ -266,6 +268,13 @@
return 0;
}
+#else /* CONFIG_XEN */
+
+#define page_kills_ppro(p) 0
+#define page_is_ram(p) 1
+
+#endif
+
#ifdef CONFIG_HIGHMEM
pte_t *kmap_pte;
pgprot_t kmap_prot;
@@ -308,7 +317,7 @@
ClearPageReserved(page);
set_bit(PG_highmem, &page->flags);
set_page_count(page, 1);
- if (pfn < xen_start_info.nr_pages)
+ if (pfn < xen_start_info->nr_pages)
__free_page(page);
totalhigh_pages++;
} else
@@ -347,7 +356,7 @@
static void __init pagetable_init (void)
{
unsigned long vaddr;
- pgd_t *pgd_base = (pgd_t *)xen_start_info.pt_base;
+ pgd_t *pgd_base = (pgd_t *)xen_start_info->pt_base;
int i;
swapper_pg_dir = pgd_base;
@@ -526,14 +535,14 @@
kmap_init();
/* Switch to the real shared_info page, and clear the dummy page. */
- set_fixmap(FIX_SHARED_INFO, xen_start_info.shared_info);
+ set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
memset(empty_zero_page, 0, sizeof(empty_zero_page));
#ifdef CONFIG_XEN_PHYSDEV_ACCESS
/* Setup mapping of lower 1st MB */
for (i = 0; i < NR_FIX_ISAMAPS; i++)
- if (xen_start_info.flags & SIF_PRIVILEGED)
+ if (xen_start_info->flags & SIF_PRIVILEGED)
set_fixmap(FIX_ISAMAP_BEGIN - i, i * PAGE_SIZE);
else
__set_fixmap(FIX_ISAMAP_BEGIN - i,
@@ -630,7 +639,7 @@
/* this will put all low memory onto the freelists */
totalram_pages += free_all_bootmem();
/* XEN: init and count low-mem pages outside initial allocation. */
- for (pfn = xen_start_info.nr_pages; pfn < max_low_pfn; pfn++) {
+ for (pfn = xen_start_info->nr_pages; pfn < max_low_pfn; pfn++) {
ClearPageReserved(&mem_map[pfn]);
set_page_count(&mem_map[pfn], 1);
totalram_pages++;
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c Fri Sep 9 16:30:54 2005
@@ -19,295 +19,17 @@
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
-#ifndef CONFIG_XEN_PHYSDEV_ACCESS
-
-void * __ioremap(unsigned long phys_addr, unsigned long size,
- unsigned long flags)
-{
- return NULL;
-}
-
-void *ioremap_nocache (unsigned long phys_addr, unsigned long size)
-{
- return NULL;
-}
-
-void iounmap(volatile void __iomem *addr)
-{
-}
-
-#ifdef __i386__
-
-void __init *bt_ioremap(unsigned long phys_addr, unsigned long size)
-{
- return NULL;
-}
-
-void __init bt_iounmap(void *addr, unsigned long size)
-{
-}
-
-#endif /* __i386__ */
-
-#else
-
-/*
- * Does @address reside within a non-highmem page that is local to this virtual
- * machine (i.e., not an I/O page, nor a memory page belonging to another VM).
- * See the comment that accompanies pte_pfn() in pgtable-2level.h to understand
- * why this works.
- */
-static inline int is_local_lowmem(unsigned long address)
-{
- extern unsigned long max_low_pfn;
- unsigned long mfn = address >> PAGE_SHIFT;
- unsigned long pfn = mfn_to_pfn(mfn);
- return ((pfn < max_low_pfn) && (phys_to_machine_mapping[pfn] == mfn));
-}
-
-/*
- * Generic mapping function (not visible outside):
- */
-
-/*
- * Remap an arbitrary physical address space into the kernel virtual
- * address space. Needed when the kernel wants to access high addresses
- * directly.
- *
- * NOTE! We need to allow non-page-aligned mappings too: we will obviously
- * have to convert them into an offset in a page-aligned mapping, but the
- * caller shouldn't need to know that small detail.
- */
-void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned
long flags)
-{
- void __iomem * addr;
- struct vm_struct * area;
- unsigned long offset, last_addr;
- domid_t domid = DOMID_IO;
-
- /* Don't allow wraparound or zero size */
- last_addr = phys_addr + size - 1;
- if (!size || last_addr < phys_addr)
- return NULL;
-
-#ifdef CONFIG_XEN_PRIVILEGED_GUEST
- /*
- * Don't remap the low PCI/ISA area, it's always mapped..
- */
- if (phys_addr >= 0x0 && last_addr < 0x100000)
- return isa_bus_to_virt(phys_addr);
-#endif
-
- /*
- * Don't allow anybody to remap normal RAM that we're using..
- */
- if (is_local_lowmem(phys_addr)) {
- char *t_addr, *t_end;
- struct page *page;
-
- t_addr = bus_to_virt(phys_addr);
- t_end = t_addr + (size - 1);
-
- for(page = virt_to_page(t_addr); page <= virt_to_page(t_end);
page++)
- if(!PageReserved(page))
- return NULL;
-
- domid = DOMID_SELF;
- }
-
- /*
- * Mappings have to be page-aligned
- */
- offset = phys_addr & ~PAGE_MASK;
- phys_addr &= PAGE_MASK;
- size = PAGE_ALIGN(last_addr+1) - phys_addr;
-
- /*
- * Ok, go for it..
- */
- area = get_vm_area(size, VM_IOREMAP | (flags << 20));
- if (!area)
- return NULL;
- area->phys_addr = phys_addr;
- addr = (void __iomem *) area->addr;
- flags |= _PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED;
-#ifdef __x86_64__
- flags |= _PAGE_USER;
-#endif
- if (direct_remap_area_pages(&init_mm, (unsigned long) addr, phys_addr,
- size, __pgprot(flags), domid)) {
- vunmap((void __force *) addr);
- return NULL;
- }
- return (void __iomem *) (offset + (char __iomem *)addr);
-}
-
-
-/**
- * ioremap_nocache - map bus memory into CPU space
- * @offset: bus address of the memory
- * @size: size of the resource to map
- *
- * ioremap_nocache performs a platform specific sequence of operations to
- * make bus memory CPU accessible via the readb/readw/readl/writeb/
- * writew/writel functions and the other mmio helpers. The returned
- * address is not guaranteed to be usable directly as a virtual
- * address.
- *
- * This version of ioremap ensures that the memory is marked uncachable
- * on the CPU as well as honouring existing caching rules from things like
- * the PCI bus. Note that there are other caches and buffers on many
- * busses. In particular driver authors should read up on PCI writes
- *
- * It's useful if some control registers are in such an area and
- * write combining or read caching is not desirable:
- *
- * Must be freed with iounmap.
- */
-
-void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size)
-{
- unsigned long last_addr;
- void __iomem *p = __ioremap(phys_addr, size, _PAGE_PCD);
- if (!p)
- return p;
-
- /* Guaranteed to be > phys_addr, as per __ioremap() */
- last_addr = phys_addr + size - 1;
-
- if (is_local_lowmem(last_addr)) {
- struct page *ppage = virt_to_page(bus_to_virt(phys_addr));
- unsigned long npages;
-
- phys_addr &= PAGE_MASK;
-
- /* This might overflow and become zero.. */
- last_addr = PAGE_ALIGN(last_addr);
-
- /* .. but that's ok, because modulo-2**n arithmetic will make
- * the page-aligned "last - first" come out right.
- */
- npages = (last_addr - phys_addr) >> PAGE_SHIFT;
-
- if (change_page_attr(ppage, npages, PAGE_KERNEL_NOCACHE) < 0) {
- iounmap(p);
- p = NULL;
- }
- global_flush_tlb();
- }
-
- return p;
-}
-
-void iounmap(volatile void __iomem *addr)
-{
- struct vm_struct *p;
- if ((void __force *) addr <= high_memory)
- return;
-#ifdef CONFIG_XEN_PRIVILEGED_GUEST
- if ((unsigned long) addr >= fix_to_virt(FIX_ISAMAP_BEGIN))
- return;
-#endif
- p = remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr));
- if (!p) {
- printk("__iounmap: bad address %p\n", addr);
- return;
- }
-
- if ((p->flags >> 20) && is_local_lowmem(p->phys_addr)) {
- /* p->size includes the guard page, but cpa doesn't like that */
- change_page_attr(virt_to_page(bus_to_virt(p->phys_addr)),
- (p->size - PAGE_SIZE) >> PAGE_SHIFT,
- PAGE_KERNEL);
- global_flush_tlb();
- }
- kfree(p);
-}
-
-#ifdef __i386__
-
-void __init *bt_ioremap(unsigned long phys_addr, unsigned long size)
-{
- unsigned long offset, last_addr;
- unsigned int nrpages;
- enum fixed_addresses idx;
-
- /* Don't allow wraparound or zero size */
- last_addr = phys_addr + size - 1;
- if (!size || last_addr < phys_addr)
- return NULL;
-
-#ifdef CONFIG_XEN_PRIVILEGED_GUEST
- /*
- * Don't remap the low PCI/ISA area, it's always mapped..
- */
- if (phys_addr >= 0x0 && last_addr < 0x100000)
- return isa_bus_to_virt(phys_addr);
-#endif
-
- /*
- * Mappings have to be page-aligned
- */
- offset = phys_addr & ~PAGE_MASK;
- phys_addr &= PAGE_MASK;
- size = PAGE_ALIGN(last_addr) - phys_addr;
-
- /*
- * Mappings have to fit in the FIX_BTMAP area.
- */
- nrpages = size >> PAGE_SHIFT;
- if (nrpages > NR_FIX_BTMAPS)
- return NULL;
-
- /*
- * Ok, go for it..
- */
- idx = FIX_BTMAP_BEGIN;
- while (nrpages > 0) {
- set_fixmap(idx, phys_addr);
- phys_addr += PAGE_SIZE;
- --idx;
- --nrpages;
- }
- return (void*) (offset + fix_to_virt(FIX_BTMAP_BEGIN));
-}
-
-void __init bt_iounmap(void *addr, unsigned long size)
-{
- unsigned long virt_addr;
- unsigned long offset;
- unsigned int nrpages;
- enum fixed_addresses idx;
-
- virt_addr = (unsigned long)addr;
- if (virt_addr < fix_to_virt(FIX_BTMAP_BEGIN))
- return;
-#ifdef CONFIG_XEN_PRIVILEGED_GUEST
- if (virt_addr >= fix_to_virt(FIX_ISAMAP_BEGIN))
- return;
-#endif
- offset = virt_addr & ~PAGE_MASK;
- nrpages = PAGE_ALIGN(offset + size - 1) >> PAGE_SHIFT;
-
- idx = FIX_BTMAP_BEGIN;
- while (nrpages > 0) {
- clear_fixmap(idx);
- --idx;
- --nrpages;
- }
-}
-
-#endif /* __i386__ */
-
-#endif /* CONFIG_XEN_PHYSDEV_ACCESS */
-
+#define ISA_START_ADDRESS 0x0
+#define ISA_END_ADDRESS 0x100000
+
+#if 0 /* not PAE safe */
/* These hacky macros avoid phys->machine translations. */
#define __direct_pte(x) ((pte_t) { (x) } )
#define __direct_mk_pte(page_nr,pgprot) \
__direct_pte(((page_nr) << PAGE_SHIFT) | pgprot_val(pgprot))
#define direct_mk_pte_phys(physpage, pgprot) \
__direct_mk_pte((physpage) >> PAGE_SHIFT, pgprot)
-
+#endif
static int direct_remap_area_pte_fn(pte_t *pte,
struct page *pte_page,
@@ -316,16 +38,16 @@
{
mmu_update_t **v = (mmu_update_t **)data;
- (*v)->ptr = ((maddr_t)pfn_to_mfn(page_to_pfn(pte_page)) <<
+ (*v)->ptr = ((u64)pfn_to_mfn(page_to_pfn(pte_page)) <<
PAGE_SHIFT) | ((unsigned long)pte & ~PAGE_MASK);
(*v)++;
return 0;
}
-int direct_remap_area_pages(struct mm_struct *mm,
+int direct_remap_pfn_range(struct mm_struct *mm,
unsigned long address,
- unsigned long machine_addr,
+ unsigned long mfn,
unsigned long size,
pgprot_t prot,
domid_t domid)
@@ -356,9 +78,9 @@
* Fill in the machine address: PTE ptr is done later by
* __direct_remap_area_pages().
*/
- v->val = pte_val_ma(pfn_pte_ma(machine_addr >> PAGE_SHIFT,
prot));
-
- machine_addr += PAGE_SIZE;
+ v->val = pte_val_ma(pfn_pte_ma(mfn, prot));
+
+ mfn++;
address += PAGE_SIZE;
v++;
}
@@ -376,8 +98,10 @@
return 0;
}
-EXPORT_SYMBOL(direct_remap_area_pages);
-
+EXPORT_SYMBOL(direct_remap_pfn_range);
+
+
+/* FIXME: This is horribly broken on PAE */
static int lookup_pte_fn(
pte_t *pte, struct page *pte_page, unsigned long addr, void *data)
{
@@ -412,6 +136,292 @@
}
EXPORT_SYMBOL(touch_pte_range);
+
+#ifdef CONFIG_XEN_PHYSDEV_ACCESS
+
+/*
+ * Does @address reside within a non-highmem page that is local to this virtual
+ * machine (i.e., not an I/O page, nor a memory page belonging to another VM).
+ * See the comment that accompanies pte_pfn() in pgtable-2level.h to understand
+ * why this works.
+ */
+static inline int is_local_lowmem(unsigned long address)
+{
+ extern unsigned long max_low_pfn;
+ unsigned long mfn = address >> PAGE_SHIFT;
+ unsigned long pfn = mfn_to_pfn(mfn);
+ return ((pfn < max_low_pfn) && (phys_to_machine_mapping[pfn] == mfn));
+}
+
+/*
+ * Generic mapping function (not visible outside):
+ */
+
+/*
+ * Remap an arbitrary physical address space into the kernel virtual
+ * address space. Needed when the kernel wants to access high addresses
+ * directly.
+ *
+ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
+ * have to convert them into an offset in a page-aligned mapping, but the
+ * caller shouldn't need to know that small detail.
+ */
+void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned
long flags)
+{
+ void __iomem * addr;
+ struct vm_struct * area;
+ unsigned long offset, last_addr;
+ domid_t domid = DOMID_IO;
+
+ /* Don't allow wraparound or zero size */
+ last_addr = phys_addr + size - 1;
+ if (!size || last_addr < phys_addr)
+ return NULL;
+
+ /*
+ * Don't remap the low PCI/ISA area, it's always mapped..
+ */
+ if (xen_start_info->flags & SIF_PRIVILEGED &&
+ phys_addr >= ISA_START_ADDRESS && last_addr < ISA_END_ADDRESS)
+ return (void __iomem *) isa_bus_to_virt(phys_addr);
+
+ /*
+ * Don't allow anybody to remap normal RAM that we're using..
+ */
+ if (is_local_lowmem(phys_addr)) {
+ char *t_addr, *t_end;
+ struct page *page;
+
+ t_addr = bus_to_virt(phys_addr);
+ t_end = t_addr + (size - 1);
+
+ for(page = virt_to_page(t_addr); page <= virt_to_page(t_end);
page++)
+ if(!PageReserved(page))
+ return NULL;
+
+ domid = DOMID_SELF;
+ }
+
+ /*
+ * Mappings have to be page-aligned
+ */
+ offset = phys_addr & ~PAGE_MASK;
+ phys_addr &= PAGE_MASK;
+ size = PAGE_ALIGN(last_addr+1) - phys_addr;
+
+ /*
+ * Ok, go for it..
+ */
+ area = get_vm_area(size, VM_IOREMAP | (flags << 20));
+ if (!area)
+ return NULL;
+ area->phys_addr = phys_addr;
+ addr = (void __iomem *) area->addr;
+ flags |= _PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED;
+#ifdef __x86_64__
+ flags |= _PAGE_USER;
+#endif
+ if (direct_remap_pfn_range(&init_mm, (unsigned long) addr,
phys_addr>>PAGE_SHIFT,
+ size, __pgprot(flags), domid)) {
+ vunmap((void __force *) addr);
+ return NULL;
+ }
+ return (void __iomem *) (offset + (char __iomem *)addr);
+}
+
+
+/**
+ * ioremap_nocache - map bus memory into CPU space
+ * @offset: bus address of the memory
+ * @size: size of the resource to map
+ *
+ * ioremap_nocache performs a platform specific sequence of operations to
+ * make bus memory CPU accessible via the readb/readw/readl/writeb/
+ * writew/writel functions and the other mmio helpers. The returned
+ * address is not guaranteed to be usable directly as a virtual
+ * address.
+ *
+ * This version of ioremap ensures that the memory is marked uncachable
+ * on the CPU as well as honouring existing caching rules from things like
+ * the PCI bus. Note that there are other caches and buffers on many
+ * busses. In particular driver authors should read up on PCI writes
+ *
+ * It's useful if some control registers are in such an area and
+ * write combining or read caching is not desirable:
+ *
+ * Must be freed with iounmap.
+ */
+
+void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size)
+{
+ unsigned long last_addr;
+ void __iomem *p = __ioremap(phys_addr, size, _PAGE_PCD);
+ if (!p)
+ return p;
+
+ /* Guaranteed to be > phys_addr, as per __ioremap() */
+ last_addr = phys_addr + size - 1;
+
+ if (is_local_lowmem(last_addr)) {
+ struct page *ppage = virt_to_page(bus_to_virt(phys_addr));
+ unsigned long npages;
+
+ phys_addr &= PAGE_MASK;
+
+ /* This might overflow and become zero.. */
+ last_addr = PAGE_ALIGN(last_addr);
+
+ /* .. but that's ok, because modulo-2**n arithmetic will make
+ * the page-aligned "last - first" come out right.
+ */
+ npages = (last_addr - phys_addr) >> PAGE_SHIFT;
+
+ if (change_page_attr(ppage, npages, PAGE_KERNEL_NOCACHE) < 0) {
+ iounmap(p);
+ p = NULL;
+ }
+ global_flush_tlb();
+ }
+
+ return p;
+}
+
+void iounmap(volatile void __iomem *addr)
+{
+ struct vm_struct *p;
+ if ((void __force *) addr <= high_memory)
+ return;
+
+ /*
+ * __ioremap special-cases the PCI/ISA range by not instantiating a
+ * vm_area and by simply returning an address into the kernel mapping
+ * of ISA space. So handle that here.
+ */
+ if ((unsigned long) addr >= fix_to_virt(FIX_ISAMAP_BEGIN))
+ return;
+
+ write_lock(&vmlist_lock);
+ p = __remove_vm_area((void *) (PAGE_MASK & (unsigned long __force)
addr));
+ if (!p) {
+ printk("iounmap: bad address %p\n", addr);
+ goto out_unlock;
+ }
+
+ if ((p->flags >> 20) && is_local_lowmem(p->phys_addr)) {
+ /* p->size includes the guard page, but cpa doesn't like that */
+ change_page_attr(virt_to_page(bus_to_virt(p->phys_addr)),
+ (p->size - PAGE_SIZE) >> PAGE_SHIFT,
+ PAGE_KERNEL);
+ global_flush_tlb();
+ }
+out_unlock:
+ write_unlock(&vmlist_lock);
+ kfree(p);
+}
+
+#ifdef __i386__
+
+void __init *bt_ioremap(unsigned long phys_addr, unsigned long size)
+{
+ unsigned long offset, last_addr;
+ unsigned int nrpages;
+ enum fixed_addresses idx;
+
+ /* Don't allow wraparound or zero size */
+ last_addr = phys_addr + size - 1;
+ if (!size || last_addr < phys_addr)
+ return NULL;
+
+ /*
+ * Don't remap the low PCI/ISA area, it's always mapped..
+ */
+ if (xen_start_info->flags & SIF_PRIVILEGED &&
+ phys_addr >= ISA_START_ADDRESS && last_addr < ISA_END_ADDRESS)
+ return isa_bus_to_virt(phys_addr);
+
+ /*
+ * Mappings have to be page-aligned
+ */
+ offset = phys_addr & ~PAGE_MASK;
+ phys_addr &= PAGE_MASK;
+ size = PAGE_ALIGN(last_addr) - phys_addr;
+
+ /*
+ * Mappings have to fit in the FIX_BTMAP area.
+ */
+ nrpages = size >> PAGE_SHIFT;
+ if (nrpages > NR_FIX_BTMAPS)
+ return NULL;
+
+ /*
+ * Ok, go for it..
+ */
+ idx = FIX_BTMAP_BEGIN;
+ while (nrpages > 0) {
+ set_fixmap(idx, phys_addr);
+ phys_addr += PAGE_SIZE;
+ --idx;
+ --nrpages;
+ }
+ return (void*) (offset + fix_to_virt(FIX_BTMAP_BEGIN));
+}
+
+void __init bt_iounmap(void *addr, unsigned long size)
+{
+ unsigned long virt_addr;
+ unsigned long offset;
+ unsigned int nrpages;
+ enum fixed_addresses idx;
+
+ virt_addr = (unsigned long)addr;
+ if (virt_addr < fix_to_virt(FIX_BTMAP_BEGIN))
+ return;
+ if (virt_addr >= fix_to_virt(FIX_ISAMAP_BEGIN))
+ return;
+ offset = virt_addr & ~PAGE_MASK;
+ nrpages = PAGE_ALIGN(offset + size - 1) >> PAGE_SHIFT;
+
+ idx = FIX_BTMAP_BEGIN;
+ while (nrpages > 0) {
+ clear_fixmap(idx);
+ --idx;
+ --nrpages;
+ }
+}
+
+#endif /* __i386__ */
+
+#else /* CONFIG_XEN_PHYSDEV_ACCESS */
+
+void __iomem * __ioremap(unsigned long phys_addr, unsigned long size,
+ unsigned long flags)
+{
+ return NULL;
+}
+
+void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size)
+{
+ return NULL;
+}
+
+void iounmap(volatile void __iomem *addr)
+{
+}
+
+#ifdef __i386__
+
+void __init *bt_ioremap(unsigned long phys_addr, unsigned long size)
+{
+ return NULL;
+}
+
+void __init bt_iounmap(void *addr, unsigned long size)
+{
+}
+
+#endif /* __i386__ */
+
+#endif /* CONFIG_XEN_PHYSDEV_ACCESS */
/*
* Local variables:
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/i386/pci/Makefile
--- a/linux-2.6-xen-sparse/arch/xen/i386/pci/Makefile Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/pci/Makefile Fri Sep 9 16:30:54 2005
@@ -4,7 +4,7 @@
c-obj-y := i386.o
-c-obj-$(CONFIG_PCI_BIOS) += pcbios.o
+#c-obj-$(CONFIG_PCI_BIOS) += pcbios.o
c-obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o
c-obj-$(CONFIG_PCI_DIRECT) += direct.o
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/kernel/Makefile
--- a/linux-2.6-xen-sparse/arch/xen/kernel/Makefile Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/Makefile Fri Sep 9 16:30:54 2005
@@ -11,7 +11,7 @@
extra-y += vmlinux.lds
-obj-y := ctrl_if.o evtchn.o fixup.o reboot.o gnttab.o devmem.o
+obj-y := evtchn.o fixup.o reboot.o gnttab.o devmem.o
obj-$(CONFIG_PROC_FS) += xen_proc.o
obj-$(CONFIG_NET) += skbuff.o
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c Fri Sep 9 16:30:54 2005
@@ -40,16 +40,8 @@
#include <asm-xen/synch_bitops.h>
#include <asm-xen/xen-public/event_channel.h>
#include <asm-xen/xen-public/physdev.h>
-#include <asm-xen/ctrl_if.h>
#include <asm-xen/hypervisor.h>
#include <asm-xen/evtchn.h>
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-EXPORT_SYMBOL(force_evtchn_callback);
-EXPORT_SYMBOL(evtchn_do_upcall);
-EXPORT_SYMBOL(bind_evtchn_to_irq);
-EXPORT_SYMBOL(unbind_evtchn_from_irq);
-#endif
/*
* This lock protects updates to the following mapping and reference-count
@@ -133,6 +125,7 @@
{
(void)HYPERVISOR_xen_version(0);
}
+EXPORT_SYMBOL(force_evtchn_callback);
/* NB. Interrupts are disabled on entry. */
asmlinkage void evtchn_do_upcall(struct pt_regs *regs)
@@ -165,6 +158,7 @@
}
}
}
+EXPORT_SYMBOL(evtchn_do_upcall);
static int find_unbound_irq(void)
{
@@ -211,6 +205,7 @@
return irq;
}
+EXPORT_SYMBOL(bind_virq_to_irq);
void unbind_virq_from_irq(int virq)
{
@@ -244,74 +239,7 @@
spin_unlock(&irq_mapping_update_lock);
}
-
-/* This is only used when a vcpu from an xm save. The ipi is expected
- to have been bound before we suspended, and so all of the xenolinux
- state is set up; we only need to restore the Xen side of things.
- The irq number has to be the same, but the evtchn number can
- change. */
-void _bind_ipi_to_irq(int ipi, int vcpu, int irq)
-{
- evtchn_op_t op;
- int evtchn;
-
- spin_lock(&irq_mapping_update_lock);
-
- op.cmd = EVTCHNOP_bind_ipi;
- if ( HYPERVISOR_event_channel_op(&op) != 0 )
- panic("Failed to bind virtual IPI %d on cpu %d\n", ipi, vcpu);
- evtchn = op.u.bind_ipi.port;
-
- printk("<0>IPI %d, old evtchn %d, evtchn %d.\n",
- ipi, per_cpu(ipi_to_evtchn, vcpu)[ipi],
- evtchn);
-
- evtchn_to_irq[irq_to_evtchn[irq]] = -1;
- irq_to_evtchn[irq] = -1;
-
- evtchn_to_irq[evtchn] = irq;
- irq_to_evtchn[irq] = evtchn;
-
- printk("<0>evtchn_to_irq[%d] = %d.\n", evtchn,
- evtchn_to_irq[evtchn]);
- per_cpu(ipi_to_evtchn, vcpu)[ipi] = evtchn;
-
- bind_evtchn_to_cpu(evtchn, vcpu);
-
- spin_unlock(&irq_mapping_update_lock);
-
- clear_bit(evtchn, (unsigned long *)HYPERVISOR_shared_info->evtchn_mask);
- clear_bit(evtchn, (unsigned long *)HYPERVISOR_shared_info->evtchn_pending);
-}
-
-void _bind_virq_to_irq(int virq, int cpu, int irq)
-{
- evtchn_op_t op;
- int evtchn;
-
- spin_lock(&irq_mapping_update_lock);
-
- op.cmd = EVTCHNOP_bind_virq;
- op.u.bind_virq.virq = virq;
- if ( HYPERVISOR_event_channel_op(&op) != 0 )
- panic("Failed to bind virtual IRQ %d\n", virq);
- evtchn = op.u.bind_virq.port;
-
- evtchn_to_irq[irq_to_evtchn[irq]] = -1;
- irq_to_evtchn[irq] = -1;
-
- evtchn_to_irq[evtchn] = irq;
- irq_to_evtchn[irq] = evtchn;
-
- per_cpu(virq_to_irq, cpu)[virq] = irq;
-
- bind_evtchn_to_cpu(evtchn, cpu);
-
- spin_unlock(&irq_mapping_update_lock);
-
- clear_bit(evtchn, (unsigned long *)HYPERVISOR_shared_info->evtchn_mask);
- clear_bit(evtchn, (unsigned long *)HYPERVISOR_shared_info->evtchn_pending);
-}
+EXPORT_SYMBOL(unbind_virq_from_irq);
int bind_ipi_to_irq(int ipi)
{
@@ -347,6 +275,7 @@
return irq;
}
+EXPORT_SYMBOL(bind_ipi_to_irq);
void unbind_ipi_from_irq(int ipi)
{
@@ -374,6 +303,7 @@
spin_unlock(&irq_mapping_update_lock);
}
+EXPORT_SYMBOL(unbind_ipi_from_irq);
int bind_evtchn_to_irq(unsigned int evtchn)
{
@@ -394,6 +324,7 @@
return irq;
}
+EXPORT_SYMBOL(bind_evtchn_to_irq);
void unbind_evtchn_from_irq(unsigned int evtchn)
{
@@ -409,6 +340,7 @@
spin_unlock(&irq_mapping_update_lock);
}
+EXPORT_SYMBOL(unbind_evtchn_from_irq);
int bind_evtchn_to_irqhandler(
unsigned int evtchn,
@@ -427,6 +359,7 @@
return retval;
}
+EXPORT_SYMBOL(bind_evtchn_to_irqhandler);
void unbind_evtchn_from_irqhandler(unsigned int evtchn, void *dev_id)
{
@@ -434,6 +367,7 @@
free_irq(irq, dev_id);
unbind_evtchn_from_irq(evtchn);
}
+EXPORT_SYMBOL(unbind_evtchn_from_irqhandler);
#ifdef CONFIG_SMP
static void do_nothing_function(void *ign)
@@ -797,7 +731,4 @@
irq_desc[pirq_to_irq(i)].depth = 1;
irq_desc[pirq_to_irq(i)].handler = &pirq_type;
}
-
- /* This needs to be done early, but after the IRQ subsystem is alive. */
- ctrl_if_init();
-}
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/kernel/reboot.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Fri Sep 9 16:30:54 2005
@@ -12,10 +12,8 @@
#include <asm-xen/evtchn.h>
#include <asm-xen/hypervisor.h>
#include <asm-xen/xen-public/dom0_ops.h>
-#include <asm-xen/linux-public/suspend.h>
#include <asm-xen/queues.h>
#include <asm-xen/xenbus.h>
-#include <asm-xen/ctrl_if.h>
#include <linux/cpu.h>
#include <linux/kthread.h>
@@ -65,69 +63,10 @@
#define cpu_up(x) (-EOPNOTSUPP)
#endif
-static void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt)
-{
- int r;
- int gdt_pages;
- r = HYPERVISOR_vcpu_pickle(vcpu, ctxt);
- if (r != 0)
- panic("pickling vcpu %d -> %d!\n", vcpu, r);
-
- /* Translate from machine to physical addresses where necessary,
- so that they can be translated to our new machine address space
- after resume. libxc is responsible for doing this to vcpu0,
- but we do it to the others. */
- gdt_pages = (ctxt->gdt_ents + 511) / 512;
- ctxt->ctrlreg[3] = machine_to_phys(ctxt->ctrlreg[3]);
- for (r = 0; r < gdt_pages; r++)
- ctxt->gdt_frames[r] = mfn_to_pfn(ctxt->gdt_frames[r]);
-}
-
-void _restore_vcpu(int cpu);
-
-atomic_t vcpus_rebooting;
-
-static int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt)
-{
- int r;
- int gdt_pages = (ctxt->gdt_ents + 511) / 512;
-
- /* This is kind of a hack, and implicitly relies on the fact that
- the vcpu stops in a place where all of the call clobbered
- registers are already dead. */
- ctxt->user_regs.esp -= 4;
- ((unsigned long *)ctxt->user_regs.esp)[0] = ctxt->user_regs.eip;
- ctxt->user_regs.eip = (unsigned long)_restore_vcpu;
-
- /* De-canonicalise. libxc handles this for vcpu 0, but we need
- to do it for the other vcpus. */
- ctxt->ctrlreg[3] = phys_to_machine(ctxt->ctrlreg[3]);
- for (r = 0; r < gdt_pages; r++)
- ctxt->gdt_frames[r] = pfn_to_mfn(ctxt->gdt_frames[r]);
-
- atomic_set(&vcpus_rebooting, 1);
- r = HYPERVISOR_boot_vcpu(vcpu, ctxt);
- if (r != 0) {
- printk(KERN_EMERG "Failed to reboot vcpu %d (%d)\n", vcpu, r);
- return -1;
- }
-
- /* Make sure we wait for the new vcpu to come up before trying to do
- anything with it or starting the next one. */
- while (atomic_read(&vcpus_rebooting))
- barrier();
-
- return 0;
-}
static int __do_suspend(void *ignore)
{
- int i, j;
- suspend_record_t *suspend_record;
- static vcpu_guest_context_t suspended_cpu_records[NR_CPUS];
-
- /* Hmmm... a cleaner interface to suspend/resume blkdevs would be nice. */
- /* XXX SMH: yes it would :-( */
+ int i, j, k, fpp;
#ifdef CONFIG_XEN_USB_FRONTEND
extern void usbif_resume();
@@ -138,16 +77,25 @@
extern int gnttab_suspend(void);
extern int gnttab_resume(void);
-#ifdef CONFIG_SMP
- extern void smp_suspend(void);
- extern void smp_resume(void);
-#endif
extern void time_suspend(void);
extern void time_resume(void);
extern unsigned long max_pfn;
- extern unsigned int *pfn_to_mfn_frame_list;
-
+ extern unsigned long *pfn_to_mfn_frame_list_list, *pfn_to_mfn_frame_list[];
+
+#ifdef CONFIG_SMP
+ extern void smp_suspend(void);
+ extern void smp_resume(void);
+
+ static vcpu_guest_context_t suspended_cpu_records[NR_CPUS];
cpumask_t prev_online_cpus, prev_present_cpus;
+
+ void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt);
+ int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt);
+#endif
+
+ extern void xencons_suspend(void);
+ extern void xencons_resume(void);
+
int err = 0;
BUG_ON(smp_processor_id() != 0);
@@ -155,15 +103,14 @@
#if defined(CONFIG_SMP) && !defined(CONFIG_HOTPLUG_CPU)
if (num_online_cpus() > 1) {
- printk(KERN_WARNING "Can't suspend SMP guests without
CONFIG_HOTPLUG_CPU\n");
+ printk(KERN_WARNING
+ "Can't suspend SMP guests without CONFIG_HOTPLUG_CPU\n");
return -EOPNOTSUPP;
}
#endif
- suspend_record = (suspend_record_t *)__get_free_page(GFP_KERNEL);
- if ( suspend_record == NULL )
- goto out;
-
+ preempt_disable();
+#ifdef CONFIG_SMP
/* Take all of the other cpus offline. We need to be careful not
to get preempted between the final test for num_online_cpus()
== 1 and disabling interrupts, since otherwise userspace could
@@ -175,7 +122,6 @@
since by the time num_online_cpus() == 1, there aren't any
other cpus) */
cpus_clear(prev_online_cpus);
- preempt_disable();
while (num_online_cpus() > 1) {
preempt_enable();
for_each_online_cpu(i) {
@@ -190,13 +136,13 @@
}
preempt_disable();
}
-
- suspend_record->nr_pfns = max_pfn; /* final number of pfns */
+#endif
__cli();
preempt_enable();
+#ifdef CONFIG_SMP
cpus_clear(prev_present_cpus);
for_each_present_cpu(i) {
if (i == 0)
@@ -204,6 +150,7 @@
save_vcpu_context(i, &suspended_cpu_records[i]);
cpu_set(i, prev_present_cpus);
}
+#endif
#ifdef __i386__
mm_pin_all();
@@ -218,7 +165,7 @@
xenbus_suspend();
- ctrl_if_suspend();
+ xencons_suspend();
irq_suspend();
@@ -227,37 +174,44 @@
HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
clear_fixmap(FIX_SHARED_INFO);
- memcpy(&suspend_record->resume_info, &xen_start_info,
- sizeof(xen_start_info));
+ xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn);
+ xen_start_info->console_mfn = mfn_to_pfn(xen_start_info->console_mfn);
/* We'll stop somewhere inside this hypercall. When it returns,
we'll start resuming after the restore. */
- HYPERVISOR_suspend(virt_to_mfn(suspend_record));
+ HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
shutting_down = SHUTDOWN_INVALID;
- memcpy(&xen_start_info, &suspend_record->resume_info,
- sizeof(xen_start_info));
-
- set_fixmap(FIX_SHARED_INFO, xen_start_info.shared_info);
+ set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
memset(empty_zero_page, 0, PAGE_SIZE);
-
- for ( i=0, j=0; i < max_pfn; i+=(PAGE_SIZE/sizeof(unsigned long)), j++ )
+
+ HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
+ virt_to_mfn(pfn_to_mfn_frame_list_list);
+
+ fpp = PAGE_SIZE/sizeof(unsigned long);
+ for ( i=0, j=0, k=-1; i< max_pfn; i+=fpp, j++ )
{
- pfn_to_mfn_frame_list[j] =
- virt_to_mfn(&phys_to_machine_mapping[i]);
- }
- HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list =
- virt_to_mfn(pfn_to_mfn_frame_list);
+ if ( (j % fpp) == 0 )
+ {
+ k++;
+ pfn_to_mfn_frame_list_list[k] =
+ virt_to_mfn(pfn_to_mfn_frame_list[k]);
+ j=0;
+ }
+ pfn_to_mfn_frame_list[k][j] =
+ virt_to_mfn(&phys_to_machine_mapping[i]);
+ }
+ HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
gnttab_resume();
irq_resume();
- ctrl_if_resume();
+ xencons_resume();
xenbus_resume();
@@ -269,12 +223,14 @@
usbif_resume();
- for_each_cpu_mask(i, prev_present_cpus) {
+#ifdef CONFIG_SMP
+ for_each_cpu_mask(i, prev_present_cpus)
restore_vcpu_context(i, &suspended_cpu_records[i]);
- }
+#endif
__sti();
+#ifdef CONFIG_SMP
out_reenable_cpus:
for_each_cpu_mask(i, prev_online_cpus) {
j = cpu_up(i);
@@ -284,10 +240,8 @@
err = j;
}
}
-
- out:
- if ( suspend_record != NULL )
- free_page((unsigned long)suspend_record);
+#endif
+
return err;
}
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/x86_64/Kconfig
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/Kconfig Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/Kconfig Fri Sep 9 16:30:54 2005
@@ -21,12 +21,12 @@
classical 32-bit x86 architecture. For details see
<http://www.x86-64.org/>.
-config X86
- bool
- default y
-
config 64BIT
def_bool y
+
+config X86
+ bool
+ default y
config MMU
bool
@@ -89,10 +89,11 @@
# Optimize for AMD Opteron/Athlon64/Hammer/K8 CPUs.
config MPSC
- bool "Intel x86-64"
+ bool "Intel EM64T"
help
- Optimize for Intel IA32 with 64bit extension CPUs
- (Prescott/Nocona/Potomac)
+ Optimize for Intel Pentium 4 and Xeon CPUs with Intel
+ Extended Memory 64 Technology(EM64T). For details see
+ <http://www.intel.com/technology/64bitextensions/>.
config GENERIC_CPU
bool "Generic-x86-64"
@@ -367,7 +368,6 @@
If unsure, say Y. Only embedded should say N here.
-
endmenu
#
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/x86_64/kernel/Makefile
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/Makefile Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/Makefile Fri Sep 9
16:30:54 2005
@@ -40,7 +40,7 @@
i386-obj-$(CONFIG_DUMMY_IOMMU) += pci-dma.o
i386-obj-$(CONFIG_SWIOTLB) += swiotlb.o
obj-$(CONFIG_KPROBES) += kprobes.o
-obj-$(CONFIG_X86_PM_TIMER) += pmtimer.o
+#obj-$(CONFIG_X86_PM_TIMER) += pmtimer.o
c-obj-$(CONFIG_MODULES) += module.o
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/x86_64/kernel/e820.c
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/e820.c Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/e820.c Fri Sep 9
16:30:54 2005
@@ -20,6 +20,9 @@
#include <asm/e820.h>
#include <asm/proto.h>
#include <asm/bootsetup.h>
+#include <asm-xen/xen-public/memory.h>
+
+unsigned long pci_mem_start = 0xaeedbabe;
/*
* PFN of last memory page.
@@ -517,14 +520,13 @@
}
#else /* CONFIX_XEN */
+
extern unsigned long xen_override_max_pfn;
extern union xen_start_info_union xen_start_info_union;
-/*
- * Guest physical starts from 0.
- */
+
unsigned long __init e820_end_of_ram(void)
{
- unsigned long max_end_pfn = xen_start_info.nr_pages;
+ unsigned long max_end_pfn = xen_start_info->nr_pages;
if ( xen_override_max_pfn < max_end_pfn)
xen_override_max_pfn = max_end_pfn;
@@ -532,64 +534,53 @@
return xen_override_max_pfn;
}
-
-
void __init e820_reserve_resources(void)
{
- return; /* Xen won't have reserved entries */
-}
-
-#endif
-
-void __init parse_memopt(char *p, char **from)
-{
- end_user_pfn = memparse(p, from);
- end_user_pfn >>= PAGE_SHIFT;
- xen_override_max_pfn = (unsigned long) end_user_pfn;
-}
-
-unsigned long pci_mem_start = 0xaeedbabe;
-
-/*
- * Search for the biggest gap in the low 32 bits of the e820
- * memory space. We pass this space to PCI to assign MMIO resources
- * for hotplug or unconfigured devices in.
- * Hopefully the BIOS let enough space left.
- */
-__init void e820_setup_gap(void)
-{
- unsigned long gapstart, gapsize;
- unsigned long last;
- int i;
- int found = 0;
-
- last = 0x100000000ull;
+ dom0_op_t op;
+ struct dom0_memory_map_entry *map;
+ unsigned long gapstart, gapsize, last;
+ int i, found = 0;
+
+ if (!(xen_start_info->flags & SIF_INITDOMAIN))
+ return;
+
+ map = alloc_bootmem_low_pages(PAGE_SIZE);
+ op.cmd = DOM0_PHYSICAL_MEMORY_MAP;
+ op.u.physical_memory_map.memory_map = map;
+ op.u.physical_memory_map.max_map_entries =
+ PAGE_SIZE / sizeof(struct dom0_memory_map_entry);
+ BUG_ON(HYPERVISOR_dom0_op(&op));
+
+ last = 0x100000000ULL;
gapstart = 0x10000000;
gapsize = 0x400000;
- i = e820.nr_map;
- while (--i >= 0) {
- unsigned long long start = e820.map[i].addr;
- unsigned long long end = start + e820.map[i].size;
-
- /*
- * Since "last" is at most 4GB, we know we'll
- * fit in 32 bits if this condition is true
- */
- if (last > end) {
- unsigned long gap = last - end;
-
- if (gap > gapsize) {
- gapsize = gap;
- gapstart = end;
- found = 1;
- }
- }
- if (start < last)
- last = start;
- }
+
+ for (i = op.u.physical_memory_map.nr_map_entries - 1; i >= 0; i--) {
+ struct resource *res;
+
+ if ((last > map[i].end) && ((last - map[i].end) > gapsize)) {
+ gapsize = last - map[i].end;
+ gapstart = map[i].end;
+ found = 1;
+ }
+ if (map[i].start < last)
+ last = map[i].start;
+
+ if (map[i].end > 0x100000000ULL)
+ continue;
+ res = alloc_bootmem_low(sizeof(struct resource));
+ res->name = map[i].is_ram ? "System RAM" : "reserved";
+ res->start = map[i].start;
+ res->end = map[i].end - 1;
+ res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+ request_resource(&iomem_resource, res);
+ }
+
+ free_bootmem(__pa(map), PAGE_SIZE);
if (!found) {
- gapstart = (end_pfn << PAGE_SHIFT) + 1024*1024;
+ HYPERVISOR_memory_op(XENMEM_maximum_ram_page, &gapstart);
+ gapstart = (gapstart << PAGE_SHIFT) + 1024*1024;
printk(KERN_ERR "PCI: Warning: Cannot find a gap in the 32bit
address range\n"
KERN_ERR "PCI: Unassigned devices with 32bit resource
registers may break!\n");
}
@@ -607,3 +598,72 @@
printk(KERN_INFO "Allocating PCI resources starting at %lx (gap:
%lx:%lx)\n",
pci_mem_start, gapstart, gapsize);
}
+
+#endif
+
+void __init parse_memopt(char *p, char **from)
+{
+ end_user_pfn = memparse(p, from);
+ end_user_pfn >>= PAGE_SHIFT;
+ xen_override_max_pfn = (unsigned long) end_user_pfn;
+}
+
+/*
+ * Search for the biggest gap in the low 32 bits of the e820
+ * memory space. We pass this space to PCI to assign MMIO resources
+ * for hotplug or unconfigured devices in.
+ * Hopefully the BIOS let enough space left.
+ */
+__init void e820_setup_gap(void)
+{
+#ifndef CONFIG_XEN
+ unsigned long gapstart, gapsize;
+ unsigned long last;
+ int i;
+ int found = 0;
+
+ last = 0x100000000ull;
+ gapstart = 0x10000000;
+ gapsize = 0x400000;
+ i = e820.nr_map;
+ while (--i >= 0) {
+ unsigned long long start = e820.map[i].addr;
+ unsigned long long end = start + e820.map[i].size;
+
+ /*
+ * Since "last" is at most 4GB, we know we'll
+ * fit in 32 bits if this condition is true
+ */
+ if (last > end) {
+ unsigned long gap = last - end;
+
+ if (gap > gapsize) {
+ gapsize = gap;
+ gapstart = end;
+ found = 1;
+ }
+ }
+ if (start < last)
+ last = start;
+ }
+
+ if (!found) {
+ gapstart = (end_pfn << PAGE_SHIFT) + 1024*1024;
+ printk(KERN_ERR "PCI: Warning: Cannot find a gap in the 32bit
address range\n"
+ KERN_ERR "PCI: Unassigned devices with 32bit resource
registers may break!\n");
+ }
+
+ /*
+ * Start allocating dynamic PCI memory a bit into the gap,
+ * aligned up to the nearest megabyte.
+ *
+ * Question: should we try to pad it up a bit (do something
+ * like " + (gapsize >> 3)" in there too?). We now have the
+ * technology.
+ */
+ pci_mem_start = (gapstart + 0xfffff) & ~0xfffff;
+
+ printk(KERN_INFO "Allocating PCI resources starting at %lx (gap:
%lx:%lx)\n",
+ pci_mem_start, gapstart, gapsize);
+#endif
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head.S
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head.S Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head.S Fri Sep 9
16:30:54 2005
@@ -40,16 +40,13 @@
.globl startup_64
startup_64:
ENTRY(_start)
- cld
- /* Copy the necessary stuff from xen_start_info structure. */
- movq $xen_start_info_union,%rdi
- movq $256,%rcx
- rep movsq
+ movq %rsi,xen_start_info(%rip)
#ifdef CONFIG_SMP
- ENTRY(startup_64_smp)
+ENTRY(startup_64_smp)
+#endif /* CONFIG_SMP */
+
cld
-#endif /* CONFIG_SMP */
movq init_rsp(%rip),%rsp
/* zero EFLAGS after setting rsp */
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head64.c
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head64.c Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head64.c Fri Sep 9
16:30:54 2005
@@ -90,8 +90,9 @@
{
int i;
- phys_to_machine_mapping = (u32 *)xen_start_info.mfn_list;
- start_pfn = (__pa(xen_start_info.pt_base) >> PAGE_SHIFT) +
xen_start_info.nr_pt_frames;
+ phys_to_machine_mapping = (unsigned long *)xen_start_info->mfn_list;
+ start_pfn = (__pa(xen_start_info->pt_base) >> PAGE_SHIFT) +
+ xen_start_info->nr_pt_frames;
for (i = 0; i < 256; i++)
set_intr_gate(i, early_idt_handler);
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c Fri Sep 9
16:30:54 2005
@@ -76,7 +76,8 @@
/* Allows setting of maximum possible memory size */
unsigned long xen_override_max_pfn;
-u32 *phys_to_machine_mapping, *pfn_to_mfn_frame_list;
+unsigned long *phys_to_machine_mapping;
+unsigned long *pfn_to_mfn_frame_list_list, *pfn_to_mfn_frame_list[512];
EXPORT_SYMBOL(phys_to_machine_mapping);
@@ -84,7 +85,7 @@
DEFINE_PER_CPU(int, nr_multicall_ents);
/* Raw start-of-day parameters from the hypervisor. */
-union xen_start_info_union xen_start_info_union;
+start_info_t *xen_start_info;
#endif
/*
@@ -314,7 +315,7 @@
if ((max_cmdline = MAX_GUEST_CMDLINE) > COMMAND_LINE_SIZE)
max_cmdline = COMMAND_LINE_SIZE;
- memcpy(saved_command_line, xen_start_info.cmd_line, max_cmdline);
+ memcpy(saved_command_line, xen_start_info->cmd_line, max_cmdline);
saved_command_line[max_cmdline-1] = '\0';
#else
memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
@@ -687,7 +688,7 @@
#endif
#ifdef CONFIG_XEN
#ifdef CONFIG_BLK_DEV_INITRD
- if (xen_start_info.mod_start) {
+ if (xen_start_info->mod_start) {
if (INITRD_START + INITRD_SIZE <= (end_pfn << PAGE_SHIFT)) {
/*reserve_bootmem_generic(INITRD_START, INITRD_SIZE);*/
initrd_start = INITRD_START + PAGE_OFFSET;
@@ -730,29 +731,50 @@
#endif
#ifdef CONFIG_XEN
{
- int i, j;
+ int i, j, k, fpp;
/* Make sure we have a large enough P->M table. */
- if (end_pfn > xen_start_info.nr_pages) {
+ if (end_pfn > xen_start_info->nr_pages) {
phys_to_machine_mapping = alloc_bootmem(
- max_pfn * sizeof(u32));
+ end_pfn * sizeof(unsigned long));
memset(phys_to_machine_mapping, ~0,
- max_pfn * sizeof(u32));
+ end_pfn * sizeof(unsigned long));
memcpy(phys_to_machine_mapping,
- (u32 *)xen_start_info.mfn_list,
- xen_start_info.nr_pages * sizeof(u32));
+ (unsigned long *)xen_start_info->mfn_list,
+ xen_start_info->nr_pages * sizeof(unsigned
long));
free_bootmem(
- __pa(xen_start_info.mfn_list),
- PFN_PHYS(PFN_UP(xen_start_info.nr_pages *
- sizeof(u32))));
- }
-
- pfn_to_mfn_frame_list = alloc_bootmem(PAGE_SIZE);
-
- for ( i=0, j=0; i < end_pfn; i+=(PAGE_SIZE/sizeof(u32)), j++ )
- {
- pfn_to_mfn_frame_list[j] =
+ __pa(xen_start_info->mfn_list),
+ PFN_PHYS(PFN_UP(xen_start_info->nr_pages *
+ sizeof(unsigned long))));
+ }
+
+ /*
+ * Initialise the list of the frames that specify the list of
+ * frames that make up the p2m table. Used by save/restore
+ */
+ pfn_to_mfn_frame_list_list = alloc_bootmem(PAGE_SIZE);
+ HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
+ virt_to_mfn(pfn_to_mfn_frame_list_list);
+
+ fpp = PAGE_SIZE/sizeof(unsigned long);
+ for ( i=0, j=0, k=-1; i< max_pfn; i+=fpp, j++ )
+ {
+ if ( (j % fpp) == 0 )
+ {
+ k++;
+ BUG_ON(k>=fpp);
+ pfn_to_mfn_frame_list[k] =
alloc_bootmem(PAGE_SIZE);
+ pfn_to_mfn_frame_list_list[k] =
+ virt_to_mfn(pfn_to_mfn_frame_list[k]);
+ j=0;
+ }
+ pfn_to_mfn_frame_list[k][j] =
virt_to_mfn(&phys_to_machine_mapping[i]);
}
+ HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
+
+
+
+
}
#endif
@@ -817,8 +839,8 @@
op.u.set_iopl.iopl = 1;
HYPERVISOR_physdev_op(&op);
- if (xen_start_info.flags & SIF_INITDOMAIN) {
- if (!(xen_start_info.flags & SIF_PRIVILEGED))
+ if (xen_start_info->flags & SIF_INITDOMAIN) {
+ if (!(xen_start_info->flags & SIF_PRIVILEGED))
panic("Xen granted us console access "
"but not privileged status");
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c Fri Sep 9
16:30:54 2005
@@ -1277,21 +1277,23 @@
void smp_suspend(void)
{
- /* XXX todo: take down time and ipi's on all cpus */
local_teardown_timer_irq();
smp_intr_exit();
}
void smp_resume(void)
{
- /* XXX todo: restore time and ipi's on all cpus */
smp_intr_init();
local_setup_timer_irq();
}
-void _restore_vcpu(void)
-{
- /* XXX need to write this */
-}
-
-#endif
+void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt)
+{
+}
+
+int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt)
+{
+ return 0;
+}
+
+#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/x86_64/mm/fault.c
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/mm/fault.c Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/mm/fault.c Fri Sep 9 16:30:54 2005
@@ -149,7 +149,7 @@
pmd_t *pmd;
pte_t *pte;
- pgd = (pgd_t *)per_cpu(cur_pgd, smp_processor_id());
+ pgd = (pgd_t *)per_cpu(cur_pgd, smp_processor_id());
pgd += pgd_index(address);
printk("PGD %lx ", pgd_val(*pgd));
@@ -296,9 +296,9 @@
#define MEM_VERBOSE 1
#ifdef MEM_VERBOSE
-#define MEM_LOG(_f, _a...) \
- printk("fault.c:[%d]-> " _f "\n", \
- __LINE__ , ## _a )
+#define MEM_LOG(_f, _a...) \
+ printk("fault.c:[%d]-> " _f "\n", \
+ __LINE__ , ## _a )
#else
#define MEM_LOG(_f, _a...) ((void)0)
#endif
@@ -325,7 +325,7 @@
siginfo_t info;
if (!user_mode(regs))
- error_code &= ~4; /* means kernel */
+ error_code &= ~4; /* means kernel */
#ifdef CONFIG_CHECKING
{
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/x86_64/mm/init.c
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/mm/init.c Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/mm/init.c Fri Sep 9 16:30:54 2005
@@ -62,14 +62,16 @@
* avaialble in init_memory_mapping().
*/
-#define addr_to_page(addr, page) \
- (addr) &= PHYSICAL_PAGE_MASK; \
- (page) = ((unsigned long *) ((unsigned long)(((mfn_to_pfn((addr) >>
PAGE_SHIFT)) << PAGE_SHIFT) + __START_KERNEL_map)))
+#define addr_to_page(addr, page) \
+ (addr) &= PHYSICAL_PAGE_MASK; \
+ (page) = ((unsigned long *) ((unsigned long) \
+ (((mfn_to_pfn((addr) >> PAGE_SHIFT)) << PAGE_SHIFT) + \
+ __START_KERNEL_map)))
static void __make_page_readonly(unsigned long va)
{
- unsigned long addr;
- pte_t pte, *ptep;
+ unsigned long addr;
+ pte_t pte, *ptep;
unsigned long *page = (unsigned long *) init_level4_pgt;
addr = (unsigned long) page[pgd_index(va)];
@@ -89,22 +91,22 @@
static void __make_page_writable(unsigned long va)
{
- unsigned long addr;
- pte_t pte, *ptep;
- unsigned long *page = (unsigned long *) init_level4_pgt;
-
- addr = (unsigned long) page[pgd_index(va)];
- addr_to_page(addr, page);
-
- addr = page[pud_index(va)];
- addr_to_page(addr, page);
-
- addr = page[pmd_index(va)];
- addr_to_page(addr, page);
-
- ptep = (pte_t *) &page[pte_index(va)];
+ unsigned long addr;
+ pte_t pte, *ptep;
+ unsigned long *page = (unsigned long *) init_level4_pgt;
+
+ addr = (unsigned long) page[pgd_index(va)];
+ addr_to_page(addr, page);
+
+ addr = page[pud_index(va)];
+ addr_to_page(addr, page);
+
+ addr = page[pmd_index(va)];
+ addr_to_page(addr, page);
+
+ ptep = (pte_t *) &page[pte_index(va)];
pte.pte = (ptep->pte | _PAGE_RW);
- xen_l1_entry_update(ptep, pte);
+ xen_l1_entry_update(ptep, pte);
__flush_tlb_one(addr);
}
@@ -115,55 +117,55 @@
void make_page_readonly(void *va)
{
pgd_t* pgd; pud_t *pud; pmd_t* pmd; pte_t pte, *ptep;
- unsigned long addr = (unsigned long) va;
-
- if (!init_mapping_done) {
- __make_page_readonly(addr);
- return;
- }
-
- pgd = pgd_offset_k(addr);
- pud = pud_offset(pgd, addr);
- pmd = pmd_offset(pud, addr);
- ptep = pte_offset_kernel(pmd, addr);
+ unsigned long addr = (unsigned long) va;
+
+ if (!init_mapping_done) {
+ __make_page_readonly(addr);
+ return;
+ }
+
+ pgd = pgd_offset_k(addr);
+ pud = pud_offset(pgd, addr);
+ pmd = pmd_offset(pud, addr);
+ ptep = pte_offset_kernel(pmd, addr);
pte.pte = (ptep->pte & ~_PAGE_RW);
- xen_l1_entry_update(ptep, pte);
+ xen_l1_entry_update(ptep, pte);
__flush_tlb_one(addr);
}
void make_page_writable(void *va)
{
- pgd_t* pgd; pud_t *pud; pmd_t* pmd; pte_t pte, *ptep;
- unsigned long addr = (unsigned long) va;
-
- if (!init_mapping_done) {
- __make_page_writable(addr);
- return;
- }
-
- pgd = pgd_offset_k(addr);
- pud = pud_offset(pgd, addr);
- pmd = pmd_offset(pud, addr);
- ptep = pte_offset_kernel(pmd, addr);
+ pgd_t* pgd; pud_t *pud; pmd_t* pmd; pte_t pte, *ptep;
+ unsigned long addr = (unsigned long) va;
+
+ if (!init_mapping_done) {
+ __make_page_writable(addr);
+ return;
+ }
+
+ pgd = pgd_offset_k(addr);
+ pud = pud_offset(pgd, addr);
+ pmd = pmd_offset(pud, addr);
+ ptep = pte_offset_kernel(pmd, addr);
pte.pte = (ptep->pte | _PAGE_RW);
- xen_l1_entry_update(ptep, pte);
+ xen_l1_entry_update(ptep, pte);
__flush_tlb_one(addr);
}
void make_pages_readonly(void* va, unsigned nr)
{
- while ( nr-- != 0 ) {
- make_page_readonly(va);
- va = (void*)((unsigned long)va + PAGE_SIZE);
- }
+ while (nr-- != 0) {
+ make_page_readonly(va);
+ va = (void*)((unsigned long)va + PAGE_SIZE);
+ }
}
void make_pages_writable(void* va, unsigned nr)
{
- while ( nr-- != 0 ) {
- make_page_writable(va);
- va = (void*)((unsigned long)va + PAGE_SIZE);
- }
+ while (nr-- != 0) {
+ make_page_writable(va);
+ va = (void*)((unsigned long)va + PAGE_SIZE);
+ }
}
/*
@@ -389,7 +391,7 @@
set_pte_phys(address, phys, prot, SET_FIXMAP_USER);
}
-unsigned long __initdata table_start, table_end, tables_space;
+unsigned long __initdata table_start, tables_space;
unsigned long get_machine_pfn(unsigned long addr)
{
@@ -400,40 +402,15 @@
return pte_mfn(*pte);
}
-#define ALIGN_TO_4K __attribute__((section(".data.page_aligned")))
-#define MAX_LOW_PAGES 0x20
-static unsigned long __init_pgt[MAX_LOW_PAGES][512] ALIGN_TO_4K;
-static int __init_pgt_index;
-
-/*
- * We start using from start_pfn
- */
static __init void *alloc_static_page(unsigned long *phys)
{
- int i = __init_pgt_index++;
-
- if (__init_pgt_index >= MAX_LOW_PAGES) {
- printk("Need to increase MAX_LOW_PAGES");
- BUG();
- }
-
- *phys = __pa(__init_pgt[i]);
-
- return (void *) __init_pgt[i];
+ unsigned long va = (start_pfn << PAGE_SHIFT) + __START_KERNEL_map;
+ *phys = start_pfn << PAGE_SHIFT;
+ start_pfn++;
+ memset((void *)va, 0, PAGE_SIZE);
+ return (void *)va;
}
-/*
- * Get RO page
- */
-static void __init *alloc_low_page(unsigned long *phys)
-{
- unsigned long pfn = table_end++;
-
- *phys = (pfn << PAGE_SHIFT);
- memset((void *) ((pfn << PAGE_SHIFT) + __START_KERNEL_map), 0,
PAGE_SIZE);
- return (void *)((pfn << PAGE_SHIFT) + __START_KERNEL_map);
-}
-
#define PTE_SIZE PAGE_SIZE
static inline void __set_pte(pte_t *dst, pte_t val)
@@ -443,30 +420,24 @@
static inline int make_readonly(unsigned long paddr)
{
- int readonly = 0;
-
- /* Make new page tables read-only. */
- if ((paddr < ((table_start << PAGE_SHIFT) + tables_space)) &&
- (paddr >= (table_start << PAGE_SHIFT)))
- readonly = 1;
-
- /* Make old page tables read-only. */
- if ((paddr < ((xen_start_info.pt_base - __START_KERNEL_map) +
- (xen_start_info.nr_pt_frames << PAGE_SHIFT))) &&
- (paddr >= (xen_start_info.pt_base - __START_KERNEL_map)))
- readonly = 1;
-
- /*
- * No need for writable mapping of kernel image. This also ensures that
- * page and descriptor tables embedded inside don't have writable mappings.
- */
- if ((paddr >= __pa_symbol(&_text)) && (paddr < __pa_symbol(&_end)))
- readonly = 1;
-
- return readonly;
-}
-
-void __init phys_pud_init(pud_t *pud, unsigned long address, unsigned long end)
+ int readonly = 0;
+
+ /* Make old and new page tables read-only. */
+ if ((paddr >= (xen_start_info->pt_base - __START_KERNEL_map))
+ && (paddr < ((table_start << PAGE_SHIFT) + tables_space)))
+ readonly = 1;
+ /*
+ * No need for writable mapping of kernel image. This also ensures that
+ * page and descriptor tables embedded inside don't have writable
+ * mappings.
+ */
+ if ((paddr >= __pa_symbol(&_text)) && (paddr < __pa_symbol(&_end)))
+ readonly = 1;
+
+ return readonly;
+}
+
+static void __init phys_pud_init(pud_t *pud, unsigned long address, unsigned
long end)
{
long i, j, k;
unsigned long paddr;
@@ -485,7 +456,7 @@
break;
}
- pmd = alloc_low_page(&pmd_phys);
+ pmd = alloc_static_page(&pmd_phys);
make_page_readonly(pmd);
xen_pmd_pin(pmd_phys);
set_pud(pud, __pud(pmd_phys | _KERNPG_TABLE));
@@ -499,18 +470,19 @@
set_pmd(pmd, __pmd(0));
break;
}
- pte = alloc_low_page(&pte_phys);
+ pte = alloc_static_page(&pte_phys);
pte_save = pte;
for (k = 0; k < PTRS_PER_PTE; pte++, k++, paddr +=
PTE_SIZE) {
+ if ((paddr >= end) ||
+ ((paddr >> PAGE_SHIFT) >=
+ xen_start_info->nr_pages)) {
+ __set_pte(pte, __pte(0));
+ continue;
+ }
if (make_readonly(paddr)) {
__set_pte(pte,
__pte(paddr | (_KERNPG_TABLE &
~_PAGE_RW)));
continue;
- }
- if (paddr >= end) {
- for (; k < PTRS_PER_PTE; k++, pte++)
- __set_pte(pte, __pte(0));
- break;
}
__set_pte(pte, __pte(paddr | _KERNPG_TABLE));
}
@@ -525,15 +497,16 @@
static void __init find_early_table_space(unsigned long end)
{
- unsigned long puds, pmds, ptes;
+ unsigned long puds, pmds, ptes;
puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
- ptes = (end + PTE_SIZE - 1) >> PAGE_SHIFT;
-
- tables_space = round_up(puds * 8, PAGE_SIZE) +
- round_up(pmds * 8, PAGE_SIZE) +
- round_up(ptes * 8, PAGE_SIZE);
+ ptes = (end + PTE_SIZE - 1) >> PAGE_SHIFT;
+
+ tables_space =
+ round_up(puds * 8, PAGE_SIZE) +
+ round_up(pmds * 8, PAGE_SIZE) +
+ round_up(ptes * 8, PAGE_SIZE);
}
void __init xen_init_pt(void)
@@ -549,7 +522,7 @@
memset((void *)level2_kernel_pgt, 0, PAGE_SIZE);
/* Find the initial pte page that was built for us. */
- page = (unsigned long *)xen_start_info.pt_base;
+ page = (unsigned long *)xen_start_info->pt_base;
addr = page[pgd_index(__START_KERNEL_map)];
addr_to_page(addr, page);
addr = page[pud_index(__START_KERNEL_map)];
@@ -579,65 +552,58 @@
mk_kernel_pgd(__pa_symbol(level3_user_pgt)));
}
-/*
- * Extend kernel mapping to access pages for page tables. The initial
- * mapping done by Xen is minimal (e.g. 8MB) and we need to extend the
- * mapping for early initialization.
- */
-static unsigned long current_size, extended_size;
-
void __init extend_init_mapping(void)
{
unsigned long va = __START_KERNEL_map;
unsigned long phys, addr, *pte_page;
- pmd_t *pmd;
+ pmd_t *pmd;
pte_t *pte, new_pte;
- unsigned long *page = (unsigned long *) init_level4_pgt;
- int i;
+ unsigned long *page = (unsigned long *)init_level4_pgt;
addr = page[pgd_index(va)];
addr_to_page(addr, page);
addr = page[pud_index(va)];
addr_to_page(addr, page);
- for (;;) {
+ /* Kill mapping of low 1MB. */
+ while (va < (unsigned long)&_text) {
+ HYPERVISOR_update_va_mapping(va, __pte_ma(0), 0);
+ va += PAGE_SIZE;
+ }
+
+ /* Ensure init mappings cover kernel text/data and initial tables. */
+ while (va < (__START_KERNEL_map
+ + (start_pfn << PAGE_SHIFT)
+ + tables_space)) {
pmd = (pmd_t *)&page[pmd_index(va)];
- if (!pmd_present(*pmd))
- break;
- addr = page[pmd_index(va)];
- addr_to_page(addr, pte_page);
- for (i = 0; i < PTRS_PER_PTE; i++) {
- pte = (pte_t *) &pte_page[pte_index(va)];
- if (!pte_present(*pte))
- break;
- va += PAGE_SIZE;
- current_size += PAGE_SIZE;
+ if (pmd_none(*pmd)) {
+ pte_page = alloc_static_page(&phys);
+ make_page_readonly(pte_page);
+ xen_pte_pin(phys);
+ set_pmd(pmd, __pmd(phys | _KERNPG_TABLE | _PAGE_USER));
+ } else {
+ addr = page[pmd_index(va)];
+ addr_to_page(addr, pte_page);
}
- }
-
- while (va < __START_KERNEL_map + current_size + tables_space) {
- pmd = (pmd_t *) &page[pmd_index(va)];
- if (!pmd_none(*pmd))
- continue;
- pte_page = (unsigned long *) alloc_static_page(&phys);
- make_page_readonly(pte_page);
- xen_pte_pin(phys);
- set_pmd(pmd, __pmd(phys | _KERNPG_TABLE | _PAGE_USER));
- for (i = 0; i < PTRS_PER_PTE; i++, va += PAGE_SIZE) {
+ pte = (pte_t *)&pte_page[pte_index(va)];
+ if (pte_none(*pte)) {
new_pte = pfn_pte(
(va - __START_KERNEL_map) >> PAGE_SHIFT,
__pgprot(_KERNPG_TABLE | _PAGE_USER));
- pte = (pte_t *)&pte_page[pte_index(va)];
xen_l1_entry_update(pte, new_pte);
- extended_size += PAGE_SIZE;
}
- }
-
- /* Kill mapping of low 1MB. */
- for (va = __START_KERNEL_map; va < (unsigned long)&_text; va +=
PAGE_SIZE)
+ va += PAGE_SIZE;
+ }
+
+ /* Finally, blow away any spurious initial mappings. */
+ while (1) {
+ pmd = (pmd_t *)&page[pmd_index(va)];
+ if (pmd_none(*pmd))
+ break;
HYPERVISOR_update_va_mapping(va, __pte_ma(0), 0);
-}
-
+ va += PAGE_SIZE;
+ }
+}
/* Setup the direct mapping of the physical memory at PAGE_OFFSET.
This runs before bootmem is initialized and gets pages directly from the
@@ -650,34 +616,31 @@
find_early_table_space(end);
extend_init_mapping();
- start_pfn = current_size >> PAGE_SHIFT;
table_start = start_pfn;
- table_end = table_start;
start = (unsigned long)__va(start);
end = (unsigned long)__va(end);
for (; start < end; start = next) {
unsigned long pud_phys;
- pud_t *pud = alloc_low_page(&pud_phys);
- make_page_readonly(pud);
- xen_pud_pin(pud_phys);
+ pud_t *pud = alloc_static_page(&pud_phys);
+ make_page_readonly(pud);
+ xen_pud_pin(pud_phys);
next = start + PGDIR_SIZE;
if (next > end)
next = end;
phys_pud_init(pud, __pa(start), __pa(next));
set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys));
- }
-
- printk("kernel direct mapping tables upto %lx @ %lx-%lx\n", end,
- table_start<<PAGE_SHIFT,
- table_end<<PAGE_SHIFT);
-
- start_pfn = ((current_size + extended_size) >> PAGE_SHIFT);
+ }
+
+ printk("kernel direct mapping tables upto %lx @ %lx-%lx\n",
+ __pa(end), table_start<<PAGE_SHIFT, start_pfn<<PAGE_SHIFT);
+
+ BUG_ON(start_pfn != (table_start + (tables_space >> PAGE_SHIFT)));
__flush_tlb_all();
- init_mapping_done = 1;
+ init_mapping_done = 1;
}
extern struct x8664_pda cpu_pda[NR_CPUS];
@@ -708,7 +671,7 @@
free_area_init(zones_size);
}
- set_fixmap(FIX_SHARED_INFO, xen_start_info.shared_info);
+ set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
memset(empty_zero_page, 0, sizeof(empty_zero_page));
@@ -719,7 +682,7 @@
int i;
/* Setup mapping of lower 1st MB */
for (i = 0; i < NR_FIX_ISAMAPS; i++)
- if (xen_start_info.flags & SIF_PRIVILEGED)
+ if (xen_start_info->flags & SIF_PRIVILEGED)
set_fixmap(FIX_ISAMAP_BEGIN - i, i * PAGE_SIZE);
else
__set_fixmap(FIX_ISAMAP_BEGIN - i,
@@ -767,9 +730,6 @@
static inline int page_is_ram (unsigned long pagenr)
{
- if (pagenr < start_pfn || pagenr >= end_pfn)
- return 0;
-
return 1;
}
@@ -1005,3 +965,13 @@
{
return (addr >= VSYSCALL_START) && (addr < VSYSCALL_END);
}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 linux-2.6-xen-sparse/drivers/char/mem.c
--- a/linux-2.6-xen-sparse/drivers/char/mem.c Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/char/mem.c Fri Sep 9 16:30:54 2005
@@ -231,7 +231,7 @@
}
#endif
-static int mmap_kmem(struct file * file, struct vm_area_struct * vma)
+static int mmap_mem(struct file * file, struct vm_area_struct * vma)
{
#if defined(__HAVE_PHYS_MEM_ACCESS_PROT)
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
@@ -258,7 +258,6 @@
return 0;
}
-#if 0
static int mmap_kmem(struct file * file, struct vm_area_struct * vma)
{
unsigned long long val;
@@ -275,7 +274,6 @@
vma->vm_pgoff = __pa(val) >> PAGE_SHIFT;
return mmap_mem(file, vma);
}
-#endif
extern long vread(char *buf, char *addr, unsigned long count);
extern long vwrite(char *buf, char *addr, unsigned long count);
@@ -731,7 +729,7 @@
.llseek = memory_lseek,
.read = read_mem,
.write = write_mem,
- .mmap = mmap_kmem,
+ .mmap = mmap_mem,
.open = open_mem,
};
#else
diff -r 10b1d30d3f66 -r b2f4823b6ff0 linux-2.6-xen-sparse/drivers/xen/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/Makefile Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/Makefile Fri Sep 9 16:30:54 2005
@@ -8,7 +8,9 @@
obj-$(CONFIG_XEN_BLKDEV_BACKEND) += blkback/
obj-$(CONFIG_XEN_NETDEV_BACKEND) += netback/
+obj-$(CONFIG_XEN_TPMDEV_BACKEND) += tpmback/
obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += blkfront/
obj-$(CONFIG_XEN_NETDEV_FRONTEND) += netfront/
obj-$(CONFIG_XEN_BLKDEV_TAP) += blktap/
+obj-$(CONFIG_XEN_TPMDEV_FRONTEND) += tpmfront/
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c
--- a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Fri Sep 9
16:30:54 2005
@@ -44,6 +44,7 @@
#include <asm-xen/xen_proc.h>
#include <asm-xen/hypervisor.h>
#include <asm-xen/balloon.h>
+#include <asm-xen/xen-public/memory.h>
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
@@ -57,6 +58,12 @@
static struct proc_dir_entry *balloon_pde;
static DECLARE_MUTEX(balloon_mutex);
+
+/*
+ * Protects atomic reservation decrease/increase against concurrent increases.
+ * Also protects non-atomic updates of current_pages and driver_pages, and
+ * balloon lists.
+ */
spinlock_t balloon_lock = SPIN_LOCK_UNLOCKED;
/* We aim for 'current allocation' == 'target allocation'. */
@@ -156,6 +163,146 @@
return target;
}
+static int increase_reservation(unsigned long nr_pages)
+{
+ unsigned long *mfn_list, pfn, i, flags;
+ struct page *page;
+ long rc;
+ struct xen_memory_reservation reservation = {
+ .address_bits = 0,
+ .extent_order = 0,
+ .domid = DOMID_SELF
+ };
+
+ if (nr_pages > (PAGE_SIZE / sizeof(unsigned long)))
+ nr_pages = PAGE_SIZE / sizeof(unsigned long);
+
+ mfn_list = (unsigned long *)__get_free_page(GFP_KERNEL);
+ if (mfn_list == NULL)
+ return -ENOMEM;
+
+ balloon_lock(flags);
+
+ reservation.extent_start = mfn_list;
+ reservation.nr_extents = nr_pages;
+ rc = HYPERVISOR_memory_op(
+ XENMEM_increase_reservation, &reservation);
+ if (rc < nr_pages) {
+ /* We hit the Xen hard limit: reprobe. */
+ reservation.extent_start = mfn_list;
+ reservation.nr_extents = rc;
+ BUG_ON(HYPERVISOR_memory_op(
+ XENMEM_decrease_reservation,
+ &reservation) != rc);
+ hard_limit = current_pages + rc - driver_pages;
+ goto out;
+ }
+
+ for (i = 0; i < nr_pages; i++) {
+ page = balloon_retrieve();
+ BUG_ON(page == NULL);
+
+ pfn = page - mem_map;
+ BUG_ON(phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY);
+
+ /* Update P->M and M->P tables. */
+ phys_to_machine_mapping[pfn] = mfn_list[i];
+ xen_machphys_update(mfn_list[i], pfn);
+
+ /* Link back into the page tables if not highmem. */
+ if (pfn < max_low_pfn)
+ BUG_ON(HYPERVISOR_update_va_mapping(
+ (unsigned long)__va(pfn << PAGE_SHIFT),
+ pfn_pte_ma(mfn_list[i], PAGE_KERNEL),
+ 0));
+
+ /* Relinquish the page back to the allocator. */
+ ClearPageReserved(page);
+ set_page_count(page, 1);
+ __free_page(page);
+ }
+
+ current_pages += nr_pages;
+
+ out:
+ balloon_unlock(flags);
+
+ free_page((unsigned long)mfn_list);
+
+ return 0;
+}
+
+static int decrease_reservation(unsigned long nr_pages)
+{
+ unsigned long *mfn_list, pfn, i, flags;
+ struct page *page;
+ void *v;
+ int need_sleep = 0;
+ struct xen_memory_reservation reservation = {
+ .address_bits = 0,
+ .extent_order = 0,
+ .domid = DOMID_SELF
+ };
+
+ if (nr_pages > (PAGE_SIZE / sizeof(unsigned long)))
+ nr_pages = PAGE_SIZE / sizeof(unsigned long);
+
+ mfn_list = (unsigned long *)__get_free_page(GFP_KERNEL);
+ if (mfn_list == NULL)
+ return -ENOMEM;
+
+ for (i = 0; i < nr_pages; i++) {
+ if ((page = alloc_page(GFP_HIGHUSER)) == NULL) {
+ nr_pages = i;
+ need_sleep = 1;
+ break;
+ }
+
+ pfn = page - mem_map;
+ mfn_list[i] = phys_to_machine_mapping[pfn];
+
+ if (!PageHighMem(page)) {
+ v = phys_to_virt(pfn << PAGE_SHIFT);
+ scrub_pages(v, 1);
+ BUG_ON(HYPERVISOR_update_va_mapping(
+ (unsigned long)v, __pte_ma(0), 0));
+ }
+#ifdef CONFIG_XEN_SCRUB_PAGES
+ else {
+ v = kmap(page);
+ scrub_pages(v, 1);
+ kunmap(page);
+ }
+#endif
+ }
+
+ /* Ensure that ballooned highmem pages don't have kmaps. */
+ kmap_flush_unused();
+ flush_tlb_all();
+
+ balloon_lock(flags);
+
+ /* No more mappings: invalidate P2M and add to balloon. */
+ for (i = 0; i < nr_pages; i++) {
+ pfn = mfn_to_pfn(mfn_list[i]);
+ phys_to_machine_mapping[pfn] = INVALID_P2M_ENTRY;
+ balloon_append(pfn_to_page(pfn));
+ }
+
+ reservation.extent_start = mfn_list;
+ reservation.nr_extents = nr_pages;
+ BUG_ON(HYPERVISOR_memory_op(
+ XENMEM_decrease_reservation, &reservation) != nr_pages);
+
+ current_pages -= nr_pages;
+
+ balloon_unlock(flags);
+
+ free_page((unsigned long)mfn_list);
+
+ return need_sleep;
+}
+
/*
* We avoid multiple worker processes conflicting via the balloon mutex.
* We may of course race updates of the target counts (which are protected
@@ -164,112 +311,23 @@
*/
static void balloon_process(void *unused)
{
- unsigned long *mfn_list, pfn, i, flags;
- struct page *page;
- long credit, debt, rc;
- void *v;
+ int need_sleep = 0;
+ long credit;
down(&balloon_mutex);
- retry:
- mfn_list = NULL;
-
- if ((credit = current_target() - current_pages) > 0) {
- mfn_list = vmalloc(credit * sizeof(*mfn_list));
- if (mfn_list == NULL)
- goto out;
-
- balloon_lock(flags);
- rc = HYPERVISOR_dom_mem_op(
- MEMOP_increase_reservation, mfn_list, credit, 0);
- balloon_unlock(flags);
- if (rc < credit) {
- /* We hit the Xen hard limit: reprobe. */
- BUG_ON(HYPERVISOR_dom_mem_op(
- MEMOP_decrease_reservation,
- mfn_list, rc, 0) != rc);
- hard_limit = current_pages + rc - driver_pages;
- vfree(mfn_list);
- goto retry;
- }
-
- for (i = 0; i < credit; i++) {
- page = balloon_retrieve();
- BUG_ON(page == NULL);
-
- pfn = page - mem_map;
- if (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY)
- BUG();
-
- /* Update P->M and M->P tables. */
- phys_to_machine_mapping[pfn] = mfn_list[i];
- xen_machphys_update(mfn_list[i], pfn);
-
- /* Link back into the page tables if not highmem. */
- if (pfn < max_low_pfn)
- BUG_ON(HYPERVISOR_update_va_mapping(
- (unsigned long)__va(pfn << PAGE_SHIFT),
- pfn_pte_ma(mfn_list[i], PAGE_KERNEL),
- 0));
-
- /* Relinquish the page back to the allocator. */
- ClearPageReserved(page);
- set_page_count(page, 1);
- __free_page(page);
- }
-
- current_pages += credit;
- } else if (credit < 0) {
- debt = -credit;
-
- mfn_list = vmalloc(debt * sizeof(*mfn_list));
- if (mfn_list == NULL)
- goto out;
-
- for (i = 0; i < debt; i++) {
- if ((page = alloc_page(GFP_HIGHUSER)) == NULL) {
- debt = i;
- break;
- }
-
- pfn = page - mem_map;
- mfn_list[i] = phys_to_machine_mapping[pfn];
-
- if (!PageHighMem(page)) {
- v = phys_to_virt(pfn << PAGE_SHIFT);
- scrub_pages(v, 1);
- BUG_ON(HYPERVISOR_update_va_mapping(
- (unsigned long)v, __pte_ma(0), 0));
- }
-#ifdef CONFIG_XEN_SCRUB_PAGES
- else {
- v = kmap(page);
- scrub_pages(v, 1);
- kunmap(page);
- }
+ do {
+ credit = current_target() - current_pages;
+ if (credit > 0)
+ need_sleep = (increase_reservation(credit) != 0);
+ if (credit < 0)
+ need_sleep = (decrease_reservation(-credit) != 0);
+
+#ifndef CONFIG_PREEMPT
+ if (need_resched())
+ schedule();
#endif
- }
-
- /* Ensure that ballooned highmem pages don't have kmaps. */
- kmap_flush_unused();
- flush_tlb_all();
-
- /* No more mappings: invalidate P2M and add to balloon. */
- for (i = 0; i < debt; i++) {
- pfn = mfn_to_pfn(mfn_list[i]);
- phys_to_machine_mapping[pfn] = INVALID_P2M_ENTRY;
- balloon_append(pfn_to_page(pfn));
- }
-
- BUG_ON(HYPERVISOR_dom_mem_op(
- MEMOP_decrease_reservation,mfn_list, debt, 0) != debt);
-
- current_pages -= debt;
- }
-
- out:
- if (mfn_list != NULL)
- vfree(mfn_list);
+ } while ((credit != 0) && !need_sleep);
/* Schedule more work if there is some still to be done. */
if (current_target() != current_pages)
@@ -295,10 +353,10 @@
/* React to a change in the target key */
static void watch_target(struct xenbus_watch *watch, const char *node)
{
- unsigned long new_target;
+ unsigned long long new_target;
int err;
- err = xenbus_scanf("memory", "target", "%lu", &new_target);
+ err = xenbus_scanf("memory", "target", "%llu", &new_target);
if (err != 1) {
printk(KERN_ERR "Unable to read memory/target\n");
return;
@@ -390,7 +448,7 @@
IPRINTK("Initialising balloon driver.\n");
- current_pages = min(xen_start_info.nr_pages, max_pfn);
+ current_pages = min(xen_start_info->nr_pages, max_pfn);
target_pages = current_pages;
balloon_low = 0;
balloon_high = 0;
@@ -410,7 +468,7 @@
balloon_pde->write_proc = balloon_write;
/* Initialise the balloon with excess memory space. */
- for (pfn = xen_start_info.nr_pages; pfn < max_pfn; pfn++) {
+ for (pfn = xen_start_info->nr_pages; pfn < max_pfn; pfn++) {
page = &mem_map[pfn];
if (!PageReserved(page))
balloon_append(page);
@@ -429,8 +487,9 @@
void balloon_update_driver_allowance(long delta)
{
unsigned long flags;
+
balloon_lock(flags);
- driver_pages += delta; /* non-atomic update */
+ driver_pages += delta;
balloon_unlock(flags);
}
@@ -438,11 +497,17 @@
pte_t *pte, struct page *pte_page, unsigned long addr, void *data)
{
unsigned long mfn = pte_mfn(*pte);
+ struct xen_memory_reservation reservation = {
+ .extent_start = &mfn,
+ .nr_extents = 1,
+ .extent_order = 0,
+ .domid = DOMID_SELF
+ };
set_pte(pte, __pte_ma(0));
phys_to_machine_mapping[__pa(addr) >> PAGE_SHIFT] =
INVALID_P2M_ENTRY;
- BUG_ON(HYPERVISOR_dom_mem_op(
- MEMOP_decrease_reservation, &mfn, 1, 0) != 1);
+ BUG_ON(HYPERVISOR_memory_op(
+ XENMEM_decrease_reservation, &reservation) != 1);
return 0;
}
@@ -457,9 +522,10 @@
scrub_pages(vstart, 1 << order);
- balloon_lock(flags);
BUG_ON(generic_page_range(
&init_mm, vstart, PAGE_SIZE << order, dealloc_pte_fn, NULL));
+
+ balloon_lock(flags);
current_pages -= 1UL << order;
balloon_unlock(flags);
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Fri Sep 9
16:30:54 2005
@@ -504,8 +504,8 @@
int i;
struct page *page;
- if ( !(xen_start_info.flags & SIF_INITDOMAIN) &&
- !(xen_start_info.flags & SIF_BLK_BE_DOMAIN) )
+ if ( !(xen_start_info->flags & SIF_INITDOMAIN) &&
+ !(xen_start_info->flags & SIF_BLK_BE_DOMAIN) )
return 0;
blkif_interface_init();
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Fri Sep 9
16:30:54 2005
@@ -32,23 +32,15 @@
*/
#if 1
-#define ASSERT(_p) \
- if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \
- __LINE__, __FILE__); *(int*)0=0; }
+#define ASSERT(p) \
+ if (!(p)) { printk("Assertion '%s' failed, line %d, file %s", #p , \
+ __LINE__, __FILE__); *(int*)0=0; }
#else
#define ASSERT(_p)
#endif
#include <linux/version.h>
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
#include "block.h"
-#else
-#include "common.h"
-#include <linux/blk.h>
-#include <linux/tqueue.h>
-#endif
-
#include <linux/cdrom.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
@@ -58,90 +50,57 @@
#include <asm-xen/xen-public/grant_table.h>
#include <asm-xen/gnttab.h>
-typedef unsigned char byte; /* from linux/ide.h */
-
-/* Control whether runtime update of vbds is enabled. */
-#define ENABLE_VBD_UPDATE 1
-
#define BLKIF_STATE_DISCONNECTED 0
#define BLKIF_STATE_CONNECTED 1
static unsigned int blkif_state = BLKIF_STATE_DISCONNECTED;
-
-#define BLK_RING_SIZE __RING_SIZE((blkif_sring_t *)0, PAGE_SIZE)
#define MAXIMUM_OUTSTANDING_BLOCK_REQS \
(BLKIF_MAX_SEGMENTS_PER_REQUEST * BLKIF_RING_SIZE)
#define GRANTREF_INVALID (1<<15)
-
-static struct blk_shadow {
- blkif_request_t req;
- unsigned long request;
- unsigned long frame[BLKIF_MAX_SEGMENTS_PER_REQUEST];
-} blk_shadow[BLK_RING_SIZE];
-unsigned long blk_shadow_free;
+#define GRANT_INVALID_REF (0xFFFF)
static int recovery = 0; /* Recovery in progress: protected by blkif_io_lock */
static void kick_pending_request_queues(struct blkfront_info *info);
-static int __init xlblk_init(void);
-
static void blkif_completion(struct blk_shadow *s);
-static inline int GET_ID_FROM_FREELIST(void)
-{
- unsigned long free = blk_shadow_free;
- BUG_ON(free > BLK_RING_SIZE);
- blk_shadow_free = blk_shadow[free].req.id;
- blk_shadow[free].req.id = 0x0fffffee; /* debug */
- return free;
-}
-
-static inline void ADD_ID_TO_FREELIST(unsigned long id)
-{
- blk_shadow[id].req.id = blk_shadow_free;
- blk_shadow[id].request = 0;
- blk_shadow_free = id;
-}
-
-
-/************************ COMMON CODE (inlined) ************************/
-
-/* Kernel-specific definitions used in the common code */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-#define DISABLE_SCATTERGATHER()
-#else
-static int sg_operation = -1;
-#define DISABLE_SCATTERGATHER() (sg_operation = -1)
-#endif
+static inline int GET_ID_FROM_FREELIST(
+ struct blkfront_info *info)
+{
+ unsigned long free = info->shadow_free;
+ BUG_ON(free > BLK_RING_SIZE);
+ info->shadow_free = info->shadow[free].req.id;
+ info->shadow[free].req.id = 0x0fffffee; /* debug */
+ return free;
+}
+
+static inline void ADD_ID_TO_FREELIST(
+ struct blkfront_info *info, unsigned long id)
+{
+ info->shadow[id].req.id = info->shadow_free;
+ info->shadow[id].request = 0;
+ info->shadow_free = id;
+}
static inline void pickle_request(struct blk_shadow *s, blkif_request_t *r)
{
- s->req = *r;
+ s->req = *r;
}
static inline void unpickle_request(blkif_request_t *r, struct blk_shadow *s)
{
- *r = s->req;
-}
-
+ *r = s->req;
+}
static inline void flush_requests(struct blkfront_info *info)
{
- DISABLE_SCATTERGATHER();
- RING_PUSH_REQUESTS(&info->ring);
- notify_via_evtchn(info->evtchn);
-}
-
-
-/************************** KERNEL VERSION 2.6 **************************/
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-
-module_init(xlblk_init);
+ RING_PUSH_REQUESTS(&info->ring);
+ notify_via_evtchn(info->evtchn);
+}
static void kick_pending_request_queues(struct blkfront_info *info)
{
@@ -169,50 +128,44 @@
int blkif_open(struct inode *inode, struct file *filep)
{
- // struct gendisk *gd = inode->i_bdev->bd_disk;
- // struct xlbd_disk_info *di = (struct xlbd_disk_info
*)gd->private_data;
-
- /* Update of usage count is protected by per-device semaphore. */
- // di->mi->usage++;
-
return 0;
}
int blkif_release(struct inode *inode, struct file *filep)
{
- /* FIXME: This is where we can actually free up majors, etc. --RR */
- return 0;
+ return 0;
}
int blkif_ioctl(struct inode *inode, struct file *filep,
unsigned command, unsigned long argument)
{
- int i;
-
- DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n",
- command, (long)argument, inode->i_rdev);
-
- switch ( command )
- {
- case HDIO_GETGEO:
- /* return ENOSYS to use defaults */
- return -ENOSYS;
-
- case CDROMMULTISESSION:
- DPRINTK("FIXME: support multisession CDs later\n");
- for ( i = 0; i < sizeof(struct cdrom_multisession); i++ )
- if ( put_user(0, (byte *)(argument + i)) ) return -EFAULT;
- return 0;
-
- default:
- /*printk(KERN_ALERT "ioctl %08x not supported by Xen blkdev\n",
- command);*/
- return -EINVAL; /* same return as native Linux */
- }
-
- return 0;
+ int i;
+
+ DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n",
+ command, (long)argument, inode->i_rdev);
+
+ switch ( command )
+ {
+ case HDIO_GETGEO:
+ /* return ENOSYS to use defaults */
+ return -ENOSYS;
+
+ case CDROMMULTISESSION:
+ DPRINTK("FIXME: support multisession CDs later\n");
+ for (i = 0; i < sizeof(struct cdrom_multisession); i++)
+ if (put_user(0, (char *)(argument + i)))
+ return -EFAULT;
+ return 0;
+
+ default:
+ /*printk(KERN_ALERT "ioctl %08x not supported by Xen blkdev\n",
+ command);*/
+ return -EINVAL; /* same return as native Linux */
+ }
+
+ return 0;
}
@@ -228,76 +181,77 @@
*/
static int blkif_queue_request(struct request *req)
{
- struct blkfront_info *info = req->rq_disk->private_data;
- unsigned long buffer_ma;
- blkif_request_t *ring_req;
- struct bio *bio;
- struct bio_vec *bvec;
- int idx;
- unsigned long id;
- unsigned int fsect, lsect;
- int ref;
- grant_ref_t gref_head;
-
- if (unlikely(info->connected != BLKIF_STATE_CONNECTED))
- return 1;
-
- if (gnttab_alloc_grant_references(BLKIF_MAX_SEGMENTS_PER_REQUEST,
- &gref_head) < 0) {
- gnttab_request_free_callback(&info->callback,
- blkif_restart_queue_callback, info,
- BLKIF_MAX_SEGMENTS_PER_REQUEST);
- return 1;
- }
-
- /* Fill out a communications ring structure. */
- ring_req = RING_GET_REQUEST(&info->ring, info->ring.req_prod_pvt);
- id = GET_ID_FROM_FREELIST();
- blk_shadow[id].request = (unsigned long)req;
-
- ring_req->id = id;
- ring_req->operation = rq_data_dir(req) ? BLKIF_OP_WRITE : BLKIF_OP_READ;
- ring_req->sector_number = (blkif_sector_t)req->sector;
- ring_req->handle = info->handle;
-
- ring_req->nr_segments = 0;
- rq_for_each_bio(bio, req)
- {
- bio_for_each_segment(bvec, bio, idx)
- {
- if ( ring_req->nr_segments == BLKIF_MAX_SEGMENTS_PER_REQUEST )
- BUG();
- buffer_ma = page_to_phys(bvec->bv_page);
- fsect = bvec->bv_offset >> 9;
- lsect = fsect + (bvec->bv_len >> 9) - 1;
- /* install a grant reference. */
- ref = gnttab_claim_grant_reference(&gref_head);
- ASSERT( ref != -ENOSPC );
-
- gnttab_grant_foreign_access_ref(
- ref,
- info->backend_id,
- buffer_ma >> PAGE_SHIFT,
- rq_data_dir(req) );
-
- blk_shadow[id].frame[ring_req->nr_segments] =
- buffer_ma >> PAGE_SHIFT;
-
- ring_req->frame_and_sects[ring_req->nr_segments] =
- blkif_fas_from_gref(ref, fsect, lsect);
-
- ring_req->nr_segments++;
- }
- }
-
- info->ring.req_prod_pvt++;
-
- /* Keep a private copy so we can reissue requests when recovering. */
- pickle_request(&blk_shadow[id], ring_req);
-
- gnttab_free_grant_references(gref_head);
-
- return 0;
+ struct blkfront_info *info = req->rq_disk->private_data;
+ unsigned long buffer_mfn;
+ blkif_request_t *ring_req;
+ struct bio *bio;
+ struct bio_vec *bvec;
+ int idx;
+ unsigned long id;
+ unsigned int fsect, lsect;
+ int ref;
+ grant_ref_t gref_head;
+
+ if (unlikely(info->connected != BLKIF_STATE_CONNECTED))
+ return 1;
+
+ if (gnttab_alloc_grant_references(
+ BLKIF_MAX_SEGMENTS_PER_REQUEST, &gref_head) < 0) {
+ gnttab_request_free_callback(
+ &info->callback,
+ blkif_restart_queue_callback,
+ info,
+ BLKIF_MAX_SEGMENTS_PER_REQUEST);
+ return 1;
+ }
+
+ /* Fill out a communications ring structure. */
+ ring_req = RING_GET_REQUEST(&info->ring, info->ring.req_prod_pvt);
+ id = GET_ID_FROM_FREELIST(info);
+ info->shadow[id].request = (unsigned long)req;
+
+ ring_req->id = id;
+ ring_req->operation = rq_data_dir(req) ?
+ BLKIF_OP_WRITE : BLKIF_OP_READ;
+ ring_req->sector_number = (blkif_sector_t)req->sector;
+ ring_req->handle = info->handle;
+
+ ring_req->nr_segments = 0;
+ rq_for_each_bio (bio, req) {
+ bio_for_each_segment (bvec, bio, idx) {
+ BUG_ON(ring_req->nr_segments
+ == BLKIF_MAX_SEGMENTS_PER_REQUEST);
+ buffer_mfn = page_to_phys(bvec->bv_page) >> PAGE_SHIFT;
+ fsect = bvec->bv_offset >> 9;
+ lsect = fsect + (bvec->bv_len >> 9) - 1;
+ /* install a grant reference. */
+ ref = gnttab_claim_grant_reference(&gref_head);
+ ASSERT(ref != -ENOSPC);
+
+ gnttab_grant_foreign_access_ref(
+ ref,
+ info->backend_id,
+ buffer_mfn,
+ rq_data_dir(req) );
+
+ info->shadow[id].frame[ring_req->nr_segments] =
+ buffer_mfn;
+
+ ring_req->frame_and_sects[ring_req->nr_segments] =
+ blkif_fas_from_gref(ref, fsect, lsect);
+
+ ring_req->nr_segments++;
+ }
+ }
+
+ info->ring.req_prod_pvt++;
+
+ /* Keep a private copy so we can reissue requests when recovering. */
+ pickle_request(&info->shadow[id], ring_req);
+
+ gnttab_free_grant_references(gref_head);
+
+ return 0;
}
/*
@@ -306,756 +260,200 @@
*/
void do_blkif_request(request_queue_t *rq)
{
- struct blkfront_info *info = NULL;
- struct request *req;
- int queued;
-
- DPRINTK("Entered do_blkif_request\n");
-
- queued = 0;
-
- while ( (req = elv_next_request(rq)) != NULL )
- {
- info = req->rq_disk->private_data;
-
- if ( !blk_fs_request(req) )
- {
- end_request(req, 0);
- continue;
- }
-
- if (RING_FULL(&info->ring))
- goto wait;
-
- DPRINTK("do_blk_req %p: cmd %p, sec %lx, (%u/%li) buffer:%p [%s]\n",
- req, req->cmd, req->sector, req->current_nr_sectors,
- req->nr_sectors, req->buffer,
- rq_data_dir(req) ? "write" : "read");
-
- blkdev_dequeue_request(req);
- if (blkif_queue_request(req)) {
- blk_requeue_request(rq, req);
- wait:
- /* Avoid pointless unplugs. */
- blk_stop_queue(rq);
- break;
- }
-
- queued++;
- }
-
- if ( queued != 0 )
- flush_requests(info);
+ struct blkfront_info *info = NULL;
+ struct request *req;
+ int queued;
+
+ DPRINTK("Entered do_blkif_request\n");
+
+ queued = 0;
+
+ while ((req = elv_next_request(rq)) != NULL) {
+ info = req->rq_disk->private_data;
+
+ if (!blk_fs_request(req)) {
+ end_request(req, 0);
+ continue;
+ }
+
+ if (RING_FULL(&info->ring))
+ goto wait;
+
+ DPRINTK("do_blk_req %p: cmd %p, sec %lx, "
+ "(%u/%li) buffer:%p [%s]\n",
+ req, req->cmd, req->sector, req->current_nr_sectors,
+ req->nr_sectors, req->buffer,
+ rq_data_dir(req) ? "write" : "read");
+
+ blkdev_dequeue_request(req);
+ if (blkif_queue_request(req)) {
+ blk_requeue_request(rq, req);
+ wait:
+ /* Avoid pointless unplugs. */
+ blk_stop_queue(rq);
+ break;
+ }
+
+ queued++;
+ }
+
+ if (queued != 0)
+ flush_requests(info);
}
static irqreturn_t blkif_int(int irq, void *dev_id, struct pt_regs *ptregs)
{
- struct request *req;
- blkif_response_t *bret;
- RING_IDX i, rp;
- unsigned long flags;
- struct blkfront_info *info = (struct blkfront_info *)dev_id;
-
- spin_lock_irqsave(&blkif_io_lock, flags);
-
- if (unlikely(info->connected != BLKIF_STATE_CONNECTED || recovery)) {
- spin_unlock_irqrestore(&blkif_io_lock, flags);
- return IRQ_HANDLED;
- }
-
- rp = info->ring.sring->rsp_prod;
- rmb(); /* Ensure we see queued responses up to 'rp'. */
-
- for ( i = info->ring.rsp_cons; i != rp; i++ )
- {
- unsigned long id;
-
- bret = RING_GET_RESPONSE(&info->ring, i);
- id = bret->id;
- req = (struct request *)blk_shadow[id].request;
-
- blkif_completion(&blk_shadow[id]);
-
- ADD_ID_TO_FREELIST(id);
-
- switch ( bret->operation )
- {
- case BLKIF_OP_READ:
- case BLKIF_OP_WRITE:
- if ( unlikely(bret->status != BLKIF_RSP_OKAY) )
- DPRINTK("Bad return from blkdev data request: %x\n",
- bret->status);
-
- if ( unlikely(end_that_request_first
- (req,
- (bret->status == BLKIF_RSP_OKAY),
- req->hard_nr_sectors)) )
- BUG();
- end_that_request_last(req);
-
- break;
- default:
- BUG();
- }
- }
-
- info->ring.rsp_cons = i;
-
- kick_pending_request_queues(info);
-
- spin_unlock_irqrestore(&blkif_io_lock, flags);
-
- return IRQ_HANDLED;
-}
-
-#else
-/************************** KERNEL VERSION 2.4 **************************/
-
-static kdev_t sg_dev;
-static unsigned long sg_next_sect;
-
-/*
- * Request queues with outstanding work, but ring is currently full.
- * We need no special lock here, as we always access this with the
- * blkif_io_lock held. We only need a small maximum list.
- */
-#define MAX_PENDING 8
-static request_queue_t *pending_queues[MAX_PENDING];
-static int nr_pending;
-
-
-#define blkif_io_lock io_request_lock
-
-/*============================================================================*/
-static void kick_pending_request_queues(void)
-{
- /* We kick pending request queues if the ring is reasonably empty. */
- if ( (nr_pending != 0) &&
- (RING_PENDING_REQUESTS(&info->ring) < (BLK_RING_SIZE >> 1)) )
- {
- /* Attempt to drain the queue, but bail if the ring becomes full. */
- while ( (nr_pending != 0) && !RING_FULL(&info->ring) )
- do_blkif_request(pending_queues[--nr_pending]);
- }
-}
-
-int blkif_open(struct inode *inode, struct file *filep)
-{
- short xldev = inode->i_rdev;
- struct gendisk *gd = get_gendisk(xldev);
- xl_disk_t *disk = xldev_to_xldisk(inode->i_rdev);
- short minor = MINOR(xldev);
-
- if ( gd->part[minor].nr_sects == 0 )
- {
- /*
- * Device either doesn't exist, or has zero capacity; we use a few
- * cheesy heuristics to return the relevant error code
- */
- if ( (gd->sizes[minor >> gd->minor_shift] != 0) ||
- ((minor & (gd->max_p - 1)) != 0) )
- {
- /*
- * We have a real device, but no such partition, or we just have a
- * partition number so guess this is the problem.
- */
- return -ENXIO; /* no such device or address */
- }
- else if ( gd->flags[minor >> gd->minor_shift] & GENHD_FL_REMOVABLE )
- {
- /* This is a removable device => assume that media is missing. */
- return -ENOMEDIUM; /* media not present (this is a guess) */
- }
- else
- {
- /* Just go for the general 'no such device' error. */
- return -ENODEV; /* no such device */
- }
- }
-
- /* Update of usage count is protected by per-device semaphore. */
- disk->usage++;
-
- return 0;
-}
-
-
-int blkif_release(struct inode *inode, struct file *filep)
-{
- xl_disk_t *disk = xldev_to_xldisk(inode->i_rdev);
-
- /*
- * When usage drops to zero it may allow more VBD updates to occur.
- * Update of usage count is protected by a per-device semaphore.
- */
- if ( --disk->usage == 0 ) {
- vbd_update();
- }
-
- return 0;
-}
-
-
-int blkif_ioctl(struct inode *inode, struct file *filep,
- unsigned command, unsigned long argument)
-{
- kdev_t dev = inode->i_rdev;
- struct hd_geometry *geo = (struct hd_geometry *)argument;
- struct gendisk *gd;
- struct hd_struct *part;
- int i;
- unsigned short cylinders;
- byte heads, sectors;
-
- /* NB. No need to check permissions. That is done for us. */
-
- DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n",
- command, (long) argument, dev);
-
- gd = get_gendisk(dev);
- part = &gd->part[MINOR(dev)];
-
- switch ( command )
- {
- case BLKGETSIZE:
- DPRINTK_IOCTL(" BLKGETSIZE: %x %lx\n", BLKGETSIZE, part->nr_sects);
- return put_user(part->nr_sects, (unsigned long *) argument);
-
- case BLKGETSIZE64:
- DPRINTK_IOCTL(" BLKGETSIZE64: %x %llx\n", BLKGETSIZE64,
- (u64)part->nr_sects * 512);
- return put_user((u64)part->nr_sects * 512, (u64 *) argument);
-
- case BLKRRPART: /* re-read partition table */
- DPRINTK_IOCTL(" BLKRRPART: %x\n", BLKRRPART);
- return blkif_revalidate(dev);
-
- case BLKSSZGET:
- return hardsect_size[MAJOR(dev)][MINOR(dev)];
-
- case BLKBSZGET: /* get block size */
- DPRINTK_IOCTL(" BLKBSZGET: %x\n", BLKBSZGET);
- break;
-
- case BLKBSZSET: /* set block size */
- DPRINTK_IOCTL(" BLKBSZSET: %x\n", BLKBSZSET);
- break;
-
- case BLKRASET: /* set read-ahead */
- DPRINTK_IOCTL(" BLKRASET: %x\n", BLKRASET);
- break;
-
- case BLKRAGET: /* get read-ahead */
- DPRINTK_IOCTL(" BLKRAFET: %x\n", BLKRAGET);
- break;
-
- case HDIO_GETGEO:
- DPRINTK_IOCTL(" HDIO_GETGEO: %x\n", HDIO_GETGEO);
- if (!argument) return -EINVAL;
-
- /* We don't have real geometry info, but let's at least return
- values consistent with the size of the device */
-
- heads = 0xff;
- sectors = 0x3f;
- cylinders = part->nr_sects / (heads * sectors);
-
- if (put_user(0x00, (unsigned long *) &geo->start)) return -EFAULT;
- if (put_user(heads, (byte *)&geo->heads)) return -EFAULT;
- if (put_user(sectors, (byte *)&geo->sectors)) return -EFAULT;
- if (put_user(cylinders, (unsigned short *)&geo->cylinders)) return
-EFAULT;
-
- return 0;
-
- case HDIO_GETGEO_BIG:
- DPRINTK_IOCTL(" HDIO_GETGEO_BIG: %x\n", HDIO_GETGEO_BIG);
- if (!argument) return -EINVAL;
-
- /* We don't have real geometry info, but let's at least return
- values consistent with the size of the device */
-
- heads = 0xff;
- sectors = 0x3f;
- cylinders = part->nr_sects / (heads * sectors);
-
- if (put_user(0x00, (unsigned long *) &geo->start)) return -EFAULT;
- if (put_user(heads, (byte *)&geo->heads)) return -EFAULT;
- if (put_user(sectors, (byte *)&geo->sectors)) return -EFAULT;
- if (put_user(cylinders, (unsigned int *) &geo->cylinders)) return
-EFAULT;
-
- return 0;
-
- case CDROMMULTISESSION:
- DPRINTK("FIXME: support multisession CDs later\n");
- for ( i = 0; i < sizeof(struct cdrom_multisession); i++ )
- if ( put_user(0, (byte *)(argument + i)) ) return -EFAULT;
- return 0;
-
- case SCSI_IOCTL_GET_BUS_NUMBER:
- DPRINTK("FIXME: SCSI_IOCTL_GET_BUS_NUMBER ioctl in XL blkif");
- return -ENOSYS;
-
- default:
- WPRINTK("ioctl %08x not supported by XL blkif\n", command);
- return -ENOSYS;
- }
-
- return 0;
-}
-
-
-
-/* check media change: should probably do something here in some cases :-) */
-int blkif_check(kdev_t dev)
-{
- DPRINTK("blkif_check\n");
- return 0;
-}
-
-int blkif_revalidate(kdev_t dev)
-{
- struct block_device *bd;
- struct gendisk *gd;
- xl_disk_t *disk;
- unsigned long capacity;
- int i, rc = 0;
-
- if ( (bd = bdget(dev)) == NULL )
- return -EINVAL;
-
- /*
- * Update of partition info, and check of usage count, is protected
- * by the per-block-device semaphore.
- */
- down(&bd->bd_sem);
-
- if ( ((gd = get_gendisk(dev)) == NULL) ||
- ((disk = xldev_to_xldisk(dev)) == NULL) ||
- ((capacity = gd->part[MINOR(dev)].nr_sects) == 0) )
- {
- rc = -EINVAL;
- goto out;
- }
-
- if ( disk->usage > 1 )
- {
- rc = -EBUSY;
- goto out;
- }
-
- /* Only reread partition table if VBDs aren't mapped to partitions. */
- if ( !(gd->flags[MINOR(dev) >> gd->minor_shift] & GENHD_FL_VIRT_PARTNS) )
- {
- for ( i = gd->max_p - 1; i >= 0; i-- )
- {
- invalidate_device(dev+i, 1);
- gd->part[MINOR(dev+i)].start_sect = 0;
- gd->part[MINOR(dev+i)].nr_sects = 0;
- gd->sizes[MINOR(dev+i)] = 0;
- }
-
- grok_partitions(gd, MINOR(dev)>>gd->minor_shift, gd->max_p, capacity);
- }
-
- out:
- up(&bd->bd_sem);
- bdput(bd);
- return rc;
-}
-
-
-/*
- * blkif_queue_request
- *
- * request block io
- *
- * id: for guest use only.
- * operation: BLKIF_OP_{READ,WRITE,PROBE}
- * buffer: buffer to read/write into. this should be a
- * virtual address in the guest os.
- */
-static int blkif_queue_request(unsigned long id,
- int operation,
- char * buffer,
- unsigned long sector_number,
- unsigned short nr_sectors,
- kdev_t device,
- blkif_vdev_t handle)
-{
- unsigned long buffer_ma = virt_to_bus(buffer);
- unsigned long xid;
- struct gendisk *gd;
- blkif_request_t *req;
- struct buffer_head *bh;
- unsigned int fsect, lsect;
- int ref;
-
- fsect = (buffer_ma & ~PAGE_MASK) >> 9;
- lsect = fsect + nr_sectors - 1;
-
- /* Buffer must be sector-aligned. Extent mustn't cross a page boundary. */
- if ( unlikely((buffer_ma & ((1<<9)-1)) != 0) )
- BUG();
- if ( lsect > ((PAGE_SIZE/512)-1) )
- BUG();
-
- buffer_ma &= PAGE_MASK;
-
- if (unlikely(info->connected != BLKIF_STATE_CONNECTED))
- return 1;
-
- switch ( operation )
- {
-
- case BLKIF_OP_READ:
- case BLKIF_OP_WRITE:
- gd = get_gendisk(device);
-
- /*
- * Update the sector_number we'll pass down as appropriate; note that
- * we could sanity check that resulting sector will be in this
- * partition, but this will happen in driver backend anyhow.
- */
- sector_number += gd->part[MINOR(device)].start_sect;
-
- /*
- * If this unit doesn't consist of virtual partitions then we clear
- * the partn bits from the device number.
- */
- if ( !(gd->flags[MINOR(device)>>gd->minor_shift] &
- GENHD_FL_VIRT_PARTNS) )
- device &= ~(gd->max_p - 1);
-
- if ( (sg_operation == operation) &&
- (sg_dev == device) &&
- (sg_next_sect == sector_number) )
- {
- req = RING_GET_REQUEST(&info->ring,
- info->ring.req_prod_pvt - 1);
- bh = (struct buffer_head *)id;
-
- bh->b_reqnext = (struct buffer_head *)blk_shadow[req->id].request;
- blk_shadow[req->id].request = (unsigned long)id;
-
- /* install a grant reference. */
- ref = gnttab_claim_grant_reference(&gref_head);
- ASSERT( ref != -ENOSPC );
-
- gnttab_grant_foreign_access_ref(
- ref,
- info->backend_id,
- buffer_ma >> PAGE_SHIFT,
- ( operation == BLKIF_OP_WRITE ? 1 : 0 ) );
-
- blk_shadow[req->id].frame[req->nr_segments] =
- buffer_ma >> PAGE_SHIFT;
-
- req->frame_and_sects[req->nr_segments] =
- blkif_fas_from_gref(ref, fsect, lsect);
- if ( ++req->nr_segments < BLKIF_MAX_SEGMENTS_PER_REQUEST )
- sg_next_sect += nr_sectors;
- else
- DISABLE_SCATTERGATHER();
-
- /* Update the copy of the request in the recovery ring. */
- pickle_request(&blk_shadow[req->id], req );
-
- return 0;
- }
- else if ( RING_FULL(&info->ring) )
- {
- return 1;
- }
- else
- {
- sg_operation = operation;
- sg_dev = device;
- sg_next_sect = sector_number + nr_sectors;
- }
- break;
-
- default:
- panic("unknown op %d\n", operation);
- }
-
- /* Fill out a communications ring structure. */
- req = RING_GET_REQUEST(&info->ring, info->ring.req_prod_pvt);
-
- xid = GET_ID_FROM_FREELIST();
- blk_shadow[xid].request = (unsigned long)id;
-
- req->id = xid;
- req->operation = operation;
- req->sector_number = (blkif_sector_t)sector_number;
- req->handle = handle;
- req->nr_segments = 1;
- /* install a grant reference. */
- ref = gnttab_claim_grant_reference(&gref_head);
- ASSERT( ref != -ENOSPC );
-
- gnttab_grant_foreign_access_ref(
- ref,
- info->backend_id,
- buffer_ma >> PAGE_SHIFT,
- ( operation == BLKIF_OP_WRITE ? 1 : 0 ) );
-
- blk_shadow[xid].frame[0] = buffer_ma >> PAGE_SHIFT;
-
- req->frame_and_sects[0] = blkif_fas_from_gref(ref, fsect, lsect);
-
- /* Keep a private copy so we can reissue requests when recovering. */
- pickle_request(&blk_shadow[xid], req);
-
- info->ring.req_prod_pvt++;
-
- return 0;
-}
-
-
-/*
- * do_blkif_request
- * read a block; request is in a request queue
- */
-void do_blkif_request(request_queue_t *rq)
-{
- struct request *req;
- struct buffer_head *bh, *next_bh;
- int rw, nsect, full, queued = 0;
-
- DPRINTK("Entered do_blkif_request\n");
-
- while ( !rq->plugged && !list_empty(&rq->queue_head))
- {
- if ( (req = blkdev_entry_next_request(&rq->queue_head)) == NULL )
- goto out;
-
- DPRINTK("do_blkif_request %p: cmd %i, sec %lx, (%li/%li) bh:%p\n",
- req, req->cmd, req->sector,
- req->current_nr_sectors, req->nr_sectors, req->bh);
-
- rw = req->cmd;
- if ( rw == READA )
- rw = READ;
- if ( unlikely((rw != READ) && (rw != WRITE)) )
- panic("XenoLinux Virtual Block Device: bad cmd: %d\n", rw);
-
- req->errors = 0;
-
- bh = req->bh;
- while ( bh != NULL )
- {
- next_bh = bh->b_reqnext;
- bh->b_reqnext = NULL;
-
- full = blkif_queue_request(
- (unsigned long)bh,
- (rw == READ) ? BLKIF_OP_READ : BLKIF_OP_WRITE,
- bh->b_data, bh->b_rsector, bh->b_size>>9, bh->b_rdev);
-
- if ( full )
- {
- bh->b_reqnext = next_bh;
- pending_queues[nr_pending++] = rq;
- if ( unlikely(nr_pending >= MAX_PENDING) )
- BUG();
- goto out;
- }
-
- queued++;
-
- /* Dequeue the buffer head from the request. */
- nsect = bh->b_size >> 9;
- bh = req->bh = next_bh;
-
- if ( bh != NULL )
- {
- /* There's another buffer head to do. Update the request. */
- req->hard_sector += nsect;
- req->hard_nr_sectors -= nsect;
- req->sector = req->hard_sector;
- req->nr_sectors = req->hard_nr_sectors;
- req->current_nr_sectors = bh->b_size >> 9;
- req->buffer = bh->b_data;
- }
- else
- {
- /* That was the last buffer head. Finalise the request. */
- if ( unlikely(end_that_request_first(req, 1, "XenBlk")) )
- BUG();
- blkdev_dequeue_request(req);
- end_that_request_last(req);
- }
- }
- }
-
- out:
- if ( queued != 0 )
- flush_requests();
-}
-
-
-static void blkif_int(int irq, void *dev_id, struct pt_regs *ptregs)
-{
- RING_IDX i, rp;
- unsigned long flags;
- struct buffer_head *bh, *next_bh;
-
- spin_lock_irqsave(&io_request_lock, flags);
-
- if ( unlikely(info->connected != BLKIF_STATE_CONNECTED || recovery) )
- {
- spin_unlock_irqrestore(&io_request_lock, flags);
- return;
- }
-
- rp = info->ring.sring->rsp_prod;
- rmb(); /* Ensure we see queued responses up to 'rp'. */
-
- for ( i = info->ring.rsp_cons; i != rp; i++ )
- {
- unsigned long id;
- blkif_response_t *bret;
-
- bret = RING_GET_RESPONSE(&info->ring, i);
- id = bret->id;
- bh = (struct buffer_head *)blk_shadow[id].request;
-
- blkif_completion(&blk_shadow[id]);
-
- ADD_ID_TO_FREELIST(id);
-
- switch ( bret->operation )
- {
- case BLKIF_OP_READ:
- case BLKIF_OP_WRITE:
- if ( unlikely(bret->status != BLKIF_RSP_OKAY) )
- DPRINTK("Bad return from blkdev data request: %lx\n",
- bret->status);
- for ( ; bh != NULL; bh = next_bh )
- {
- next_bh = bh->b_reqnext;
- bh->b_reqnext = NULL;
- bh->b_end_io(bh, bret->status == BLKIF_RSP_OKAY);
- }
-
- break;
- case BLKIF_OP_PROBE:
- memcpy(&blkif_control_rsp, bret, sizeof(*bret));
- blkif_control_rsp_valid = 1;
- break;
- default:
- BUG();
- }
-
- }
- info->ring.rsp_cons = i;
-
- kick_pending_request_queues();
-
- spin_unlock_irqrestore(&io_request_lock, flags);
-}
-
-#endif
-
-/***************************** COMMON CODE *******************************/
+ struct request *req;
+ blkif_response_t *bret;
+ RING_IDX i, rp;
+ unsigned long flags;
+ struct blkfront_info *info = (struct blkfront_info *)dev_id;
+
+ spin_lock_irqsave(&blkif_io_lock, flags);
+
+ if (unlikely(info->connected != BLKIF_STATE_CONNECTED || recovery)) {
+ spin_unlock_irqrestore(&blkif_io_lock, flags);
+ return IRQ_HANDLED;
+ }
+
+ rp = info->ring.sring->rsp_prod;
+ rmb(); /* Ensure we see queued responses up to 'rp'. */
+
+ for (i = info->ring.rsp_cons; i != rp; i++) {
+ unsigned long id;
+
+ bret = RING_GET_RESPONSE(&info->ring, i);
+ id = bret->id;
+ req = (struct request *)info->shadow[id].request;
+
+ blkif_completion(&info->shadow[id]);
+
+ ADD_ID_TO_FREELIST(info, id);
+
+ switch (bret->operation) {
+ case BLKIF_OP_READ:
+ case BLKIF_OP_WRITE:
+ if (unlikely(bret->status != BLKIF_RSP_OKAY))
+ DPRINTK("Bad return from blkdev data "
+ "request: %x\n", bret->status);
+
+ BUG_ON(end_that_request_first(
+ req, (bret->status == BLKIF_RSP_OKAY),
+ req->hard_nr_sectors));
+ end_that_request_last(req);
+ break;
+ default:
+ BUG();
+ }
+ }
+
+ info->ring.rsp_cons = i;
+
+ kick_pending_request_queues(info);
+
+ spin_unlock_irqrestore(&blkif_io_lock, flags);
+
+ return IRQ_HANDLED;
+}
static void blkif_free(struct blkfront_info *info)
{
- /* Prevent new requests being issued until we fix things up. */
- spin_lock_irq(&blkif_io_lock);
- info->connected = BLKIF_STATE_DISCONNECTED;
- spin_unlock_irq(&blkif_io_lock);
-
- /* Free resources associated with old device channel. */
- if ( info->ring.sring != NULL )
- {
- free_page((unsigned long)info->ring.sring);
- info->ring.sring = NULL;
- }
- unbind_evtchn_from_irqhandler(info->evtchn, NULL);
- info->evtchn = 0;
+ /* Prevent new requests being issued until we fix things up. */
+ spin_lock_irq(&blkif_io_lock);
+ info->connected = BLKIF_STATE_DISCONNECTED;
+ spin_unlock_irq(&blkif_io_lock);
+
+ /* Free resources associated with old device channel. */
+ if (info->ring.sring != NULL) {
+ free_page((unsigned long)info->ring.sring);
+ info->ring.sring = NULL;
+ }
+ if (info->ring_ref != GRANT_INVALID_REF)
+ gnttab_end_foreign_access(info->ring_ref, 0);
+ info->ring_ref = GRANT_INVALID_REF;
+ unbind_evtchn_from_irqhandler(info->evtchn, info);
+ info->evtchn = 0;
}
static void blkif_recover(struct blkfront_info *info)
{
- int i;
- blkif_request_t *req;
- struct blk_shadow *copy;
- int j;
-
- /* Stage 1: Make a safe copy of the shadow state. */
- copy = (struct blk_shadow *)kmalloc(sizeof(blk_shadow), GFP_KERNEL);
- BUG_ON(copy == NULL);
- memcpy(copy, blk_shadow, sizeof(blk_shadow));
-
- /* Stage 2: Set up free list. */
- memset(&blk_shadow, 0, sizeof(blk_shadow));
- for ( i = 0; i < BLK_RING_SIZE; i++ )
- blk_shadow[i].req.id = i+1;
- blk_shadow_free = info->ring.req_prod_pvt;
- blk_shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff;
-
- /* Stage 3: Find pending requests and requeue them. */
- for ( i = 0; i < BLK_RING_SIZE; i++ )
- {
- /* Not in use? */
- if ( copy[i].request == 0 )
- continue;
-
- /* Grab a request slot and unpickle shadow state into it. */
- req = RING_GET_REQUEST(
- &info->ring, info->ring.req_prod_pvt);
- unpickle_request(req, ©[i]);
-
- /* We get a new request id, and must reset the shadow state. */
- req->id = GET_ID_FROM_FREELIST();
- memcpy(&blk_shadow[req->id], ©[i], sizeof(copy[i]));
-
- /* Rewrite any grant references invalidated by suspend/resume. */
- for ( j = 0; j < req->nr_segments; j++ )
- {
- if ( req->frame_and_sects[j] & GRANTREF_INVALID )
- gnttab_grant_foreign_access_ref(
- blkif_gref_from_fas(req->frame_and_sects[j]),
- info->backend_id,
- blk_shadow[req->id].frame[j],
- rq_data_dir((struct request *)
- blk_shadow[req->id].request));
- req->frame_and_sects[j] &= ~GRANTREF_INVALID;
- }
- blk_shadow[req->id].req = *req;
-
- info->ring.req_prod_pvt++;
- }
-
- kfree(copy);
-
- recovery = 0;
-
- /* info->ring->req_prod will be set when we flush_requests().*/
- wmb();
-
- /* Kicks things back into life. */
- flush_requests(info);
-
- /* Now safe to left other people use the interface. */
- info->connected = BLKIF_STATE_CONNECTED;
+ int i;
+ blkif_request_t *req;
+ struct blk_shadow *copy;
+ int j;
+
+ /* Stage 1: Make a safe copy of the shadow state. */
+ copy = (struct blk_shadow *)kmalloc(sizeof(info->shadow), GFP_KERNEL);
+ BUG_ON(copy == NULL);
+ memcpy(copy, info->shadow, sizeof(info->shadow));
+
+ /* Stage 2: Set up free list. */
+ memset(&info->shadow, 0, sizeof(info->shadow));
+ for (i = 0; i < BLK_RING_SIZE; i++)
+ info->shadow[i].req.id = i+1;
+ info->shadow_free = info->ring.req_prod_pvt;
+ info->shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff;
+
+ /* Stage 3: Find pending requests and requeue them. */
+ for (i = 0; i < BLK_RING_SIZE; i++) {
+ /* Not in use? */
+ if (copy[i].request == 0)
+ continue;
+
+ /* Grab a request slot and unpickle shadow state into it. */
+ req = RING_GET_REQUEST(
+ &info->ring, info->ring.req_prod_pvt);
+ unpickle_request(req, ©[i]);
+
+ /* We get a new request id, and must reset the shadow state. */
+ req->id = GET_ID_FROM_FREELIST(info);
+ memcpy(&info->shadow[req->id], ©[i], sizeof(copy[i]));
+
+ /* Rewrite any grant references invalidated by susp/resume. */
+ for (j = 0; j < req->nr_segments; j++) {
+ if ( req->frame_and_sects[j] & GRANTREF_INVALID )
+ gnttab_grant_foreign_access_ref(
+ blkif_gref_from_fas(
+ req->frame_and_sects[j]),
+ info->backend_id,
+ info->shadow[req->id].frame[j],
+ rq_data_dir(
+ (struct request *)
+ info->shadow[req->id].request));
+ req->frame_and_sects[j] &= ~GRANTREF_INVALID;
+ }
+ info->shadow[req->id].req = *req;
+
+ info->ring.req_prod_pvt++;
+ }
+
+ kfree(copy);
+
+ recovery = 0;
+
+ /* info->ring->req_prod will be set when we flush_requests().*/
+ wmb();
+
+ /* Kicks things back into life. */
+ flush_requests(info);
+
+ /* Now safe to left other people use the interface. */
+ info->connected = BLKIF_STATE_CONNECTED;
}
static void blkif_connect(struct blkfront_info *info, u16 evtchn)
{
- int err = 0;
-
- info->evtchn = evtchn;
-
- err = bind_evtchn_to_irqhandler(
- info->evtchn, blkif_int, SA_SAMPLE_RANDOM, "blkif", info);
- if ( err != 0 )
- {
- WPRINTK("bind_evtchn_to_irqhandler failed (err=%d)\n", err);
- return;
- }
+ int err = 0;
+
+ info->evtchn = evtchn;
+
+ err = bind_evtchn_to_irqhandler(
+ info->evtchn, blkif_int, SA_SAMPLE_RANDOM, "blkif", info);
+ if (err != 0) {
+ WPRINTK("bind_evtchn_to_irqhandler failed (err=%d)\n", err);
+ return;
+ }
}
@@ -1107,6 +505,8 @@
blkif_sring_t *sring;
evtchn_op_t op = { .cmd = EVTCHNOP_alloc_unbound };
int err;
+
+ info->ring_ref = GRANT_INVALID_REF;
sring = (void *)__get_free_page(GFP_KERNEL);
if (!sring) {
@@ -1130,6 +530,7 @@
err = HYPERVISOR_event_channel_op(&op);
if (err) {
gnttab_end_foreign_access(info->ring_ref, 0);
+ info->ring_ref = GRANT_INVALID_REF;
free_page((unsigned long)info->ring.sring);
info->ring.sring = 0;
xenbus_dev_error(dev, err, "allocating event channel");
@@ -1227,9 +628,8 @@
static int blkfront_probe(struct xenbus_device *dev,
const struct xenbus_device_id *id)
{
- int err;
+ int err, vdevice, i;
struct blkfront_info *info;
- int vdevice;
/* FIXME: Use dynamic device id if this is not set. */
err = xenbus_scanf(dev->nodename, "virtual-device", "%i", &vdevice);
@@ -1250,6 +650,12 @@
info->connected = BLKIF_STATE_DISCONNECTED;
info->mi = NULL;
INIT_WORK(&info->work, blkif_restart_queue, (void *)info);
+
+ info->shadow_free = 0;
+ memset(info->shadow, 0, sizeof(info->shadow));
+ for (i = 0; i < BLK_RING_SIZE; i++)
+ info->shadow[i].req.id = i+1;
+ info->shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff;
/* Front end dir is a number, which is used as the id. */
info->handle = simple_strtoul(strrchr(dev->nodename,'/')+1, NULL, 0);
@@ -1329,55 +735,57 @@
static int wait_for_blkif(void)
{
- int err = 0;
- int i;
-
- /*
- * We should figure out how many and which devices we need to
- * proceed and only wait for those. For now, continue once the
- * first device is around.
- */
- for ( i=0; blkif_state != BLKIF_STATE_CONNECTED && (i < 10*HZ); i++ )
- {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
-
- if ( blkif_state != BLKIF_STATE_CONNECTED )
- {
- WPRINTK("Timeout connecting to device!\n");
- err = -ENOSYS;
- }
- return err;
+ int err = 0;
+ int i;
+
+ /*
+ * We should figure out how many and which devices we need to
+ * proceed and only wait for those. For now, continue once the
+ * first device is around.
+ */
+ for (i = 0; blkif_state != BLKIF_STATE_CONNECTED && (i < 10*HZ); i++) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
+ }
+
+ if (blkif_state != BLKIF_STATE_CONNECTED) {
+ WPRINTK("Timeout connecting to device!\n");
+ err = -ENOSYS;
+ }
+ return err;
}
static int __init xlblk_init(void)
{
- int i;
-
- if ( (xen_start_info.flags & SIF_INITDOMAIN) ||
- (xen_start_info.flags & SIF_BLK_BE_DOMAIN) )
- return 0;
-
- IPRINTK("Initialising virtual block device driver\n");
-
- blk_shadow_free = 0;
- memset(blk_shadow, 0, sizeof(blk_shadow));
- for ( i = 0; i < BLK_RING_SIZE; i++ )
- blk_shadow[i].req.id = i+1;
- blk_shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff;
-
- init_blk_xenbus();
-
- wait_for_blkif();
-
- return 0;
-}
+ if ((xen_start_info->flags & SIF_INITDOMAIN) ||
+ (xen_start_info->flags & SIF_BLK_BE_DOMAIN) )
+ return 0;
+
+ IPRINTK("Initialising virtual block device driver\n");
+
+ init_blk_xenbus();
+
+ wait_for_blkif();
+
+ return 0;
+}
+
+module_init(xlblk_init);
static void blkif_completion(struct blk_shadow *s)
{
- int i;
- for ( i = 0; i < s->req.nr_segments; i++ )
- gnttab_free_grant_reference(
- blkif_gref_from_fas(s->req.frame_and_sects[i]));
-}
+ int i;
+ for (i = 0; i < s->req.nr_segments; i++)
+ gnttab_end_foreign_access(
+ blkif_gref_from_fas(s->req.frame_and_sects[i]), 0);
+}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/blkfront/block.h
--- a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h Fri Sep 9 16:30:54 2005
@@ -96,6 +96,14 @@
struct xlbd_type_info *type;
};
+struct blk_shadow {
+ blkif_request_t req;
+ unsigned long request;
+ unsigned long frame[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+};
+
+#define BLK_RING_SIZE __RING_SIZE((blkif_sring_t *)0, PAGE_SIZE)
+
/*
* We have one of these per vbd, whether ide, scsi or 'other'. They
* hang in private_data off the gendisk structure. We may end up
@@ -116,11 +124,11 @@
blkif_front_ring_t ring;
unsigned int evtchn;
struct xlbd_major_info *mi;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
request_queue_t *rq;
-#endif
struct work_struct work;
struct gnttab_free_callback callback;
+ struct blk_shadow shadow[BLK_RING_SIZE];
+ unsigned long shadow_free;
};
extern spinlock_t blkif_io_lock;
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/blktap/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/Makefile Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/Makefile Fri Sep 9 16:30:54 2005
@@ -1,3 +1,3 @@
-obj-y := blktap_userdev.o blktap_datapath.o blktap_controlmsg.o blktap.o
+obj-y := xenbus.o interface.o blktap.o
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c Fri Sep 9 16:30:54 2005
@@ -1,90 +1,916 @@
/******************************************************************************
- * blktap.c
+ * arch/xen/drivers/blkif/blktap/blktap.c
*
- * XenLinux virtual block-device tap.
+ * This is a modified version of the block backend driver that remaps requests
+ * to a user-space memory region. It is intended to be used to write
+ * application-level servers that provide block interfaces to client VMs.
*
- * Copyright (c) 2004, Andrew Warfield
+ */
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <asm-xen/balloon.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/errno.h>
+#include <linux/major.h>
+#include <linux/gfp.h>
+#include <linux/poll.h>
+#include <asm/tlbflush.h>
+#include "common.h"
+
+/* Only one process may open /dev/xen/blktap at any time. */
+static unsigned long blktap_dev_inuse;
+unsigned long blktap_ring_ok; /* make this ring->state */
+
+/* Rings up to user space. */
+static blkif_front_ring_t blktap_ufe_ring;
+
+/* for poll: */
+static wait_queue_head_t blktap_wait;
+
+/* current switching mode */
+static unsigned long blktap_mode;
+
+/* local prototypes */
+static int blktap_read_ufe_ring(void);
+
+
+/* /dev/xen/blktap resides at device number major=10, minor=200 */
+#define BLKTAP_MINOR 202
+
+/* blktap IOCTLs: */
+#define BLKTAP_IOCTL_KICK_FE 1
+#define BLKTAP_IOCTL_KICK_BE 2 /* currently unused */
+#define BLKTAP_IOCTL_SETMODE 3
+#define BLKTAP_IOCTL_PRINT_IDXS 100
+
+/* blktap switching modes: (Set with BLKTAP_IOCTL_SETMODE) */
+#define BLKTAP_MODE_PASSTHROUGH 0x00000000 /* default */
+#define BLKTAP_MODE_INTERCEPT_FE 0x00000001
+#define BLKTAP_MODE_INTERCEPT_BE 0x00000002 /* unimp. */
+#define BLKTAP_MODE_COPY_FE 0x00000004 /* unimp. */
+#define BLKTAP_MODE_COPY_BE 0x00000008 /* unimp. */
+#define BLKTAP_MODE_COPY_FE_PAGES 0x00000010 /* unimp. */
+#define BLKTAP_MODE_COPY_BE_PAGES 0x00000020 /* unimp. */
+
+#define BLKTAP_MODE_INTERPOSE \
+ (BLKTAP_MODE_INTERCEPT_FE | BLKTAP_MODE_INTERCEPT_BE)
+
+#define BLKTAP_MODE_COPY_BOTH \
+ (BLKTAP_MODE_COPY_FE | BLKTAP_MODE_COPY_BE)
+
+#define BLKTAP_MODE_COPY_BOTH_PAGES \
+ (BLKTAP_MODE_COPY_FE_PAGES | BLKTAP_MODE_COPY_BE_PAGES)
+
+static inline int BLKTAP_MODE_VALID(unsigned long arg)
+{
+ return (
+ ( arg == BLKTAP_MODE_PASSTHROUGH ) ||
+ ( arg == BLKTAP_MODE_INTERCEPT_FE ) ||
+ ( arg == BLKTAP_MODE_INTERPOSE ) );
+/*
+ return (
+ ( arg == BLKTAP_MODE_PASSTHROUGH ) ||
+ ( arg == BLKTAP_MODE_INTERCEPT_FE ) ||
+ ( arg == BLKTAP_MODE_INTERCEPT_BE ) ||
+ ( arg == BLKTAP_MODE_INTERPOSE ) ||
+ ( (arg & ~BLKTAP_MODE_COPY_FE_PAGES) == BLKTAP_MODE_COPY_FE ) ||
+ ( (arg & ~BLKTAP_MODE_COPY_BE_PAGES) == BLKTAP_MODE_COPY_BE ) ||
+ ( (arg & ~BLKTAP_MODE_COPY_BOTH_PAGES) == BLKTAP_MODE_COPY_BOTH )
+ );
+*/
+}
+
+
+/******************************************************************
+ * MMAP REGION
+ */
+
+/*
+ * We use a big chunk of address space to map in-flight requests into,
+ * and export this region up to user-space. See the comments in blkback
+ * about this -- the two must be kept in sync if the tap is used as a
+ * passthrough.
+ */
+
+#define MAX_PENDING_REQS 64
+#define BATCH_PER_DOMAIN 16
+
+/* immediately before the mmap area, we have a bunch of pages reserved
+ * for shared memory rings.
+ */
+#define RING_PAGES 1 /* Front */
+
+/* Where things are inside the device mapping. */
+struct vm_area_struct *blktap_vma = NULL;
+unsigned long mmap_vstart; /* Kernel pages for mapping in data. */
+unsigned long rings_vstart; /* start of mmaped vma */
+unsigned long user_vstart; /* start of user mappings */
+
+#define MMAP_PAGES \
+ (MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST)
+#define MMAP_VADDR(_start, _req,_seg) \
+ (_start + \
+ ((_req) * BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE) + \
+ ((_seg) * PAGE_SIZE))
+
+
+
+/*
+ * Each outstanding request that we've passed to the lower device layers has a
+ * 'pending_req' allocated to it. Each buffer_head that completes decrements
+ * the pendcnt towards zero. When it hits zero, the specified domain has a
+ * response queued for it, with the saved 'id' passed back.
+ */
+typedef struct {
+ blkif_t *blkif;
+ unsigned long id;
+ int nr_pages;
+ atomic_t pendcnt;
+ unsigned short operation;
+ int status;
+} pending_req_t;
+
+/*
+ * We can't allocate pending_req's in order, since they may complete out of
+ * order. We therefore maintain an allocation ring. This ring also indicates
+ * when enough work has been passed down -- at that point the allocation ring
+ * will be empty.
+ */
+static pending_req_t pending_reqs[MAX_PENDING_REQS];
+static unsigned char pending_ring[MAX_PENDING_REQS];
+static spinlock_t pend_prod_lock = SPIN_LOCK_UNLOCKED;
+/* NB. We use a different index type to differentiate from shared blk rings. */
+typedef unsigned int PEND_RING_IDX;
+#define MASK_PEND_IDX(_i) ((_i)&(MAX_PENDING_REQS-1))
+static PEND_RING_IDX pending_prod, pending_cons;
+#define NR_PENDING_REQS (MAX_PENDING_REQS - pending_prod + pending_cons)
+
+/* Requests passing through the tap to the backend hijack the id field
+ * in the request message. In it we put the AR index _AND_ the fe domid.
+ * the domid is used by the backend to map the pages properly.
+ */
+
+static inline unsigned long MAKE_ID(domid_t fe_dom, PEND_RING_IDX idx)
+{
+ return ( (fe_dom << 16) | MASK_PEND_IDX(idx) );
+}
+
+extern inline PEND_RING_IDX ID_TO_IDX(unsigned long id)
+{
+ return (PEND_RING_IDX)( id & 0x0000ffff );
+}
+
+extern inline domid_t ID_TO_DOM(unsigned long id)
+{
+ return (domid_t)(id >> 16);
+}
+
+
+
+/******************************************************************
+ * GRANT HANDLES
+ */
+
+/* When using grant tables to map a frame for device access then the
+ * handle returned must be used to unmap the frame. This is needed to
+ * drop the ref count on the frame.
+ */
+struct grant_handle_pair
+{
+ u16 kernel;
+ u16 user;
+};
+static struct grant_handle_pair pending_grant_handles[MMAP_PAGES];
+#define pending_handle(_idx, _i) \
+ (pending_grant_handles[((_idx) * BLKIF_MAX_SEGMENTS_PER_REQUEST) + (_i)])
+#define BLKTAP_INVALID_HANDLE(_g) \
+ (((_g->kernel) == 0xFFFF) && ((_g->user) == 0xFFFF))
+#define BLKTAP_INVALIDATE_HANDLE(_g) do { \
+ (_g)->kernel = 0xFFFF; (_g)->user = 0xFFFF; \
+ } while(0)
+
+
+/******************************************************************
+ * BLKTAP VM OPS
+ */
+
+static struct page *blktap_nopage(struct vm_area_struct *vma,
+ unsigned long address,
+ int *type)
+{
+ /*
+ * if the page has not been mapped in by the driver then generate
+ * a SIGBUS to the domain.
+ */
+
+ force_sig(SIGBUS, current);
+
+ return 0;
+}
+
+struct vm_operations_struct blktap_vm_ops = {
+ nopage: blktap_nopage,
+};
+
+/******************************************************************
+ * BLKTAP FILE OPS
+ */
+
+static int blktap_open(struct inode *inode, struct file *filp)
+{
+ blkif_sring_t *sring;
+
+ if ( test_and_set_bit(0, &blktap_dev_inuse) )
+ return -EBUSY;
+
+ /* Allocate the fe ring. */
+ sring = (blkif_sring_t *)get_zeroed_page(GFP_KERNEL);
+ if (sring == NULL)
+ goto fail_nomem;
+
+ SetPageReserved(virt_to_page(sring));
+
+ SHARED_RING_INIT(sring);
+ FRONT_RING_INIT(&blktap_ufe_ring, sring, PAGE_SIZE);
+
+ return 0;
+
+ fail_nomem:
+ return -ENOMEM;
+}
+
+static int blktap_release(struct inode *inode, struct file *filp)
+{
+ blktap_dev_inuse = 0;
+ blktap_ring_ok = 0;
+
+ /* Free the ring page. */
+ ClearPageReserved(virt_to_page(blktap_ufe_ring.sring));
+ free_page((unsigned long) blktap_ufe_ring.sring);
+
+ /* Clear any active mappings and free foreign map table */
+ if (blktap_vma != NULL) {
+ zap_page_range(blktap_vma, blktap_vma->vm_start,
+ blktap_vma->vm_end - blktap_vma->vm_start, NULL);
+ blktap_vma = NULL;
+ }
+
+ return 0;
+}
+
+
+/* Note on mmap:
+ * We need to map pages to user space in a way that will allow the block
+ * subsystem set up direct IO to them. This couldn't be done before, because
+ * there isn't really a sane way to translate a user virtual address down to a
+ * physical address when the page belongs to another domain.
*
- * Based on the original split block driver:
- * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
- * Modifications by Mark A. Williamson are (c) Intel Research Cambridge
- * Copyright (c) 2004, Christian Limpach
- *
- * Note that unlike the split block driver code, this driver has been developed
- * strictly for Linux 2.6
- */
-
-#include "blktap.h"
-
-int __init xlblktap_init(void)
-{
- ctrl_msg_t cmsg;
- blkif_fe_driver_status_t fe_st;
- blkif_be_driver_status_t be_st;
-
- printk(KERN_INFO "Initialising Xen block tap device\n");
-#ifdef CONFIG_XEN_BLKDEV_GRANT
- printk(KERN_INFO "Block tap is using grant tables.\n");
-#endif
-
- DPRINTK(" tap - Backend connection init:\n");
-
-
- (void)ctrl_if_register_receiver(CMSG_BLKIF_FE, blkif_ctrlif_rx,
- CALLBACK_IN_BLOCKING_CONTEXT);
-
- /* Send a driver-UP notification to the domain controller. */
- cmsg.type = CMSG_BLKIF_FE;
- cmsg.subtype = CMSG_BLKIF_FE_DRIVER_STATUS;
- cmsg.length = sizeof(blkif_fe_driver_status_t);
- fe_st.status = BLKIF_DRIVER_STATUS_UP;
- memcpy(cmsg.msg, &fe_st, sizeof(fe_st));
- ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
-
- DPRINTK(" tap - Frontend connection init:\n");
+ * My first approach was to map the page in to kernel memory, add an entry
+ * for it in the physical frame list (using alloc_lomem_region as in blkback)
+ * and then attempt to map that page up to user space. This is disallowed
+ * by xen though, which realizes that we don't really own the machine frame
+ * underlying the physical page.
+ *
+ * The new approach is to provide explicit support for this in xen linux.
+ * The VMA now has a flag, VM_FOREIGN, to indicate that it contains pages
+ * mapped from other vms. vma->vm_private_data is set up as a mapping
+ * from pages to actual page structs. There is a new clause in get_user_pages
+ * that does the right thing for this sort of mapping.
+ */
+static int blktap_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ int size;
+ struct page **map;
+ int i;
+
+ DPRINTK(KERN_ALERT "blktap mmap (%lx, %lx)\n",
+ vma->vm_start, vma->vm_end);
+
+ vma->vm_flags |= VM_RESERVED;
+ vma->vm_ops = &blktap_vm_ops;
+
+ size = vma->vm_end - vma->vm_start;
+ if ( size != ( (MMAP_PAGES + RING_PAGES) << PAGE_SHIFT ) ) {
+ printk(KERN_INFO
+ "blktap: you _must_ map exactly %d pages!\n",
+ MMAP_PAGES + RING_PAGES);
+ return -EAGAIN;
+ }
+
+ size >>= PAGE_SHIFT;
+ DPRINTK(KERN_INFO "blktap: 2 rings + %d pages.\n", size-1);
- active_reqs_init();
+ rings_vstart = vma->vm_start;
+ user_vstart = rings_vstart + (RING_PAGES << PAGE_SHIFT);
+
+ /* Map the ring pages to the start of the region and reserve it. */
+
+ /* not sure if I really need to do this... */
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ if (remap_pfn_range(vma, vma->vm_start,
+ __pa(blktap_ufe_ring.sring) >> PAGE_SHIFT,
+ PAGE_SIZE, vma->vm_page_prot))
+ {
+ WPRINTK("Mapping user ring failed!\n");
+ goto fail;
+ }
+
+ /* Mark this VM as containing foreign pages, and set up mappings. */
+ map = kmalloc(((vma->vm_end - vma->vm_start) >> PAGE_SHIFT)
+ * sizeof(struct page_struct*),
+ GFP_KERNEL);
+ if (map == NULL)
+ {
+ WPRINTK("Couldn't alloc VM_FOREIGH map.\n");
+ goto fail;
+ }
+
+ for (i=0; i<((vma->vm_end - vma->vm_start) >> PAGE_SHIFT); i++)
+ map[i] = NULL;
+
+ vma->vm_private_data = map;
+ vma->vm_flags |= VM_FOREIGN;
+
+ blktap_vma = vma;
+ blktap_ring_ok = 1;
+
+ return 0;
+ fail:
+ /* Clear any active mappings. */
+ zap_page_range(vma, vma->vm_start,
+ vma->vm_end - vma->vm_start, NULL);
+
+ return -ENOMEM;
+}
+
+static int blktap_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ switch(cmd) {
+ case BLKTAP_IOCTL_KICK_FE: /* There are fe messages to process. */
+ return blktap_read_ufe_ring();
+
+ case BLKTAP_IOCTL_SETMODE:
+ if (BLKTAP_MODE_VALID(arg)) {
+ blktap_mode = arg;
+ /* XXX: may need to flush rings here. */
+ printk(KERN_INFO "blktap: set mode to %lx\n", arg);
+ return 0;
+ }
+ case BLKTAP_IOCTL_PRINT_IDXS:
+ {
+ //print_fe_ring_idxs();
+ WPRINTK("User Rings: \n-----------\n");
+ WPRINTK("UF: rsp_cons: %2d, req_prod_prv: %2d "
+ "| req_prod: %2d, rsp_prod: %2d\n",
+ blktap_ufe_ring.rsp_cons,
+ blktap_ufe_ring.req_prod_pvt,
+ blktap_ufe_ring.sring->req_prod,
+ blktap_ufe_ring.sring->rsp_prod);
+
+ }
+ }
+ return -ENOIOCTLCMD;
+}
+
+static unsigned int blktap_poll(struct file *file, poll_table *wait)
+{
+ poll_wait(file, &blktap_wait, wait);
+ if ( RING_HAS_UNPUSHED_REQUESTS(&blktap_ufe_ring) )
+ {
+ flush_tlb_all();
+
+ RING_PUSH_REQUESTS(&blktap_ufe_ring);
+ return POLLIN | POLLRDNORM;
+ }
+
+ return 0;
+}
+
+void blktap_kick_user(void)
+{
+ /* blktap_ring->req_prod = blktap_req_prod; */
+ wake_up_interruptible(&blktap_wait);
+}
+
+static struct file_operations blktap_fops = {
+ owner: THIS_MODULE,
+ poll: blktap_poll,
+ ioctl: blktap_ioctl,
+ open: blktap_open,
+ release: blktap_release,
+ mmap: blktap_mmap,
+};
+
+
+
+static int do_block_io_op(blkif_t *blkif, int max_to_do);
+static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req);
+static void make_response(blkif_t *blkif, unsigned long id,
+ unsigned short op, int st);
+
+
+static void fast_flush_area(int idx, int nr_pages)
+{
+ struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
+ unsigned int i, op = 0;
+ struct grant_handle_pair *handle;
+ unsigned long ptep;
+
+ for (i=0; i<nr_pages; i++)
+ {
+ handle = &pending_handle(idx, i);
+ if (!BLKTAP_INVALID_HANDLE(handle))
+ {
+
+ unmap[op].host_addr = MMAP_VADDR(mmap_vstart, idx, i);
+ unmap[op].dev_bus_addr = 0;
+ unmap[op].handle = handle->kernel;
+ op++;
+
+ if (create_lookup_pte_addr(blktap_vma->vm_mm,
+ MMAP_VADDR(user_vstart, idx, i),
+ &ptep) !=0) {
+ DPRINTK("Couldn't get a pte addr!\n");
+ return;
+ }
+ unmap[op].host_addr = ptep;
+ unmap[op].dev_bus_addr = 0;
+ unmap[op].handle = handle->user;
+ op++;
+
+ BLKTAP_INVALIDATE_HANDLE(handle);
+ }
+ }
+ if ( unlikely(HYPERVISOR_grant_table_op(
+ GNTTABOP_unmap_grant_ref, unmap, op)))
+ BUG();
+
+ if (blktap_vma != NULL)
+ zap_page_range(blktap_vma,
+ MMAP_VADDR(user_vstart, idx, 0),
+ nr_pages << PAGE_SHIFT, NULL);
+}
+
+/******************************************************************
+ * BLOCK-DEVICE SCHEDULER LIST MAINTENANCE
+ */
+
+static struct list_head blkio_schedule_list;
+static spinlock_t blkio_schedule_list_lock;
+
+static int __on_blkdev_list(blkif_t *blkif)
+{
+ return blkif->blkdev_list.next != NULL;
+}
+
+static void remove_from_blkdev_list(blkif_t *blkif)
+{
+ unsigned long flags;
+ if ( !__on_blkdev_list(blkif) ) return;
+ spin_lock_irqsave(&blkio_schedule_list_lock, flags);
+ if ( __on_blkdev_list(blkif) )
+ {
+ list_del(&blkif->blkdev_list);
+ blkif->blkdev_list.next = NULL;
+ blkif_put(blkif);
+ }
+ spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
+}
+
+static void add_to_blkdev_list_tail(blkif_t *blkif)
+{
+ unsigned long flags;
+ if ( __on_blkdev_list(blkif) ) return;
+ spin_lock_irqsave(&blkio_schedule_list_lock, flags);
+ if ( !__on_blkdev_list(blkif) && (blkif->status == CONNECTED) )
+ {
+ list_add_tail(&blkif->blkdev_list, &blkio_schedule_list);
+ blkif_get(blkif);
+ }
+ spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
+}
+
+
+/******************************************************************
+ * SCHEDULER FUNCTIONS
+ */
+
+static DECLARE_WAIT_QUEUE_HEAD(blkio_schedule_wait);
+
+static int blkio_schedule(void *arg)
+{
+ DECLARE_WAITQUEUE(wq, current);
+
+ blkif_t *blkif;
+ struct list_head *ent;
+
+ daemonize("xenblkd");
+
+ for ( ; ; )
+ {
+ /* Wait for work to do. */
+ add_wait_queue(&blkio_schedule_wait, &wq);
+ set_current_state(TASK_INTERRUPTIBLE);
+ if ( (NR_PENDING_REQS == MAX_PENDING_REQS) ||
+ list_empty(&blkio_schedule_list) )
+ schedule();
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(&blkio_schedule_wait, &wq);
+
+ /* Queue up a batch of requests. */
+ while ( (NR_PENDING_REQS < MAX_PENDING_REQS) &&
+ !list_empty(&blkio_schedule_list) )
+ {
+ ent = blkio_schedule_list.next;
+ blkif = list_entry(ent, blkif_t, blkdev_list);
+ blkif_get(blkif);
+ remove_from_blkdev_list(blkif);
+ if ( do_block_io_op(blkif, BATCH_PER_DOMAIN) )
+ add_to_blkdev_list_tail(blkif);
+ blkif_put(blkif);
+ }
+ }
+}
+
+static void maybe_trigger_blkio_schedule(void)
+{
+ /*
+ * Needed so that two processes, who together make the following predicate
+ * true, don't both read stale values and evaluate the predicate
+ * incorrectly. Incredibly unlikely to stall the scheduler on x86, but...
+ */
+ smp_mb();
+
+ if ( (NR_PENDING_REQS < (MAX_PENDING_REQS/2)) &&
+ !list_empty(&blkio_schedule_list) )
+ wake_up(&blkio_schedule_wait);
+}
+
+
+
+/******************************************************************
+ * COMPLETION CALLBACK -- Called as bh->b_end_io()
+ */
+
+
+static int blktap_read_ufe_ring(void)
+{
+ /* This is called to read responses from the UFE ring. */
+
+ RING_IDX i, j, rp;
+ blkif_response_t *resp;
+ blkif_t *blkif;
+ int pending_idx;
+ pending_req_t *pending_req;
+ unsigned long flags;
+
+ /* if we are forwarding from UFERring to FERing */
+ if (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) {
+
+ /* for each outstanding message on the UFEring */
+ rp = blktap_ufe_ring.sring->rsp_prod;
+ rmb();
+
+ for ( i = blktap_ufe_ring.rsp_cons; i != rp; i++ )
+ {
+ resp = RING_GET_RESPONSE(&blktap_ufe_ring, i);
+ pending_idx = MASK_PEND_IDX(ID_TO_IDX(resp->id));
+ pending_req = &pending_reqs[pending_idx];
+
+ blkif = pending_req->blkif;
+ for (j = 0; j < pending_req->nr_pages; j++) {
+ unsigned long vaddr;
+ struct page **map = blktap_vma->vm_private_data;
+ int offset;
+
+ vaddr = MMAP_VADDR(user_vstart, pending_idx, j);
+ offset = (vaddr - blktap_vma->vm_start) >> PAGE_SHIFT;
+
+ //ClearPageReserved(virt_to_page(vaddr));
+ ClearPageReserved((struct page *)map[offset]);
+ map[offset] = NULL;
+ }
+
+ fast_flush_area(pending_idx, pending_req->nr_pages);
+ make_response(blkif, pending_req->id, resp->operation,
+ resp->status);
+ blkif_put(pending_req->blkif);
+ spin_lock_irqsave(&pend_prod_lock, flags);
+ pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
+ spin_unlock_irqrestore(&pend_prod_lock, flags);
+ }
+ blktap_ufe_ring.rsp_cons = i;
+ maybe_trigger_blkio_schedule();
+ }
+ return 0;
+}
+
+
+/******************************************************************************
+ * NOTIFICATION FROM GUEST OS.
+ */
+
+irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs)
+{
+ blkif_t *blkif = dev_id;
+ add_to_blkdev_list_tail(blkif);
+ maybe_trigger_blkio_schedule();
+ return IRQ_HANDLED;
+}
+
+
+
+/******************************************************************
+ * DOWNWARD CALLS -- These interface with the block-device layer proper.
+ */
+
+static int do_block_io_op(blkif_t *blkif, int max_to_do)
+{
+ blkif_back_ring_t *blk_ring = &blkif->blk_ring;
+ blkif_request_t *req;
+ RING_IDX i, rp;
+ int more_to_do = 0;
+
+ rp = blk_ring->sring->req_prod;
+ rmb(); /* Ensure we see queued requests up to 'rp'. */
+
+ for ( i = blk_ring->req_cons;
+ (i != rp) && !RING_REQUEST_CONS_OVERFLOW(blk_ring, i);
+ i++ )
+ {
+ if ( (max_to_do-- == 0) || (NR_PENDING_REQS == MAX_PENDING_REQS) )
+ {
+ more_to_do = 1;
+ break;
+ }
+
+ req = RING_GET_REQUEST(blk_ring, i);
+ switch ( req->operation )
+ {
+ case BLKIF_OP_READ:
+ case BLKIF_OP_WRITE:
+ dispatch_rw_block_io(blkif, req);
+ break;
+
+ default:
+ DPRINTK("error: unknown block io operation [%d]\n",
+ req->operation);
+ make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
+ break;
+ }
+ }
+
+ blk_ring->req_cons = i;
+ blktap_kick_user();
+
+ return more_to_do;
+}
+
+static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req)
+{
+ blkif_request_t *target;
+ int i, pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
+ pending_req_t *pending_req;
+ struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
+ int op, ret;
+ unsigned int nseg;
+
+ /* Check that number of segments is sane. */
+ nseg = req->nr_segments;
+ if ( unlikely(nseg == 0) ||
+ unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST) )
+ {
+ DPRINTK("Bad number of segments in request (%d)\n", nseg);
+ goto bad_descriptor;
+ }
+
+ /* Make sure userspace is ready. */
+ if (!blktap_ring_ok) {
+ DPRINTK("blktap: ring not ready for requests!\n");
+ goto bad_descriptor;
+ }
+
+
+ if ( RING_FULL(&blktap_ufe_ring) ) {
+ WPRINTK("blktap: fe_ring is full, can't add (very broken!).\n");
+ goto bad_descriptor;
+ }
+
+ flush_cache_all(); /* a noop on intel... */
+
+ /* Map the foreign pages directly in to the application */
+ op = 0;
+ for (i=0; i<req->nr_segments; i++) {
+
+ unsigned long uvaddr;
+ unsigned long kvaddr;
+ unsigned long ptep;
+
+ uvaddr = MMAP_VADDR(user_vstart, pending_idx, i);
+ kvaddr = MMAP_VADDR(mmap_vstart, pending_idx, i);
+
+ /* Map the remote page to kernel. */
+ map[op].host_addr = kvaddr;
+ map[op].dom = blkif->domid;
+ map[op].ref = blkif_gref_from_fas(req->frame_and_sects[i]);
+ map[op].flags = GNTMAP_host_map;
+ /* This needs a bit more thought in terms of interposition:
+ * If we want to be able to modify pages during write using
+ * grant table mappings, the guest will either need to allow
+ * it, or we'll need to incur a copy. Bit of an fbufs moment. ;) */
+ if (req->operation == BLKIF_OP_WRITE)
+ map[op].flags |= GNTMAP_readonly;
+ op++;
+
+ /* Now map it to user. */
+ ret = create_lookup_pte_addr(blktap_vma->vm_mm, uvaddr, &ptep);
+ if (ret)
+ {
+ DPRINTK("Couldn't get a pte addr!\n");
+ fast_flush_area(pending_idx, req->nr_segments);
+ goto bad_descriptor;
+ }
+
+ map[op].host_addr = ptep;
+ map[op].dom = blkif->domid;
+ map[op].ref = blkif_gref_from_fas(req->frame_and_sects[i]);
+ map[op].flags = GNTMAP_host_map | GNTMAP_application_map
+ | GNTMAP_contains_pte;
+ /* Above interposition comment applies here as well. */
+ if (req->operation == BLKIF_OP_WRITE)
+ map[op].flags |= GNTMAP_readonly;
+ op++;
+ }
+
+ if ( unlikely(HYPERVISOR_grant_table_op(
+ GNTTABOP_map_grant_ref, map, op)))
+ BUG();
+
+ op = 0;
+ for (i=0; i<(req->nr_segments*2); i+=2) {
+ unsigned long uvaddr;
+ unsigned long kvaddr;
+ unsigned long offset;
+ int cancel = 0;
+
+ uvaddr = MMAP_VADDR(user_vstart, pending_idx, i/2);
+ kvaddr = MMAP_VADDR(mmap_vstart, pending_idx, i/2);
+
+ if ( unlikely(map[i].handle < 0) )
+ {
+ DPRINTK("Error on kernel grant mapping (%d)\n", map[i].handle);
+ ret = map[i].handle;
+ cancel = 1;
+ }
+
+ if ( unlikely(map[i+1].handle < 0) )
+ {
+ DPRINTK("Error on user grant mapping (%d)\n", map[i+1].handle);
+ ret = map[i+1].handle;
+ cancel = 1;
+ }
+
+ if (cancel)
+ {
+ fast_flush_area(pending_idx, req->nr_segments);
+ goto bad_descriptor;
+ }
+
+ /* Set the necessary mappings in p2m and in the VM_FOREIGN
+ * vm_area_struct to allow user vaddr -> struct page lookups
+ * to work. This is needed for direct IO to foreign pages. */
+ phys_to_machine_mapping[__pa(kvaddr) >> PAGE_SHIFT] =
+ FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT);
+
+ offset = (uvaddr - blktap_vma->vm_start) >> PAGE_SHIFT;
+ ((struct page **)blktap_vma->vm_private_data)[offset] =
+ pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT);
+
+ /* Save handles for unmapping later. */
+ pending_handle(pending_idx, i/2).kernel = map[i].handle;
+ pending_handle(pending_idx, i/2).user = map[i+1].handle;
+ }
+
+ /* Mark mapped pages as reserved: */
+ for ( i = 0; i < req->nr_segments; i++ )
+ {
+ unsigned long kvaddr;
+
+ kvaddr = MMAP_VADDR(mmap_vstart, pending_idx, i);
+ SetPageReserved(pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT));
+ }
+
+ pending_req = &pending_reqs[pending_idx];
+ pending_req->blkif = blkif;
+ pending_req->id = req->id;
+ pending_req->operation = req->operation;
+ pending_req->status = BLKIF_RSP_OKAY;
+ pending_req->nr_pages = nseg;
+ req->id = MAKE_ID(blkif->domid, pending_idx);
+ //atomic_set(&pending_req->pendcnt, nbio);
+ pending_cons++;
+ blkif_get(blkif);
+
+ /* Finally, write the request message to the user ring. */
+ target = RING_GET_REQUEST(&blktap_ufe_ring, blktap_ufe_ring.req_prod_pvt);
+ memcpy(target, req, sizeof(*req));
+ blktap_ufe_ring.req_prod_pvt++;
+ return;
+
+ bad_descriptor:
+ make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
+}
+
+
+
+/******************************************************************
+ * MISCELLANEOUS SETUP / TEARDOWN / DEBUGGING
+ */
+
+
+static void make_response(blkif_t *blkif, unsigned long id,
+ unsigned short op, int st)
+{
+ blkif_response_t *resp;
+ unsigned long flags;
+ blkif_back_ring_t *blk_ring = &blkif->blk_ring;
+
+ /* Place on the response ring for the relevant domain. */
+ spin_lock_irqsave(&blkif->blk_ring_lock, flags);
+ resp = RING_GET_RESPONSE(blk_ring, blk_ring->rsp_prod_pvt);
+ resp->id = id;
+ resp->operation = op;
+ resp->status = st;
+ wmb(); /* Ensure other side can see the response fields. */
+ blk_ring->rsp_prod_pvt++;
+ RING_PUSH_RESPONSES(blk_ring);
+ spin_unlock_irqrestore(&blkif->blk_ring_lock, flags);
+
+ /* Kick the relevant domain. */
+ notify_via_evtchn(blkif->evtchn);
+}
+
+static struct miscdevice blktap_miscdev = {
+ .minor = BLKTAP_MINOR,
+ .name = "blktap",
+ .fops = &blktap_fops,
+ .devfs_name = "misc/blktap",
+};
+
+void blkif_deschedule(blkif_t *blkif)
+{
+ remove_from_blkdev_list(blkif);
+}
+
+static int __init blkif_init(void)
+{
+ int i, j, err;
+ struct page *page;
+/*
+ if ( !(xen_start_info->flags & SIF_INITDOMAIN) &&
+ !(xen_start_info->flags & SIF_BLK_BE_DOMAIN) )
+ return 0;
+*/
blkif_interface_init();
- blkdev_schedule_init();
+
+ page = balloon_alloc_empty_page_range(MMAP_PAGES);
+ BUG_ON(page == NULL);
+ mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
+
+ pending_cons = 0;
+ pending_prod = MAX_PENDING_REQS;
+ memset(pending_reqs, 0, sizeof(pending_reqs));
+ for ( i = 0; i < MAX_PENDING_REQS; i++ )
+ pending_ring[i] = i;
- (void)ctrl_if_register_receiver(CMSG_BLKIF_BE, blkif_ctrlif_rx,
- CALLBACK_IN_BLOCKING_CONTEXT);
-
- /* Send a driver-UP notification to the domain controller. */
- cmsg.type = CMSG_BLKIF_BE;
- cmsg.subtype = CMSG_BLKIF_BE_DRIVER_STATUS;
- cmsg.length = sizeof(blkif_be_driver_status_t);
- be_st.status = BLKIF_DRIVER_STATUS_UP;
- memcpy(cmsg.msg, &be_st, sizeof(be_st));
- ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
-
- DPRINTK(" tap - Userland channel init:\n");
-
- blktap_init();
-
- DPRINTK("Blkif tap device initialized.\n");
+ spin_lock_init(&blkio_schedule_list_lock);
+ INIT_LIST_HEAD(&blkio_schedule_list);
+
+ if ( kernel_thread(blkio_schedule, 0, CLONE_FS | CLONE_FILES) < 0 )
+ BUG();
+
+ blkif_xenbus_init();
+
+ for (i=0; i<MAX_PENDING_REQS ; i++)
+ for (j=0; j<BLKIF_MAX_SEGMENTS_PER_REQUEST; j++)
+ BLKTAP_INVALIDATE_HANDLE(&pending_handle(i, j));
+
+ err = misc_register(&blktap_miscdev);
+ if ( err != 0 )
+ {
+ printk(KERN_ALERT "Couldn't register /dev/misc/blktap (%d)\n", err);
+ return err;
+ }
+
+ init_waitqueue_head(&blktap_wait);
return 0;
}
-#if 0 /* tap doesn't handle suspend/resume */
-void blkdev_suspend(void)
-{
-}
-
-void blkdev_resume(void)
-{
- ctrl_msg_t cmsg;
- blkif_fe_driver_status_t st;
-
- /* Send a driver-UP notification to the domain controller. */
- cmsg.type = CMSG_BLKIF_FE;
- cmsg.subtype = CMSG_BLKIF_FE_DRIVER_STATUS;
- cmsg.length = sizeof(blkif_fe_driver_status_t);
- st.status = BLKIF_DRIVER_STATUS_UP;
- memcpy(cmsg.msg, &st, sizeof(st));
- ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
-}
-#endif
-
-__initcall(xlblktap_init);
+__initcall(blkif_init);
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/blktap/blktap.h
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.h Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.h Fri Sep 9 16:30:54 2005
@@ -15,7 +15,6 @@
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
-#include <asm-xen/ctrl_if.h>
#include <linux/slab.h>
#include <linux/blkdev.h>
#include <asm/io.h>
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/console/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/console/Makefile Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/console/Makefile Fri Sep 9 16:30:54 2005
@@ -1,2 +1,2 @@
-obj-y := console.o
+obj-y := console.o xencons_ring.o
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/console/console.c
--- a/linux-2.6-xen-sparse/drivers/xen/console/console.c Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/console/console.c Fri Sep 9
16:30:54 2005
@@ -45,14 +45,15 @@
#include <linux/init.h>
#include <linux/console.h>
#include <linux/bootmem.h>
+#include <linux/sysrq.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <asm-xen/xen-public/event_channel.h>
#include <asm-xen/hypervisor.h>
#include <asm-xen/evtchn.h>
-#include <asm-xen/ctrl_if.h>
-
+
+#include "xencons_ring.h"
/*
* Modes:
* 'xencons=off' [XC_OFF]: Console is disabled.
@@ -66,6 +67,11 @@
static enum { XC_OFF, XC_DEFAULT, XC_TTY, XC_SERIAL } xc_mode = XC_DEFAULT;
static int xc_num = -1;
+#ifdef CONFIG_MAGIC_SYSRQ
+static unsigned long sysrq_requested;
+extern int sysrq_enabled;
+#endif
+
static int __init xencons_setup(char *str)
{
char *q;
@@ -118,13 +124,6 @@
/* Common transmit-kick routine. */
static void __xencons_tx_flush(void);
-/* This task is used to defer sending console data until there is space. */
-static void xencons_tx_flush_task_routine(void *data);
-
-static DECLARE_TQUEUE(xencons_tx_flush_task,
- xencons_tx_flush_task_routine,
- NULL);
-
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
static struct tty_driver *xencons_driver;
#else
@@ -196,7 +195,7 @@
void xen_console_init(void)
#endif
{
- if ( xen_start_info.flags & SIF_INITDOMAIN )
+ if ( xen_start_info->flags & SIF_INITDOMAIN )
{
if ( xc_mode == XC_DEFAULT )
xc_mode = XC_SERIAL;
@@ -264,39 +263,22 @@
/*** Forcibly flush console data before dying. ***/
void xencons_force_flush(void)
{
- ctrl_msg_t msg;
int sz;
/* Emergency console is synchronous, so there's nothing to flush. */
- if ( xen_start_info.flags & SIF_INITDOMAIN )
- return;
-
- /*
- * We use dangerous control-interface functions that require a quiescent
- * system and no interrupts. Try to ensure this with a global cli().
- */
- local_irq_disable(); /* XXXsmp */
+ if ( xen_start_info->flags & SIF_INITDOMAIN )
+ return;
+
/* Spin until console data is flushed through to the domain controller. */
- while ( (wc != wp) && !ctrl_if_transmitter_empty() )
- {
- /* Interrupts are disabled -- we must manually reap responses. */
- ctrl_if_discard_responses();
-
+ while ( (wc != wp) )
+ {
+ int sent = 0;
if ( (sz = wp - wc) == 0 )
continue;
- if ( sz > sizeof(msg.msg) )
- sz = sizeof(msg.msg);
- if ( sz > (wbuf_size - WBUF_MASK(wc)) )
- sz = wbuf_size - WBUF_MASK(wc);
-
- msg.type = CMSG_CONSOLE;
- msg.subtype = CMSG_CONSOLE_DATA;
- msg.length = sz;
- memcpy(msg.msg, &wbuf[WBUF_MASK(wc)], sz);
-
- if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 )
- wc += sz;
+ sent = xencons_ring_send(&wbuf[WBUF_MASK(wc)], sz);
+ if (sent > 0)
+ wc += sent;
}
}
@@ -320,7 +302,7 @@
static char x_char;
/* Non-privileged receive callback. */
-static void xencons_rx(ctrl_msg_t *msg, unsigned long id)
+static void xencons_rx(char *buf, unsigned len, struct pt_regs *regs)
{
int i;
unsigned long flags;
@@ -328,23 +310,39 @@
spin_lock_irqsave(&xencons_lock, flags);
if ( xencons_tty != NULL )
{
- for ( i = 0; i < msg->length; i++ )
- tty_insert_flip_char(xencons_tty, msg->msg[i], 0);
+ for ( i = 0; i < len; i++ ) {
+#ifdef CONFIG_MAGIC_SYSRQ
+ if (sysrq_enabled) {
+ if (buf[i] == '\x0f') { /* ^O */
+ sysrq_requested = jiffies;
+ continue; /* don't print the sysrq key */
+ } else if (sysrq_requested) {
+ unsigned long sysrq_timeout = sysrq_requested + HZ*2;
+ sysrq_requested = 0;
+ /* if it's been less than a timeout, do the sysrq */
+ if (time_before(jiffies, sysrq_timeout)) {
+ spin_unlock_irqrestore(&xencons_lock, flags);
+ handle_sysrq(buf[i], regs, xencons_tty);
+ spin_lock_irqsave(&xencons_lock, flags);
+ continue;
+ }
+ }
+ }
+#endif
+ tty_insert_flip_char(xencons_tty, buf[i], 0);
+ }
tty_flip_buffer_push(xencons_tty);
}
spin_unlock_irqrestore(&xencons_lock, flags);
- msg->length = 0;
- ctrl_if_send_response(msg);
}
/* Privileged and non-privileged transmit worker. */
static void __xencons_tx_flush(void)
{
int sz, work_done = 0;
- ctrl_msg_t msg;
-
- if ( xen_start_info.flags & SIF_INITDOMAIN )
+
+ if ( xen_start_info->flags & SIF_INITDOMAIN )
{
if ( x_char )
{
@@ -367,38 +365,23 @@
{
while ( x_char )
{
- msg.type = CMSG_CONSOLE;
- msg.subtype = CMSG_CONSOLE_DATA;
- msg.length = 1;
- msg.msg[0] = x_char;
-
- if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 )
- x_char = 0;
- else if ( ctrl_if_enqueue_space_callback(&xencons_tx_flush_task) )
- break;
-
- work_done = 1;
+ if (xencons_ring_send(&x_char, 1) == 1) {
+ x_char = 0;
+ work_done = 1;
+ }
}
while ( wc != wp )
{
+ int sent;
sz = wp - wc;
- if ( sz > sizeof(msg.msg) )
- sz = sizeof(msg.msg);
- if ( sz > (wbuf_size - WBUF_MASK(wc)) )
- sz = wbuf_size - WBUF_MASK(wc);
-
- msg.type = CMSG_CONSOLE;
- msg.subtype = CMSG_CONSOLE_DATA;
- msg.length = sz;
- memcpy(msg.msg, &wbuf[WBUF_MASK(wc)], sz);
-
- if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 )
- wc += sz;
- else if ( ctrl_if_enqueue_space_callback(&xencons_tx_flush_task) )
- break;
-
- work_done = 1;
+ if ( sz > (wbuf_size - WBUF_MASK(wc)) )
+ sz = wbuf_size - WBUF_MASK(wc);
+ sent = xencons_ring_send(&wbuf[WBUF_MASK(wc)], sz);
+ if ( sent > 0 ) {
+ wc += sent;
+ work_done = 1;
+ }
}
}
@@ -409,15 +392,6 @@
(xencons_tty->ldisc.write_wakeup != NULL) )
(xencons_tty->ldisc.write_wakeup)(xencons_tty);
}
-}
-
-/* Non-privileged transmit kicker. */
-static void xencons_tx_flush_task_routine(void *data)
-{
- unsigned long flags;
- spin_lock_irqsave(&xencons_lock, flags);
- __xencons_tx_flush();
- spin_unlock_irqrestore(&xencons_lock, flags);
}
/* Privileged receive callback and transmit kicker. */
@@ -726,6 +700,8 @@
if ( xc_mode == XC_OFF )
return 0;
+ xencons_ring_init();
+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
xencons_driver = alloc_tty_driver((xc_mode == XC_SERIAL) ?
1 : MAX_NR_CONSOLES);
@@ -794,7 +770,7 @@
tty_register_device(xencons_driver, 0, NULL);
#endif
- if ( xen_start_info.flags & SIF_INITDOMAIN )
+ if ( xen_start_info->flags & SIF_INITDOMAIN )
{
xencons_priv_irq = bind_virq_to_irq(VIRQ_CONSOLE);
(void)request_irq(xencons_priv_irq,
@@ -802,7 +778,8 @@
}
else
{
- (void)ctrl_if_register_receiver(CMSG_CONSOLE, xencons_rx, 0);
+
+ xencons_ring_register_receiver(xencons_rx);
}
printk("Xen virtual console successfully installed as %s%d\n",
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c
--- a/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c Fri Sep 9 16:30:54 2005
@@ -350,6 +350,8 @@
spin_unlock_irq(&port_user_lock);
+ kfree(u);
+
return 0;
}
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/netback/common.h
--- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h Fri Sep 9 16:30:54 2005
@@ -14,15 +14,17 @@
#include <linux/in.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
-#include <asm-xen/ctrl_if.h>
#include <asm-xen/evtchn.h>
#include <asm-xen/xen-public/io/netif.h>
#include <asm/io.h>
#include <asm/pgalloc.h>
-#if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX)
+#ifdef CONFIG_XEN_NETDEV_GRANT
#include <asm-xen/xen-public/grant_table.h>
#include <asm-xen/gnttab.h>
+
+#define GRANT_INVALID_REF (0xFFFF)
+
#endif
@@ -37,6 +39,11 @@
#define ASSERT(_p) ((void)0)
#define DPRINTK(_f, _a...) ((void)0)
#endif
+#define IPRINTK(fmt, args...) \
+ printk(KERN_INFO "xen_net: " fmt, ##args)
+#define WPRINTK(fmt, args...) \
+ printk(KERN_WARNING "xen_net: " fmt, ##args)
+
typedef struct netif_st {
/* Unique identifier for this interface. */
@@ -47,13 +54,13 @@
/* Physical parameters of the comms window. */
unsigned long tx_shmem_frame;
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
u16 tx_shmem_handle;
unsigned long tx_shmem_vaddr;
grant_ref_t tx_shmem_ref;
#endif
unsigned long rx_shmem_frame;
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
u16 rx_shmem_handle;
unsigned long rx_shmem_vaddr;
grant_ref_t rx_shmem_ref;
@@ -68,7 +75,7 @@
/* Private indexes into shared ring. */
NETIF_RING_IDX rx_req_cons;
NETIF_RING_IDX rx_resp_prod; /* private version of shared variable */
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
NETIF_RING_IDX rx_resp_prod_copy; /* private version of shared variable */
#endif
NETIF_RING_IDX tx_req_cons;
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/netback/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Fri Sep 9
16:30:54 2005
@@ -111,91 +111,81 @@
return netif;
}
-static int map_frontend_page(netif_t *netif, unsigned long localaddr,
- unsigned long tx_ring_ref, unsigned long
rx_ring_ref)
-{
-#if !defined(CONFIG_XEN_NETDEV_GRANT_TX)||!defined(CONFIG_XEN_NETDEV_GRANT_RX)
+static int map_frontend_pages(netif_t *netif, unsigned long localaddr,
+ unsigned long tx_ring_ref,
+ unsigned long rx_ring_ref)
+{
+#ifdef CONFIG_XEN_NETDEV_GRANT
+ struct gnttab_map_grant_ref op;
+
+ /* Map: Use the Grant table reference */
+ op.host_addr = localaddr;
+ op.flags = GNTMAP_host_map;
+ op.ref = tx_ring_ref;
+ op.dom = netif->domid;
+
+ BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) );
+ if (op.handle < 0) {
+ DPRINTK(" Grant table operation failure mapping tx_ring_ref!\n");
+ return op.handle;
+ }
+
+ netif->tx_shmem_ref = tx_ring_ref;
+ netif->tx_shmem_handle = op.handle;
+ netif->tx_shmem_vaddr = localaddr;
+
+ /* Map: Use the Grant table reference */
+ op.host_addr = localaddr + PAGE_SIZE;
+ op.flags = GNTMAP_host_map;
+ op.ref = rx_ring_ref;
+ op.dom = netif->domid;
+
+ BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) );
+ if (op.handle < 0) {
+ DPRINTK(" Grant table operation failure mapping rx_ring_ref!\n");
+ return op.handle;
+ }
+
+ netif->rx_shmem_ref = rx_ring_ref;
+ netif->rx_shmem_handle = op.handle;
+ netif->rx_shmem_vaddr = localaddr + PAGE_SIZE;
+
+#else
pgprot_t prot = __pgprot(_KERNPG_TABLE);
int err;
-#endif
-#if defined(CONFIG_XEN_NETDEV_GRANT_TX)
- {
- struct gnttab_map_grant_ref op;
-
- /* Map: Use the Grant table reference */
- op.host_addr = localaddr;
- op.flags = GNTMAP_host_map;
- op.ref = tx_ring_ref;
- op.dom = netif->domid;
-
- BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) );
- if (op.handle < 0) {
- DPRINTK(" Grant table operation failure !\n");
- return op.handle;
- }
-
- netif->tx_shmem_ref = tx_ring_ref;
- netif->tx_shmem_handle = op.handle;
- netif->tx_shmem_vaddr = localaddr;
- }
-#else
- err = direct_remap_area_pages(&init_mm, localaddr,
- tx_ring_ref<<PAGE_SHIFT, PAGE_SIZE,
+
+ err = direct_remap_pfn_range(&init_mm, localaddr,
+ tx_ring_ref, PAGE_SIZE,
prot, netif->domid);
+
+ err |= direct_remap_pfn_range(&init_mm, localaddr + PAGE_SIZE,
+ rx_ring_ref, PAGE_SIZE,
+ prot, netif->domid);
+
if (err)
return err;
#endif
-#if defined(CONFIG_XEN_NETDEV_GRANT_RX)
- {
- struct gnttab_map_grant_ref op;
-
- /* Map: Use the Grant table reference */
- op.host_addr = localaddr + PAGE_SIZE;
- op.flags = GNTMAP_host_map;
- op.ref = rx_ring_ref;
- op.dom = netif->domid;
-
- BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) );
- if (op.handle < 0) {
- DPRINTK(" Grant table operation failure !\n");
- return op.handle;
- }
-
- netif->rx_shmem_ref = rx_ring_ref;
- netif->rx_shmem_handle = op.handle;
- netif->rx_shmem_vaddr = localaddr + PAGE_SIZE;
- }
-#else
- err = direct_remap_area_pages(&init_mm, localaddr + PAGE_SIZE,
- rx_ring_ref<<PAGE_SHIFT, PAGE_SIZE,
- prot, netif->domid);
- if (err)
- return err;
-#endif
-
return 0;
}
-static void unmap_frontend_page(netif_t *netif)
-{
-#if defined(CONFIG_XEN_NETDEV_GRANT_RX) || defined(CONFIG_XEN_NETDEV_GRANT_TX)
+static void unmap_frontend_pages(netif_t *netif)
+{
+#ifdef CONFIG_XEN_NETDEV_GRANT
struct gnttab_unmap_grant_ref op;
-#endif
-
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+
op.host_addr = netif->tx_shmem_vaddr;
op.handle = netif->tx_shmem_handle;
op.dev_bus_addr = 0;
BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
-#endif
-
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+
op.host_addr = netif->rx_shmem_vaddr;
op.handle = netif->rx_shmem_handle;
op.dev_bus_addr = 0;
BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
#endif
+
+ return;
}
int netif_map(netif_t *netif, unsigned long tx_ring_ref,
@@ -209,8 +199,8 @@
if (vma == NULL)
return -ENOMEM;
- err = map_frontend_page(netif, (unsigned long)vma->addr, tx_ring_ref,
- rx_ring_ref);
+ err = map_frontend_pages(netif, (unsigned long)vma->addr, tx_ring_ref,
+ rx_ring_ref);
if (err) {
vfree(vma->addr);
return err;
@@ -222,7 +212,7 @@
op.u.bind_interdomain.port2 = evtchn;
err = HYPERVISOR_event_channel_op(&op);
if (err) {
- unmap_frontend_page(netif);
+ unmap_frontend_pages(netif);
vfree(vma->addr);
return err;
}
@@ -267,7 +257,7 @@
unregister_netdev(netif->dev);
if (netif->tx) {
- unmap_frontend_page(netif);
+ unmap_frontend_pages(netif);
vfree(netif->tx); /* Frees netif->rx as well. */
}
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/netback/loopback.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c Fri Sep 9
16:30:54 2005
@@ -29,136 +29,163 @@
#include <linux/skbuff.h>
#include <net/dst.h>
+static int nloopbacks = 1;
+module_param(nloopbacks, int, 0);
+MODULE_PARM_DESC(nloopbacks, "Number of netback-loopback devices to create");
+
struct net_private {
- struct net_device *loopback_dev;
- struct net_device_stats stats;
+ struct net_device *loopback_dev;
+ struct net_device_stats stats;
};
static int loopback_open(struct net_device *dev)
{
- struct net_private *np = netdev_priv(dev);
- memset(&np->stats, 0, sizeof(np->stats));
- netif_start_queue(dev);
- return 0;
+ struct net_private *np = netdev_priv(dev);
+ memset(&np->stats, 0, sizeof(np->stats));
+ netif_start_queue(dev);
+ return 0;
}
static int loopback_close(struct net_device *dev)
{
- netif_stop_queue(dev);
- return 0;
+ netif_stop_queue(dev);
+ return 0;
}
static int loopback_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct net_private *np = netdev_priv(dev);
+ struct net_private *np = netdev_priv(dev);
- dst_release(skb->dst);
- skb->dst = NULL;
+ dst_release(skb->dst);
+ skb->dst = NULL;
- skb_orphan(skb);
+ skb_orphan(skb);
- np->stats.tx_bytes += skb->len;
- np->stats.tx_packets++;
+ np->stats.tx_bytes += skb->len;
+ np->stats.tx_packets++;
- /* Switch to loopback context. */
- dev = np->loopback_dev;
- np = netdev_priv(dev);
+ /* Switch to loopback context. */
+ dev = np->loopback_dev;
+ np = netdev_priv(dev);
- np->stats.rx_bytes += skb->len;
- np->stats.rx_packets++;
+ np->stats.rx_bytes += skb->len;
+ np->stats.rx_packets++;
- if ( skb->ip_summed == CHECKSUM_HW )
- {
- /* Defer checksum calculation. */
- skb->proto_csum_blank = 1;
- /* Must be a local packet: assert its integrity. */
- skb->proto_csum_valid = 1;
- }
+ if (skb->ip_summed == CHECKSUM_HW) {
+ /* Defer checksum calculation. */
+ skb->proto_csum_blank = 1;
+ /* Must be a local packet: assert its integrity. */
+ skb->proto_csum_valid = 1;
+ }
- skb->ip_summed = skb->proto_csum_valid ?
- CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
+ skb->ip_summed = skb->proto_csum_valid ?
+ CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
- skb->pkt_type = PACKET_HOST; /* overridden by eth_type_trans() */
- skb->protocol = eth_type_trans(skb, dev);
- skb->dev = dev;
- dev->last_rx = jiffies;
- netif_rx(skb);
+ skb->pkt_type = PACKET_HOST; /* overridden by eth_type_trans() */
+ skb->protocol = eth_type_trans(skb, dev);
+ skb->dev = dev;
+ dev->last_rx = jiffies;
+ netif_rx(skb);
- return 0;
+ return 0;
}
static struct net_device_stats *loopback_get_stats(struct net_device *dev)
{
- struct net_private *np = netdev_priv(dev);
- return &np->stats;
+ struct net_private *np = netdev_priv(dev);
+ return &np->stats;
}
static void loopback_construct(struct net_device *dev, struct net_device *lo)
{
- struct net_private *np = netdev_priv(dev);
+ struct net_private *np = netdev_priv(dev);
- np->loopback_dev = lo;
+ np->loopback_dev = lo;
- dev->open = loopback_open;
- dev->stop = loopback_close;
- dev->hard_start_xmit = loopback_start_xmit;
- dev->get_stats = loopback_get_stats;
+ dev->open = loopback_open;
+ dev->stop = loopback_close;
+ dev->hard_start_xmit = loopback_start_xmit;
+ dev->get_stats = loopback_get_stats;
- dev->tx_queue_len = 0;
+ dev->tx_queue_len = 0;
- dev->features = NETIF_F_HIGHDMA | NETIF_F_LLTX;
+ dev->features = NETIF_F_HIGHDMA | NETIF_F_LLTX;
- /*
- * We do not set a jumbo MTU on the interface. Otherwise the network
- * stack will try to send large packets that will get dropped by the
- * Ethernet bridge (unless the physical Ethernet interface is configured
- * to transfer jumbo packets). If a larger MTU is desired then the system
- * administrator can specify it using the 'ifconfig' command.
- */
- /*dev->mtu = 16*1024;*/
+ /*
+ * We do not set a jumbo MTU on the interface. Otherwise the network
+ * stack will try to send large packets that will get dropped by the
+ * Ethernet bridge (unless the physical Ethernet interface is
+ * configured to transfer jumbo packets). If a larger MTU is desired
+ * then the system administrator can specify it using the 'ifconfig'
+ * command.
+ */
+ /*dev->mtu = 16*1024;*/
+}
+
+static int __init make_loopback(int i)
+{
+ struct net_device *dev1, *dev2;
+ char dev_name[IFNAMSIZ];
+ int err = -ENOMEM;
+
+ sprintf(dev_name, "vif0.%d", i);
+ dev1 = alloc_netdev(sizeof(struct net_private), dev_name, ether_setup);
+ sprintf(dev_name, "veth%d", i);
+ dev2 = alloc_netdev(sizeof(struct net_private), dev_name, ether_setup);
+ if ((dev1 == NULL) || (dev2 == NULL))
+ goto fail;
+
+ loopback_construct(dev1, dev2);
+ loopback_construct(dev2, dev1);
+
+ dev1->features |= NETIF_F_NO_CSUM;
+ dev2->features |= NETIF_F_IP_CSUM;
+
+ /*
+ * Initialise a dummy MAC address for the 'dummy backend' interface. We
+ * choose the numerically largest non-broadcast address to prevent the
+ * address getting stolen by an Ethernet bridge for STP purposes.
+ */
+ memset(dev1->dev_addr, 0xFF, ETH_ALEN);
+ dev1->dev_addr[0] &= ~0x01;
+
+ if ((err = register_netdev(dev1)) != 0)
+ goto fail;
+
+ if ((err = register_netdev(dev2)) != 0) {
+ unregister_netdev(dev1);
+ goto fail;
+ }
+
+ return 0;
+
+ fail:
+ if (dev1 != NULL)
+ kfree(dev1);
+ if (dev2 != NULL)
+ kfree(dev2);
+ return err;
}
static int __init loopback_init(void)
{
- struct net_device *dev1, *dev2;
- int err = -ENOMEM;
+ int i, err = 0;
- dev1 = alloc_netdev(sizeof(struct net_private), "vif0.0", ether_setup);
- dev2 = alloc_netdev(sizeof(struct net_private), "veth0", ether_setup);
- if ( (dev1 == NULL) || (dev2 == NULL) )
- goto fail;
+ for (i = 0; i < nloopbacks; i++)
+ if ((err = make_loopback(i)) != 0)
+ break;
- loopback_construct(dev1, dev2);
- loopback_construct(dev2, dev1);
-
- dev1->features |= NETIF_F_NO_CSUM;
- dev2->features |= NETIF_F_IP_CSUM;
-
- /*
- * Initialise a dummy MAC address for the 'dummy backend' interface. We
- * choose the numerically largest non-broadcast address to prevent the
- * address getting stolen by an Ethernet bridge for STP purposes.
- */
- memset(dev1->dev_addr, 0xFF, ETH_ALEN);
- dev1->dev_addr[0] &= ~0x01;
-
- if ( (err = register_netdev(dev1)) != 0 )
- goto fail;
-
- if ( (err = register_netdev(dev2)) != 0 )
- {
- unregister_netdev(dev1);
- goto fail;
- }
-
- return 0;
-
- fail:
- if ( dev1 != NULL )
- kfree(dev1);
- if ( dev2 != NULL )
- kfree(dev2);
- return err;
+ return err;
}
module_init(loopback_init);
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/netback/netback.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Fri Sep 9
16:30:54 2005
@@ -12,24 +12,8 @@
#include "common.h"
#include <asm-xen/balloon.h>
-
-#if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX)
-#include <asm-xen/xen-public/grant_table.h>
-#include <asm-xen/gnttab.h>
-#ifdef GRANT_DEBUG
-static void
-dump_packet(int tag, u32 addr, unsigned char *p)
-{
- int i;
-
- printk(KERN_ALERT "#### rx_action %c %08x ", tag & 0xff, addr);
- for (i = 0; i < 20; i++) {
- printk("%02x", p[i]);
- }
- printk("\n");
-}
-#endif
-#endif
+#include <asm-xen/xen-public/memory.h>
+
static void netif_idx_release(u16 pending_idx);
static void netif_page_release(struct page *page);
@@ -56,7 +40,8 @@
static struct sk_buff_head rx_queue;
static multicall_entry_t rx_mcl[NETIF_RX_RING_SIZE*2+1];
static mmu_update_t rx_mmu[NETIF_RX_RING_SIZE];
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+
+#ifdef CONFIG_XEN_NETDEV_GRANT
static gnttab_donate_t grant_rx_op[MAX_PENDING_REQS];
#else
static struct mmuext_op rx_mmuext[NETIF_RX_RING_SIZE];
@@ -87,16 +72,13 @@
static struct sk_buff_head tx_queue;
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
static u16 grant_tx_ref[MAX_PENDING_REQS];
static gnttab_unmap_grant_ref_t tx_unmap_ops[MAX_PENDING_REQS];
static gnttab_map_grant_ref_t tx_map_ops[MAX_PENDING_REQS];
+
#else
static multicall_entry_t tx_mcl[MAX_PENDING_REQS];
-#endif
-
-#if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX)
-#define GRANT_INVALID_REF (0xFFFF)
#endif
static struct list_head net_schedule_list;
@@ -110,25 +92,37 @@
static unsigned long alloc_mfn(void)
{
unsigned long mfn = 0, flags;
+ struct xen_memory_reservation reservation = {
+ .extent_start = mfn_list,
+ .nr_extents = MAX_MFN_ALLOC,
+ .extent_order = 0,
+ .domid = DOMID_SELF
+ };
spin_lock_irqsave(&mfn_lock, flags);
if ( unlikely(alloc_index == 0) )
- alloc_index = HYPERVISOR_dom_mem_op(
- MEMOP_increase_reservation, mfn_list, MAX_MFN_ALLOC, 0);
+ alloc_index = HYPERVISOR_memory_op(
+ XENMEM_increase_reservation, &reservation);
if ( alloc_index != 0 )
mfn = mfn_list[--alloc_index];
spin_unlock_irqrestore(&mfn_lock, flags);
return mfn;
}
-#ifndef CONFIG_XEN_NETDEV_GRANT_RX
+#ifndef CONFIG_XEN_NETDEV_GRANT
static void free_mfn(unsigned long mfn)
{
unsigned long flags;
+ struct xen_memory_reservation reservation = {
+ .extent_start = &mfn,
+ .nr_extents = 1,
+ .extent_order = 0,
+ .domid = DOMID_SELF
+ };
spin_lock_irqsave(&mfn_lock, flags);
if ( alloc_index != MAX_MFN_ALLOC )
mfn_list[alloc_index++] = mfn;
- else if ( HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation,
- &mfn, 1, 0) != 1 )
+ else if ( HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation)
+ != 1 )
BUG();
spin_unlock_irqrestore(&mfn_lock, flags);
}
@@ -187,7 +181,7 @@
dev_kfree_skb(skb);
skb = nskb;
}
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
#ifdef DEBUG_GRANT
printk(KERN_ALERT "#### be_xmit: req_prod=%d req_cons=%d id=%04x
gr=%04x\n",
netif->rx->req_prod,
@@ -233,12 +227,12 @@
static void net_rx_action(unsigned long unused)
{
- netif_t *netif;
+ netif_t *netif = NULL;
s8 status;
u16 size, id, evtchn;
multicall_entry_t *mcl;
mmu_update_t *mmu;
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
gnttab_donate_t *gop;
#else
struct mmuext_op *mmuext;
@@ -253,7 +247,7 @@
mcl = rx_mcl;
mmu = rx_mmu;
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
gop = grant_rx_op;
#else
mmuext = rx_mmuext;
@@ -269,7 +263,7 @@
if ( (new_mfn = alloc_mfn()) == 0 )
{
if ( net_ratelimit() )
- printk(KERN_WARNING "Memory squeeze in netback driver.\n");
+ WPRINTK("Memory squeeze in netback driver.\n");
mod_timer(&net_timer, jiffies + HZ);
skb_queue_head(&rx_queue, skb);
break;
@@ -284,7 +278,7 @@
pfn_pte_ma(new_mfn, PAGE_KERNEL), 0);
mcl++;
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
gop->mfn = old_mfn;
gop->domid = netif->domid;
gop->handle = netif->rx->ring[
@@ -303,7 +297,7 @@
mmuext->mfn = old_mfn;
mmuext++;
#endif
- mmu->ptr = (new_mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
+ mmu->ptr = ((unsigned long long)new_mfn << PAGE_SHIFT) |
MMU_MACHPHYS_UPDATE;
mmu->val = __pa(vdata) >> PAGE_SHIFT;
mmu++;
@@ -327,7 +321,7 @@
mcl->args[3] = DOMID_SELF;
mcl++;
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
mcl[-2].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
#else
mcl[-3].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
@@ -336,9 +330,17 @@
BUG();
mcl = rx_mcl;
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
- BUG_ON(HYPERVISOR_grant_table_op(
- GNTTABOP_donate, grant_rx_op, gop - grant_rx_op));
+#ifdef CONFIG_XEN_NETDEV_GRANT
+ if(HYPERVISOR_grant_table_op(GNTTABOP_donate, grant_rx_op,
+ gop - grant_rx_op)) {
+ /*
+ ** The other side has given us a bad grant ref, or has no headroom,
+ ** or has gone away. Unfortunately the current grant table code
+ ** doesn't inform us which is the case, so not much we can do.
+ */
+ DPRINTK("net_rx: donate to DOM%u failed; dropping (up to) %d "
+ "packets.\n", grant_rx_op[0].domid, gop - grant_rx_op);
+ }
gop = grant_rx_op;
#else
mmuext = rx_mmuext;
@@ -350,7 +352,7 @@
/* Rederive the machine addresses. */
new_mfn = mcl[0].args[1] >> PAGE_SHIFT;
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
old_mfn = 0; /* XXX Fix this so we can free_mfn() on error! */
#else
old_mfn = mmuext[0].mfn;
@@ -367,8 +369,13 @@
/* Check the reassignment error code. */
status = NETIF_RSP_OKAY;
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
- BUG_ON(gop->status != 0); /* XXX */
+#ifdef CONFIG_XEN_NETDEV_GRANT
+ if(gop->status != 0) {
+ DPRINTK("Bad status %d from grant donate to DOM%u\n",
+ gop->status, netif->domid);
+ /* XXX SMH: should free 'old_mfn' here */
+ status = NETIF_RSP_ERROR;
+ }
#else
if ( unlikely(mcl[1].result != 0) )
{
@@ -391,7 +398,7 @@
netif_put(netif);
dev_kfree_skb(skb);
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
mcl++;
gop++;
#else
@@ -407,6 +414,7 @@
notify_via_evtchn(evtchn);
}
+ out:
/* More work to do? */
if ( !skb_queue_empty(&rx_queue) && !timer_pending(&net_timer) )
tasklet_schedule(&net_rx_tasklet);
@@ -483,7 +491,7 @@
inline static void net_tx_action_dealloc(void)
{
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
gnttab_unmap_grant_ref_t *gop;
#else
multicall_entry_t *mcl;
@@ -495,7 +503,7 @@
dc = dealloc_cons;
dp = dealloc_prod;
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
/*
* Free up any grants we have finished using
*/
@@ -529,7 +537,7 @@
#endif
while ( dealloc_cons != dp )
{
-#ifndef CONFIG_XEN_NETDEV_GRANT_TX
+#ifndef CONFIG_XEN_NETDEV_GRANT
/* The update_va_mapping() must not fail. */
BUG_ON(mcl[0].result != 0);
#endif
@@ -556,7 +564,7 @@
netif_put(netif);
-#ifndef CONFIG_XEN_NETDEV_GRANT_TX
+#ifndef CONFIG_XEN_NETDEV_GRANT
mcl++;
#endif
}
@@ -572,7 +580,7 @@
netif_tx_request_t txreq;
u16 pending_idx;
NETIF_RING_IDX i;
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
gnttab_map_grant_ref_t *mop;
#else
multicall_entry_t *mcl;
@@ -582,7 +590,7 @@
if ( dealloc_cons != dealloc_prod )
net_tx_action_dealloc();
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
mop = tx_map_ops;
#else
mcl = tx_mcl;
@@ -683,7 +691,7 @@
/* Packets passed to netif_rx() must have some headroom. */
skb_reserve(skb, 16);
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
mop->host_addr = MMAP_VADDR(pending_idx);
mop->dom = netif->domid;
mop->ref = txreq.addr >> PAGE_SHIFT;
@@ -706,7 +714,7 @@
pending_cons++;
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
if ( (mop - tx_map_ops) >= ARRAY_SIZE(tx_map_ops) )
break;
#else
@@ -716,7 +724,7 @@
#endif
}
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
if ( mop == tx_map_ops )
return;
@@ -739,7 +747,7 @@
memcpy(&txreq, &pending_tx_info[pending_idx].req, sizeof(txreq));
/* Check the remap error code. */
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
/*
XXX SMH: error returns from grant operations are pretty poorly
specified/thought out, but the below at least conforms with
@@ -813,7 +821,7 @@
netif_rx(skb);
netif->dev->last_rx = jiffies;
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
mop++;
#else
mcl++;
@@ -932,16 +940,13 @@
int i;
struct page *page;
- if ( !(xen_start_info.flags & SIF_NET_BE_DOMAIN) &&
- !(xen_start_info.flags & SIF_INITDOMAIN) )
+ if ( !(xen_start_info->flags & SIF_NET_BE_DOMAIN) &&
+ !(xen_start_info->flags & SIF_INITDOMAIN) )
return 0;
- printk("Initialising Xen netif backend\n");
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
- printk("#### netback tx using grant tables\n");
-#endif
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
- printk("#### netback rx using grant tables\n");
+ IPRINTK("Initialising Xen netif backend.\n");
+#ifdef CONFIG_XEN_NETDEV_GRANT
+ IPRINTK("Using grant tables.\n");
#endif
/* We can increase reservation by this much in net_rx_action(). */
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Fri Sep 9 16:30:54 2005
@@ -160,9 +160,47 @@
}
#endif
+ kobject_hotplug(&dev->dev.kobj, KOBJ_ONLINE);
+
/* Pass in NULL node to skip exist test. */
frontend_changed(&be->watch, NULL);
}
+}
+
+static int netback_hotplug(struct xenbus_device *xdev, char **envp,
+ int num_envp, char *buffer, int buffer_size)
+{
+ struct backend_info *be;
+ netif_t *netif;
+ char **key, *val;
+ int i = 0, length = 0;
+ static char *env_vars[] = { "script", "domain", "mac", "bridge", "ip",
+ NULL };
+
+ be = xdev->data;
+ netif = be->netif;
+
+ add_hotplug_env_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "vif=%s", netif->dev->name);
+
+ key = env_vars;
+ while (*key != NULL) {
+ val = xenbus_read(xdev->nodename, *key, NULL);
+ if (!IS_ERR(val)) {
+ char buf[strlen(*key) + 4];
+ sprintf(buf, "%s=%%s", *key);
+ add_hotplug_env_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ buf, val);
+ kfree(val);
+ }
+ key++;
+ }
+
+ envp[i] = NULL;
+
+ return 0;
}
static int netback_probe(struct xenbus_device *dev,
@@ -249,6 +287,7 @@
.ids = netback_ids,
.probe = netback_probe,
.remove = netback_remove,
+ .hotplug = netback_hotplug,
};
void netif_xenbus_init(void)
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Fri Sep 9
16:30:54 2005
@@ -50,13 +50,23 @@
#include <asm-xen/evtchn.h>
#include <asm-xen/xenbus.h>
#include <asm-xen/xen-public/io/netif.h>
+#include <asm-xen/xen-public/memory.h>
#include <asm-xen/balloon.h>
#include <asm/page.h>
#include <asm/uaccess.h>
-#if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX)
+#ifdef CONFIG_XEN_NETDEV_GRANT
#include <asm-xen/xen-public/grant_table.h>
#include <asm-xen/gnttab.h>
+
+static grant_ref_t gref_tx_head;
+static grant_ref_t grant_tx_ref[NETIF_TX_RING_SIZE + 1];
+
+static grant_ref_t gref_rx_head;
+static grant_ref_t grant_rx_ref[NETIF_RX_RING_SIZE + 1];
+
+#define GRANT_INVALID_REF (0xFFFF)
+
#ifdef GRANT_DEBUG
static void
dump_packet(int tag, void *addr, u32 ap)
@@ -70,8 +80,17 @@
}
printk("\n");
}
-#endif
-#endif
+
+#define GDPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \
+ __FILE__ , __LINE__ , ## _a )
+#else
+#define dump_packet(x,y,z) ((void)0)
+#define GDPRINTK(_f, _a...) ((void)0)
+#endif
+
+#endif
+
+
#ifndef __GFP_NOWARN
#define __GFP_NOWARN 0
@@ -101,22 +120,10 @@
#define TX_TEST_IDX req_cons /* conservative: not seen all our requests? */
#endif
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
-static grant_ref_t gref_tx_head;
-static grant_ref_t grant_tx_ref[NETIF_TX_RING_SIZE + 1];
-#endif
-
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
-static grant_ref_t gref_rx_head;
-static grant_ref_t grant_rx_ref[NETIF_RX_RING_SIZE + 1];
-#endif
-
-#if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX)
-#define GRANT_INVALID_REF (0xFFFF)
-#endif
#define NETIF_STATE_DISCONNECTED 0
#define NETIF_STATE_CONNECTED 1
+
static unsigned int netif_state = NETIF_STATE_DISCONNECTED;
@@ -278,7 +285,7 @@
for (i = np->tx_resp_cons; i != prod; i++) {
id = np->tx->ring[MASK_NETIF_TX_IDX(i)].resp.id;
skb = np->tx_skbs[id];
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
if (unlikely(gnttab_query_foreign_access(grant_tx_ref[id]) != 0)) {
/* other domain is still using this grant - shouldn't happen
but if it does, we'll try to reclaim the grant later */
@@ -309,7 +316,7 @@
mb();
} while (prod != np->tx->resp_prod);
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
out:
#endif
@@ -328,8 +335,9 @@
struct sk_buff *skb;
int i, batch_target;
NETIF_RING_IDX req_prod = np->rx->req_prod;
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
- int ref;
+ struct xen_memory_reservation reservation;
+#ifdef CONFIG_XEN_NETDEV_GRANT
+ grant_ref_t ref;
#endif
if (unlikely(np->backend_state != BEST_CONNECTED))
@@ -363,9 +371,9 @@
np->rx_skbs[id] = skb;
np->rx->ring[MASK_NETIF_RX_IDX(req_prod + i)].req.id = id;
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
ref = gnttab_claim_grant_reference(&gref_rx_head);
- if (unlikely(ref < 0)) {
+ if (unlikely((signed short)ref < 0)) {
printk(KERN_ALERT "#### netfront can't claim rx reference\n");
BUG();
}
@@ -388,12 +396,15 @@
rx_mcl[i-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
/* Give away a batch of pages. */
- rx_mcl[i].op = __HYPERVISOR_dom_mem_op;
- rx_mcl[i].args[0] = MEMOP_decrease_reservation;
- rx_mcl[i].args[1] = (unsigned long)rx_pfn_array;
- rx_mcl[i].args[2] = (unsigned long)i;
- rx_mcl[i].args[3] = 0;
- rx_mcl[i].args[4] = DOMID_SELF;
+ rx_mcl[i].op = __HYPERVISOR_memory_op;
+ rx_mcl[i].args[0] = XENMEM_decrease_reservation;
+ rx_mcl[i].args[1] = (unsigned long)&reservation;
+
+ reservation.extent_start = rx_pfn_array;
+ reservation.nr_extents = i;
+ reservation.extent_order = 0;
+ reservation.address_bits = 0;
+ reservation.domid = DOMID_SELF;
/* Tell the ballon driver what is going on. */
balloon_update_driver_allowance(i);
@@ -401,7 +412,7 @@
/* Zap PTEs and give away pages in one big multicall. */
(void)HYPERVISOR_multicall(rx_mcl, i+1);
- /* Check return status of HYPERVISOR_dom_mem_op(). */
+ /* Check return status of HYPERVISOR_memory_op(). */
if (unlikely(rx_mcl[i].result != i))
panic("Unable to reduce memory reservation\n");
@@ -421,8 +432,8 @@
struct net_private *np = netdev_priv(dev);
netif_tx_request_t *tx;
NETIF_RING_IDX i;
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
- unsigned int ref;
+#ifdef CONFIG_XEN_NETDEV_GRANT
+ grant_ref_t ref;
unsigned long mfn;
#endif
@@ -459,9 +470,9 @@
tx = &np->tx->ring[MASK_NETIF_TX_IDX(i)].req;
tx->id = id;
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
ref = gnttab_claim_grant_reference(&gref_tx_head);
- if (unlikely(ref < 0)) {
+ if (unlikely((signed short)ref < 0)) {
printk(KERN_ALERT "#### netfront can't claim tx grant reference\n");
BUG();
}
@@ -514,7 +525,7 @@
network_tx_buf_gc(dev);
spin_unlock_irqrestore(&np->tx_lock, flags);
- if ((np->rx_resp_cons != np->rx->resp_prod) && (np->user_state ==
UST_OPEN))
+ if((np->rx_resp_cons != np->rx->resp_prod) && (np->user_state == UST_OPEN))
netif_rx_schedule(dev);
return IRQ_HANDLED;
@@ -532,7 +543,7 @@
int work_done, budget, more_to_do = 1;
struct sk_buff_head rxq;
unsigned long flags;
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
unsigned long mfn;
grant_ref_t ref;
#endif
@@ -569,8 +580,19 @@
continue;
}
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
- ref = grant_rx_ref[rx->id];
+#ifdef CONFIG_XEN_NETDEV_GRANT
+ ref = grant_rx_ref[rx->id];
+
+ if(ref == GRANT_INVALID_REF) {
+ printk(KERN_WARNING "Bad rx grant reference %d from dom %d.\n",
+ ref, np->backend_id);
+ np->rx->ring[MASK_NETIF_RX_IDX(np->rx->req_prod)].req.id = rx->id;
+ wmb();
+ np->rx->req_prod++;
+ work_done--;
+ continue;
+ }
+
grant_rx_ref[rx->id] = GRANT_INVALID_REF;
mfn = gnttab_end_foreign_transfer_ref(ref);
gnttab_release_grant_reference(&gref_rx_head, ref);
@@ -580,7 +602,7 @@
ADD_ID_TO_FREELIST(np->rx_skbs, rx->id);
/* NB. We handle skb overflow later. */
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
skb->data = skb->head + rx->addr;
#else
skb->data = skb->head + (rx->addr & ~PAGE_MASK);
@@ -595,14 +617,14 @@
np->stats.rx_bytes += rx->status;
/* Remap the page. */
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
- mmu->ptr = mfn << PAGE_SHIFT | MMU_MACHPHYS_UPDATE;
+#ifdef CONFIG_XEN_NETDEV_GRANT
+ mmu->ptr = ((unsigned long long)mfn << PAGE_SHIFT) |
MMU_MACHPHYS_UPDATE;
#else
mmu->ptr = (rx->addr & PAGE_MASK) | MMU_MACHPHYS_UPDATE;
#endif
mmu->val = __pa(skb->head) >> PAGE_SHIFT;
mmu++;
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
MULTI_update_va_mapping(mcl, (unsigned long)skb->head,
pfn_pte_ma(mfn, PAGE_KERNEL), 0);
#else
@@ -612,19 +634,19 @@
#endif
mcl++;
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] = mfn;
+ GDPRINTK("#### rx_poll enqueue vdata=%p mfn=%lu ref=%x\n",
+ skb->data, mfn, ref);
#else
phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] =
rx->addr >> PAGE_SHIFT;
-#endif
-
-#ifdef GRANT_DEBUG
- printk(KERN_ALERT "#### rx_poll enqueue vdata=%p mfn=%lu ref=%x\n",
- skb->data, mfn, ref);
-#endif
+#endif
+
+
__skb_queue_tail(&rxq, skb);
}
+
/* Some pages are no longer absent... */
balloon_update_driver_allowance(-work_done);
@@ -641,9 +663,9 @@
}
while ((skb = __skb_dequeue(&rxq)) != NULL) {
-#ifdef GRANT_DEBUG
- printk(KERN_ALERT "#### rx_poll dequeue vdata=%p mfn=%lu\n",
- skb->data, virt_to_mfn(skb->data));
+#ifdef CONFIG_XEN_NETDEV_GRANT
+ GDPRINTK("#### rx_poll dequeue vdata=%p mfn=%lu\n",
+ skb->data, virt_to_mfn(skb->data));
dump_packet('d', skb->data, (unsigned long)skb->data);
#endif
/*
@@ -742,7 +764,6 @@
return &np->stats;
}
-
static void network_connect(struct net_device *dev)
{
struct net_private *np;
@@ -782,8 +803,11 @@
tx = &np->tx->ring[requeue_idx++].req;
tx->id = i;
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
- tx->addr = 0; /*(ref << PAGE_SHIFT) |*/
+#ifdef CONFIG_XEN_NETDEV_GRANT
+ gnttab_grant_foreign_access_ref(grant_tx_ref[i], np->backend_id,
+ virt_to_mfn(np->tx_skbs[i]->data),
+ GNTMAP_readonly);
+ tx->addr = grant_tx_ref[i] << PAGE_SHIFT;
#else
tx->addr = virt_to_mfn(skb->data) << PAGE_SHIFT;
#endif
@@ -798,9 +822,20 @@
np->tx->req_prod = requeue_idx;
/* Rebuild the RX buffer freelist and the RX ring itself. */
- for (requeue_idx = 0, i = 1; i <= NETIF_RX_RING_SIZE; i++)
- if ((unsigned long)np->rx_skbs[i] >= __PAGE_OFFSET)
- np->rx->ring[requeue_idx++].req.id = i;
+ for (requeue_idx = 0, i = 1; i <= NETIF_RX_RING_SIZE; i++) {
+ if ((unsigned long)np->rx_skbs[i] >= __PAGE_OFFSET) {
+#ifdef CONFIG_XEN_NETDEV_GRANT
+ /* Reinstate the grant ref so backend can 'donate' mfn to us. */
+ gnttab_grant_foreign_transfer_ref(grant_rx_ref[i], np->backend_id,
+ virt_to_mfn(np->rx_skbs[i]->head)
+ );
+ np->rx->ring[requeue_idx].req.gref = grant_rx_ref[i];
+#endif
+ np->rx->ring[requeue_idx].req.id = i;
+ requeue_idx++;
+ }
+ }
+
wmb();
np->rx->req_prod = requeue_idx;
@@ -896,13 +931,14 @@
/* Initialise {tx,rx}_skbs to be a free chain containing every entry. */
for (i = 0; i <= NETIF_TX_RING_SIZE; i++) {
np->tx_skbs[i] = (void *)((unsigned long) i+1);
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
grant_tx_ref[i] = GRANT_INVALID_REF;
#endif
}
+
for (i = 0; i <= NETIF_RX_RING_SIZE; i++) {
np->rx_skbs[i] = (void *)((unsigned long) i+1);
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
grant_rx_ref[i] = GRANT_INVALID_REF;
#endif
}
@@ -986,10 +1022,8 @@
evtchn_op_t op = { .cmd = EVTCHNOP_alloc_unbound };
int err;
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
info->tx_ring_ref = GRANT_INVALID_REF;
-#endif
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
info->rx_ring_ref = GRANT_INVALID_REF;
#endif
@@ -1009,7 +1043,7 @@
memset(info->rx, 0, PAGE_SIZE);
info->backend_state = BEST_DISCONNECTED;
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
err = gnttab_grant_foreign_access(info->backend_id,
virt_to_mfn(info->tx), 0);
if (err < 0) {
@@ -1017,11 +1051,7 @@
goto out;
}
info->tx_ring_ref = err;
-#else
- info->tx_ring_ref = virt_to_mfn(info->tx);
-#endif
-
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+
err = gnttab_grant_foreign_access(info->backend_id,
virt_to_mfn(info->rx), 0);
if (err < 0) {
@@ -1029,7 +1059,9 @@
goto out;
}
info->rx_ring_ref = err;
+
#else
+ info->tx_ring_ref = virt_to_mfn(info->tx);
info->rx_ring_ref = virt_to_mfn(info->rx);
#endif
@@ -1049,16 +1081,17 @@
if (info->rx)
free_page((unsigned long)info->rx);
info->rx = 0;
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+
+#ifdef CONFIG_XEN_NETDEV_GRANT
if (info->tx_ring_ref != GRANT_INVALID_REF)
gnttab_end_foreign_access(info->tx_ring_ref, 0);
info->tx_ring_ref = GRANT_INVALID_REF;
-#endif
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+
if (info->rx_ring_ref != GRANT_INVALID_REF)
gnttab_end_foreign_access(info->rx_ring_ref, 0);
info->rx_ring_ref = GRANT_INVALID_REF;
#endif
+
return err;
}
@@ -1070,16 +1103,17 @@
if (info->rx)
free_page((unsigned long)info->rx);
info->rx = 0;
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+
+#ifdef CONFIG_XEN_NETDEV_GRANT
if (info->tx_ring_ref != GRANT_INVALID_REF)
gnttab_end_foreign_access(info->tx_ring_ref, 0);
info->tx_ring_ref = GRANT_INVALID_REF;
-#endif
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+
if (info->rx_ring_ref != GRANT_INVALID_REF)
gnttab_end_foreign_access(info->rx_ring_ref, 0);
info->rx_ring_ref = GRANT_INVALID_REF;
#endif
+
unbind_evtchn_from_irqhandler(info->evtchn, info->netdev);
info->evtchn = 0;
}
@@ -1272,25 +1306,25 @@
static int netfront_suspend(struct xenbus_device *dev)
{
- struct net_private *np = dev->data;
- /* Avoid having tx/rx stuff happen until we're ready. */
- unbind_evtchn_from_irqhandler(np->evtchn, np->netdev);
- return 0;
+ struct netfront_info *info = dev->data;
+
+ unregister_xenbus_watch(&info->watch);
+ kfree(info->backend);
+ info->backend = NULL;
+
+ netif_free(info);
+
+ return 0;
}
static int netfront_resume(struct xenbus_device *dev)
{
- struct net_private *np = dev->data;
- /*
- * Connect regardless of whether IFF_UP flag set.
- * Stop bad things from happening until we're back up.
- */
- np->backend_state = BEST_DISCONNECTED;
- memset(np->tx, 0, PAGE_SIZE);
- memset(np->rx, 0, PAGE_SIZE);
-
- // send_interface_connect(np);
- return 0;
+ struct net_private *np = dev->data;
+ int err;
+
+ err = talk_to_backend(dev, np);
+
+ return err;
}
static struct xenbus_driver netfront = {
@@ -1335,32 +1369,31 @@
{
int err = 0;
- if (xen_start_info.flags & SIF_INITDOMAIN)
+ if (xen_start_info->flags & SIF_INITDOMAIN)
return 0;
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
- /* A grant for every ring slot */
+ if ((err = xennet_proc_init()) != 0)
+ return err;
+
+ IPRINTK("Initialising virtual ethernet driver.\n");
+
+#ifdef CONFIG_XEN_NETDEV_GRANT
+ IPRINTK("Using grant tables.\n");
+
+ /* A grant for every tx ring slot */
if (gnttab_alloc_grant_references(NETIF_TX_RING_SIZE,
&gref_tx_head) < 0) {
printk(KERN_ALERT "#### netfront can't alloc tx grant refs\n");
return 1;
}
- printk(KERN_ALERT "Netdev frontend (TX) is using grant tables.\n");
-#endif
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
- /* A grant for every ring slot */
+ /* A grant for every rx ring slot */
if (gnttab_alloc_grant_references(NETIF_RX_RING_SIZE,
&gref_rx_head) < 0) {
printk(KERN_ALERT "#### netfront can't alloc rx grant refs\n");
return 1;
}
- printk(KERN_ALERT "Netdev frontend (RX) is using grant tables.\n");
-#endif
-
- if ((err = xennet_proc_init()) != 0)
- return err;
-
- IPRINTK("Initialising virtual ethernet driver.\n");
+#endif
+
(void)register_inetaddr_notifier(¬ifier_inetdev);
@@ -1373,10 +1406,8 @@
static void netif_exit(void)
{
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
gnttab_free_grant_references(gref_tx_head);
-#endif
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
gnttab_free_grant_references(gref_rx_head);
#endif
}
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c
--- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Fri Sep 9
16:30:54 2005
@@ -63,27 +63,23 @@
"popl %%edi; popl %%esi; popl %%edx; popl %%ecx; popl %%ebx"
: "=a" (ret) : "0" (&hypercall) : "memory" );
#elif defined (__x86_64__)
- __asm__ __volatile__ (
- "movq %5,%%r10; movq %6,%%r8;" TRAP_INSTR
- : "=a" (ret)
- : "a" ((unsigned long)hypercall.op),
- "D" ((unsigned long)hypercall.arg[0]),
- "S" ((unsigned long)hypercall.arg[1]),
- "d" ((unsigned long)hypercall.arg[2]),
- "g" ((unsigned long)hypercall.arg[3]),
- "g" ((unsigned long)hypercall.arg[4])
- : "r11","rcx","r8","r10","memory");
+ {
+ long ign1, ign2, ign3;
+ __asm__ __volatile__ (
+ "movq %8,%%r10; movq %9,%%r8;" TRAP_INSTR
+ : "=a" (ret), "=D" (ign1), "=S" (ign2), "=d" (ign3)
+ : "0" ((unsigned long)hypercall.op),
+ "1" ((unsigned long)hypercall.arg[0]),
+ "2" ((unsigned long)hypercall.arg[1]),
+ "3" ((unsigned long)hypercall.arg[2]),
+ "g" ((unsigned long)hypercall.arg[3]),
+ "g" ((unsigned long)hypercall.arg[4])
+ : "r11","rcx","r8","r10","memory");
+ }
#endif
}
break;
- case IOCTL_PRIVCMD_INITDOMAIN_EVTCHN:
- {
- extern int initdom_ctrlif_domcontroller_port;
- ret = initdom_ctrlif_domcontroller_port;
- }
- break;
-
#if defined(CONFIG_XEN_PRIVILEGED_GUEST)
case IOCTL_PRIVCMD_MMAP:
{
@@ -120,9 +116,9 @@
if ( (msg[j].va + (msg[j].npages<<PAGE_SHIFT)) > vma->vm_end )
return -EINVAL;
- if ( (rc = direct_remap_area_pages(vma->vm_mm,
+ if ( (rc = direct_remap_pfn_range(vma->vm_mm,
msg[j].va&PAGE_MASK,
- msg[j].mfn<<PAGE_SHIFT,
+ msg[j].mfn,
msg[j].npages<<PAGE_SHIFT,
vma->vm_page_prot,
mmapcmd.dom)) < 0 )
@@ -202,8 +198,8 @@
extern int do_xenbus_probe(void*);
unsigned long page;
- if (xen_start_info.store_evtchn != 0) {
- ret = xen_start_info.store_mfn;
+ if (xen_start_info->store_evtchn != 0) {
+ ret = xen_start_info->store_mfn;
break;
}
@@ -219,10 +215,10 @@
SetPageReserved(virt_to_page(page));
/* Initial connect. Setup channel and page. */
- xen_start_info.store_evtchn = data;
- xen_start_info.store_mfn = pfn_to_mfn(virt_to_phys((void *)page) >>
+ xen_start_info->store_evtchn = data;
+ xen_start_info->store_mfn = pfn_to_mfn(virt_to_phys((void *)page) >>
PAGE_SHIFT);
- ret = xen_start_info.store_mfn;
+ ret = xen_start_info->store_mfn;
/* We'll return then this will wait for daemon to answer */
kthread_run(do_xenbus_probe, NULL, "xenbus_probe");
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/usbback/common.h
--- a/linux-2.6-xen-sparse/drivers/xen/usbback/common.h Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/usbback/common.h Fri Sep 9 16:30:54 2005
@@ -12,7 +12,6 @@
#include <asm/io.h>
#include <asm/setup.h>
#include <asm/pgalloc.h>
-#include <asm-xen/ctrl_if.h>
#include <asm-xen/hypervisor.h>
#include <asm-xen/xen-public/io/usbif.h>
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/usbback/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/usbback/interface.c Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/usbback/interface.c Fri Sep 9
16:30:54 2005
@@ -161,8 +161,8 @@
}
prot = __pgprot(_KERNPG_TABLE);
- error = direct_remap_area_pages(&init_mm, VMALLOC_VMADDR(vma->addr),
- shmem_frame<<PAGE_SHIFT, PAGE_SIZE,
+ error = direct_remap_pfn_range(&init_mm, VMALLOC_VMADDR(vma->addr),
+ shmem_frame, PAGE_SIZE,
prot, domid);
if ( error != 0 )
{
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/usbback/usbback.c
--- a/linux-2.6-xen-sparse/drivers/xen/usbback/usbback.c Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/usbback/usbback.c Fri Sep 9
16:30:54 2005
@@ -1029,8 +1029,8 @@
int i;
struct page *page;
- if ( !(xen_start_info.flags & SIF_INITDOMAIN) &&
- !(xen_start_info.flags & SIF_USB_BE_DOMAIN) )
+ if ( !(xen_start_info->flags & SIF_INITDOMAIN) &&
+ !(xen_start_info->flags & SIF_USB_BE_DOMAIN) )
return 0;
page = balloon_alloc_empty_page_range(MMAP_PAGES);
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/usbfront/usbfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/usbfront/usbfront.c Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/usbfront/usbfront.c Fri Sep 9
16:30:54 2005
@@ -70,7 +70,6 @@
#include "../../../../../drivers/usb/hcd.h"
#include <asm-xen/xen-public/io/usbif.h>
-#include <asm/ctrl_if.h>
#include <asm/xen-public/io/domain_controller.h>
/*
@@ -1675,8 +1674,8 @@
{
int retval = -ENOMEM, i;
- if ( (xen_start_info.flags & SIF_INITDOMAIN)
- || (xen_start_info.flags & SIF_USB_BE_DOMAIN) )
+ if ( (xen_start_info->flags & SIF_INITDOMAIN) ||
+ (xen_start_info->flags & SIF_USB_BE_DOMAIN) )
return 0;
info(DRIVER_DESC " " DRIVER_VERSION);
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/xenbus/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/Makefile Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/Makefile Fri Sep 9 16:30:54 2005
@@ -4,3 +4,4 @@
xenbus-objs += xenbus_comms.o
xenbus-objs += xenbus_xs.o
xenbus-objs += xenbus_probe.o
+xenbus-objs += xenbus_dev.o
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Fri Sep 9
16:30:54 2005
@@ -48,12 +48,12 @@
static inline struct ringbuf_head *outbuf(void)
{
- return mfn_to_virt(xen_start_info.store_mfn);
+ return mfn_to_virt(xen_start_info->store_mfn);
}
static inline struct ringbuf_head *inbuf(void)
{
- return mfn_to_virt(xen_start_info.store_mfn) + PAGE_SIZE/2;
+ return mfn_to_virt(xen_start_info->store_mfn) + PAGE_SIZE/2;
}
static irqreturn_t wake_waiting(int irq, void *unused, struct pt_regs *regs)
@@ -145,7 +145,7 @@
data += avail;
len -= avail;
update_output_chunk(out, avail);
- notify_via_evtchn(xen_start_info.store_evtchn);
+ notify_via_evtchn(xen_start_info->store_evtchn);
} while (len != 0);
return 0;
@@ -190,7 +190,7 @@
pr_debug("Finished read of %i bytes (%i to go)\n", avail, len);
/* If it was full, tell them we've taken some. */
if (was_full)
- notify_via_evtchn(xen_start_info.store_evtchn);
+ notify_via_evtchn(xen_start_info->store_evtchn);
}
/* If we left something, wake watch thread to deal with it. */
@@ -205,20 +205,20 @@
{
int err;
- if (!xen_start_info.store_evtchn)
+ if (!xen_start_info->store_evtchn)
return 0;
err = bind_evtchn_to_irqhandler(
- xen_start_info.store_evtchn, wake_waiting,
+ xen_start_info->store_evtchn, wake_waiting,
0, "xenbus", &xb_waitq);
if (err) {
printk(KERN_ERR "XENBUS request irq failed %i\n", err);
- unbind_evtchn_from_irq(xen_start_info.store_evtchn);
+ unbind_evtchn_from_irq(xen_start_info->store_evtchn);
return err;
}
/* FIXME zero out page -- domain builder should probably do this*/
- memset(mfn_to_virt(xen_start_info.store_mfn), 0, PAGE_SIZE);
+ memset(mfn_to_virt(xen_start_info->store_mfn), 0, PAGE_SIZE);
return 0;
}
@@ -226,8 +226,8 @@
void xb_suspend_comms(void)
{
- if (!xen_start_info.store_evtchn)
+ if (!xen_start_info->store_evtchn)
return;
- unbind_evtchn_from_irqhandler(xen_start_info.store_evtchn, &xb_waitq);
-}
+ unbind_evtchn_from_irqhandler(xen_start_info->store_evtchn, &xb_waitq);
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Fri Sep 9
16:30:54 2005
@@ -147,6 +147,39 @@
return 0;
}
+static int xenbus_hotplug_backend(struct device *dev, char **envp,
+ int num_envp, char *buffer, int buffer_size)
+{
+ struct xenbus_device *xdev;
+ int i = 0;
+ int length = 0;
+
+ if (dev == NULL)
+ return -ENODEV;
+
+ xdev = to_xenbus_device(dev);
+ if (xdev == NULL)
+ return -ENODEV;
+
+ /* stuff we want to pass to /sbin/hotplug */
+ add_hotplug_env_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "XENBUS_TYPE=%s", xdev->devicetype);
+
+ /* terminate, set to next free slot, shrink available space */
+ envp[i] = NULL;
+ envp = &envp[i];
+ num_envp -= i;
+ buffer = &buffer[length];
+ buffer_size -= length;
+
+ if (dev->driver && to_xenbus_driver(dev->driver)->hotplug)
+ return to_xenbus_driver(dev->driver)->hotplug
+ (xdev, envp, num_envp, buffer, buffer_size);
+
+ return 0;
+}
+
static int xenbus_probe_backend(const char *type, const char *uuid);
static struct xen_bus_type xenbus_backend = {
.root = "backend",
@@ -156,6 +189,7 @@
.bus = {
.name = "xen-backend",
.match = xenbus_match,
+ .hotplug = xenbus_hotplug_backend,
},
.dev = {
.bus_id = "xen-backend",
@@ -209,6 +243,7 @@
{
return xenbus_register_driver(drv, &xenbus_frontend);
}
+EXPORT_SYMBOL(xenbus_register_device);
int xenbus_register_backend(struct xenbus_driver *drv)
{
@@ -586,7 +621,7 @@
down(&xenbus_lock);
- if (xen_start_info.store_evtchn) {
+ if (xen_start_info->store_evtchn) {
ret = nb->notifier_call(nb, 0, NULL);
} else {
notifier_chain_register(&xenstore_chain, nb);
@@ -612,7 +647,7 @@
int err = 0;
/* Initialize xenstore comms unless already done. */
- printk("store_evtchn = %i\n", xen_start_info.store_evtchn);
+ printk("store_evtchn = %i\n", xen_start_info->store_evtchn);
err = xs_init();
if (err) {
printk("XENBUS: Error initializing xenstore comms:"
@@ -640,7 +675,7 @@
device_register(&xenbus_frontend.dev);
device_register(&xenbus_backend.dev);
- if (!xen_start_info.store_evtchn)
+ if (!xen_start_info->store_evtchn)
return 0;
do_xenbus_probe(NULL);
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Fri Sep 9
16:30:54 2005
@@ -45,7 +45,9 @@
static char printf_buffer[4096];
static LIST_HEAD(watches);
+
DECLARE_MUTEX(xenbus_lock);
+EXPORT_SYMBOL(xenbus_lock);
static int get_error(const char *errorstring)
{
@@ -104,10 +106,10 @@
}
/* Send message to xs, get kmalloc'ed reply. ERR_PTR() on error. */
-static void *xs_talkv(enum xsd_sockmsg_type type,
- const struct kvec *iovec,
- unsigned int num_vecs,
- unsigned int *len)
+void *xs_talkv(enum xsd_sockmsg_type type,
+ const struct kvec *iovec,
+ unsigned int num_vecs,
+ unsigned int *len)
{
struct xsd_sockmsg msg;
void *ret = NULL;
@@ -224,6 +226,7 @@
ret[(*num)++] = p;
return ret;
}
+EXPORT_SYMBOL(xenbus_directory);
/* Check if a path exists. Return 1 if it does. */
int xenbus_exists(const char *dir, const char *node)
@@ -237,6 +240,7 @@
kfree(d);
return 1;
}
+EXPORT_SYMBOL(xenbus_exists);
/* Get the value of a single file.
* Returns a kmalloced value: call free() on it after use.
@@ -246,6 +250,7 @@
{
return xs_single(XS_READ, join(dir, node), len);
}
+EXPORT_SYMBOL(xenbus_read);
/* Write the value of a single file.
* Returns -err on failure. createflags can be 0, O_CREAT, or O_CREAT|O_EXCL.
@@ -276,18 +281,21 @@
return xs_error(xs_talkv(XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL));
}
+EXPORT_SYMBOL(xenbus_write);
/* Create a new directory. */
int xenbus_mkdir(const char *dir, const char *node)
{
return xs_error(xs_single(XS_MKDIR, join(dir, node), NULL));
}
+EXPORT_SYMBOL(xenbus_mkdir);
/* Destroy a file or directory (directories must be empty). */
int xenbus_rm(const char *dir, const char *node)
{
return xs_error(xs_single(XS_RM, join(dir, node), NULL));
}
+EXPORT_SYMBOL(xenbus_rm);
/* Start a transaction: changes by others will not be seen during this
* transaction, and changes will not be visible to others until end.
@@ -298,6 +306,7 @@
{
return xs_error(xs_single(XS_TRANSACTION_START, subtree, NULL));
}
+EXPORT_SYMBOL(xenbus_transaction_start);
/* End a transaction.
* If abandon is true, transaction is discarded instead of committed.
@@ -312,6 +321,7 @@
strcpy(abortstr, "T");
return xs_error(xs_single(XS_TRANSACTION_END, abortstr, NULL));
}
+EXPORT_SYMBOL(xenbus_transaction_end);
/* Single read and scanf: returns -errno or num scanned. */
int xenbus_scanf(const char *dir, const char *node, const char *fmt, ...)
@@ -333,6 +343,7 @@
return -ERANGE;
return ret;
}
+EXPORT_SYMBOL(xenbus_scanf);
/* Single printf and write: returns -errno or 0. */
int xenbus_printf(const char *dir, const char *node, const char *fmt, ...)
@@ -348,6 +359,7 @@
BUG_ON(ret > sizeof(printf_buffer)-1);
return xenbus_write(dir, node, printf_buffer, O_CREAT);
}
+EXPORT_SYMBOL(xenbus_printf);
/* Report a (negative) errno into the store, with explanation. */
void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...)
@@ -369,6 +381,7 @@
printk("xenbus: failed to write error node for %s (%s)\n",
dev->nodename, printf_buffer);
}
+EXPORT_SYMBOL(xenbus_dev_error);
/* Clear any error. */
void xenbus_dev_ok(struct xenbus_device *dev)
@@ -381,6 +394,7 @@
dev->has_error = 0;
}
}
+EXPORT_SYMBOL(xenbus_dev_ok);
/* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
int xenbus_gather(const char *dir, ...)
@@ -410,6 +424,7 @@
va_end(ap);
return ret;
}
+EXPORT_SYMBOL(xenbus_gather);
static int xs_watch(const char *path, const char *token)
{
@@ -482,6 +497,7 @@
list_add(&watch->list, &watches);
return err;
}
+EXPORT_SYMBOL(register_xenbus_watch);
void unregister_xenbus_watch(struct xenbus_watch *watch)
{
@@ -499,6 +515,7 @@
"XENBUS Failed to release watch %s: %i\n",
watch->node, err);
}
+EXPORT_SYMBOL(unregister_xenbus_watch);
/* Re-register callbacks to all watches. */
void reregister_xenbus_watches(void)
@@ -540,7 +557,7 @@
BUG_ON(!w);
w->callback(w, node);
kfree(node);
- } else
+ } else if (node)
printk(KERN_WARNING "XENBUS xs_read_watch: %li\n",
PTR_ERR(node));
up(&xenbus_lock);
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h Fri Sep 9
16:30:54 2005
@@ -29,551 +29,360 @@
#ifndef __HYPERCALL_H__
#define __HYPERCALL_H__
+
#include <asm-xen/xen-public/xen.h>
-/*
- * Assembler stubs for hyper-calls.
- */
+#define _hypercall0(type, name) \
+({ \
+ long __res; \
+ asm volatile ( \
+ TRAP_INSTR \
+ : "=a" (__res) \
+ : "0" (__HYPERVISOR_##name) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall1(type, name, a1) \
+({ \
+ long __res, __ign1; \
+ asm volatile ( \
+ TRAP_INSTR \
+ : "=a" (__res), "=b" (__ign1) \
+ : "0" (__HYPERVISOR_##name), "1" ((long)(a1)) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall2(type, name, a1, a2) \
+({ \
+ long __res, __ign1, __ign2; \
+ asm volatile ( \
+ TRAP_INSTR \
+ : "=a" (__res), "=b" (__ign1), "=c" (__ign2) \
+ : "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \
+ "2" ((long)(a2)) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall3(type, name, a1, a2, a3) \
+({ \
+ long __res, __ign1, __ign2, __ign3; \
+ asm volatile ( \
+ TRAP_INSTR \
+ : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
+ "=d" (__ign3) \
+ : "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \
+ "2" ((long)(a2)), "3" ((long)(a3)) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall4(type, name, a1, a2, a3, a4) \
+({ \
+ long __res, __ign1, __ign2, __ign3, __ign4; \
+ asm volatile ( \
+ TRAP_INSTR \
+ : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
+ "=d" (__ign3), "=S" (__ign4) \
+ : "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \
+ "2" ((long)(a2)), "3" ((long)(a3)), \
+ "4" ((long)(a4)) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall5(type, name, a1, a2, a3, a4, a5) \
+({ \
+ long __res, __ign1, __ign2, __ign3, __ign4, __ign5; \
+ asm volatile ( \
+ TRAP_INSTR \
+ : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
+ "=d" (__ign3), "=S" (__ign4), "=D" (__ign5) \
+ : "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \
+ "2" ((long)(a2)), "3" ((long)(a3)), \
+ "4" ((long)(a4)), "5" ((long)(a5)) \
+ : "memory" ); \
+ (type)__res; \
+})
static inline int
HYPERVISOR_set_trap_table(
- trap_info_t *table)
-{
- int ret;
- unsigned long ignore;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ignore)
- : "0" (__HYPERVISOR_set_trap_table), "1" (table)
- : "memory" );
-
- return ret;
+ trap_info_t *table)
+{
+ return _hypercall1(int, set_trap_table, table);
}
static inline int
HYPERVISOR_mmu_update(
- mmu_update_t *req, int count, int *success_count, domid_t domid)
-{
- int ret;
- unsigned long ign1, ign2, ign3, ign4;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
- : "0" (__HYPERVISOR_mmu_update), "1" (req), "2" (count),
- "3" (success_count), "4" (domid)
- : "memory" );
-
- return ret;
+ mmu_update_t *req, int count, int *success_count, domid_t domid)
+{
+ return _hypercall4(int, mmu_update, req, count, success_count, domid);
}
static inline int
HYPERVISOR_mmuext_op(
- struct mmuext_op *op, int count, int *success_count, domid_t domid)
-{
- int ret;
- unsigned long ign1, ign2, ign3, ign4;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
- : "0" (__HYPERVISOR_mmuext_op), "1" (op), "2" (count),
- "3" (success_count), "4" (domid)
- : "memory" );
-
- return ret;
+ struct mmuext_op *op, int count, int *success_count, domid_t domid)
+{
+ return _hypercall4(int, mmuext_op, op, count, success_count, domid);
}
static inline int
HYPERVISOR_set_gdt(
- unsigned long *frame_list, int entries)
-{
- int ret;
- unsigned long ign1, ign2;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2)
- : "0" (__HYPERVISOR_set_gdt), "1" (frame_list), "2" (entries)
- : "memory" );
-
-
- return ret;
+ unsigned long *frame_list, int entries)
+{
+ return _hypercall2(int, set_gdt, frame_list, entries);
}
static inline int
HYPERVISOR_stack_switch(
- unsigned long ss, unsigned long esp)
-{
- int ret;
- unsigned long ign1, ign2;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2)
- : "0" (__HYPERVISOR_stack_switch), "1" (ss), "2" (esp)
- : "memory" );
-
- return ret;
+ unsigned long ss, unsigned long esp)
+{
+ return _hypercall2(int, stack_switch, ss, esp);
}
static inline int
HYPERVISOR_set_callbacks(
- unsigned long event_selector, unsigned long event_address,
- unsigned long failsafe_selector, unsigned long failsafe_address)
-{
- int ret;
- unsigned long ign1, ign2, ign3, ign4;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
- : "0" (__HYPERVISOR_set_callbacks), "1" (event_selector),
- "2" (event_address), "3" (failsafe_selector), "4" (failsafe_address)
- : "memory" );
-
- return ret;
+ unsigned long event_selector, unsigned long event_address,
+ unsigned long failsafe_selector, unsigned long failsafe_address)
+{
+ return _hypercall4(int, set_callbacks,
+ event_selector, event_address,
+ failsafe_selector, failsafe_address);
}
static inline int
HYPERVISOR_fpu_taskswitch(
- int set)
-{
- int ret;
- unsigned long ign;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign)
- : "0" (__HYPERVISOR_fpu_taskswitch), "1" (set)
- : "memory" );
-
- return ret;
+ int set)
+{
+ return _hypercall1(int, fpu_taskswitch, set);
}
static inline int
HYPERVISOR_yield(
- void)
-{
- int ret;
- unsigned long ign;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign)
- : "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_yield)
- : "memory", "ecx" );
-
- return ret;
+ void)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_yield, 0);
}
static inline int
HYPERVISOR_block(
- void)
-{
- int ret;
- unsigned long ign1;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1)
- : "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_block)
- : "memory", "ecx" );
-
- return ret;
+ void)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_block, 0);
}
static inline int
HYPERVISOR_shutdown(
- void)
-{
- int ret;
- unsigned long ign1;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1)
- : "0" (__HYPERVISOR_sched_op),
- "1" (SCHEDOP_shutdown | (SHUTDOWN_poweroff << SCHEDOP_reasonshift))
- : "memory", "ecx" );
-
- return ret;
+ void)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_shutdown |
+ (SHUTDOWN_poweroff << SCHEDOP_reasonshift), 0);
}
static inline int
HYPERVISOR_reboot(
- void)
-{
- int ret;
- unsigned long ign1;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1)
- : "0" (__HYPERVISOR_sched_op),
- "1" (SCHEDOP_shutdown | (SHUTDOWN_reboot << SCHEDOP_reasonshift))
- : "memory", "ecx" );
-
- return ret;
-}
-
-static inline int
-HYPERVISOR_suspend(
- unsigned long srec)
-{
- int ret;
- unsigned long ign1, ign2;
-
- /* NB. On suspend, control software expects a suspend record in %esi. */
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=S" (ign2)
- : "0" (__HYPERVISOR_sched_op),
- "b" (SCHEDOP_shutdown | (SHUTDOWN_suspend << SCHEDOP_reasonshift)),
- "S" (srec) : "memory", "ecx");
-
- return ret;
+ void)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_shutdown |
+ (SHUTDOWN_reboot << SCHEDOP_reasonshift), 0);
}
static inline int
HYPERVISOR_crash(
- void)
-{
- int ret;
- unsigned long ign1;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1)
- : "0" (__HYPERVISOR_sched_op),
- "1" (SCHEDOP_shutdown | (SHUTDOWN_crash << SCHEDOP_reasonshift))
- : "memory", "ecx" );
-
- return ret;
+ void)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_shutdown |
+ (SHUTDOWN_crash << SCHEDOP_reasonshift), 0);
}
static inline long
HYPERVISOR_set_timer_op(
- u64 timeout)
-{
- int ret;
- unsigned long timeout_hi = (unsigned long)(timeout>>32);
- unsigned long timeout_lo = (unsigned long)timeout;
- unsigned long ign1, ign2;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2)
- : "0" (__HYPERVISOR_set_timer_op), "b" (timeout_lo), "c" (timeout_hi)
- : "memory");
-
- return ret;
+ u64 timeout)
+{
+ unsigned long timeout_hi = (unsigned long)(timeout>>32);
+ unsigned long timeout_lo = (unsigned long)timeout;
+ return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
}
static inline int
HYPERVISOR_dom0_op(
- dom0_op_t *dom0_op)
-{
- int ret;
- unsigned long ign1;
-
- dom0_op->interface_version = DOM0_INTERFACE_VERSION;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1)
- : "0" (__HYPERVISOR_dom0_op), "1" (dom0_op)
- : "memory");
-
- return ret;
+ dom0_op_t *dom0_op)
+{
+ dom0_op->interface_version = DOM0_INTERFACE_VERSION;
+ return _hypercall1(int, dom0_op, dom0_op);
}
static inline int
HYPERVISOR_set_debugreg(
- int reg, unsigned long value)
-{
- int ret;
- unsigned long ign1, ign2;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2)
- : "0" (__HYPERVISOR_set_debugreg), "1" (reg), "2" (value)
- : "memory" );
-
- return ret;
+ int reg, unsigned long value)
+{
+ return _hypercall2(int, set_debugreg, reg, value);
}
static inline unsigned long
HYPERVISOR_get_debugreg(
- int reg)
-{
- unsigned long ret;
- unsigned long ign;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign)
- : "0" (__HYPERVISOR_get_debugreg), "1" (reg)
- : "memory" );
-
- return ret;
+ int reg)
+{
+ return _hypercall1(unsigned long, get_debugreg, reg);
}
static inline int
HYPERVISOR_update_descriptor(
- u64 ma, u64 desc)
-{
- int ret;
- unsigned long ign1, ign2, ign3, ign4;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
- : "0" (__HYPERVISOR_update_descriptor),
- "1" ((unsigned long)ma), "2" ((unsigned long)(ma>>32)),
- "3" ((unsigned long)desc), "4" ((unsigned long)(desc>>32))
- : "memory" );
-
- return ret;
-}
-
-static inline int
-HYPERVISOR_dom_mem_op(
- unsigned int op, unsigned long *extent_list,
- unsigned long nr_extents, unsigned int extent_order)
-{
- int ret;
- unsigned long ign1, ign2, ign3, ign4, ign5;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4),
- "=D" (ign5)
- : "0" (__HYPERVISOR_dom_mem_op), "1" (op), "2" (extent_list),
- "3" (nr_extents), "4" (extent_order), "5" (DOMID_SELF)
- : "memory" );
-
- return ret;
+ u64 ma, u64 desc)
+{
+ return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32);
+}
+
+static inline int
+HYPERVISOR_memory_op(
+ unsigned int cmd, void *arg)
+{
+ return _hypercall2(int, memory_op, cmd, arg);
}
static inline int
HYPERVISOR_multicall(
- void *call_list, int nr_calls)
-{
- int ret;
- unsigned long ign1, ign2;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2)
- : "0" (__HYPERVISOR_multicall), "1" (call_list), "2" (nr_calls)
- : "memory" );
-
- return ret;
+ void *call_list, int nr_calls)
+{
+ return _hypercall2(int, multicall, call_list, nr_calls);
}
static inline int
HYPERVISOR_update_va_mapping(
- unsigned long va, pte_t new_val, unsigned long flags)
-{
- int ret;
- unsigned long ign1, ign2, ign3, ign4;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
- : "0" (__HYPERVISOR_update_va_mapping),
- "1" (va), "2" ((new_val).pte_low),
+ unsigned long va, pte_t new_val, unsigned long flags)
+{
+ unsigned long pte_hi = 0;
#ifdef CONFIG_X86_PAE
- "3" ((new_val).pte_high),
-#else
- "3" (0),
+ pte_hi = new_val.pte_high;
#endif
- "4" (flags)
- : "memory" );
-
- return ret;
+ return _hypercall4(int, update_va_mapping, va,
+ new_val.pte_low, pte_hi, flags);
}
static inline int
HYPERVISOR_event_channel_op(
- void *op)
-{
- int ret;
- unsigned long ignore;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ignore)
- : "0" (__HYPERVISOR_event_channel_op), "1" (op)
- : "memory" );
-
- return ret;
+ void *op)
+{
+ return _hypercall1(int, event_channel_op, op);
}
static inline int
HYPERVISOR_xen_version(
- int cmd)
-{
- int ret;
- unsigned long ignore;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ignore)
- : "0" (__HYPERVISOR_xen_version), "1" (cmd)
- : "memory" );
-
- return ret;
+ int cmd)
+{
+ return _hypercall1(int, xen_version, cmd);
}
static inline int
HYPERVISOR_console_io(
- int cmd, int count, char *str)
-{
- int ret;
- unsigned long ign1, ign2, ign3;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
- : "0" (__HYPERVISOR_console_io), "1" (cmd), "2" (count), "3" (str)
- : "memory" );
-
- return ret;
+ int cmd, int count, char *str)
+{
+ return _hypercall3(int, console_io, cmd, count, str);
}
static inline int
HYPERVISOR_physdev_op(
- void *physdev_op)
-{
- int ret;
- unsigned long ign;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign)
- : "0" (__HYPERVISOR_physdev_op), "1" (physdev_op)
- : "memory" );
-
- return ret;
+ void *physdev_op)
+{
+ return _hypercall1(int, physdev_op, physdev_op);
}
static inline int
HYPERVISOR_grant_table_op(
- unsigned int cmd, void *uop, unsigned int count)
-{
- int ret;
- unsigned long ign1, ign2, ign3;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
- : "0" (__HYPERVISOR_grant_table_op), "1" (cmd), "2" (uop), "3" (count)
- : "memory" );
-
- return ret;
+ unsigned int cmd, void *uop, unsigned int count)
+{
+ return _hypercall3(int, grant_table_op, cmd, uop, count);
}
static inline int
HYPERVISOR_update_va_mapping_otherdomain(
- unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
-{
- int ret;
- unsigned long ign1, ign2, ign3, ign4, ign5;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3),
- "=S" (ign4), "=D" (ign5)
- : "0" (__HYPERVISOR_update_va_mapping_otherdomain),
- "1" (va), "2" ((new_val).pte_low),
+ unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
+{
+ unsigned long pte_hi = 0;
#ifdef CONFIG_X86_PAE
- "3" ((new_val).pte_high),
-#else
- "3" (0),
+ pte_hi = new_val.pte_high;
#endif
- "4" (flags), "5" (domid) :
- "memory" );
-
- return ret;
+ return _hypercall5(int, update_va_mapping_otherdomain, va,
+ new_val.pte_low, pte_hi, flags, domid);
}
static inline int
HYPERVISOR_vm_assist(
- unsigned int cmd, unsigned int type)
-{
- int ret;
- unsigned long ign1, ign2;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2)
- : "0" (__HYPERVISOR_vm_assist), "1" (cmd), "2" (type)
- : "memory" );
-
- return ret;
+ unsigned int cmd, unsigned int type)
+{
+ return _hypercall2(int, vm_assist, cmd, type);
}
static inline int
HYPERVISOR_boot_vcpu(
- unsigned long vcpu, vcpu_guest_context_t *ctxt)
-{
- int ret;
- unsigned long ign1, ign2;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2)
- : "0" (__HYPERVISOR_boot_vcpu), "1" (vcpu), "2" (ctxt)
- : "memory");
-
- return ret;
+ unsigned long vcpu, vcpu_guest_context_t *ctxt)
+{
+ return _hypercall2(int, boot_vcpu, vcpu, ctxt);
+}
+
+static inline int
+HYPERVISOR_vcpu_up(
+ int vcpu)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_vcpu_up |
+ (vcpu << SCHEDOP_vcpushift), 0);
+}
+
+static inline int
+HYPERVISOR_vcpu_pickle(
+ int vcpu, vcpu_guest_context_t *ctxt)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_vcpu_pickle |
+ (vcpu << SCHEDOP_vcpushift), ctxt);
+}
+
+static inline int
+HYPERVISOR_suspend(
+ unsigned long srec)
+{
+ int ret;
+ unsigned long ign1, ign2;
+
+ /* On suspend, control software expects a suspend record in %esi. */
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=S" (ign2)
+ : "0" (__HYPERVISOR_sched_op),
+ "1" (SCHEDOP_shutdown | (SHUTDOWN_suspend <<
+ SCHEDOP_reasonshift)),
+ "2" (srec) : "memory", "ecx");
+
+ return ret;
}
static inline int
HYPERVISOR_vcpu_down(
- int vcpu)
-{
- int ret;
- unsigned long ign1;
- /* Yes, I really do want to clobber edx here: when we resume a
- vcpu after unpickling a multi-processor domain, it returns
- here, but clobbers all of the call clobbered registers. */
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1)
- : "0" (__HYPERVISOR_sched_op),
- "1" (SCHEDOP_vcpu_down | (vcpu << SCHEDOP_vcpushift))
- : "memory", "ecx", "edx" );
-
- return ret;
-}
-
-static inline int
-HYPERVISOR_vcpu_up(
- int vcpu)
-{
- int ret;
- unsigned long ign1;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1)
- : "0" (__HYPERVISOR_sched_op),
- "1" (SCHEDOP_vcpu_up | (vcpu << SCHEDOP_vcpushift))
- : "memory", "ecx" );
-
- return ret;
-}
-
-static inline int
-HYPERVISOR_vcpu_pickle(
- int vcpu, vcpu_guest_context_t *ctxt)
-{
- int ret;
- unsigned long ign1, ign2;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1), "=c" (ign2)
- : "0" (__HYPERVISOR_sched_op),
- "1" (SCHEDOP_vcpu_pickle | (vcpu << SCHEDOP_vcpushift)),
- "2" (ctxt)
- : "memory" );
-
- return ret;
+ int vcpu)
+{
+ int ret;
+ unsigned long ign1;
+ /* Yes, I really do want to clobber edx here: when we resume a
+ vcpu after unpickling a multi-processor domain, it returns
+ here, but clobbers all of the call clobbered registers. */
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1)
+ : "0" (__HYPERVISOR_sched_op),
+ "1" (SCHEDOP_vcpu_down | (vcpu << SCHEDOP_vcpushift))
+ : "memory", "ecx", "edx" );
+ return ret;
}
#endif /* __HYPERCALL_H__ */
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h
Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h
Fri Sep 9 16:30:54 2005
@@ -8,7 +8,7 @@
static char * __init machine_specific_memory_setup(void)
{
- unsigned long max_pfn = xen_start_info.nr_pages;
+ unsigned long max_pfn = xen_start_info->nr_pages;
e820.nr_map = 0;
add_memory_region(0, PFN_PHYS(max_pfn), E820_RAM);
@@ -23,7 +23,7 @@
clear_bit(X86_FEATURE_PSE, c->x86_capability);
clear_bit(X86_FEATURE_PGE, c->x86_capability);
clear_bit(X86_FEATURE_SEP, c->x86_capability);
- if (!(xen_start_info.flags & SIF_PRIVILEGED))
+ if (!(xen_start_info->flags & SIF_PRIVILEGED))
clear_bit(X86_FEATURE_MTRR, c->x86_capability);
}
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/include/asm-xen/asm-i386/mmu_context.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mmu_context.h Thu Sep
8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mmu_context.h Fri Sep
9 16:30:54 2005
@@ -35,9 +35,9 @@
* happen before reload of cr3/ldt (i.e., not in __switch_to).
*/
asm volatile ( "mov %%fs,%0 ; mov %%gs,%1"
- : "=m" (*(int *)¤t->thread.fs),
- "=m" (*(int *)¤t->thread.gs));
- asm volatile ( "mov %0,%%fs ; mov %0,%%gs"
+ : "=m" (current->thread.fs),
+ "=m" (current->thread.gs));
+ asm volatile ( "movl %0,%%fs ; movl %0,%%gs"
: : "r" (0) );
}
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/include/asm-xen/asm-i386/page.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/page.h Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/page.h Fri Sep 9
16:30:54 2005
@@ -60,14 +60,14 @@
#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
/**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
-#define INVALID_P2M_ENTRY (~0U)
-#define FOREIGN_FRAME(m) ((m) | 0x80000000U)
-extern unsigned int *phys_to_machine_mapping;
+#define INVALID_P2M_ENTRY (~0UL)
+#define FOREIGN_FRAME(m) ((m) | (1UL<<31))
+extern unsigned long *phys_to_machine_mapping;
#define pfn_to_mfn(pfn) \
-((unsigned long)phys_to_machine_mapping[(unsigned int)(pfn)] & 0x7FFFFFFFUL)
+(phys_to_machine_mapping[(unsigned int)(pfn)] & ~(1UL<<31))
static inline unsigned long mfn_to_pfn(unsigned long mfn)
{
- unsigned int pfn;
+ unsigned long pfn;
/*
* The array access can fail (e.g., device space beyond end of RAM).
@@ -83,7 +83,7 @@
".previous"
: "=r" (pfn) : "m" (machine_to_phys_mapping[mfn]) );
- return (unsigned long)pfn;
+ return pfn;
}
/* Definitions for machine and pseudophysical addresses. */
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/include/asm-xen/asm-i386/pci.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pci.h Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pci.h Fri Sep 9
16:30:54 2005
@@ -43,8 +43,32 @@
struct pci_dev;
+#ifdef CONFIG_SWIOTLB
+
+
/* On Xen we use SWIOTLB instead of blk-specific bounce buffers. */
#define PCI_DMA_BUS_IS_PHYS (0)
+
+#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \
+ dma_addr_t ADDR_NAME;
+#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \
+ __u32 LEN_NAME;
+#define pci_unmap_addr(PTR, ADDR_NAME) \
+ ((PTR)->ADDR_NAME)
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) \
+ (((PTR)->ADDR_NAME) = (VAL))
+#define pci_unmap_len(PTR, LEN_NAME) \
+ ((PTR)->LEN_NAME)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL) \
+ (((PTR)->LEN_NAME) = (VAL))
+
+#else
+
+/* The PCI address space does equal the physical memory
+ * address space. The networking and block device layers use
+ * this boolean for bounce buffer decisions.
+ */
+#define PCI_DMA_BUS_IS_PHYS (1)
/* pci_unmap_{page,single} is a nop so... */
#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
@@ -53,6 +77,8 @@
#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0)
#define pci_unmap_len(PTR, LEN_NAME) (0)
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
+
+#endif
/* This is always fine. */
#define pci_dac_dma_supported(pci_dev, mask) (1)
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h Fri Sep 9
16:30:54 2005
@@ -460,9 +460,9 @@
#define kern_addr_valid(addr) (1)
#endif /* !CONFIG_DISCONTIGMEM */
-int direct_remap_area_pages(struct mm_struct *mm,
+int direct_remap_pfn_range(struct mm_struct *mm,
unsigned long address,
- unsigned long machine_addr,
+ unsigned long mfn,
unsigned long size,
pgprot_t prot,
domid_t domid);
@@ -474,10 +474,10 @@
unsigned long size);
#define io_remap_page_range(vma,from,phys,size,prot) \
-direct_remap_area_pages(vma->vm_mm,from,phys,size,prot,DOMID_IO)
+direct_remap_pfn_range(vma->vm_mm,from,phys>>PAGE_SHIFT,size,prot,DOMID_IO)
#define io_remap_pfn_range(vma,from,pfn,size,prot) \
-direct_remap_area_pages(vma->vm_mm,from,pfn<<PAGE_SHIFT,size,prot,DOMID_IO)
+direct_remap_pfn_range(vma->vm_mm,from,pfn,size,prot,DOMID_IO)
#define MK_IOSPACE_PFN(space, pfn) (pfn)
#define GET_IOSPACE(pfn) 0
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/include/asm-xen/asm-i386/processor.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/processor.h Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/processor.h Fri Sep 9
16:30:54 2005
@@ -517,8 +517,8 @@
* This special macro can be used to load a debugging register
*/
#define loaddebug(thread,register) \
- HYPERVISOR_set_debugreg((register), \
- ((thread)->debugreg[register]))
+ HYPERVISOR_set_debugreg((register), \
+ ((thread)->debugreg[register]))
/* Forward declaration, a strange C thing */
struct task_struct;
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/include/asm-xen/asm-i386/setup.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/setup.h Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/setup.h Fri Sep 9
16:30:54 2005
@@ -53,8 +53,8 @@
#define AUX_DEVICE_INFO (*(unsigned char *) (PARAM+0x1FF))
#define LOADER_TYPE (*(unsigned char *) (PARAM+0x210))
#define KERNEL_START (*(unsigned long *) (PARAM+0x214))
-#define INITRD_START (__pa(xen_start_info.mod_start))
-#define INITRD_SIZE (xen_start_info.mod_len)
+#define INITRD_START (__pa(xen_start_info->mod_start))
+#define INITRD_SIZE (xen_start_info->mod_len)
#define EDID_INFO (*(struct edid_info *) (PARAM+0x440))
#define EDD_NR (*(unsigned char *) (PARAM+EDDNR))
#define EDD_MBR_SIG_NR (*(unsigned char *) (PARAM+EDD_MBR_SIG_NR_BUF))
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/include/asm-xen/asm-i386/system.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/system.h Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/system.h Fri Sep 9
16:30:54 2005
@@ -561,8 +561,14 @@
#define local_irq_disable() __cli()
#define local_irq_enable() __sti()
+/* Don't use smp_processor_id: this is called in debug versions of that fn. */
+#ifdef CONFIG_SMP
#define irqs_disabled() \
- HYPERVISOR_shared_info->vcpu_data[smp_processor_id()].evtchn_upcall_mask
+ HYPERVISOR_shared_info->vcpu_data[__smp_processor_id()].evtchn_upcall_mask
+#else
+#define irqs_disabled() \
+ HYPERVISOR_shared_info->vcpu_data[0].evtchn_upcall_mask
+#endif
/*
* disable hlt during certain critical i/o operations
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/bootsetup.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/bootsetup.h Thu Sep
8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/bootsetup.h Fri Sep
9 16:30:54 2005
@@ -25,8 +25,8 @@
#define LOADER_TYPE (*(unsigned char *) (PARAM+0x210))
#define KERNEL_START (*(unsigned int *) (PARAM+0x214))
-#define INITRD_START (__pa(xen_start_info.mod_start))
-#define INITRD_SIZE (xen_start_info.mod_len)
+#define INITRD_START (__pa(xen_start_info->mod_start))
+#define INITRD_SIZE (xen_start_info->mod_len)
#define EDID_INFO (*(struct edid_info *) (PARAM+0x440))
#define EDD_NR (*(unsigned char *) (PARAM+EDDNR))
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h Thu Sep
8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h Fri Sep
9 16:30:54 2005
@@ -4,6 +4,10 @@
* Linux-specific hypervisor handling.
*
* Copyright (c) 2002-2004, K A Fraser
+ *
+ * 64-bit updates:
+ * Benjamin Liu <benjamin.liu@xxxxxxxxx>
+ * Jun Nakajima <jun.nakajima@xxxxxxxxx>
*
* This file may be distributed separately from the Linux kernel, or
* incorporated into other software packages, subject to the following license:
@@ -26,497 +30,329 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
-/*
- * Benjamin Liu <benjamin.liu@xxxxxxxxx>
- * Jun Nakajima <jun.nakajima@xxxxxxxxx>
- * Ported to x86-64.
- *
- */
#ifndef __HYPERCALL_H__
#define __HYPERCALL_H__
+
#include <asm-xen/xen-public/xen.h>
#define __syscall_clobber "r11","rcx","memory"
-/*
- * Assembler stubs for hyper-calls.
- */
+#define _hypercall0(type, name) \
+({ \
+ long __res; \
+ asm volatile ( \
+ TRAP_INSTR \
+ : "=a" (__res) \
+ : "0" (__HYPERVISOR_##name) \
+ : __syscall_clobber ); \
+ (type)__res; \
+})
+
+#define _hypercall1(type, name, a1) \
+({ \
+ long __res, __ign1; \
+ asm volatile ( \
+ TRAP_INSTR \
+ : "=a" (__res), "=D" (__ign1) \
+ : "0" (__HYPERVISOR_##name), "1" ((long)(a1)) \
+ : __syscall_clobber ); \
+ (type)__res; \
+})
+
+#define _hypercall2(type, name, a1, a2) \
+({ \
+ long __res, __ign1, __ign2; \
+ asm volatile ( \
+ TRAP_INSTR \
+ : "=a" (__res), "=D" (__ign1), "=S" (__ign2) \
+ : "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \
+ "2" ((long)(a2)) \
+ : __syscall_clobber ); \
+ (type)__res; \
+})
+
+#define _hypercall3(type, name, a1, a2, a3) \
+({ \
+ long __res, __ign1, __ign2, __ign3; \
+ asm volatile ( \
+ TRAP_INSTR \
+ : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \
+ "=d" (__ign3) \
+ : "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \
+ "2" ((long)(a2)), "3" ((long)(a3)) \
+ : __syscall_clobber ); \
+ (type)__res; \
+})
+
+#define _hypercall4(type, name, a1, a2, a3, a4) \
+({ \
+ long __res, __ign1, __ign2, __ign3; \
+ asm volatile ( \
+ "movq %8,%%r10; " TRAP_INSTR \
+ : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \
+ "=d" (__ign3) \
+ : "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \
+ "2" ((long)(a2)), "3" ((long)(a3)), \
+ "g" ((long)(a4)) \
+ : __syscall_clobber, "r10" ); \
+ (type)__res; \
+})
+
+#define _hypercall5(type, name, a1, a2, a3, a4, a5) \
+({ \
+ long __res, __ign1, __ign2, __ign3; \
+ asm volatile ( \
+ "movq %8,%%r10; movq %9,%%r8; " TRAP_INSTR \
+ : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \
+ "=d" (__ign3) \
+ : "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \
+ "2" ((long)(a2)), "3" ((long)(a3)), \
+ "g" ((long)(a4)), "g" ((long)(a5)) \
+ : __syscall_clobber, "r10", "r8" ); \
+ (type)__res; \
+})
+
static inline int
HYPERVISOR_set_trap_table(
- trap_info_t *table)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_set_trap_table), "D" (table)
- : __syscall_clobber );
-
- return ret;
+ trap_info_t *table)
+{
+ return _hypercall1(int, set_trap_table, table);
}
static inline int
HYPERVISOR_mmu_update(
- mmu_update_t *req, int count, int *success_count, domid_t domid)
-{
- int ret;
-
- __asm__ __volatile__ (
- "movq %5, %%r10;" TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_mmu_update), "D" (req), "S"
((long)count),
- "d" (success_count), "g" ((unsigned long)domid)
- : __syscall_clobber, "r10" );
-
- return ret;
+ mmu_update_t *req, int count, int *success_count, domid_t domid)
+{
+ return _hypercall4(int, mmu_update, req, count, success_count, domid);
}
static inline int
HYPERVISOR_mmuext_op(
- struct mmuext_op *op, int count, int *success_count, domid_t domid)
-{
- int ret;
-
- __asm__ __volatile__ (
- "movq %5, %%r10;" TRAP_INSTR
- : "=a" (ret)
- : "0" (__HYPERVISOR_mmuext_op), "D" (op), "S" ((long)count),
- "d" (success_count), "g" ((unsigned long)domid)
- : __syscall_clobber, "r10" );
-
- return ret;
+ struct mmuext_op *op, int count, int *success_count, domid_t domid)
+{
+ return _hypercall4(int, mmuext_op, op, count, success_count, domid);
}
static inline int
HYPERVISOR_set_gdt(
- unsigned long *frame_list, int entries)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_set_gdt), "D" (frame_list), "S"
((long)entries)
- : __syscall_clobber );
-
-
- return ret;
-}
+ unsigned long *frame_list, int entries)
+{
+ return _hypercall2(int, set_gdt, frame_list, entries);
+}
+
static inline int
HYPERVISOR_stack_switch(
- unsigned long ss, unsigned long esp)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_stack_switch), "D" (ss), "S" (esp)
- : __syscall_clobber );
-
- return ret;
+ unsigned long ss, unsigned long esp)
+{
+ return _hypercall2(int, stack_switch, ss, esp);
}
static inline int
HYPERVISOR_set_callbacks(
- unsigned long event_address, unsigned long failsafe_address,
- unsigned long syscall_address)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_set_callbacks), "D" (event_address),
- "S" (failsafe_address), "d" (syscall_address)
- : __syscall_clobber );
-
- return ret;
+ unsigned long event_address, unsigned long failsafe_address,
+ unsigned long syscall_address)
+{
+ return _hypercall3(int, set_callbacks,
+ event_address, failsafe_address, syscall_address);
}
static inline int
HYPERVISOR_fpu_taskswitch(
- int set)
-{
- int ret;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret) : "0" ((unsigned long)__HYPERVISOR_fpu_taskswitch),
- "D" ((unsigned long) set) : __syscall_clobber );
-
- return ret;
+ int set)
+{
+ return _hypercall1(int, fpu_taskswitch, set);
}
static inline int
HYPERVISOR_yield(
- void)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_sched_op), "D" ((unsigned
long)SCHEDOP_yield)
- : __syscall_clobber );
-
- return ret;
+ void)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_yield, 0);
}
static inline int
HYPERVISOR_block(
- void)
-{
- int ret;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_sched_op), "D" ((unsigned
long)SCHEDOP_block)
- : __syscall_clobber );
-
- return ret;
+ void)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_block, 0);
}
static inline int
HYPERVISOR_shutdown(
- void)
-{
- int ret;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_sched_op),
- "D" ((unsigned long)(SCHEDOP_shutdown | (SHUTDOWN_poweroff <<
SCHEDOP_reasonshift)))
- : __syscall_clobber );
-
- return ret;
+ void)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_shutdown |
+ (SHUTDOWN_poweroff << SCHEDOP_reasonshift), 0);
}
static inline int
HYPERVISOR_reboot(
- void)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_sched_op),
- "D" ((unsigned long)(SCHEDOP_shutdown | (SHUTDOWN_reboot <<
SCHEDOP_reasonshift)))
- : __syscall_clobber );
-
- return ret;
-}
-
-static inline int
-HYPERVISOR_suspend(
- unsigned long srec)
-{
- int ret;
-
- /* NB. On suspend, control software expects a suspend record in %esi. */
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_sched_op),
- "D" ((unsigned long)(SCHEDOP_shutdown | (SHUTDOWN_suspend <<
SCHEDOP_reasonshift))),
- "S" (srec)
- : __syscall_clobber );
-
- return ret;
-}
-
-/*
- * We can have the timeout value in a single argument for the hypercall, but
- * that will break the common code.
- */
+ void)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_shutdown |
+ (SHUTDOWN_reboot << SCHEDOP_reasonshift), 0);
+}
+
static inline long
HYPERVISOR_set_timer_op(
- u64 timeout)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_set_timer_op),
- "D" (timeout)
- : __syscall_clobber );
-
- return ret;
+ u64 timeout)
+{
+ return _hypercall1(long, set_timer_op, timeout);
}
static inline int
HYPERVISOR_dom0_op(
- dom0_op_t *dom0_op)
-{
- int ret;
-
- dom0_op->interface_version = DOM0_INTERFACE_VERSION;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_dom0_op), "D" (dom0_op)
- : __syscall_clobber );
-
- return ret;
+ dom0_op_t *dom0_op)
+{
+ dom0_op->interface_version = DOM0_INTERFACE_VERSION;
+ return _hypercall1(int, dom0_op, dom0_op);
}
static inline int
HYPERVISOR_set_debugreg(
- int reg, unsigned long value)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_set_debugreg), "D" ((unsigned
long)reg), "S" (value)
- : __syscall_clobber );
-
- return ret;
+ int reg, unsigned long value)
+{
+ return _hypercall2(int, set_debugreg, reg, value);
}
static inline unsigned long
HYPERVISOR_get_debugreg(
- int reg)
-{
- unsigned long ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_get_debugreg), "D" ((unsigned
long)reg)
- : __syscall_clobber );
-
- return ret;
+ int reg)
+{
+ return _hypercall1(unsigned long, get_debugreg, reg);
}
static inline int
HYPERVISOR_update_descriptor(
- unsigned long ma, unsigned long word)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_update_descriptor), "D" (ma),
- "S" (word)
- : __syscall_clobber );
-
- return ret;
-}
-
-static inline int
-HYPERVISOR_dom_mem_op(
- unsigned int op, unsigned long *extent_list,
- unsigned long nr_extents, unsigned int extent_order)
-{
- int ret;
-
- __asm__ __volatile__ (
- "movq %5,%%r10; movq %6,%%r8;" TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_dom_mem_op), "D" ((unsigned
long)op), "S" (extent_list),
- "d" (nr_extents), "g" ((unsigned long) extent_order), "g" ((unsigned
long) DOMID_SELF)
- : __syscall_clobber,"r8","r10");
-
- return ret;
+ unsigned long ma, unsigned long word)
+{
+ return _hypercall2(int, update_descriptor, ma, word);
+}
+
+static inline int
+HYPERVISOR_memory_op(
+ unsigned int cmd, void *arg)
+{
+ return _hypercall2(int, memory_op, cmd, arg);
}
static inline int
HYPERVISOR_multicall(
- void *call_list, int nr_calls)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_multicall), "D" (call_list), "S"
((unsigned long)nr_calls)
- : __syscall_clobber);
-
- return ret;
+ void *call_list, int nr_calls)
+{
+ return _hypercall2(int, multicall, call_list, nr_calls);
}
static inline int
HYPERVISOR_update_va_mapping(
- unsigned long page_nr, pte_t new_val, unsigned long flags)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_update_va_mapping),
- "D" (page_nr), "S" (new_val.pte), "d" (flags)
- : __syscall_clobber);
-
- return ret;
+ unsigned long va, pte_t new_val, unsigned long flags)
+{
+ return _hypercall3(int, update_va_mapping, va, new_val.pte, flags);
}
static inline int
HYPERVISOR_event_channel_op(
- void *op)
-{
- int ret;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_event_channel_op), "D" (op)
- : __syscall_clobber);
-
- return ret;
+ void *op)
+{
+ return _hypercall1(int, event_channel_op, op);
}
static inline int
HYPERVISOR_xen_version(
- int cmd)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_xen_version), "D" ((unsigned
long)cmd)
- : __syscall_clobber);
-
- return ret;
+ int cmd)
+{
+ return _hypercall1(int, xen_version, cmd);
}
static inline int
HYPERVISOR_console_io(
- int cmd, int count, char *str)
-{
- int ret;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_console_io), "D" ((unsigned
long)cmd), "S" ((unsigned long)count), "d" (str)
- : __syscall_clobber);
-
- return ret;
+ int cmd, int count, char *str)
+{
+ return _hypercall3(int, console_io, cmd, count, str);
}
static inline int
HYPERVISOR_physdev_op(
- void *physdev_op)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_physdev_op), "D" (physdev_op)
- : __syscall_clobber);
-
- return ret;
+ void *physdev_op)
+{
+ return _hypercall1(int, physdev_op, physdev_op);
}
static inline int
HYPERVISOR_grant_table_op(
- unsigned int cmd, void *uop, unsigned int count)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_grant_table_op), "D" ((unsigned
long)cmd), "S" ((unsigned long)uop), "d" (count)
- : __syscall_clobber);
-
- return ret;
+ unsigned int cmd, void *uop, unsigned int count)
+{
+ return _hypercall3(int, grant_table_op, cmd, uop, count);
}
static inline int
HYPERVISOR_update_va_mapping_otherdomain(
- unsigned long page_nr, pte_t new_val, unsigned long flags, domid_t domid)
-{
- int ret;
-
- __asm__ __volatile__ (
- "movq %5, %%r10;" TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_update_va_mapping_otherdomain),
- "D" (page_nr), "S" (new_val.pte), "d" (flags), "g" ((unsigned
long)domid)
- : __syscall_clobber,"r10");
-
- return ret;
+ unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
+{
+ return _hypercall4(int, update_va_mapping_otherdomain, va,
+ new_val.pte, flags, domid);
}
static inline int
HYPERVISOR_vm_assist(
- unsigned int cmd, unsigned int type)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_vm_assist), "D" ((unsigned
long)cmd), "S" ((unsigned long)type)
- : __syscall_clobber);
-
- return ret;
+ unsigned int cmd, unsigned int type)
+{
+ return _hypercall2(int, vm_assist, cmd, type);
+}
+
+static inline int
+HYPERVISOR_boot_vcpu(
+ unsigned long vcpu, vcpu_guest_context_t *ctxt)
+{
+ return _hypercall2(int, boot_vcpu, vcpu, ctxt);
+}
+
+static inline int
+HYPERVISOR_vcpu_up(
+ int vcpu)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_vcpu_up |
+ (vcpu << SCHEDOP_vcpushift), 0);
+}
+
+static inline int
+HYPERVISOR_vcpu_pickle(
+ int vcpu, vcpu_guest_context_t *ctxt)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_vcpu_pickle |
+ (vcpu << SCHEDOP_vcpushift), ctxt);
}
static inline int
HYPERVISOR_switch_to_user(void)
{
- int ret;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret) : "0" ((unsigned long)__HYPERVISOR_switch_to_user) :
__syscall_clobber );
-
- return ret;
-}
-
-static inline int
-HYPERVISOR_boot_vcpu(
- unsigned long vcpu, vcpu_guest_context_t *ctxt)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" (__HYPERVISOR_boot_vcpu), "D" (vcpu), "S" (ctxt)
- : __syscall_clobber);
-
- return ret;
+ return _hypercall0(int, switch_to_user);
}
static inline int
HYPERVISOR_set_segment_base(
- int reg, unsigned long value)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_set_segment_base), "D" ((unsigned
long)reg), "S" (value)
- : __syscall_clobber );
-
- return ret;
-}
-
-static inline int
-HYPERVISOR_vcpu_pickle(
- int vcpu, vcpu_guest_context_t *ctxt)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_sched_op),
- "D" ((unsigned long)SCHEDOP_vcpu_pickle | (vcpu << SCHEDOP_vcpushift)),
- "S" ((unsigned long)ctxt)
- : __syscall_clobber );
-
- return ret;
+ int reg, unsigned long value)
+{
+ return _hypercall2(int, set_segment_base, reg, value);
+}
+
+static inline int
+HYPERVISOR_suspend(
+ unsigned long srec)
+{
+ return _hypercall2(int, sched_op, SCHEDOP_shutdown |
+ (SHUTDOWN_suspend << SCHEDOP_reasonshift), srec);
}
#endif /* __HYPERCALL_H__ */
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/setup_arch_post.h
---
a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/setup_arch_post.h
Thu Sep 8 15:18:40 2005
+++
b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/setup_arch_post.h
Fri Sep 9 16:30:54 2005
@@ -14,7 +14,7 @@
who = "Xen";
start_pfn = 0;
- max_pfn = xen_start_info.nr_pages;
+ 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);
@@ -29,7 +29,7 @@
clear_bit(X86_FEATURE_PSE, c->x86_capability);
clear_bit(X86_FEATURE_PGE, c->x86_capability);
clear_bit(X86_FEATURE_SEP, c->x86_capability);
- if (!(xen_start_info.flags & SIF_PRIVILEGED))
+ if (!(xen_start_info->flags & SIF_PRIVILEGED))
clear_bit(X86_FEATURE_MTRR, c->x86_capability);
}
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/page.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/page.h Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/page.h Fri Sep 9
16:30:54 2005
@@ -62,14 +62,14 @@
#define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
/**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
-#define INVALID_P2M_ENTRY (~0U)
-#define FOREIGN_FRAME(m) ((m) | 0x80000000U)
-extern u32 *phys_to_machine_mapping;
+#define INVALID_P2M_ENTRY (~0UL)
+#define FOREIGN_FRAME(m) ((m) | (1UL<<63))
+extern unsigned long *phys_to_machine_mapping;
#define pfn_to_mfn(pfn) \
-((unsigned long)phys_to_machine_mapping[(unsigned int)(pfn)] & 0x7FFFFFFFUL)
+(phys_to_machine_mapping[(unsigned int)(pfn)] & ~(1UL << 63))
static inline unsigned long mfn_to_pfn(unsigned long mfn)
{
- unsigned int pfn;
+ unsigned long pfn;
/*
* The array access can fail (e.g., device space beyond end of RAM).
@@ -77,7 +77,7 @@
* but we must handle the fault without crashing!
*/
asm (
- "1: movl %1,%k0\n"
+ "1: movq %1,%0\n"
"2:\n"
".section __ex_table,\"a\"\n"
" .align 8\n"
@@ -85,7 +85,7 @@
".previous"
: "=r" (pfn) : "m" (machine_to_phys_mapping[mfn]) );
- return (unsigned long)pfn;
+ return pfn;
}
/* Definitions for machine and pseudophysical addresses. */
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pci.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pci.h Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pci.h Fri Sep 9
16:30:54 2005
@@ -76,12 +76,29 @@
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) \
(((PTR)->LEN_NAME) = (VAL))
+#elif defined(CONFIG_SWIOTLB)
+
+#define PCI_DMA_BUS_IS_PHYS 0
+
+#define pci_dac_dma_supported(pci_dev, mask) 1
+
+#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \
+ dma_addr_t ADDR_NAME;
+#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \
+ __u32 LEN_NAME;
+#define pci_unmap_addr(PTR, ADDR_NAME) \
+ ((PTR)->ADDR_NAME)
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) \
+ (((PTR)->ADDR_NAME) = (VAL))
+#define pci_unmap_len(PTR, LEN_NAME) \
+ ((PTR)->LEN_NAME)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL) \
+ (((PTR)->LEN_NAME) = (VAL))
+
#else
/* No IOMMU */
-/* On Xen we use SWIOTLB instead of blk-specific bounce buffers. */
-#define PCI_DMA_BUS_IS_PHYS (0)
-
+#define PCI_DMA_BUS_IS_PHYS 1
#define pci_dac_dma_supported(pci_dev, mask) 1
#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h Fri Sep 9
16:30:54 2005
@@ -307,7 +307,7 @@
#define pte_pfn(_pte) \
({ \
unsigned long mfn = pte_mfn(_pte); \
- unsigned pfn = mfn_to_pfn(mfn); \
+ unsigned long pfn = mfn_to_pfn(mfn); \
if ((pfn >= max_mapnr) || (phys_to_machine_mapping[pfn] != mfn))\
pfn = max_mapnr; /* special: force !pfn_valid() */ \
pfn; \
@@ -526,28 +526,26 @@
#define DOMID_LOCAL (0xFFFFU)
-int direct_remap_area_pages(struct mm_struct *mm,
+int direct_remap_pfn_range(struct mm_struct *mm,
unsigned long address,
- unsigned long machine_addr,
+ unsigned long mfn,
unsigned long size,
pgprot_t prot,
domid_t domid);
-int __direct_remap_area_pages(struct mm_struct *mm,
- unsigned long address,
- unsigned long size,
- mmu_update_t *v);
+
int create_lookup_pte_addr(struct mm_struct *mm,
unsigned long address,
unsigned long *ptep);
+
int touch_pte_range(struct mm_struct *mm,
unsigned long address,
unsigned long size);
#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
-
direct_remap_area_pages((vma)->vm_mm,vaddr,paddr,size,prot,DOMID_IO)
+
direct_remap_pfn_range((vma)->vm_mm,vaddr,paddr>>PAGE_SHIFT,size,prot,DOMID_IO)
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
-
direct_remap_area_pages((vma)->vm_mm,vaddr,(pfn)<<PAGE_SHIFT,size,prot,DOMID_IO)
+
direct_remap_pfn_range((vma)->vm_mm,vaddr,pfn,size,prot,DOMID_IO)
#define MK_IOSPACE_PFN(space, pfn) (pfn)
#define GET_IOSPACE(pfn) 0
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/system.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/system.h Thu Sep 8
15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/system.h Fri Sep 9
16:30:54 2005
@@ -387,8 +387,14 @@
#define local_irq_disable() __cli()
#define local_irq_enable() __sti()
+/* Don't use smp_processor_id: this is called in debug versions of that fn. */
+#ifdef CONFIG_SMP
#define irqs_disabled() \
- HYPERVISOR_shared_info->vcpu_data[smp_processor_id()].evtchn_upcall_mask
+ HYPERVISOR_shared_info->vcpu_data[__smp_processor_id()].evtchn_upcall_mask
+#else
+#define irqs_disabled() \
+ HYPERVISOR_shared_info->vcpu_data[0].evtchn_upcall_mask
+#endif
/*
* disable hlt during certain critical i/o operations
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/include/asm-xen/hypervisor.h
--- a/linux-2.6-xen-sparse/include/asm-xen/hypervisor.h Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/hypervisor.h Fri Sep 9 16:30:54 2005
@@ -52,13 +52,7 @@
#endif
/* arch/xen/i386/kernel/setup.c */
-union xen_start_info_union
-{
- start_info_t xen_start_info;
- char padding[2048];
-};
-extern union xen_start_info_union xen_start_info_union;
-#define xen_start_info (xen_start_info_union.xen_start_info)
+extern start_info_t *xen_start_info;
/* arch/xen/kernel/evtchn.c */
/* Force a proper event-channel callback from Xen. */
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/include/asm-xen/linux-public/privcmd.h
--- a/linux-2.6-xen-sparse/include/asm-xen/linux-public/privcmd.h Thu Sep
8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/linux-public/privcmd.h Fri Sep
9 16:30:54 2005
@@ -70,14 +70,6 @@
#define IOCTL_PRIVCMD_HYPERCALL \
_IOC(_IOC_NONE, 'P', 0, sizeof(privcmd_hypercall_t))
-/*
- * @cmd: IOCTL_PRIVCMD_INITDOMAIN_EVTCHN
- * @arg: n/a
- * Return: Port associated with domain-controller end of control event channel
- * for the initial domain.
- */
-#define IOCTL_PRIVCMD_INITDOMAIN_EVTCHN \
- _IOC(_IOC_NONE, 'P', 1, 0)
#define IOCTL_PRIVCMD_MMAP \
_IOC(_IOC_NONE, 'P', 2, sizeof(privcmd_mmap_t))
#define IOCTL_PRIVCMD_MMAPBATCH \
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/include/asm-xen/xenbus.h
--- a/linux-2.6-xen-sparse/include/asm-xen/xenbus.h Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/xenbus.h Fri Sep 9 16:30:54 2005
@@ -64,6 +64,7 @@
int (*remove)(struct xenbus_device *dev);
int (*suspend)(struct xenbus_device *dev);
int (*resume)(struct xenbus_device *dev);
+ int (*hotplug)(struct xenbus_device *, char **, int, char *, int);
struct device_driver driver;
};
diff -r 10b1d30d3f66 -r b2f4823b6ff0 linux-2.6-xen-sparse/mm/memory.c
--- a/linux-2.6-xen-sparse/mm/memory.c Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/mm/memory.c Fri Sep 9 16:30:54 2005
@@ -954,10 +954,8 @@
i++;
start += PAGE_SIZE;
len--;
-printk(KERN_ALERT "HIT 0x%lx\n", start);
continue;
}
-else printk(KERN_ALERT "MISS 0x%lx\n", start);
}
if (!vma || (vma->vm_flags & VM_IO)
@@ -1367,20 +1365,15 @@
struct page *old_page, *new_page;
unsigned long pfn = pte_pfn(pte);
pte_t entry;
+ struct page invalid_page;
if (unlikely(!pfn_valid(pfn))) {
- /*
- * This should really halt the system so it can be debugged or
- * at least the kernel stops what it's doing before it corrupts
- * data, but for the moment just pretend this is OOM.
- */
- pte_unmap(page_table);
- printk(KERN_ERR "do_wp_page: bogus page at address %08lx\n",
- address);
- spin_unlock(&mm->page_table_lock);
- return VM_FAULT_OOM;
- }
- old_page = pfn_to_page(pfn);
+ /* This can happen with /dev/mem (PROT_WRITE, MAP_PRIVATE). */
+ invalid_page.flags = (1<<PG_reserved) | (1<<PG_locked);
+ old_page = &invalid_page;
+ } else {
+ old_page = pfn_to_page(pfn);
+ }
if (!TestSetPageLocked(old_page)) {
int reuse = can_share_swap_page(old_page);
@@ -1416,7 +1409,13 @@
new_page = alloc_page_vma(GFP_HIGHUSER, vma, address);
if (!new_page)
goto no_new_page;
- copy_user_highpage(new_page, old_page, address);
+ if (old_page == &invalid_page) {
+ char *vto = kmap_atomic(new_page, KM_USER1);
+ copy_page(vto, (void *)(address & PAGE_MASK));
+ kunmap_atomic(vto, KM_USER1);
+ } else {
+ copy_user_highpage(new_page, old_page, address);
+ }
}
/*
* Re-check the pte - we dropped the lock
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/Makefile
--- a/tools/Makefile Thu Sep 8 15:18:40 2005
+++ b/tools/Makefile Fri Sep 9 16:30:54 2005
@@ -7,14 +7,23 @@
SUBDIRS += misc
SUBDIRS += examples
SUBDIRS += xentrace
-SUBDIRS += python
-SUBDIRS += xcs
SUBDIRS += xcutils
-#SUBDIRS += pygrub
SUBDIRS += firmware
SUBDIRS += security
SUBDIRS += console
+ifeq ($(VTPM_TOOLS),y)
+SUBDIRS += vtpm_manager
+SUBDIRS += vtpm
+endif
SUBDIRS += xenstat
+
+.PHONY: all install clean check check_clean ioemu eioemuinstall ioemuclean
+
+# These don't cross-compile
+ifeq ($(XEN_COMPILE_ARCH),$(XEN_TARGET_ARCH))
+SUBDIRS += python
+#SUBDIRS += pygrub
+endif
.PHONY: all install clean check check_clean ioemu eioemuinstall ioemuclean
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/Rules.mk
--- a/tools/Rules.mk Thu Sep 8 15:18:40 2005
+++ b/tools/Rules.mk Fri Sep 9 16:30:54 2005
@@ -4,7 +4,6 @@
XEN_XC = $(XEN_ROOT)/tools/python/xen/lowlevel/xc
XEN_LIBXC = $(XEN_ROOT)/tools/libxc
-XEN_XCS = $(XEN_ROOT)/tools/xcs
XEN_XENSTORE = $(XEN_ROOT)/tools/xenstore
XEN_LIBXENSTAT = $(XEN_ROOT)/tools/xenstat/libxenstat/src
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/blktap/Makefile
--- a/tools/blktap/Makefile Thu Sep 8 15:18:40 2005
+++ b/tools/blktap/Makefile Fri Sep 9 16:30:54 2005
@@ -6,7 +6,8 @@
include $(XEN_ROOT)/tools/Rules.mk
SUBDIRS :=
-SUBDIRS += parallax
+SUBDIRS += ublkback
+#SUBDIRS += parallax
BLKTAP_INSTALL_DIR = /usr/sbin
@@ -14,12 +15,12 @@
INSTALL_PROG = $(INSTALL) -m0755
INSTALL_DIR = $(INSTALL) -d -m0755
-INCLUDES += -I. -I $(XEN_LIBXC)
+INCLUDES += -I. -I $(XEN_LIBXC) -I $(XEN_XENSTORE)
LIBS := -lpthread -lz
SRCS :=
-SRCS += blktaplib.c
+SRCS += blktaplib.c xenbus.c blkif.c
CFLAGS += -Wall
CFLAGS += -Werror
@@ -28,17 +29,20 @@
CFLAGS += -g3
CFLAGS += -fno-strict-aliasing
CFLAGS += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
+# get asprintf():
+CFLAGS += -D _GNU_SOURCE
# Get gcc to generate the dependencies for us.
CFLAGS += -Wp,-MD,.$(@F).d
CFLAGS += $(INCLUDES)
DEPS = .*.d
OBJS = $(patsubst %.c,%.o,$(SRCS))
-IBINS = blkdump
+IBINS :=
+#IBINS += blkdump
LIB = libblktap.so libblktap.so.$(MAJOR) libblktap.so.$(MAJOR).$(MINOR)
-all: mk-symlinks libblktap.so blkdump
+all: mk-symlinks libblktap.so #blkdump
@set -e; for subdir in $(SUBDIRS); do \
$(MAKE) -C $$subdir $@; \
done
@@ -59,7 +63,7 @@
$(INSTALL_DIR) -p $(DESTDIR)/usr/include
$(INSTALL_PROG) $(LIB) $(DESTDIR)/usr/$(LIBDIR)
$(INSTALL_PROG) blktaplib.h $(DESTDIR)/usr/include
- $(INSTALL_PROG) $(IBINS) $(DESTDIR)$(BLKTAP_INSTALL_DIR)
+ #$(INSTALL_PROG) $(IBINS) $(DESTDIR)$(BLKTAP_INSTALL_DIR)
@set -e; for subdir in $(SUBDIRS); do \
$(MAKE) -C $$subdir $@; \
done
@@ -79,14 +83,16 @@
mv staging/i386/*.rpm .
rm -rf staging
-libblktap.so: $(OBJS)
- $(CC) $(CFLAGS) -Wl,-soname -Wl,$(SONAME) -shared -o \
- libblktap.so.$(MAJOR).$(MINOR) $^ $(LIBS)
+libblktap.so: $(OBJS)
+ $(CC) $(CFLAGS) -Wl,-soname -Wl,$(SONAME) -shared \
+ -L$(XEN_XENSTORE) -l xenstore \
+ -o libblktap.so.$(MAJOR).$(MINOR) $^ $(LIBS)
ln -sf libblktap.so.$(MAJOR).$(MINOR) libblktap.so.$(MAJOR)
ln -sf libblktap.so.$(MAJOR) $@
blkdump: libblktap.so
- $(CC) $(CFLAGS) -o blkdump -L$(XEN_LIBXC) -L. -l blktap blkdump.c
+ $(CC) $(CFLAGS) -o blkdump -L$(XEN_LIBXC) -L. \
+ -l blktap blkdump.c
.PHONY: TAGS clean install mk-symlinks rpm
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/blktap/blkdump.c
--- a/tools/blktap/blkdump.c Thu Sep 8 15:18:40 2005
+++ b/tools/blktap/blkdump.c Fri Sep 9 16:30:54 2005
@@ -8,85 +8,18 @@
#include <stdio.h>
#include "blktaplib.h"
-int control_print(control_msg_t *msg)
-{
- if (msg->type != CMSG_BLKIF_BE)
- {
- printf("***\nUNEXPECTED CTRL MSG MAJOR TYPE(%d)\n***\n", msg->type);
- return 0;
- }
-
- switch(msg->subtype)
- {
- case CMSG_BLKIF_BE_CREATE:
- if ( msg->length != sizeof(blkif_be_create_t) )
- goto parse_error;
- printf("[CONTROL_MSG] CMSG_BLKIF_BE_CREATE(d:%d,h:%d)\n",
- ((blkif_be_create_t *)msg->msg)->domid,
- ((blkif_be_create_t *)msg->msg)->blkif_handle);
- break;
- case CMSG_BLKIF_BE_DESTROY:
- if ( msg->length != sizeof(blkif_be_destroy_t) )
- goto parse_error;
- printf("[CONTROL_MSG] CMSG_BLKIF_BE_DESTROY(d:%d,h:%d)\n",
- ((blkif_be_destroy_t *)msg->msg)->domid,
- ((blkif_be_destroy_t *)msg->msg)->blkif_handle);
- break;
- case CMSG_BLKIF_BE_CONNECT:
- if ( msg->length != sizeof(blkif_be_connect_t) )
- goto parse_error;
- printf("[CONTROL_MSG] CMSG_BLKIF_BE_CONNECT(d:%d,h:%d)\n",
- ((blkif_be_connect_t *)msg->msg)->domid,
- ((blkif_be_connect_t *)msg->msg)->blkif_handle);
- break;
- case CMSG_BLKIF_BE_DISCONNECT:
- if ( msg->length != sizeof(blkif_be_disconnect_t) )
- goto parse_error;
- printf("[CONTROL_MSG] CMSG_BLKIF_BE_DISCONNECT(d:%d,h:%d)\n",
- ((blkif_be_disconnect_t *)msg->msg)->domid,
- ((blkif_be_disconnect_t *)msg->msg)->blkif_handle);
- break;
- case CMSG_BLKIF_BE_VBD_CREATE:
- if ( msg->length != sizeof(blkif_be_vbd_create_t) )
- goto parse_error;
- printf("[CONTROL_MSG] CMSG_BLKIF_BE_VBD_CREATE(d:%d,h:%d,v:%d)\n",
- ((blkif_be_vbd_create_t *)msg->msg)->domid,
- ((blkif_be_vbd_create_t *)msg->msg)->blkif_handle,
- ((blkif_be_vbd_create_t *)msg->msg)->vdevice);
- break;
- case CMSG_BLKIF_BE_VBD_DESTROY:
- if ( msg->length != sizeof(blkif_be_vbd_destroy_t) )
- goto parse_error;
- printf("[CONTROL_MSG] CMSG_BLKIF_BE_VBD_DESTROY(d:%d,h:%d,v:%d)\n",
- ((blkif_be_vbd_destroy_t *)msg->msg)->domid,
- ((blkif_be_vbd_destroy_t *)msg->msg)->blkif_handle,
- ((blkif_be_vbd_destroy_t *)msg->msg)->vdevice);
- break;
- default:
- goto parse_error;
- }
-
- return 0;
-
-parse_error:
- printf("[CONTROL_MSG] Bad message type or length!\n");
- return 0;
-}
-
int request_print(blkif_request_t *req)
{
int i;
unsigned long fas;
- if ( req->operation == BLKIF_OP_PROBE ) {
- printf("[%2u:%2u<%s]\n", ID_TO_DOM(req->id), ID_TO_IDX(req->id),
- blkif_op_name[req->operation]);
- return BLKTAP_PASS;
- } else {
+ if ( (req->operation == BLKIF_OP_READ) ||
+ (req->operation == BLKIF_OP_WRITE) )
+ {
printf("[%2u:%2u<%5s] (nr_segs: %03u, dev: %03u, %010llu)\n",
ID_TO_DOM(req->id), ID_TO_IDX(req->id),
blkif_op_name[req->operation],
- req->nr_segments, req->device,
+ req->nr_segments, req->handle,
req->sector_number);
@@ -99,6 +32,8 @@
);
}
+ } else {
+ printf("Unknown request message type.\n");
}
return BLKTAP_PASS;
@@ -106,23 +41,22 @@
int response_print(blkif_response_t *rsp)
{
- if ( rsp->operation == BLKIF_OP_PROBE ) {
- printf("[%2u:%2u>%s]\n", ID_TO_DOM(rsp->id), ID_TO_IDX(rsp->id),
- blkif_op_name[rsp->operation]);
- return BLKTAP_PASS;
- } else {
+ if ( (rsp->operation == BLKIF_OP_READ) ||
+ (rsp->operation == BLKIF_OP_WRITE) )
+ {
printf("[%2u:%2u>%5s] (status: %d)\n",
ID_TO_DOM(rsp->id), ID_TO_IDX(rsp->id),
blkif_op_name[rsp->operation],
rsp->status);
+ } else {
+ printf("Unknown request message type.\n");
}
return BLKTAP_PASS;
}
int main(int argc, char *argv[])
{
- blktap_register_ctrl_hook("control_print", control_print);
blktap_register_request_hook("request_print", request_print);
blktap_register_response_hook("response_print", response_print);
blktap_listen();
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/blktap/blktaplib.c
--- a/tools/blktap/blktaplib.c Thu Sep 8 15:18:40 2005
+++ b/tools/blktap/blktaplib.c Fri Sep 9 16:30:54 2005
@@ -24,7 +24,7 @@
#include <string.h>
#include <unistd.h>
#include <pthread.h>
-
+#include <xs.h>
#define __COMPILING_BLKTAP_LIB
#include "blktaplib.h"
@@ -34,11 +34,12 @@
#else
#define DPRINTF(_f, _a...) ((void)0)
#endif
-#define DEBUG_RING_IDXS 1
+#define DEBUG_RING_IDXS 0
#define POLLRDNORM 0x040
#define BLKTAP_IOCTL_KICK 1
+
void got_sig_bus();
void got_sig_int();
@@ -46,17 +47,13 @@
/* in kernel these are opposite, but we are a consumer now. */
blkif_back_ring_t fe_ring; /* slightly counterintuitive ;) */
blkif_front_ring_t be_ring;
-ctrl_back_ring_t ctrl_ring;
unsigned long mmap_vstart = 0;
char *blktap_mem;
int fd = 0;
-#define BLKTAP_RING_PAGES 3 /* Ctrl, Back, Front */
-/*#define BLKTAP_MMAP_PAGES ((11 + 1) * 64)*/
-#define BLKTAP_MMAP_PAGES \
- ((BLKIF_MAX_SEGMENTS_PER_REQUEST + 1) * BLKIF_RING_SIZE)
-#define BLKTAP_MMAP_REGION_SIZE (BLKTAP_RING_PAGES + BLKTAP_MMAP_PAGES)
+#define BLKTAP_RING_PAGES 1 /* Front */
+#define BLKTAP_MMAP_REGION_SIZE (BLKTAP_RING_PAGES + MMAP_PAGES)
int bad_count = 0;
void bad(void)
@@ -79,126 +76,13 @@
}
inline domid_t ID_TO_DOM(unsigned long id) { return (id >> 16); }
-/*
+
static int (*request_hook)(blkif_request_t *req) = NULL;
static int (*response_hook)(blkif_response_t *req) = NULL;
-*/
-
-/*-----[ Request/Response hook chains.]----------------------------------*/
-
-#define HOOK_NAME_MAX 50
-
-typedef struct ctrl_hook_st {
- char name[HOOK_NAME_MAX];
- int (*func)(control_msg_t *);
- struct ctrl_hook_st *next;
-} ctrl_hook_t;
-
-typedef struct request_hook_st {
- char name[HOOK_NAME_MAX];
- int (*func)(blkif_request_t *);
- struct request_hook_st *next;
-} request_hook_t;
-
-typedef struct response_hook_st {
- char name[HOOK_NAME_MAX];
- int (*func)(blkif_response_t *);
- struct response_hook_st *next;
-} response_hook_t;
-
-static ctrl_hook_t *ctrl_hook_chain = NULL;
-static request_hook_t *request_hook_chain = NULL;
-static response_hook_t *response_hook_chain = NULL;
-
-void blktap_register_ctrl_hook(char *name, int (*ch)(control_msg_t *))
-{
- ctrl_hook_t *ch_ent, **c;
-
- ch_ent = (ctrl_hook_t *)malloc(sizeof(ctrl_hook_t));
- if (!ch_ent) { printf("couldn't allocate a new hook\n"); exit(-1); }
-
- ch_ent->func = ch;
- ch_ent->next = NULL;
- strncpy(ch_ent->name, name, HOOK_NAME_MAX);
- ch_ent->name[HOOK_NAME_MAX-1] = '\0';
-
- c = &ctrl_hook_chain;
- while (*c != NULL) {
- c = &(*c)->next;
- }
- *c = ch_ent;
-}
-
-void blktap_register_request_hook(char *name, int (*rh)(blkif_request_t *))
-{
- request_hook_t *rh_ent, **c;
-
- rh_ent = (request_hook_t *)malloc(sizeof(request_hook_t));
- if (!rh_ent) { printf("couldn't allocate a new hook\n"); exit(-1); }
-
- rh_ent->func = rh;
- rh_ent->next = NULL;
- strncpy(rh_ent->name, name, HOOK_NAME_MAX);
-
- c = &request_hook_chain;
- while (*c != NULL) {
- c = &(*c)->next;
- }
- *c = rh_ent;
-}
-
-void blktap_register_response_hook(char *name, int (*rh)(blkif_response_t *))
-{
- response_hook_t *rh_ent, **c;
-
- rh_ent = (response_hook_t *)malloc(sizeof(response_hook_t));
- if (!rh_ent) { printf("couldn't allocate a new hook\n"); exit(-1); }
-
- rh_ent->func = rh;
- rh_ent->next = NULL;
- strncpy(rh_ent->name, name, HOOK_NAME_MAX);
-
- c = &response_hook_chain;
- while (*c != NULL) {
- c = &(*c)->next;
- }
- *c = rh_ent;
-}
-
-void print_hooks(void)
-{
- request_hook_t *req_hook;
- response_hook_t *rsp_hook;
- ctrl_hook_t *ctrl_hook;
-
- DPRINTF("Control Hooks:\n");
- ctrl_hook = ctrl_hook_chain;
- while (ctrl_hook != NULL)
- {
- DPRINTF(" [0x%p] %s\n", ctrl_hook->func, ctrl_hook->name);
- ctrl_hook = ctrl_hook->next;
- }
-
- DPRINTF("Request Hooks:\n");
- req_hook = request_hook_chain;
- while (req_hook != NULL)
- {
- DPRINTF(" [0x%p] %s\n", req_hook->func, req_hook->name);
- req_hook = req_hook->next;
- }
-
- DPRINTF("Response Hooks:\n");
- rsp_hook = response_hook_chain;
- while (rsp_hook != NULL)
- {
- DPRINTF(" [0x%p] %s\n", rsp_hook->func, rsp_hook->name);
- rsp_hook = rsp_hook->next;
- }
-}
/*-----[ Data to/from Backend (server) VM ]------------------------------*/
-
+/*
inline int write_req_to_be_ring(blkif_request_t *req)
{
@@ -214,6 +98,7 @@
return 0;
}
+*/
inline int write_rsp_to_fe_ring(blkif_response_t *rsp)
{
@@ -230,14 +115,14 @@
return 0;
}
-static void apply_rsp_hooks(blkif_response_t *rsp)
+static void apply_rsp_hooks(blkif_t *blkif, blkif_response_t *rsp)
{
response_hook_t *rsp_hook;
- rsp_hook = response_hook_chain;
+ rsp_hook = blkif->response_hook_chain;
while (rsp_hook != NULL)
{
- switch(rsp_hook->func(rsp))
+ switch(rsp_hook->func(blkif, rsp, 1))
{
case BLKTAP_PASS:
break;
@@ -248,15 +133,19 @@
}
}
+
static pthread_mutex_t push_mutex = PTHREAD_MUTEX_INITIALIZER;
-void blktap_inject_response(blkif_response_t *rsp)
-{
-
- apply_rsp_hooks(rsp);
-
+void blkif_inject_response(blkif_t *blkif, blkif_response_t *rsp)
+{
+
+ apply_rsp_hooks(blkif, rsp);
+
write_rsp_to_fe_ring(rsp);
-
+}
+
+void blktap_kick_responses(void)
+{
pthread_mutex_lock(&push_mutex);
RING_PUSH_RESPONSES(&fe_ring);
@@ -277,7 +166,7 @@
int active;
} pollhook_t;
-static struct pollfd pfd[MAX_POLLFDS+1];
+static struct pollfd pfd[MAX_POLLFDS+2]; /* tap and store are extra */
static pollhook_t pollhooks[MAX_POLLFDS];
static unsigned int ph_freelist[MAX_POLLFDS];
static unsigned int ph_cons, ph_prod;
@@ -344,65 +233,65 @@
int blktap_listen(void)
{
- int notify_be, notify_fe, tap_pfd;
-
+ int notify_be, notify_fe, tap_pfd, store_pfd, xs_fd, ret;
+ struct xs_handle *h;
+ blkif_t *blkif;
+
/* comms rings: */
blkif_request_t *req;
blkif_response_t *rsp;
- control_msg_t *msg;
blkif_sring_t *sring;
- ctrl_sring_t *csring;
RING_IDX rp, i, pfd_count;
/* pending rings */
blkif_request_t req_pending[BLKIF_RING_SIZE];
- blkif_response_t rsp_pending[BLKIF_RING_SIZE];
+ /* blkif_response_t rsp_pending[BLKIF_RING_SIZE] */;
/* handler hooks: */
request_hook_t *req_hook;
response_hook_t *rsp_hook;
- ctrl_hook_t *ctrl_hook;
signal (SIGBUS, got_sig_bus);
signal (SIGINT, got_sig_int);
- print_hooks();
-
+ __init_blkif();
+
fd = open("/dev/blktap", O_RDWR);
- if (fd == -1) {
- printf("open failed! (%d)\n", errno);
- goto open_failed;
- }
+ if (fd == -1)
+ err(-1, "open failed!");
blktap_mem = mmap(0, PAGE_SIZE * BLKTAP_MMAP_REGION_SIZE,
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- if ((int)blktap_mem == -1) {
- printf("mmap failed! (%d)\n", errno);
- goto mmap_failed;
- }
+ if ((int)blktap_mem == -1)
+ err(-1, "mmap failed!");
/* assign the rings to the mapped memory */
- csring = (ctrl_sring_t *)blktap_mem;
- BACK_RING_INIT(&ctrl_ring, csring, PAGE_SIZE);
-
+/*
sring = (blkif_sring_t *)((unsigned long)blktap_mem + PAGE_SIZE);
FRONT_RING_INIT(&be_ring, sring, PAGE_SIZE);
-
- sring = (blkif_sring_t *)((unsigned long)blktap_mem + (2 *PAGE_SIZE));
+*/
+ sring = (blkif_sring_t *)((unsigned long)blktap_mem);
BACK_RING_INIT(&fe_ring, sring, PAGE_SIZE);
mmap_vstart = (unsigned long)blktap_mem +(BLKTAP_RING_PAGES << PAGE_SHIFT);
+
+ /* Set up store connection and watch. */
+ h = xs_daemon_open();
+ if (h == NULL)
+ err(-1, "xs_daemon_open");
+
+ ret = add_blockdevice_probe_watch(h, "Domain-0");
+ if (ret != 0)
+ err(0, "adding device probewatch");
+
ioctl(fd, BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_INTERPOSE );
while(1) {
int ret;
/* build the poll list */
-
- DPRINTF("Building poll list.\n");
-
pfd_count = 0;
for ( i=0; i < MAX_POLLFDS; i++ ) {
pollhook_t *ph = &pollhooks[i];
@@ -415,49 +304,31 @@
}
}
- tap_pfd = pfd_count;
+ tap_pfd = pfd_count++;
pfd[tap_pfd].fd = fd;
pfd[tap_pfd].events = POLLIN;
- DPRINTF("poll() %d fds.\n", pfd_count);
+ store_pfd = pfd_count++;
+ pfd[store_pfd].fd = xs_fileno(h);
+ pfd[store_pfd].events = POLLIN;
- if ( (ret = (poll(pfd, pfd_count+1, 10000)) == 0) ) {
+ if ( (ret = (poll(pfd, pfd_count, 10000)) == 0) ) {
if (DEBUG_RING_IDXS)
ioctl(fd, BLKTAP_IOCTL_PRINT_IDXS);
continue;
}
- DPRINTF("poll returned %d\n", ret);
-
for (i=0; i < MAX_POLLFDS; i++) {
if ( (pollhooks[i].active ) && (pollhooks[i].pfd->revents ) )
pollhooks[i].func(pollhooks[i].pfd->fd);
}
- if (pfd[tap_pfd].revents) {
-
- /* empty the control ring */
- rp = ctrl_ring.sring->req_prod;
- rmb();
- for (i = ctrl_ring.req_cons; i < rp; i++)
- {
- msg = RING_GET_REQUEST(&ctrl_ring, i);
-
- ctrl_hook = ctrl_hook_chain;
- while (ctrl_hook != NULL)
- {
- DPRINTF("CTRL_HOOK: %s\n", ctrl_hook->name);
- /* We currently don't respond to ctrl messages. */
- ctrl_hook->func(msg);
- ctrl_hook = ctrl_hook->next;
- }
- }
- /* Using this as a unidirectional ring. */
- ctrl_ring.req_cons = ctrl_ring.rsp_prod_pvt = i;
-pthread_mutex_lock(&push_mutex);
- RING_PUSH_RESPONSES(&ctrl_ring);
-pthread_mutex_unlock(&push_mutex);
-
+ if (pfd[store_pfd].revents) {
+ ret = xs_fire_next_watch(h);
+ }
+
+ if (pfd[tap_pfd].revents)
+ {
/* empty the fe_ring */
notify_fe = 0;
notify_be = RING_HAS_UNCONSUMED_REQUESTS(&fe_ring);
@@ -465,44 +336,62 @@
rmb();
for (i = fe_ring.req_cons; i != rp; i++)
{
- int done = 0; /* stop forwarding this request */
+ int done = 0;
req = RING_GET_REQUEST(&fe_ring, i);
memcpy(&req_pending[ID_TO_IDX(req->id)], req, sizeof(*req));
req = &req_pending[ID_TO_IDX(req->id)];
- DPRINTF("copying an fe request\n");
-
- req_hook = request_hook_chain;
- while (req_hook != NULL)
+ blkif = blkif_find_by_handle(ID_TO_DOM(req->id), req->handle);
+
+ if (blkif != NULL)
{
- DPRINTF("REQ_HOOK: %s\n", req_hook->name);
- switch(req_hook->func(req))
+ req_hook = blkif->request_hook_chain;
+ while (req_hook != NULL)
{
- case BLKTAP_RESPOND:
- apply_rsp_hooks((blkif_response_t *)req);
- write_rsp_to_fe_ring((blkif_response_t *)req);
- notify_fe = 1;
- done = 1;
- break;
- case BLKTAP_STOLEN:
- done = 1;
- break;
- case BLKTAP_PASS:
- break;
- default:
- printf("Unknown request hook return value!\n");
+ switch(req_hook->func(blkif, req, ((i+1) == rp)))
+ {
+ case BLKTAP_RESPOND:
+ apply_rsp_hooks(blkif, (blkif_response_t *)req);
+ write_rsp_to_fe_ring((blkif_response_t *)req);
+ notify_fe = 1;
+ done = 1;
+ break;
+ case BLKTAP_STOLEN:
+ done = 1;
+ break;
+ case BLKTAP_PASS:
+ break;
+ default:
+ printf("Unknown request hook return value!\n");
+ }
+ if (done) break;
+ req_hook = req_hook->next;
}
- if (done) break;
- req_hook = req_hook->next;
}
- if (done == 0) write_req_to_be_ring(req);
+ if (done == 0)
+ {
+ /* this was: */
+ /* write_req_to_be_ring(req); */
+
+ unsigned long id = req->id;
+ unsigned short operation = req->operation;
+ printf("Unterminated request!\n");
+ rsp = (blkif_response_t *)req;
+ rsp->id = id;
+ rsp->operation = operation;
+ rsp->status = BLKIF_RSP_ERROR;
+ write_rsp_to_fe_ring(rsp);
+ notify_fe = 1;
+ done = 1;
+ }
}
fe_ring.req_cons = i;
/* empty the be_ring */
+/*
notify_fe |= RING_HAS_UNCONSUMED_RESPONSES(&be_ring);
rp = be_ring.sring->rsp_prod;
rmb();
@@ -519,9 +408,9 @@
write_rsp_to_fe_ring(rsp);
}
be_ring.rsp_cons = i;
-
+*/
/* notify the domains */
-
+/*
if (notify_be) {
DPRINTF("notifying be\n");
pthread_mutex_lock(&push_mutex);
@@ -529,13 +418,13 @@
ioctl(fd, BLKTAP_IOCTL_KICK_BE);
pthread_mutex_unlock(&push_mutex);
}
-
+*/
if (notify_fe) {
DPRINTF("notifying fe\n");
-pthread_mutex_lock(&push_mutex);
+ pthread_mutex_lock(&push_mutex);
RING_PUSH_RESPONSES(&fe_ring);
ioctl(fd, BLKTAP_IOCTL_KICK_FE);
-pthread_mutex_unlock(&push_mutex);
+ pthread_mutex_unlock(&push_mutex);
}
}
}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/blktap/blktaplib.h
--- a/tools/blktap/blktaplib.h Thu Sep 8 15:18:40 2005
+++ b/tools/blktap/blktaplib.h Fri Sep 9 16:30:54 2005
@@ -2,6 +2,9 @@
*
* userland accessors to the block tap.
*
+ * Sept 2/05 -- I'm scaling this back to only support block remappings
+ * to user in a backend domain. Passthrough and interposition can be readded
+ * once transitive grants are available.
*/
#ifndef __BLKTAPLIB_H__
@@ -13,6 +16,7 @@
#include <xen/io/blkif.h>
#include <xen/io/ring.h>
#include <xen/io/domain_controller.h>
+#include <xs.h>
/* /dev/xen/blktap resides at device number major=10, minor=202 */
#define BLKTAP_MINOR 202
@@ -49,12 +53,18 @@
return (
( arg == BLKTAP_MODE_PASSTHROUGH ) ||
( arg == BLKTAP_MODE_INTERCEPT_FE ) ||
+ ( arg == BLKTAP_MODE_INTERPOSE ) );
+/*
+ return (
+ ( arg == BLKTAP_MODE_PASSTHROUGH ) ||
+ ( arg == BLKTAP_MODE_INTERCEPT_FE ) ||
( arg == BLKTAP_MODE_INTERCEPT_BE ) ||
( arg == BLKTAP_MODE_INTERPOSE ) ||
( (arg & ~BLKTAP_MODE_COPY_FE_PAGES) == BLKTAP_MODE_COPY_FE ) ||
( (arg & ~BLKTAP_MODE_COPY_BE_PAGES) == BLKTAP_MODE_COPY_BE ) ||
( (arg & ~BLKTAP_MODE_COPY_BOTH_PAGES) == BLKTAP_MODE_COPY_BOTH )
);
+*/
}
/* Return values for handling messages in hooks. */
@@ -62,29 +72,88 @@
#define BLKTAP_RESPOND 1 /* Request is now a reply. Return it. */
#define BLKTAP_STOLEN 2 /* Hook has stolen request. */
-#define domid_t unsigned short
+//#define domid_t unsigned short
inline unsigned int ID_TO_IDX(unsigned long id);
inline domid_t ID_TO_DOM(unsigned long id);
-void blktap_register_ctrl_hook(char *name, int (*ch)(control_msg_t *));
-void blktap_register_request_hook(char *name, int (*rh)(blkif_request_t *));
-void blktap_register_response_hook(char *name, int (*rh)(blkif_response_t *));
-void blktap_inject_response(blkif_response_t *);
int blktap_attach_poll(int fd, short events, int (*func)(int));
void blktap_detach_poll(int fd);
int blktap_listen(void);
+struct blkif;
+
+typedef struct request_hook_st {
+ char *name;
+ int (*func)(struct blkif *, blkif_request_t *, int);
+ struct request_hook_st *next;
+} request_hook_t;
+
+typedef struct response_hook_st {
+ char *name;
+ int (*func)(struct blkif *, blkif_response_t *, int);
+ struct response_hook_st *next;
+} response_hook_t;
+
+struct blkif_ops {
+ long int (*get_size)(struct blkif *blkif);
+ long int (*get_secsize)(struct blkif *blkif);
+ unsigned (*get_info)(struct blkif *blkif);
+};
+
+typedef struct blkif {
+ domid_t domid;
+ long int handle;
+
+ long int pdev;
+ long int readonly;
+
+ enum { DISCONNECTED, CONNECTED } state;
+
+ struct blkif_ops *ops;
+ request_hook_t *request_hook_chain;
+ response_hook_t *response_hook_chain;
+
+ struct blkif *hash_next;
+
+ void *prv; /* device-specific data */
+} blkif_t;
+
+void register_new_blkif_hook(int (*fn)(blkif_t *blkif));
+blkif_t *blkif_find_by_handle(domid_t domid, unsigned int handle);
+blkif_t *alloc_blkif(domid_t domid);
+int blkif_init(blkif_t *blkif, long int handle, long int pdev,
+ long int readonly);
+void free_blkif(blkif_t *blkif);
+void __init_blkif(void);
+
+
+/* xenstore/xenbus: */
+extern int add_blockdevice_probe_watch(struct xs_handle *h,
+ const char *domname);
+int xs_fire_next_watch(struct xs_handle *h);
+
+
+void blkif_print_hooks(blkif_t *blkif);
+void blkif_register_request_hook(blkif_t *blkif, char *name,
+ int (*rh)(blkif_t *, blkif_request_t *, int));
+void blkif_register_response_hook(blkif_t *blkif, char *name,
+ int (*rh)(blkif_t *, blkif_response_t *, int));
+void blkif_inject_response(blkif_t *blkif, blkif_response_t *);
+void blktap_kick_responses(void);
+
+/* this must match the underlying driver... */
+#define MAX_PENDING_REQS 64
+
/* Accessing attached data page mappings */
-#define MMAP_PAGES_PER_REQUEST \
- (BLKIF_MAX_SEGMENTS_PER_REQUEST + 1)
-#define MMAP_VADDR(_req,_seg) \
- (mmap_vstart + \
- ((_req) * MMAP_PAGES_PER_REQUEST * PAGE_SIZE) + \
+#define MMAP_PAGES \
+ (MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST)
+#define MMAP_VADDR(_req,_seg) \
+ (mmap_vstart + \
+ ((_req) * BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE) + \
((_seg) * PAGE_SIZE))
extern unsigned long mmap_vstart;
-
/* Defines that are only used by library clients */
@@ -93,7 +162,6 @@
static char *blkif_op_name[] = {
[BLKIF_OP_READ] = "READ",
[BLKIF_OP_WRITE] = "WRITE",
- [BLKIF_OP_PROBE] = "PROBE",
};
#endif /* __COMPILING_BLKTAP_LIB */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/check/check_brctl
--- a/tools/check/check_brctl Thu Sep 8 15:18:40 2005
+++ b/tools/check/check_brctl Fri Sep 9 16:30:54 2005
@@ -2,8 +2,9 @@
# CHECK-INSTALL
function error {
- echo 'Check for the bridge control utils (brctl) failed.'
+ echo
+ echo ' *** Check for the bridge control utils (brctl) FAILED'
exit 1
}
-brctl show || error
\ No newline at end of file
+which brctl 1>/dev/null 2>&1 || error
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/check/check_iproute
--- a/tools/check/check_iproute Thu Sep 8 15:18:40 2005
+++ b/tools/check/check_iproute Fri Sep 9 16:30:54 2005
@@ -2,9 +2,10 @@
# CHECK-INSTALL
function error {
- echo 'Check for iproute (ip addr) failed.'
+ echo
+ echo ' *** Check for iproute (ip addr) FAILED'
exit 1
}
-ip addr list || error
+ip addr list 1>/dev/null 2>&1 || error
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/check/check_logging
--- a/tools/check/check_logging Thu Sep 8 15:18:40 2005
+++ b/tools/check/check_logging Fri Sep 9 16:30:54 2005
@@ -18,11 +18,12 @@
import logging
except ImportError:
hline()
- msg("Python logging is not installed.")
- msg("Use 'make install-logging' at the xen root to install.")
msg("")
- msg("Alternatively download and install from")
- msg("http://www.red-dove.com/python_logging.html")
+ msg(" *** Python logging is not installed.")
+ msg(" *** Use 'make install-logging' at the xen root to install.")
+ msg(" *** ")
+ msg(" *** Alternatively download and install from")
+ msg(" *** http://www.red-dove.com/python_logging.html")
hline()
sys.exit(1)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/check/check_python
--- a/tools/check/check_python Thu Sep 8 15:18:40 2005
+++ b/tools/check/check_python Fri Sep 9 16:30:54 2005
@@ -2,9 +2,9 @@
# CHECK-BUILD CHECK-INSTALL
function error {
- echo "Check for Python version 2.2 or higher failed."
+ echo
+ echo " *** Check for Python version >= 2.2 FAILED"
exit 1
}
-python -V
python -V 2>&1 | cut -d ' ' -f 2 | grep -q -E '^2.2|^2.3|^2.4' || error
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/check/check_zlib_devel
--- a/tools/check/check_zlib_devel Thu Sep 8 15:18:40 2005
+++ b/tools/check/check_zlib_devel Fri Sep 9 16:30:54 2005
@@ -2,9 +2,10 @@
# CHECK-BUILD
function error {
- echo 'Check for zlib includes failed.'
+ echo
+ echo " *** Check for zlib headers FAILED"
exit 1
}
set -e
-[ -e /usr/include/zlib.h ] || error
\ No newline at end of file
+[ -e /usr/include/zlib.h ] || error
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/check/check_zlib_lib
--- a/tools/check/check_zlib_lib Thu Sep 8 15:18:40 2005
+++ b/tools/check/check_zlib_lib Fri Sep 9 16:30:54 2005
@@ -2,9 +2,10 @@
# CHECK-BUILD CHECK-INSTALL
function error {
- echo 'Check for zlib library failed.'
+ echo
+ echo " *** Check for zlib library FAILED"
exit 1
}
set -e
-ldconfig -p | grep libz.so || error
\ No newline at end of file
+ldconfig -p | grep -q libz.so || error
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/check/chk
--- a/tools/check/chk Thu Sep 8 15:18:40 2005
+++ b/tools/check/chk Fri Sep 9 16:30:54 2005
@@ -17,14 +17,11 @@
case $1 in
build)
check="CHECK-BUILD"
- info=".chkbuild"
;;
install)
check="CHECK-INSTALL"
- info=".chkinstall"
;;
clean)
- rm -f .chkbuild .chkinstall
exit 0
;;
*)
@@ -34,7 +31,7 @@
failed=0
-echo "Xen ${check} " $(date) > ${info}
+echo "Xen ${check} " $(date)
for f in check_* ; do
case $f in
*~)
@@ -49,24 +46,12 @@
if ! grep -q ${check} $f ; then
continue
fi
- echo ' ' >> ${info}
- echo "Checking $f" >> ${info}
- if ./$f 1>>${info} 2>&1 ; then
- echo OK >> ${info}
+ echo -n "Checking $f: "
+ if ./$f 2>&1 ; then
+ echo OK
else
failed=1
- echo "FAILED $f"
- echo FAILED >> ${info}
fi
done
-echo >> ${info}
-
-if [ "$failed" == "1" ] ; then
- echo "Checks failed. See `pwd`/${info} for details."
- echo "FAILED" >> ${info}
- exit 1
-else
- echo "OK" >> ${info}
- exit 0
-fi
+exit $failed
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/console/Makefile
--- a/tools/console/Makefile Thu Sep 8 15:18:40 2005
+++ b/tools/console/Makefile Fri Sep 9 16:30:54 2005
@@ -9,10 +9,8 @@
INSTALL_PROG = $(INSTALL) -m0755
INSTALL_DIR = $(INSTALL) -d -m0755
-CC = gcc
-CFLAGS = -Wall -Werror -g3
+CFLAGS += -Wall -Werror -g3
-CFLAGS += -I $(XEN_XCS)
CFLAGS += -I $(XEN_LIBXC)
CFLAGS += -I $(XEN_XENSTORE)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/console/client/main.c
--- a/tools/console/client/main.c Thu Sep 8 15:18:40 2005
+++ b/tools/console/client/main.c Fri Sep 9 16:30:54 2005
@@ -170,12 +170,12 @@
{ 0 },
};
- char *str_pty;
- char path[1024];
+ char *str_pty, *path;
int spty;
unsigned int len = 0;
struct xs_handle *xs;
char *end;
+ time_t now;
while((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
switch(ch) {
@@ -213,20 +213,51 @@
signal(SIGTERM, sighandler);
- snprintf(path, sizeof(path), "/console/%d/tty", domid);
+ path = xs_get_domain_path(xs, domid);
+ if (path == NULL)
+ err(errno, "xs_get_domain_path()");
+ path = realloc(path, strlen(path) + strlen("/console/tty") + 1);
+ if (path == NULL)
+ err(ENOMEM, "realloc");
+ strcat(path, "/console/tty");
str_pty = xs_read(xs, path, &len);
+
/* FIXME consoled currently does not assume domain-0 doesn't have a
console which is good when we break domain-0 up. To keep us
user friendly, we'll bail out here since no data will ever show
up on domain-0. */
- if (domid == 0 || str_pty == NULL) {
+ if (domid == 0) {
err(errno, "Could not read tty from store");
}
+
+ /* Wait a little bit for tty to appear. There is a race
+ condition that occurs after xend creates a domain. This
+ code might be running before consoled has noticed the new
+ domain and setup a pty for it.
+
+ A xenstore watch would slightly improve responsiveness but
+ a timeout would still be needed since we don't want to
+ block forever if given an invalid domain or worse yet, a
+ domain that someone else has connected to. */
+
+ now = time(0);
+ while (str_pty == NULL && (now + 5) > time(0)) {
+ struct timeval tv = { 0, 500 };
+ select(0, NULL, NULL, NULL, &tv); /* pause briefly */
+
+ str_pty = xs_read(xs, path, &len);
+ }
+
+ if (str_pty == NULL) {
+ err(errno, "Could not read tty from store");
+ }
+
spty = open(str_pty, O_RDWR | O_NOCTTY);
if (spty == -1) {
err(errno, "Could not open tty `%s'", str_pty);
}
free(str_pty);
+ free(path);
init_term(STDIN_FILENO, &attr);
console_loop(xc_handle, domid, spty);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/console/daemon/io.c
--- a/tools/console/daemon/io.c Thu Sep 8 15:18:40 2005
+++ b/tools/console/daemon/io.c Fri Sep 9 16:30:54 2005
@@ -26,7 +26,6 @@
#include "xenctrl.h"
#include "xs.h"
#include "xen/io/domain_controller.h"
-#include "xcs_proto.h"
#include <malloc.h>
#include <stdlib.h>
@@ -36,9 +35,15 @@
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
+#include <stdarg.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+/* Each 10 bits takes ~ 3 digits, plus one, plus one for nul terminator. */
+#define MAX_STRLEN(x) ((sizeof(x) * CHAR_BIT + CHAR_BIT-1) / 10 * 3 + 2)
struct buffer
{
@@ -48,41 +53,6 @@
size_t max_capacity;
};
-static void buffer_append(struct buffer *buffer, const void *data, size_t size)
-{
- if ((buffer->capacity - buffer->size) < size) {
- buffer->capacity += (size + 1024);
- buffer->data = realloc(buffer->data, buffer->capacity);
- if (buffer->data == NULL) {
- dolog(LOG_ERR, "Memory allocation failed");
- exit(ENOMEM);
- }
- }
-
- memcpy(buffer->data + buffer->size, data, size);
- buffer->size += size;
-
- if (buffer->max_capacity &&
- buffer->size > buffer->max_capacity) {
- memmove(buffer->data + (buffer->size - buffer->max_capacity),
- buffer->data, buffer->max_capacity);
- buffer->data = realloc(buffer->data, buffer->max_capacity);
- buffer->capacity = buffer->max_capacity;
- }
-}
-
-static bool buffer_empty(struct buffer *buffer)
-{
- return buffer->size == 0;
-}
-
-static void buffer_advance(struct buffer *buffer, size_t size)
-{
- size = MIN(size, buffer->size);
- memmove(buffer->data, buffer + size, buffer->size - size);
- buffer->size -= size;
-}
-
struct domain
{
int domid;
@@ -90,9 +60,74 @@
bool is_dead;
struct buffer buffer;
struct domain *next;
+ char *conspath;
+ int ring_ref;
+ int local_port;
+ char *page;
+ int evtchn_fd;
};
static struct domain *dom_head;
+
+struct ring_head
+{
+ u32 cons;
+ u32 prod;
+ char buf[0];
+} __attribute__((packed));
+
+#define PAGE_SIZE (getpagesize())
+#define XENCONS_RING_SIZE (PAGE_SIZE/2 - sizeof (struct ring_head))
+#define XENCONS_IDX(cnt) ((cnt) % XENCONS_RING_SIZE)
+#define XENCONS_FULL(ring) (((ring)->prod - (ring)->cons) == XENCONS_RING_SIZE)
+#define XENCONS_SPACE(ring) (XENCONS_RING_SIZE - ((ring)->prod - (ring)->cons))
+
+static void buffer_append(struct domain *dom)
+{
+ struct buffer *buffer = &dom->buffer;
+ struct ring_head *ring = (struct ring_head *)dom->page;
+ size_t size;
+
+ while ((size = ring->prod - ring->cons) != 0) {
+ if ((buffer->capacity - buffer->size) < size) {
+ buffer->capacity += (size + 1024);
+ buffer->data = realloc(buffer->data, buffer->capacity);
+ if (buffer->data == NULL) {
+ dolog(LOG_ERR, "Memory allocation failed");
+ exit(ENOMEM);
+ }
+ }
+
+ while (ring->cons < ring->prod) {
+ buffer->data[buffer->size] =
+ ring->buf[XENCONS_IDX(ring->cons)];
+ buffer->size++;
+ ring->cons++;
+ }
+
+ if (buffer->max_capacity &&
+ buffer->size > buffer->max_capacity) {
+ memmove(buffer->data + (buffer->size -
+ buffer->max_capacity),
+ buffer->data, buffer->max_capacity);
+ buffer->data = realloc(buffer->data,
+ buffer->max_capacity);
+ buffer->capacity = buffer->max_capacity;
+ }
+ }
+}
+
+static bool buffer_empty(struct buffer *buffer)
+{
+ return buffer->size == 0;
+}
+
+static void buffer_advance(struct buffer *buffer, size_t size)
+{
+ size = MIN(size, buffer->size);
+ memmove(buffer->data, buffer + size, buffer->size - size);
+ buffer->size -= size;
+}
static bool domain_is_valid(int domid)
{
@@ -107,8 +142,9 @@
static int domain_create_tty(struct domain *dom)
{
- char path[1024];
+ char *path;
int master;
+ bool success;
if ((master = getpt()) == -1 ||
grantpt(master) == -1 || unlockpt(master) == -1) {
@@ -126,27 +162,134 @@
tcsetattr(master, TCSAFLUSH, &term);
}
- xs_mkdir(xs, "/console");
- snprintf(path, sizeof(path), "/console/%d", dom->domid);
- xs_mkdir(xs, path);
- strcat(path, "/tty");
-
- xs_write(xs, path, slave, strlen(slave), O_CREAT);
-
- snprintf(path, sizeof(path), "/console/%d/limit", dom->domid);
+ success = asprintf(&path, "%s/tty", dom->conspath) != -1;
+ if (!success)
+ goto out;
+ success = xs_write(xs, path, slave, strlen(slave), O_CREAT);
+ free(path);
+ if (!success)
+ goto out;
+
+ success = asprintf(&path, "%s/limit", dom->conspath) != -1;
+ if (!success)
+ goto out;
data = xs_read(xs, path, &len);
if (data) {
dom->buffer.max_capacity = strtoul(data, 0, 0);
free(data);
}
+ free(path);
}
return master;
+ out:
+ close(master);
+ return -1;
+}
+
+/* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
+int xs_gather(struct xs_handle *xs, const char *dir, ...)
+{
+ va_list ap;
+ const char *name;
+ char *path;
+ int ret = 0;
+
+ va_start(ap, dir);
+ while (ret == 0 && (name = va_arg(ap, char *)) != NULL) {
+ const char *fmt = va_arg(ap, char *);
+ void *result = va_arg(ap, void *);
+ char *p;
+
+ asprintf(&path, "%s/%s", dir, name);
+ p = xs_read(xs, path, NULL);
+ free(path);
+ if (p == NULL) {
+ ret = ENOENT;
+ break;
+ }
+ if (fmt) {
+ if (sscanf(p, fmt, result) == 0)
+ ret = EINVAL;
+ free(p);
+ } else
+ *(char **)result = p;
+ }
+ va_end(ap);
+ return ret;
+}
+
+#define EVENTCHN_BIND _IO('E', 2)
+#define EVENTCHN_UNBIND _IO('E', 3)
+
+static int domain_create_ring(struct domain *dom)
+{
+ int err, local_port, ring_ref;
+
+ err = xs_gather(xs, dom->conspath,
+ "ring-ref", "%u", &ring_ref,
+ "port", "%i", &local_port,
+ NULL);
+ if (err)
+ goto out;
+
+ if (ring_ref != dom->ring_ref) {
+ if (dom->page)
+ munmap(dom->page, getpagesize());
+ dom->page = xc_map_foreign_range(xc, dom->domid, getpagesize(),
+ PROT_READ|PROT_WRITE,
+ (unsigned long)ring_ref);
+ if (dom->page == NULL) {
+ err = EINVAL;
+ goto out;
+ }
+ dom->ring_ref = ring_ref;
+ }
+
+ if (local_port != dom->local_port) {
+ dom->local_port = -1;
+ if (dom->evtchn_fd != -1)
+ close(dom->evtchn_fd);
+ /* Opening evtchn independently for each console is a bit
+ * wastefule, but that's how the code is structured... */
+ dom->evtchn_fd = open("/dev/xen/evtchn", O_RDWR);
+ if (dom->evtchn_fd == -1) {
+ err = errno;
+ goto out;
+ }
+
+ if (ioctl(dom->evtchn_fd, EVENTCHN_BIND, local_port) == -1) {
+ err = errno;
+ close(dom->evtchn_fd);
+ dom->evtchn_fd = -1;
+ goto out;
+ }
+ dom->local_port = local_port;
+ }
+
+ out:
+ return err;
+}
+
+static bool watch_domain(struct domain *dom, bool watch)
+{
+ char domid_str[3 + MAX_STRLEN(dom->domid)];
+ bool success;
+
+ sprintf(domid_str, "dom%u", dom->domid);
+ if (watch)
+ success = xs_watch(xs, dom->conspath, domid_str);
+ else
+ success = xs_unwatch(xs, dom->conspath, domid_str);
+ if (success)
+ domain_create_ring(dom);
+ return success;
}
static struct domain *create_domain(int domid)
{
struct domain *dom;
+ char *s;
dom = (struct domain *)malloc(sizeof(struct domain));
if (dom == NULL) {
@@ -156,99 +299,145 @@
}
dom->domid = domid;
+
+ dom->conspath = xs_get_domain_path(xs, dom->domid);
+ if (dom->conspath == NULL)
+ goto out;
+ s = realloc(dom->conspath, strlen(dom->conspath) +
+ strlen("/console") + 1);
+ if (s == NULL)
+ goto out;
+ dom->conspath = s;
+ strcat(dom->conspath, "/console");
+
dom->tty_fd = domain_create_tty(dom);
dom->is_dead = false;
dom->buffer.data = 0;
dom->buffer.size = 0;
dom->buffer.capacity = 0;
dom->buffer.max_capacity = 0;
- dom->next = 0;
+ dom->next = NULL;
+
+ dom->ring_ref = -1;
+ dom->local_port = -1;
+ dom->page = NULL;
+ dom->evtchn_fd = -1;
+
+ if (!watch_domain(dom, true))
+ goto out;
+
+ dom->next = dom_head;
+ dom_head = dom;
dolog(LOG_DEBUG, "New domain %d", domid);
return dom;
+ out:
+ if (dom->conspath)
+ free(dom->conspath);
+ free(dom);
+ return NULL;
}
static struct domain *lookup_domain(int domid)
{
+ struct domain *dom;
+
+ for (dom = dom_head; dom; dom = dom->next)
+ if (dom->domid == domid)
+ return dom;
+ return NULL;
+}
+
+static void remove_domain(struct domain *dom)
+{
struct domain **pp;
+ dolog(LOG_DEBUG, "Removing domain-%d", dom->domid);
+
for (pp = &dom_head; *pp; pp = &(*pp)->next) {
- struct domain *dom = *pp;
-
- if (dom->domid == domid) {
- return dom;
- } else if (dom->domid > domid) {
- *pp = create_domain(domid);
- (*pp)->next = dom;
- return *pp;
- }
- }
-
- *pp = create_domain(domid);
- return *pp;
-}
-
-static void remove_domain(struct domain *dom)
-{
- struct domain **pp;
-
- dolog(LOG_DEBUG, "Removing domain-%d", dom->domid);
-
- for (pp = &dom_head; *pp; pp = &(*pp)->next) {
- struct domain *d = *pp;
-
- if (dom->domid == d->domid) {
- *pp = d->next;
- if (d->buffer.data) {
- free(d->buffer.data);
- }
- free(d);
+ if (dom == *pp) {
+ *pp = dom->next;
+ free(dom);
break;
}
}
}
-static void remove_dead_domains(struct domain *dom)
-{
- if (dom == NULL) return;
- remove_dead_domains(dom->next);
-
- if (dom->is_dead) {
- remove_domain(dom);
+static void cleanup_domain(struct domain *d)
+{
+ if (!buffer_empty(&d->buffer))
+ return;
+
+ if (d->buffer.data)
+ free(d->buffer.data);
+ d->buffer.data = NULL;
+ if (d->tty_fd != -1)
+ close(d->tty_fd);
+ d->tty_fd = -1;
+ remove_domain(d);
+}
+
+static void shutdown_domain(struct domain *d)
+{
+ d->is_dead = true;
+ watch_domain(d, false);
+ if (d->page)
+ munmap(d->page, getpagesize());
+ d->page = NULL;
+ if (d->evtchn_fd != -1)
+ close(d->evtchn_fd);
+ d->evtchn_fd = -1;
+ cleanup_domain(d);
+}
+
+void enum_domains(void)
+{
+ int domid = 1;
+ xc_dominfo_t dominfo;
+ struct domain *dom;
+
+ while (xc_domain_getinfo(xc, domid, 1, &dominfo) == 1) {
+ dom = lookup_domain(dominfo.domid);
+ if (dominfo.dying || dominfo.crashed || dominfo.shutdown) {
+ if (dom)
+ shutdown_domain(dom);
+ } else {
+ if (dom == NULL)
+ create_domain(dominfo.domid);
+ }
+ domid = dominfo.domid + 1;
}
}
static void handle_tty_read(struct domain *dom)
{
ssize_t len;
- xcs_msg_t msg;
-
- msg.type = XCS_REQUEST;
- msg.u.control.remote_dom = dom->domid;
- msg.u.control.msg.type = CMSG_CONSOLE;
- msg.u.control.msg.subtype = CMSG_CONSOLE_DATA;
- msg.u.control.msg.id = 1;
-
- len = read(dom->tty_fd, msg.u.control.msg.msg, 60);
+ char msg[80];
+ struct ring_head *inring =
+ (struct ring_head *)(dom->page + PAGE_SIZE/2);
+ int i;
+
+ len = read(dom->tty_fd, msg, MIN(XENCONS_SPACE(inring), sizeof(msg)));
if (len < 1) {
close(dom->tty_fd);
+ dom->tty_fd = -1;
if (domain_is_valid(dom->domid)) {
dom->tty_fd = domain_create_tty(dom);
} else {
- dom->is_dead = true;
+ shutdown_domain(dom);
}
} else if (domain_is_valid(dom->domid)) {
- msg.u.control.msg.length = len;
-
- if (!write_sync(xcs_data_fd, &msg, sizeof(msg))) {
- dolog(LOG_ERR, "Write to xcs failed: %m");
- exit(1);
- }
+ for (i = 0; i < len; i++) {
+ inring->buf[XENCONS_IDX(inring->prod)] = msg[i];
+ inring->prod++;
+ }
+ xc_evtchn_send(xc, dom->local_port);
} else {
close(dom->tty_fd);
- dom->is_dead = true;
+ dom->tty_fd = -1;
+ shutdown_domain(dom);
}
}
@@ -259,104 +448,105 @@
len = write(dom->tty_fd, dom->buffer.data, dom->buffer.size);
if (len < 1) {
close(dom->tty_fd);
+ dom->tty_fd = -1;
if (domain_is_valid(dom->domid)) {
dom->tty_fd = domain_create_tty(dom);
} else {
- dom->is_dead = true;
+ shutdown_domain(dom);
}
} else {
buffer_advance(&dom->buffer, len);
}
}
-static void handle_xcs_msg(int fd)
-{
- xcs_msg_t msg;
-
- if (!read_sync(fd, &msg, sizeof(msg))) {
- dolog(LOG_ERR, "read from xcs failed! %m");
- exit(1);
- } else if (msg.type == XCS_REQUEST) {
- struct domain *dom;
-
- dom = lookup_domain(msg.u.control.remote_dom);
- buffer_append(&dom->buffer,
- msg.u.control.msg.msg,
- msg.u.control.msg.length);
- }
-}
-
-static void enum_domains(void)
-{
- int domid = 0;
- xc_dominfo_t dominfo;
-
- while (xc_domain_getinfo(xc, domid, 1, &dominfo) == 1) {
- lookup_domain(dominfo.domid);
- domid = dominfo.domid + 1;
- }
+static void handle_ring_read(struct domain *dom)
+{
+ u16 v;
+
+ if (!read_sync(dom->evtchn_fd, &v, sizeof(v)))
+ return;
+
+ buffer_append(dom);
+
+ (void)write_sync(dom->evtchn_fd, &v, sizeof(v));
+}
+
+static void handle_xs(int fd)
+{
+ char **vec;
+ int domid;
+ struct domain *dom;
+
+ vec = xs_read_watch(xs);
+ if (!vec)
+ return;
+
+ if (!strcmp(vec[1], "domlist"))
+ enum_domains();
+ else if (sscanf(vec[1], "dom%u", &domid) == 1) {
+ dom = lookup_domain(domid);
+ if (dom->is_dead == false)
+ domain_create_ring(dom);
+ }
+
+ xs_acknowledge_watch(xs, vec[1]);
+ free(vec);
}
void handle_io(void)
{
fd_set readfds, writefds;
int ret;
- int max_fd = -1;
- int num_of_writes = 0;
do {
- struct domain *d;
- struct timeval tv = { 1, 0 };
+ struct domain *d, *n;
+ struct timeval tv = { 100, 0 };
+ int max_fd = -1;
FD_ZERO(&readfds);
FD_ZERO(&writefds);
- FD_SET(xcs_data_fd, &readfds);
- max_fd = MAX(xcs_data_fd, max_fd);
+ FD_SET(xs_fileno(xs), &readfds);
+ max_fd = MAX(xs_fileno(xs), max_fd);
for (d = dom_head; d; d = d->next) {
+ if (d->evtchn_fd != -1) {
+ FD_SET(d->evtchn_fd, &readfds);
+ max_fd = MAX(d->evtchn_fd, max_fd);
+ }
+
if (d->tty_fd != -1) {
- FD_SET(d->tty_fd, &readfds);
+ if (!d->is_dead)
+ FD_SET(d->tty_fd, &readfds);
+
+ if (!buffer_empty(&d->buffer))
+ FD_SET(d->tty_fd, &writefds);
+ max_fd = MAX(d->tty_fd, max_fd);
}
-
- if (d->tty_fd != -1 && !buffer_empty(&d->buffer)) {
- FD_SET(d->tty_fd, &writefds);
+ }
+
+ ret = select(max_fd + 1, &readfds, &writefds, 0, &tv);
+
+ if (FD_ISSET(xs_fileno(xs), &readfds))
+ handle_xs(xs_fileno(xs));
+
+ for (d = dom_head; d; d = n) {
+ n = d->next;
+ if (d->evtchn_fd != -1 &&
+ FD_ISSET(d->evtchn_fd, &readfds))
+ handle_ring_read(d);
+
+ if (d->tty_fd != -1) {
+ if (FD_ISSET(d->tty_fd, &readfds))
+ handle_tty_read(d);
+
+ if (FD_ISSET(d->tty_fd, &writefds))
+ handle_tty_write(d);
+
+ if (d->is_dead)
+ cleanup_domain(d);
}
-
- max_fd = MAX(d->tty_fd, max_fd);
- }
-
- ret = select(max_fd + 1, &readfds, &writefds, 0, &tv);
- if (tv.tv_sec == 1 && (++num_of_writes % 100) == 0) {
-#if 0
- /* FIXME */
- /* This is a nasty hack. xcs does not handle the
- control channels filling up well at all. We'll
- throttle ourselves here since we do proper
- queueing to give the domains a shot at pulling out
- the data. Fixing xcs is not worth it as it's
- going away */
- tv.tv_usec = 1000;
- select(0, 0, 0, 0, &tv);
-#endif
- }
- enum_domains();
-
- if (FD_ISSET(xcs_data_fd, &readfds)) {
- handle_xcs_msg(xcs_data_fd);
- }
-
- for (d = dom_head; d; d = d->next) {
- if (!d->is_dead && FD_ISSET(d->tty_fd, &readfds)) {
- handle_tty_read(d);
- }
-
- if (!d->is_dead && FD_ISSET(d->tty_fd, &writefds)) {
- handle_tty_write(d);
- }
- }
-
- remove_dead_domains(dom_head);
+ }
} while (ret > -1);
}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/console/daemon/io.h
--- a/tools/console/daemon/io.h Thu Sep 8 15:18:40 2005
+++ b/tools/console/daemon/io.h Fri Sep 9 16:30:54 2005
@@ -21,6 +21,7 @@
#ifndef CONSOLED_IO_H
#define CONSOLED_IO_H
+void enum_domains(void);
void handle_io(void);
#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/console/daemon/main.c
--- a/tools/console/daemon/main.c Thu Sep 8 15:18:40 2005
+++ b/tools/console/daemon/main.c Fri Sep 9 16:30:54 2005
@@ -26,8 +26,6 @@
#include <sys/types.h>
#include "xenctrl.h"
-#include "xen/io/domain_controller.h"
-#include "xcs_proto.h"
#include "utils.h"
#include "io.h"
@@ -83,7 +81,10 @@
daemonize("/var/run/xenconsoled.pid");
}
- xen_setup();
+ if (!xen_setup())
+ exit(1);
+
+ enum_domains();
handle_io();
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/console/daemon/utils.c
--- a/tools/console/daemon/utils.c Thu Sep 8 15:18:40 2005
+++ b/tools/console/daemon/utils.c Fri Sep 9 16:30:54 2005
@@ -35,15 +35,11 @@
#include "xenctrl.h"
#include "xen/io/domain_controller.h"
-#include "xcs_proto.h"
#include "utils.h"
struct xs_handle *xs;
int xc;
-
-int xcs_ctrl_fd = -1;
-int xcs_data_fd = -1;
bool _read_write_sync(int fd, void *data, size_t size, bool do_read)
{
@@ -69,32 +65,6 @@
}
return true;
-}
-
-static int open_domain_socket(const char *path)
-{
- struct sockaddr_un addr;
- int sock;
- size_t addr_len;
-
- if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
- goto out;
- }
-
- addr.sun_family = AF_UNIX;
- strcpy(addr.sun_path, path);
- addr_len = sizeof(addr.sun_family) + strlen(XCS_SUN_PATH) + 1;
-
- if (connect(sock, (struct sockaddr *)&addr, addr_len) == -1) {
- goto out_close_sock;
- }
-
- return sock;
-
- out_close_sock:
- close(sock);
- out:
- return -1;
}
static void child_exit(int sig)
@@ -155,34 +125,8 @@
signal(SIGTTIN, SIG_IGN);
}
-/* synchronized send/recv strictly for setting up xcs */
-/* always use asychronize callbacks any other time */
-static bool xcs_send_recv(int fd, xcs_msg_t *msg)
-{
- bool ret = false;
-
- if (!write_sync(fd, msg, sizeof(*msg))) {
- dolog(LOG_ERR, "Write failed at %s:%s():L%d? Possible bug.",
- __FILE__, __FUNCTION__, __LINE__);
- goto out;
- }
-
- if (!read_sync(fd, msg, sizeof(*msg))) {
- dolog(LOG_ERR, "Read failed at %s:%s():L%d? Possible bug.",
- __FILE__, __FUNCTION__, __LINE__);
- goto out;
- }
-
- ret = true;
-
- out:
- return ret;
-}
-
bool xen_setup(void)
{
- int sock;
- xcs_msg_t msg;
xs = xs_daemon_open();
if (xs == NULL) {
@@ -197,57 +141,23 @@
goto out;
}
- sock = open_domain_socket(XCS_SUN_PATH);
- if (sock == -1) {
- dolog(LOG_ERR, "Failed to contact xcs (%m). Is it running?");
- goto out_close_store;
+ if (!xs_watch(xs, "@introduceDomain", "domlist")) {
+ dolog(LOG_ERR, "xenstore watch on @introduceDomain fails.");
+ goto out;
}
- xcs_ctrl_fd = sock;
-
- sock = open_domain_socket(XCS_SUN_PATH);
- if (sock == -1) {
- dolog(LOG_ERR, "Failed to contact xcs (%m). Is it running?");
- goto out_close_ctrl;
- }
-
- xcs_data_fd = sock;
-
- memset(&msg, 0, sizeof(msg));
- msg.type = XCS_CONNECT_CTRL;
- if (!xcs_send_recv(xcs_ctrl_fd, &msg) || msg.result != XCS_RSLT_OK) {
- dolog(LOG_ERR, "xcs control connect failed. Possible bug.");
- goto out_close_data;
+ if (!xs_watch(xs, "@releaseDomain", "domlist")) {
+ dolog(LOG_ERR, "xenstore watch on @releaseDomain fails.");
+ goto out;
}
- msg.type = XCS_CONNECT_DATA;
- if (!xcs_send_recv(xcs_data_fd, &msg) || msg.result != XCS_RSLT_OK) {
- dolog(LOG_ERR, "xcs data connect failed. Possible bug.");
- goto out_close_data;
- }
-
- /* Since the vast majority of control messages are console messages
- it's just easier to ignore other messages that try to bind to
- a specific type. */
- msg.type = XCS_MSG_BIND;
- msg.u.bind.port = PORT_WILDCARD;
- msg.u.bind.type = TYPE_WILDCARD;
- if (!xcs_send_recv(xcs_ctrl_fd, &msg) || msg.result != XCS_RSLT_OK) {
- dolog(LOG_ERR, "xcs vind failed. Possible bug.");
- goto out_close_data;
- }
-
return true;
- out_close_data:
- close(xcs_ctrl_fd);
- xcs_data_fd = -1;
- out_close_ctrl:
- close(xcs_ctrl_fd);
- xcs_ctrl_fd = -1;
- out_close_store:
- xs_daemon_close(xs);
out:
+ if (xs)
+ xs_daemon_close(xs);
+ if (xc != -1)
+ xc_interface_close(xc);
return false;
}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/console/daemon/utils.h
--- a/tools/console/daemon/utils.h Thu Sep 8 15:18:40 2005
+++ b/tools/console/daemon/utils.h Fri Sep 9 16:30:54 2005
@@ -33,13 +33,15 @@
#define write_sync(fd, buffer, size) _read_write_sync(fd, buffer, size, false)
bool _read_write_sync(int fd, void *data, size_t size, bool do_read);
-extern int xcs_ctrl_fd;
-extern int xcs_data_fd;
extern struct xs_handle *xs;
extern int xc;
#if 1
-#define dolog(val, fmt, ...) syslog(val, fmt, ## __VA_ARGS__)
+#define dolog(val, fmt, ...) do { \
+ if ((val) == LOG_ERR) \
+ fprintf(stderr, fmt "\n", ## __VA_ARGS__); \
+ syslog(val, fmt, ## __VA_ARGS__); \
+} while (/* CONSTCOND */0)
#else
#define dolog(val, fmt, ...) fprintf(stderr, fmt "\n", ## __VA_ARGS__)
#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/examples/Makefile
--- a/tools/examples/Makefile Thu Sep 8 15:18:40 2005
+++ b/tools/examples/Makefile Fri Sep 9 16:30:54 2005
@@ -1,3 +1,6 @@
+XEN_ROOT = ../../
+include $(XEN_ROOT)/tools/Rules.mk
+
INSTALL = install
INSTALL_DIR = $(INSTALL) -d -m0755
INSTALL_PROG = $(INSTALL) -m0755
@@ -24,8 +27,8 @@
XEN_BOOT_DIR = /usr/lib/xen/boot
XEN_BOOT = mem-map.sxp
-XEN_HOTPLUG_DIR = /etc/hotplug.d/xen-backend
-XEN_HOTPLUG_SCRIPTS = backend.hotplug
+XEN_HOTPLUG_DIR = /etc/hotplug
+XEN_HOTPLUG_SCRIPTS = xen-backend.agent
all:
build:
@@ -68,7 +71,7 @@
[ -d $(DESTDIR)$(XEN_HOTPLUG_DIR) ] || \
$(INSTALL_DIR) $(DESTDIR)$(XEN_HOTPLUG_DIR)
for i in $(XEN_HOTPLUG_SCRIPTS); \
- do [ -a $(DESTDIR)$(XEN_HOTPLUG_DIR)/$$i ] || \
+ do \
$(INSTALL_PROG) $$i $(DESTDIR)$(XEN_HOTPLUG_DIR); \
done
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/examples/init.d/xend
--- a/tools/examples/init.d/xend Thu Sep 8 15:18:40 2005
+++ b/tools/examples/init.d/xend Fri Sep 9 16:30:54 2005
@@ -11,7 +11,7 @@
exit 0
fi
-# Wait for Xend and xcs to be up
+# Wait for Xend to be up
function await_daemons_up
{
i=1
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/examples/vif-bridge
--- a/tools/examples/vif-bridge Thu Sep 8 15:18:40 2005
+++ b/tools/examples/vif-bridge Fri Sep 9 16:30:54 2005
@@ -80,7 +80,7 @@
fi
ifconfig ${vif} $OP
-if [ ${ip} ] ; then
+if [ "${ip}" ] ; then
# If we've been given a list of IP networks, allow pkts with these src
addrs.
for addr in ${ip} ; do
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/examples/vif-route
--- a/tools/examples/vif-route Thu Sep 8 15:18:40 2005
+++ b/tools/examples/vif-route Fri Sep 9 16:30:54 2005
@@ -63,7 +63,7 @@
;;
esac
-if [ ${ip} ] ; then
+if [ "${ip}" ] ; then
# If we've been given a list of IP networks, allow pkts with these src
addrs.
for addr in ${ip} ; do
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/examples/xmexample.vmx
--- a/tools/examples/xmexample.vmx Thu Sep 8 15:18:40 2005
+++ b/tools/examples/xmexample.vmx Fri Sep 9 16:30:54 2005
@@ -73,6 +73,10 @@
vnc=1
#----------------------------------------------------------------------------
+# enable spawning vncviewer(only valid when vnc=1), default = 1
+vncviewer=1
+
+#----------------------------------------------------------------------------
# no graphics, use serial port
#nographic=0
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/examples/xmexample1
--- a/tools/examples/xmexample1 Thu Sep 8 15:18:40 2005
+++ b/tools/examples/xmexample1 Fri Sep 9 16:30:54 2005
@@ -48,6 +48,20 @@
disk = [ 'phy:hda1,hda1,w' ]
#----------------------------------------------------------------------------
+# Define to which TPM instance the user domain should communicate.
+# The vtpm entry is of the form 'instance=INSTANCE,backend=DOM'
+# where INSTANCE indicates the instance number of the TPM the VM
+# should be talking to and DOM provides the domain where the backend
+# is located.
+# Note that no two virtual machines should try to connect to the same
+# TPM instance. The handling of all TPM instances does require
+# some management effort in so far that VM configration files (and thus
+# a VM) should be associated with a TPM instance throughout the lifetime
+# of the VM / VM configuration file. The instance number must be
+# greater or equal to 1.
+#vtpm = [ 'instance=1,backend=0' ]
+
+#----------------------------------------------------------------------------
# Set the kernel command line for the new domain.
# You only need to define the IP parameters and hostname if the domain's
# IP config doesn't, e.g. in ifcfg-eth0 or via DHCP.
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/examples/xmexample2
--- a/tools/examples/xmexample2 Thu Sep 8 15:18:40 2005
+++ b/tools/examples/xmexample2 Fri Sep 9 16:30:54 2005
@@ -84,6 +84,20 @@
'phy:sda6,sda6,r' ]
#----------------------------------------------------------------------------
+# Define to which TPM instance the user domain should communicate.
+# The vtpm entry is of the form 'instance=INSTANCE,backend=DOM'
+# where INSTANCE indicates the instance number of the TPM the VM
+# should be talking to and DOM provides the domain where the backend
+# is located.
+# Note that no two virtual machines should try to connect to the same
+# TPM instance. The handling of all TPM instances does require
+# some management effort in so far that VM configration files (and thus
+# a VM) should be associated with a TPM instance throughout the lifetime
+# of the VM / VM configuration file. The instance number must be
+# greater or equal to 1.
+#vtpm = ['instance=%d,backend=0' % (vmid) ]
+
+#----------------------------------------------------------------------------
# Set the kernel command line for the new domain.
# You only need to define the IP parameters and hostname if the domain's
# IP config doesn't, e.g. in ifcfg-eth0 or via DHCP.
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/examples/xmexample3
--- a/tools/examples/xmexample3 Thu Sep 8 15:18:40 2005
+++ b/tools/examples/xmexample3 Fri Sep 9 16:30:54 2005
@@ -80,6 +80,20 @@
disk = [ 'phy:hda%d,hda1,w' % (vmid)]
#----------------------------------------------------------------------------
+# Define to which TPM instance the user domain should communicate.
+# The vtpm entry is of the form 'instance=INSTANCE,backend=DOM'
+# where INSTANCE indicates the instance number of the TPM the VM
+# should be talking to and DOM provides the domain where the backend
+# is located.
+# Note that no two virtual machines should try to connect to the same
+# TPM instance. The handling of all TPM instances does require
+# some management effort in so far that VM configration files (and thus
+# a VM) should be associated with a TPM instance throughout the lifetime
+# of the VM / VM configuration file. The instance number must be
+# greater or equal to 1.
+#vtpm = ['instance=%d,backend=0' % (vmid) ]
+
+#----------------------------------------------------------------------------
# Set the kernel command line for the new domain.
# You only need to define the IP parameters and hostname if the domain's
# IP config doesn't, e.g. in ifcfg-eth0 or via DHCP.
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/firmware/rombios/rombios.c
--- a/tools/firmware/rombios/rombios.c Thu Sep 8 15:18:40 2005
+++ b/tools/firmware/rombios/rombios.c Fri Sep 9 16:30:54 2005
@@ -31,7 +31,7 @@
// Xen full virtualization does not handle unaligned IO with page crossing.
// Disable 32-bit PIO as a workaround.
-#define NO_PIO32
+#undef NO_PIO32
// ROM BIOS compatability entry points:
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/firmware/vmxassist/Makefile
--- a/tools/firmware/vmxassist/Makefile Thu Sep 8 15:18:40 2005
+++ b/tools/firmware/vmxassist/Makefile Fri Sep 9 16:30:54 2005
@@ -24,7 +24,7 @@
# The emulator code lives in ROM space
TEXTADDR=0x000D0000
-DEFINES=-DDEBUG -DENABLE_VME -DTEXTADDR=${TEXTADDR}
+DEFINES=-DDEBUG -DTEXTADDR=${TEXTADDR}
XENINC=-I$(XEN_ROOT)/xen/include -I$(XEN_ROOT)/tools/libxc
#DEFINES=-DDEBUG -DTEST -DTEXTADDR=${TEXTADDR}
#XENINC=-I/home/leendert/xen/xeno-unstable.bk/xen/include
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/firmware/vmxassist/setup.c
--- a/tools/firmware/vmxassist/setup.c Thu Sep 8 15:18:40 2005
+++ b/tools/firmware/vmxassist/setup.c Fri Sep 9 16:30:54 2005
@@ -353,7 +353,7 @@
#endif
setup_gdt();
setup_idt();
-#ifdef ENABLE_VME
+#ifndef TEST
set_cr4(get_cr4() | CR4_VME);
#endif
setup_ctx();
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/firmware/vmxassist/vm86.c
--- a/tools/firmware/vmxassist/vm86.c Thu Sep 8 15:18:40 2005
+++ b/tools/firmware/vmxassist/vm86.c Fri Sep 9 16:30:54 2005
@@ -465,8 +465,7 @@
* Emulate a segment load in protected mode
*/
int
-load_seg(unsigned long sel, unsigned long *base, unsigned long *limit,
- union vmcs_arbytes *arbytes)
+load_seg(unsigned long sel, u32 *base, u32 *limit, union vmcs_arbytes *arbytes)
{
unsigned long long entry;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/firmware/vmxassist/vmxloader.c
--- a/tools/firmware/vmxassist/vmxloader.c Thu Sep 8 15:18:40 2005
+++ b/tools/firmware/vmxassist/vmxloader.c Fri Sep 9 16:30:54 2005
@@ -110,8 +110,8 @@
}
#ifdef _ACPI_
puts("Loading ACPI ...\n");
- if (ACPI_PHYSICAL_ADDRESS+sizeof(acpi) <= 0xF0000 ){
- /* make sure acpi table does not overlap rombios
+ if (ACPI_PHYSICAL_ADDRESS+sizeof(acpi) <= 0xF0000 ){
+ /* make sure acpi table does not overlap rombios
* currently acpi less than 8K will be OK.
*/
memcpy((void *)ACPI_PHYSICAL_ADDRESS, acpi, sizeof(acpi));
@@ -122,5 +122,6 @@
memcpy((void *)TEXTADDR, vmxassist, sizeof(vmxassist));
puts("Go ...\n");
((void (*)())TEXTADDR)();
+ return 0;
}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/ioemu/cpu-all.h
--- a/tools/ioemu/cpu-all.h Thu Sep 8 15:18:40 2005
+++ b/tools/ioemu/cpu-all.h Fri Sep 9 16:30:54 2005
@@ -672,6 +672,8 @@
int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
uint8_t *buf, int len, int is_write);
+#define VGA_DIRTY_FLAG 0x01
+
/* read dirty bit (return 0 or 1) */
static inline int cpu_physical_memory_is_dirty(target_ulong addr)
{
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/ioemu/exec.c
--- a/tools/ioemu/exec.c Thu Sep 8 15:18:40 2005
+++ b/tools/ioemu/exec.c Fri Sep 9 16:30:54 2005
@@ -142,6 +142,10 @@
#else
setvbuf(logfile, NULL, _IOLBF, 0);
#endif
+/*
+ stdout = logfile;
+ stderr = logfile;
+*/
}
}
@@ -386,9 +390,6 @@
io_mem_write[io_index][1](io_mem_opaque[io_index], addr,
val);
l = 2;
} else {
- if (l!=1){
- fprintf(logfile, "ERROR 8 bit mmio\n");
- }
/* 8 bit access */
val = ldub_raw(buf);
io_mem_write[io_index][0](io_mem_opaque[io_index], addr,
val);
@@ -461,4 +462,14 @@
void cpu_physical_memory_reset_dirty(target_ulong start, target_ulong end)
{
-}
+ uint8_t *p;
+ int len;
+
+ if ((len = (end - start)) <= 0)
+ return;
+ p = phys_ram_dirty + (start >> TARGET_PAGE_BITS);
+ len = len >> TARGET_PAGE_BITS;
+ while (len > 0)
+ p[--len] &= ~VGA_DIRTY_FLAG;
+ return;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/ioemu/hw/pc.c
--- a/tools/ioemu/hw/pc.c Thu Sep 8 15:18:40 2005
+++ b/tools/ioemu/hw/pc.c Fri Sep 9 16:30:54 2005
@@ -540,7 +540,10 @@
if (pci_enabled) {
for(i = 0; i < nb_nics; i++) {
- pci_ne2000_init(pci_bus, &nd_table[i]);
+ if (nic_pcnet)
+ pci_pcnet_init(pci_bus, &nd_table[i]);
+ else
+ pci_ne2000_init(pci_bus, &nd_table[i]);
}
pci_piix3_ide_init(pci_bus, bs_table);
#ifdef APIC_SUPPORT
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/ioemu/hw/vga.c
--- a/tools/ioemu/hw/vga.c Thu Sep 8 15:18:40 2005
+++ b/tools/ioemu/hw/vga.c Fri Sep 9 16:30:54 2005
@@ -1620,7 +1620,6 @@
static void vga_save(QEMUFile *f, void *opaque)
{
VGAState *s = opaque;
- int i;
qemu_put_be32s(f, &s->latch);
qemu_put_8s(f, &s->sr_index);
@@ -1661,7 +1660,7 @@
static int vga_load(QEMUFile *f, void *opaque, int version_id)
{
VGAState *s = opaque;
- int is_vbe, i;
+ int is_vbe;
if (version_id != 1)
return -EINVAL;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/ioemu/target-i386-dm/Makefile
--- a/tools/ioemu/target-i386-dm/Makefile Thu Sep 8 15:18:40 2005
+++ b/tools/ioemu/target-i386-dm/Makefile Fri Sep 9 16:30:54 2005
@@ -272,7 +272,7 @@
# Hardware support
VL_OBJS+= ide.o ne2000.o pckbd.o vga.o dma.o
VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o port-e9.o
-VL_OBJS+= cirrus_vga.o
+VL_OBJS+= cirrus_vga.o pcnet.o
ifeq ($(TARGET_ARCH), ppc)
VL_OBJS+= ppc.o ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/ioemu/target-i386-dm/helper2.c
--- a/tools/ioemu/target-i386-dm/helper2.c Thu Sep 8 15:18:40 2005
+++ b/tools/ioemu/target-i386-dm/helper2.c Fri Sep 9 16:30:54 2005
@@ -169,133 +169,217 @@
unsigned long
do_inp(CPUState *env, unsigned long addr, unsigned long size)
{
- switch(size) {
- case 1:
- return cpu_inb(env, addr);
- case 2:
- return cpu_inw(env, addr);
- case 4:
- return cpu_inl(env, addr);
- default:
- fprintf(logfile, "inp: bad size: %lx %lx\n", addr, size);
- exit(-1);
- }
+ switch(size) {
+ case 1:
+ return cpu_inb(env, addr);
+ case 2:
+ return cpu_inw(env, addr);
+ case 4:
+ return cpu_inl(env, addr);
+ default:
+ fprintf(logfile, "inp: bad size: %lx %lx\n", addr, size);
+ exit(-1);
+ }
}
void
do_outp(CPUState *env, unsigned long addr, unsigned long size,
unsigned long val)
{
- switch(size) {
- case 1:
- return cpu_outb(env, addr, val);
- case 2:
- return cpu_outw(env, addr, val);
- case 4:
- return cpu_outl(env, addr, val);
- default:
- fprintf(logfile, "outp: bad size: %lx %lx\n", addr, size);
- exit(-1);
- }
+ switch(size) {
+ case 1:
+ return cpu_outb(env, addr, val);
+ case 2:
+ return cpu_outw(env, addr, val);
+ case 4:
+ return cpu_outl(env, addr, val);
+ default:
+ fprintf(logfile, "outp: bad size: %lx %lx\n", addr, size);
+ exit(-1);
+ }
}
extern void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
int len, int is_write);
static inline void
-read_physical(target_phys_addr_t addr, unsigned long size, void *val)
-{
- return cpu_physical_memory_rw(addr, val, size, 0);
+read_physical(u64 addr, unsigned long size, void *val)
+{
+ return cpu_physical_memory_rw((target_phys_addr_t)addr, val, size, 0);
}
static inline void
-write_physical(target_phys_addr_t addr, unsigned long size, void *val)
-{
- return cpu_physical_memory_rw(addr, val, size, 1);
-}
-
-//send the ioreq to device model
-void cpu_dispatch_ioreq(CPUState *env, ioreq_t *req)
-{
- int i;
- int sign;
-
- sign = (req->df) ? -1 : 1;
-
- if ((!req->pdata_valid) && (req->dir == IOREQ_WRITE)) {
- if (req->size != 4) {
- // Bochs expects higher bits to be 0
- req->u.data &= (1UL << (8 * req->size))-1;
- }
- }
-
- if (req->port_mm == 0){//port io
- if(req->dir == IOREQ_READ){//read
- if (!req->pdata_valid) {
- req->u.data = do_inp(env, req->addr, req->size);
- } else {
- unsigned long tmp;
-
- for (i = 0; i < req->count; i++) {
- tmp = do_inp(env, req->addr, req->size);
-
write_physical((target_phys_addr_t)req->u.pdata + (sign * i * req->size),
- req->size, &tmp);
- }
- }
- } else if(req->dir == IOREQ_WRITE) {
- if (!req->pdata_valid) {
- do_outp(env, req->addr, req->size, req->u.data);
- } else {
- for (i = 0; i < req->count; i++) {
- unsigned long tmp;
-
-
read_physical((target_phys_addr_t)req->u.pdata + (sign * i * req->size),
req->size,
- &tmp);
- do_outp(env, req->addr, req->size, tmp);
- }
- }
-
- }
- } else if (req->port_mm == 1){//memory map io
+write_physical(u64 addr, unsigned long size, void *val)
+{
+ return cpu_physical_memory_rw((target_phys_addr_t)addr, val, size, 1);
+}
+
+void
+cpu_ioreq_pio(CPUState *env, ioreq_t *req)
+{
+ int i, sign;
+
+ sign = req->df ? -1 : 1;
+
+ if (req->dir == IOREQ_READ) {
if (!req->pdata_valid) {
- //handle stos
- if(req->dir == IOREQ_READ) { //read
- for (i = 0; i < req->count; i++) {
-
read_physical((target_phys_addr_t)req->addr + (sign * i * req->size),
req->size, &req->u.data);
- }
- } else if(req->dir == IOREQ_WRITE) { //write
- for (i = 0; i < req->count; i++) {
-
write_physical((target_phys_addr_t)req->addr + (sign * i * req->size),
req->size, &req->u.data);
- }
- }
+ req->u.data = do_inp(env, req->addr, req->size);
} else {
- //handle movs
- unsigned long tmp;
- if (req->dir == IOREQ_READ) {
- for (i = 0; i < req->count; i++) {
-
read_physical((target_phys_addr_t)req->addr + (sign * i * req->size),
req->size, &tmp);
-
write_physical((target_phys_addr_t)req->u.pdata + (sign * i * req->size),
req->size, &tmp);
- }
- } else if (req->dir == IOREQ_WRITE) {
- for (i = 0; i < req->count; i++) {
-
read_physical((target_phys_addr_t)req->u.pdata + (sign * i * req->size),
req->size, &tmp);
-
write_physical((target_phys_addr_t)req->addr + (sign * i * req->size),
req->size, &tmp);
- }
- }
- }
- }
- /* No state change if state = STATE_IORESP_HOOK */
- if (req->state == STATE_IOREQ_INPROCESS)
- req->state = STATE_IORESP_READY;
- env->send_event = 1;
+ unsigned long tmp;
+
+ for (i = 0; i < req->count; i++) {
+ tmp = do_inp(env, req->addr, req->size);
+ write_physical((target_phys_addr_t) req->u.pdata
+ + (sign * i * req->size),
+ req->size, &tmp);
+ }
+ }
+ } else if (req->dir == IOREQ_WRITE) {
+ if (!req->pdata_valid) {
+ do_outp(env, req->addr, req->size, req->u.data);
+ } else {
+ for (i = 0; i < req->count; i++) {
+ unsigned long tmp;
+
+ read_physical((target_phys_addr_t) req->u.pdata
+ + (sign * i * req->size),
+ req->size, &tmp);
+ do_outp(env, req->addr, req->size, tmp);
+ }
+ }
+ }
+}
+
+void
+cpu_ioreq_move(CPUState *env, ioreq_t *req)
+{
+ int i, sign;
+
+ sign = req->df ? -1 : 1;
+
+ if (!req->pdata_valid) {
+ if (req->dir == IOREQ_READ) {
+ for (i = 0; i < req->count; i++) {
+ read_physical(req->addr
+ + (sign * i * req->size),
+ req->size, &req->u.data);
+ }
+ } else if (req->dir == IOREQ_WRITE) {
+ for (i = 0; i < req->count; i++) {
+ write_physical(req->addr
+ + (sign * i * req->size),
+ req->size, &req->u.data);
+ }
+ }
+ } else {
+ unsigned long tmp;
+
+ if (req->dir == IOREQ_READ) {
+ for (i = 0; i < req->count; i++) {
+ read_physical(req->addr
+ + (sign * i * req->size),
+ req->size, &tmp);
+ write_physical((target_phys_addr_t )req->u.pdata
+ + (sign * i * req->size),
+ req->size, &tmp);
+ }
+ } else if (req->dir == IOREQ_WRITE) {
+ for (i = 0; i < req->count; i++) {
+ read_physical((target_phys_addr_t) req->u.pdata
+ + (sign * i * req->size),
+ req->size, &tmp);
+ write_physical(req->addr
+ + (sign * i * req->size),
+ req->size, &tmp);
+ }
+ }
+ }
+}
+
+void
+cpu_ioreq_and(CPUState *env, ioreq_t *req)
+{
+ unsigned long tmp1, tmp2;
+
+ if (req->pdata_valid != 0)
+ hw_error("expected scalar value");
+
+ read_physical(req->addr, req->size, &tmp1);
+ if (req->dir == IOREQ_WRITE) {
+ tmp2 = tmp1 & (unsigned long) req->u.data;
+ write_physical(req->addr, req->size, &tmp2);
+ }
+ req->u.data = tmp1;
+}
+
+void
+cpu_ioreq_or(CPUState *env, ioreq_t *req)
+{
+ unsigned long tmp1, tmp2;
+
+ if (req->pdata_valid != 0)
+ hw_error("expected scalar value");
+
+ read_physical(req->addr, req->size, &tmp1);
+ if (req->dir == IOREQ_WRITE) {
+ tmp2 = tmp1 | (unsigned long) req->u.data;
+ write_physical(req->addr, req->size, &tmp2);
+ }
+ req->u.data = tmp1;
+}
+
+void
+cpu_ioreq_xor(CPUState *env, ioreq_t *req)
+{
+ unsigned long tmp1, tmp2;
+
+ if (req->pdata_valid != 0)
+ hw_error("expected scalar value");
+
+ read_physical(req->addr, req->size, &tmp1);
+ if (req->dir == IOREQ_WRITE) {
+ tmp2 = tmp1 ^ (unsigned long) req->u.data;
+ write_physical(req->addr, req->size, &tmp2);
+ }
+ req->u.data = tmp1;
}
void
cpu_handle_ioreq(CPUState *env)
{
ioreq_t *req = cpu_get_ioreq();
- if (req)
- cpu_dispatch_ioreq(env, req);
+
+ if (req) {
+ if ((!req->pdata_valid) && (req->dir == IOREQ_WRITE)) {
+ if (req->size != 4)
+ req->u.data &= (1UL << (8 * req->size))-1;
+ }
+
+ switch (req->type) {
+ case IOREQ_TYPE_PIO:
+ cpu_ioreq_pio(env, req);
+ break;
+ case IOREQ_TYPE_COPY:
+ cpu_ioreq_move(env, req);
+ break;
+ case IOREQ_TYPE_AND:
+ cpu_ioreq_and(env, req);
+ break;
+ case IOREQ_TYPE_OR:
+ cpu_ioreq_or(env, req);
+ break;
+ case IOREQ_TYPE_XOR:
+ cpu_ioreq_xor(env, req);
+ break;
+ default:
+ hw_error("Invalid ioreq type 0x%x", req->type);
+ }
+
+ /* No state change if state = STATE_IORESP_HOOK */
+ if (req->state == STATE_IOREQ_INPROCESS)
+ req->state = STATE_IORESP_READY;
+ env->send_event = 1;
+ }
}
void
@@ -321,7 +405,7 @@
// Send a message on the event channel. Add the vector to the shared mem
// page.
- intr = &(shared_page->sp_global.pic_intr[0]);
+ intr = (unsigned long *) &(shared_page->sp_global.pic_intr[0]);
atomic_set_bit(vector, intr);
if (loglevel & CPU_LOG_INT)
fprintf(logfile, "injecting vector: %x\n", vector);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/ioemu/vl.c
--- a/tools/ioemu/vl.c Thu Sep 8 15:18:40 2005
+++ b/tools/ioemu/vl.c Fri Sep 9 16:30:54 2005
@@ -125,6 +125,7 @@
QEMUTimer *polling_timer;
int vm_running;
int audio_enabled = 0;
+int nic_pcnet = 1;
int sb16_enabled = 1;
int adlib_enabled = 1;
int gus_enabled = 1;
@@ -412,6 +413,11 @@
fprintf(stderr, "qemu: hardware error: ");
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
+ if (logfile) {
+ fprintf(logfile, "qemu: hardware error: ");
+ vfprintf(logfile, fmt, ap);
+ fprintf(logfile, "\n");
+ }
va_end(ap);
abort();
}
@@ -2115,6 +2121,7 @@
"-prep Simulate a PREP system (default is PowerMAC)\n"
"-g WxH[xDEPTH] Set the initial VGA graphic mode\n"
#endif
+ "-nic-pcnet simulate an AMD PC-Net PCI ethernet adaptor\n"
"\n"
"Network options:\n"
"-nics n simulate 'n' network cards [default=1]\n"
@@ -2229,6 +2236,7 @@
QEMU_OPTION_L,
QEMU_OPTION_no_code_copy,
QEMU_OPTION_pci,
+ QEMU_OPTION_nic_pcnet,
QEMU_OPTION_isa,
QEMU_OPTION_prep,
QEMU_OPTION_k,
@@ -2313,6 +2321,7 @@
/* temporary options */
{ "pci", 0, QEMU_OPTION_pci },
+ { "nic-pcnet", 0, QEMU_OPTION_nic_pcnet },
{ "cirrusvga", 0, QEMU_OPTION_cirrusvga },
{ NULL },
};
@@ -2639,6 +2648,9 @@
break;
case QEMU_OPTION_pci:
pci_enabled = 1;
+ break;
+ case QEMU_OPTION_nic_pcnet:
+ nic_pcnet = 1;
break;
case QEMU_OPTION_isa:
pci_enabled = 0;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/ioemu/vl.h
--- a/tools/ioemu/vl.h Thu Sep 8 15:18:40 2005
+++ b/tools/ioemu/vl.h Fri Sep 9 16:30:54 2005
@@ -600,6 +600,12 @@
void isa_ne2000_init(int base, int irq, NetDriverState *nd);
void pci_ne2000_init(PCIBus *bus, NetDriverState *nd);
+/* pcnet.c */
+
+extern int nic_pcnet;
+
+void pci_pcnet_init(PCIBus *bus, NetDriverState *nd);
+
/* pckbd.c */
void kbd_init(void);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/libxc/Makefile
--- a/tools/libxc/Makefile Thu Sep 8 15:18:40 2005
+++ b/tools/libxc/Makefile Fri Sep 9 16:30:54 2005
@@ -139,7 +139,7 @@
libxenguest.so.$(MAJOR): libxenguest.so.$(MAJOR).$(MINOR)
ln -sf $< $@
-libxenguest.so.$(MAJOR).$(MINOR): $(PIC_BUILD_OBJS)
+libxenguest.so.$(MAJOR).$(MINOR): $(PIC_BUILD_OBJS) libxenctrl.so
$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-soname -Wl,libxenguest.so.$(MAJOR)
-shared -o $@ $^ -lz -lxenctrl
-include $(DEPS)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/libxc/xc_core.c
--- a/tools/libxc/xc_core.c Thu Sep 8 15:18:40 2005
+++ b/tools/libxc/xc_core.c Fri Sep 9 16:30:54 2005
@@ -2,6 +2,7 @@
#define ELFSIZE 32
#include "xc_elf.h"
#include <stdlib.h>
+#include <unistd.h>
#include <zlib.h>
/* number of pages to write at a time */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c Thu Sep 8 15:18:40 2005
+++ b/tools/libxc/xc_domain.c Fri Sep 9 16:30:54 2005
@@ -7,6 +7,7 @@
*/
#include "xc_private.h"
+#include <xen/memory.h>
int xc_domain_create(int xc_handle,
u32 ssidref,
@@ -261,19 +262,66 @@
int xc_domain_memory_increase_reservation(int xc_handle,
u32 domid,
- unsigned int mem_kb)
+ unsigned long nr_extents,
+ unsigned int extent_order,
+ unsigned int address_bits,
+ unsigned long *extent_start)
{
int err;
- unsigned int npages = mem_kb / (PAGE_SIZE/1024);
-
- err = xc_dom_mem_op(xc_handle, MEMOP_increase_reservation, NULL,
- npages, 0, domid);
- if (err == npages)
+ struct xen_memory_reservation reservation = {
+ .extent_start = extent_start, /* may be NULL */
+ .nr_extents = nr_extents,
+ .extent_order = extent_order,
+ .address_bits = address_bits,
+ .domid = domid
+ };
+
+ err = xc_memory_op(xc_handle, XENMEM_increase_reservation, &reservation);
+ if (err == nr_extents)
return 0;
if (err > 0) {
+ fprintf(stderr,"Failed alocation for dom %d : %ld pages order %d
addr_bits %d\n",
+ domid, nr_extents, extent_order,
address_bits);
errno = ENOMEM;
err = -1;
}
return err;
}
+
+int xc_domain_memory_decrease_reservation(int xc_handle,
+ u32 domid,
+ unsigned long nr_extents,
+ unsigned int extent_order,
+ unsigned long *extent_start)
+{
+ int err;
+ struct xen_memory_reservation reservation = {
+ .extent_start = extent_start,
+ .nr_extents = nr_extents,
+ .extent_order = extent_order,
+ .address_bits = 0,
+ .domid = domid
+ };
+
+ if (extent_start == NULL)
+ {
+ fprintf(stderr,"decrease_reservation extent_start is NULL!\n");
+ errno = EINVAL;
+ err = -1;
+ goto out;
+ }
+
+ err = xc_memory_op(xc_handle, XENMEM_increase_reservation, &reservation);
+ if (err == nr_extents)
+ return 0;
+
+ if (err > 0) {
+ fprintf(stderr,"Failed de-alocation for dom %d : %ld pages order %d\n",
+ domid, nr_extents, extent_order);
+ errno = EBUSY;
+ err = -1;
+ }
+out:
+ return err;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/libxc/xc_linux_build.c
--- a/tools/libxc/xc_linux_build.c Thu Sep 8 15:18:40 2005
+++ b/tools/libxc/xc_linux_build.c Fri Sep 9 16:30:54 2005
@@ -17,6 +17,7 @@
#include "xc_elf.h"
#include "xc_aout9.h"
#include <stdlib.h>
+#include <unistd.h>
#include <zlib.h>
#if defined(__i386__)
@@ -56,7 +57,7 @@
}
#define alloc_pt(ltab, vltab) \
- ltab = page_array[ppt_alloc++] << PAGE_SHIFT; \
+ ltab = (unsigned long long)(page_array[ppt_alloc++]) << PAGE_SHIFT; \
if (vltab != NULL) { \
munmap(vltab, PAGE_SIZE); \
} \
@@ -127,18 +128,37 @@
l1_pgentry_64_t *vl1tab=NULL, *vl1e=NULL;
l2_pgentry_64_t *vl2tab=NULL, *vl2e=NULL;
l3_pgentry_64_t *vl3tab=NULL, *vl3e=NULL;
- unsigned long l1tab = 0;
- unsigned long l2tab = 0;
- unsigned long l3tab = 0;
+ unsigned long long l1tab = 0;
+ unsigned long long l2tab = 0;
+ unsigned long long l3tab = 0;
unsigned long ppt_alloc;
unsigned long count;
/* First allocate page for page dir. */
ppt_alloc = (vpt_start - dsi_v_start) >> PAGE_SHIFT;
+
+ if ( page_array[ppt_alloc] > 0xfffff )
+ {
+ unsigned long nmfn;
+ nmfn = xc_make_page_below_4G( xc_handle, dom, page_array[ppt_alloc] );
+ if ( nmfn == 0 )
+ {
+ fprintf(stderr, "Couldn't get a page below 4GB :-(\n");
+ goto error_out;
+ }
+ page_array[ppt_alloc] = nmfn;
+ }
+
alloc_pt(l3tab, vl3tab);
vl3e = &vl3tab[l3_table_offset_pae(dsi_v_start)];
ctxt->ctrlreg[3] = l3tab;
-
+
+ if(l3tab>0xfffff000ULL)
+ {
+ fprintf(stderr,"L3TAB = %llx above 4GB!\n",l3tab);
+ goto error_out;
+ }
+
for ( count = 0; count < ((v_end-dsi_v_start)>>PAGE_SHIFT); count++)
{
if ( !((unsigned long)vl1e & (PAGE_SIZE-1)) )
@@ -274,7 +294,6 @@
unsigned long *pvss, vcpu_guest_context_t *ctxt,
const char *cmdline,
unsigned long shared_info_frame,
- unsigned int control_evtchn,
unsigned long flags,
unsigned int vcpus,
unsigned int store_evtchn, unsigned long *store_mfn)
@@ -332,10 +351,10 @@
unsigned long *pvss, vcpu_guest_context_t *ctxt,
const char *cmdline,
unsigned long shared_info_frame,
- unsigned int control_evtchn,
unsigned long flags,
unsigned int vcpus,
- unsigned int store_evtchn, unsigned long *store_mfn)
+ unsigned int store_evtchn, unsigned long *store_mfn,
+ unsigned int console_evtchn, unsigned long *console_mfn)
{
unsigned long *page_array = NULL;
unsigned long count, i;
@@ -346,7 +365,7 @@
unsigned long nr_pt_pages;
unsigned long physmap_pfn;
- u32 *physmap, *physmap_e;
+ unsigned long *physmap, *physmap_e;
struct load_funcs load_funcs;
struct domain_setup_info dsi;
@@ -358,6 +377,8 @@
unsigned long vstartinfo_end;
unsigned long vstoreinfo_start;
unsigned long vstoreinfo_end;
+ unsigned long vconsole_start;
+ unsigned long vconsole_end;
unsigned long vstack_start;
unsigned long vstack_end;
unsigned long vpt_start;
@@ -391,16 +412,18 @@
vinitrd_end = vinitrd_start + initrd_len;
vphysmap_start = round_pgup(vinitrd_end);
vphysmap_end = vphysmap_start + (nr_pages * sizeof(unsigned long));
- vstoreinfo_start = round_pgup(vphysmap_end);
+ vstartinfo_start = round_pgup(vphysmap_end);
+ vstartinfo_end = vstartinfo_start + PAGE_SIZE;
+ vstoreinfo_start = vstartinfo_end;
vstoreinfo_end = vstoreinfo_start + PAGE_SIZE;
- vpt_start = vstoreinfo_end;
+ vconsole_start = vstoreinfo_end;
+ vconsole_end = vconsole_start + PAGE_SIZE;
+ vpt_start = vconsole_end;
for ( nr_pt_pages = 2; ; nr_pt_pages++ )
{
vpt_end = vpt_start + (nr_pt_pages * PAGE_SIZE);
- vstartinfo_start = vpt_end;
- vstartinfo_end = vstartinfo_start + PAGE_SIZE;
- vstack_start = vstartinfo_end;
+ vstack_start = vpt_end;
vstack_end = vstack_start + PAGE_SIZE;
v_end = (vstack_end + (1UL<<22)-1) & ~((1UL<<22)-1);
if ( (v_end - vstack_end) < (512UL << 10) )
@@ -436,17 +459,19 @@
" Loaded kernel: %p->%p\n"
" Init. ramdisk: %p->%p\n"
" Phys-Mach map: %p->%p\n"
+ " Start info: %p->%p\n"
" Store page: %p->%p\n"
+ " Console page: %p->%p\n"
" Page tables: %p->%p\n"
- " Start info: %p->%p\n"
" Boot stack: %p->%p\n"
" TOTAL: %p->%p\n",
_p(dsi.v_kernstart), _p(dsi.v_kernend),
_p(vinitrd_start), _p(vinitrd_end),
_p(vphysmap_start), _p(vphysmap_end),
+ _p(vstartinfo_start), _p(vstartinfo_end),
_p(vstoreinfo_start), _p(vstoreinfo_end),
+ _p(vconsole_start), _p(vconsole_end),
_p(vpt_start), _p(vpt_end),
- _p(vstartinfo_start), _p(vstartinfo_end),
_p(vstack_start), _p(vstack_end),
_p(dsi.v_start), _p(v_end));
printf(" ENTRY ADDRESS: %p\n", _p(dsi.v_kernentry));
@@ -519,12 +544,14 @@
physmap = physmap_e = xc_map_foreign_range(
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
page_array[physmap_pfn++]);
+
for ( count = 0; count < nr_pages; count++ )
{
if ( xc_add_mmu_update(xc_handle, mmu,
- (page_array[count] << PAGE_SHIFT) |
+ ((unsigned long long)page_array[count] <<
PAGE_SHIFT) |
MMU_MACHPHYS_UPDATE, count) )
{
+ fprintf(stderr,"m2p update failure p=%lx
m=%lx\n",count,page_array[count] );
munmap(physmap, PAGE_SIZE);
goto error_out;
}
@@ -566,6 +593,8 @@
#endif
*store_mfn = page_array[(vstoreinfo_start-dsi.v_start) >> PAGE_SHIFT];
+ *console_mfn = page_array[(vconsole_start-dsi.v_start) >> PAGE_SHIFT];
+
start_info = xc_map_foreign_range(
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
@@ -577,9 +606,10 @@
start_info->pt_base = vpt_start;
start_info->nr_pt_frames = nr_pt_pages;
start_info->mfn_list = vphysmap_start;
- start_info->domain_controller_evtchn = control_evtchn;
start_info->store_mfn = *store_mfn;
start_info->store_evtchn = store_evtchn;
+ start_info->console_mfn = *console_mfn;
+ start_info->console_evtchn = console_evtchn;
if ( initrd_len != 0 )
{
start_info->mod_start = vinitrd_start;
@@ -627,11 +657,12 @@
const char *image_name,
const char *ramdisk_name,
const char *cmdline,
- unsigned int control_evtchn,
unsigned long flags,
unsigned int vcpus,
unsigned int store_evtchn,
- unsigned long *store_mfn)
+ unsigned long *store_mfn,
+ unsigned int console_evtchn,
+ unsigned long *console_mfn)
{
dom0_op_t launch_op, op;
int initrd_fd = -1;
@@ -706,8 +737,9 @@
&vstartinfo_start, &vkern_entry,
&vstack_start, ctxt, cmdline,
op.u.getdomaininfo.shared_info_frame,
- control_evtchn, flags, vcpus,
- store_evtchn, store_mfn) < 0 )
+ flags, vcpus,
+ store_evtchn, store_mfn,
+ console_evtchn, console_mfn) < 0 )
{
ERROR("Error constructing guest OS");
goto error_out;
@@ -727,7 +759,6 @@
ctxt->regs.ar_fpsr = FPSR_DEFAULT;
/* ctxt->regs.r28 = dom_fw_setup(); currently done by hypervisor, should
move here */
ctxt->vcpu.privregs = 0;
- ctxt->shared.domain_controller_evtchn = control_evtchn;
ctxt->shared.flags = flags;
i = 0; /* silence unused variable warning */
#else /* x86 */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/libxc/xc_linux_restore.c
--- a/tools/libxc/xc_linux_restore.c Thu Sep 8 15:18:40 2005
+++ b/tools/libxc/xc_linux_restore.c Fri Sep 9 16:30:54 2005
@@ -8,24 +8,22 @@
#include <stdlib.h>
#include <unistd.h>
-
#include "xg_private.h"
#include <xenctrl.h>
-
-#include <xen/linux/suspend.h>
+#include <xen/memory.h>
#define MAX_BATCH_SIZE 1024
#define DEBUG 0
#if 1
-#define ERR(_f, _a...) fprintf ( stderr, _f , ## _a ); fflush(stderr)
+#define ERR(_f, _a...) do { fprintf ( stderr, _f , ## _a ); fflush(stderr); }
while(0)
#else
#define ERR(_f, _a...) ((void)0)
#endif
#if DEBUG
-#define DPRINTF(_f, _a...) fprintf ( stdout, _f , ## _a ); fflush(stdout)
+#define DPRINTF(_f, _a...) do { fprintf ( stdout, _f , ## _a );
fflush(stdout); } while (0)
#else
#define DPRINTF(_f, _a...) ((void)0)
#endif
@@ -54,7 +52,8 @@
}
int xc_linux_restore(int xc_handle, int io_fd, u32 dom, unsigned long nr_pfns,
- unsigned int store_evtchn, unsigned long *store_mfn)
+ unsigned int store_evtchn, unsigned long *store_mfn,
+ unsigned int console_evtchn, unsigned long *console_mfn)
{
dom0_op_t op;
int rc = 1, i, n, k;
@@ -89,8 +88,8 @@
/* used by mapper for updating the domain's copy of the table */
unsigned long *live_pfn_to_mfn_table = NULL;
- /* A temporary mapping of the guest's suspend record. */
- suspend_record_t *p_srec;
+ /* A temporary mapping of the guest's start_info page. */
+ start_info_t *start_info;
char *region_base;
@@ -103,7 +102,7 @@
struct mmuext_op pin[MAX_PIN_BATCH];
unsigned int nr_pins = 0;
- DPRINTF("xc_linux_restore start\n");
+ DPRINTF("xc_linux_restore start: nr_pfns = %lx\n", nr_pfns);
if (mlock(&ctxt, sizeof(ctxt))) {
/* needed for when we do the build dom0 op,
@@ -150,8 +149,10 @@
}
err = xc_domain_memory_increase_reservation(xc_handle, dom,
- nr_pfns * PAGE_SIZE / 1024);
+ nr_pfns, 0, 0, NULL);
if (err != 0) {
+ ERR("Failed to increase reservation by %lx\n",
+ nr_pfns * PAGE_SIZE / 1024);
errno = ENOMEM;
goto out;
}
@@ -409,7 +410,8 @@
/* Get the list of PFNs that are not in the psuedo-phys map */
{
- unsigned int count, *pfntab;
+ unsigned int count;
+ unsigned long *pfntab;
int rc;
if ( read_exact(io_fd, &count, sizeof(count)) != sizeof(count) )
@@ -441,9 +443,15 @@
if ( count > 0 )
{
- if ( (rc = xc_dom_mem_op( xc_handle,
- MEMOP_decrease_reservation,
- pfntab, count, 0, dom )) <0 )
+ struct xen_memory_reservation reservation = {
+ .extent_start = pfntab,
+ .nr_extents = count,
+ .extent_order = 0,
+ .domid = dom
+ };
+ if ( (rc = xc_memory_op(xc_handle,
+ XENMEM_decrease_reservation,
+ &reservation)) != count )
{
ERR("Could not decrease reservation : %d",rc);
goto out;
@@ -470,15 +478,18 @@
goto out;
}
ctxt.user_regs.esi = mfn = pfn_to_mfn_table[pfn];
- p_srec = xc_map_foreign_range(
+ start_info = xc_map_foreign_range(
xc_handle, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, mfn);
- p_srec->resume_info.nr_pages = nr_pfns;
- p_srec->resume_info.shared_info = shared_info_frame << PAGE_SHIFT;
- p_srec->resume_info.flags = 0;
- *store_mfn = p_srec->resume_info.store_mfn =
- pfn_to_mfn_table[p_srec->resume_info.store_mfn];
- p_srec->resume_info.store_evtchn = store_evtchn;
- munmap(p_srec, PAGE_SIZE);
+ start_info->nr_pages = nr_pfns;
+ start_info->shared_info = shared_info_frame << PAGE_SHIFT;
+ start_info->flags = 0;
+ *store_mfn = start_info->store_mfn =
+ pfn_to_mfn_table[start_info->store_mfn];
+ start_info->store_evtchn = store_evtchn;
+ *console_mfn = start_info->console_mfn =
+ pfn_to_mfn_table[start_info->console_mfn];
+ start_info->console_evtchn = console_evtchn;
+ munmap(start_info, PAGE_SIZE);
/* Uncanonicalise each GDT frame number. */
if ( ctxt.gdt_ents > 8192 )
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/libxc/xc_linux_save.c
--- a/tools/libxc/xc_linux_save.c Thu Sep 8 15:18:40 2005
+++ b/tools/libxc/xc_linux_save.c Fri Sep 9 16:30:54 2005
@@ -14,12 +14,29 @@
#include "xg_private.h"
-#include <xen/linux/suspend.h>
#include <xen/io/domain_controller.h>
#define BATCH_SIZE 1024 /* 1024 pages (4MB) at a time */
#define MAX_MBIT_RATE 500
+
+
+/*
+** Default values for important tuning parameters. Can override by passing
+** non-zero replacement values to xc_linux_save().
+**
+** XXX SMH: should consider if want to be able to override MAX_MBIT_RATE too.
+**
+*/
+#define DEF_MAX_ITERS 29 /* limit us to 30 times round loop */
+#define DEF_MAX_FACTOR 3 /* never send more than 3x nr_pfns */
+
+
+
+/* Flags to control behaviour of xc_linux_save */
+#define XCFLAGS_LIVE 1
+#define XCFLAGS_DEBUG 2
+
#define DEBUG 0
@@ -320,18 +337,18 @@
xc_dominfo_t *info,
vcpu_guest_context_t *ctxt)
{
- int i=0;
+ int i = 0;
char ans[30];
printf("suspend\n");
fflush(stdout);
if (fgets(ans, sizeof(ans), stdin) == NULL) {
- ERR("failed reading suspend reply");
- return -1;
+ ERR("failed reading suspend reply");
+ return -1;
}
if (strncmp(ans, "done\n", 5)) {
- ERR("suspend reply incorrect: %s", ans);
- return -1;
+ ERR("suspend reply incorrect: %s", ans);
+ return -1;
}
retry:
@@ -377,19 +394,16 @@
return -1;
}
-int xc_linux_save(int xc_handle, int io_fd, u32 dom)
+int xc_linux_save(int xc_handle, int io_fd, u32 dom, u32 max_iters,
+ u32 max_factor, u32 flags)
{
xc_dominfo_t info;
int rc = 1, i, j, k, last_iter, iter = 0;
unsigned long mfn;
- int live = 0; // (ioctxt->flags & XCFLAGS_LIVE);
- int debug = 0; // (ioctxt->flags & XCFLAGS_DEBUG);
+ int live = (flags & XCFLAGS_LIVE);
+ int debug = (flags & XCFLAGS_DEBUG);
int sent_last_iter, skip_this_iter;
-
- /* Important tuning parameters */
- int max_iters = 29; /* limit us to 30 times round loop */
- int max_factor = 3; /* never send more than 3x nr_pfns */
/* The new domain's shared-info frame number. */
unsigned long shared_info_frame;
@@ -405,6 +419,7 @@
unsigned long page[1024];
/* A copy of the pfn-to-mfn table frame list. */
+ unsigned long *live_pfn_to_mfn_frame_list_list = NULL;
unsigned long *live_pfn_to_mfn_frame_list = NULL;
unsigned long pfn_to_mfn_frame_list[1024];
@@ -420,9 +435,6 @@
/* base of the region in which domain memory is mapped */
unsigned char *region_base = NULL;
- /* A temporary mapping, and a copy, of the guest's suspend record. */
- suspend_record_t *p_srec = NULL;
-
/* number of pages we're dealing with */
unsigned long nr_pfns;
@@ -442,8 +454,16 @@
MBIT_RATE = START_MBIT_RATE;
- DPRINTF("xc_linux_save start %d\n", dom);
-
+
+ /* If no explicit control parameters given, use defaults */
+ if(!max_iters)
+ max_iters = DEF_MAX_ITERS;
+ if(!max_factor)
+ max_factor = DEF_MAX_FACTOR;
+
+
+ DPRINTF("xc_linux_save start DOM%u live=%s\n", dom, live?"true":"false");
+
if (mlock(&ctxt, sizeof(ctxt))) {
ERR("Unable to mlock ctxt");
return 1;
@@ -487,11 +507,20 @@
goto out;
}
- /* the pfn_to_mfn_frame_list fits in a single page */
+ live_pfn_to_mfn_frame_list_list = xc_map_foreign_range(xc_handle, dom,
+ PAGE_SIZE, PROT_READ,
+
live_shinfo->arch.pfn_to_mfn_frame_list_list);
+
+ if (!live_pfn_to_mfn_frame_list_list){
+ ERR("Couldn't map pfn_to_mfn_frame_list_list");
+ goto out;
+ }
+
live_pfn_to_mfn_frame_list =
- xc_map_foreign_range(xc_handle, dom,
- PAGE_SIZE, PROT_READ,
- live_shinfo->arch.pfn_to_mfn_frame_list );
+ xc_map_foreign_batch(xc_handle, dom,
+ PROT_READ,
+ live_pfn_to_mfn_frame_list_list,
+ (nr_pfns+(1024*1024)-1)/(1024*1024) );
if (!live_pfn_to_mfn_frame_list){
ERR("Couldn't map pfn_to_mfn_frame_list");
@@ -647,22 +676,6 @@
goto out;
}
- /* Map the suspend-record MFN to pin it. The page must be owned by
- dom for this to succeed. */
- p_srec = xc_map_foreign_range(xc_handle, dom,
- sizeof(*p_srec), PROT_READ | PROT_WRITE,
- ctxt.user_regs.esi);
- if (!p_srec){
- ERR("Couldn't map suspend record");
- goto out;
- }
-
- /* Canonicalize store mfn. */
- if ( !translate_mfn_to_pfn(&p_srec->resume_info.store_mfn) ) {
- ERR("Store frame is not in range of pseudophys map");
- goto out;
- }
-
print_stats( xc_handle, dom, 0, &stats, 0 );
/* Now write out each data page, canonicalising page tables as we go... */
@@ -763,8 +776,6 @@
batch++;
}
-// DPRINTF("batch %d:%d (n=%d)\n", iter, batch, n);
-
if ( batch == 0 )
goto skip; /* vanishingly unlikely... */
@@ -915,7 +926,7 @@
continue;
}
- if ( last_iter ) break;
+ if ( last_iter ) break;
if ( live )
{
@@ -1003,13 +1014,6 @@
}
}
- if (nr_pfns != p_srec->nr_pfns )
- {
- ERR("Suspend record nr_pfns unexpected (%ld != %ld)",
- p_srec->nr_pfns, nr_pfns);
- goto out;
- }
-
/* Canonicalise the suspend-record frame number. */
if ( !translate_mfn_to_pfn(&ctxt.user_regs.esi) ){
ERR("Suspend record is not in range of pseudophys map");
@@ -1043,9 +1047,6 @@
if(live_shinfo)
munmap(live_shinfo, PAGE_SIZE);
- if(p_srec)
- munmap(p_srec, sizeof(*p_srec));
-
if(live_pfn_to_mfn_frame_list)
munmap(live_pfn_to_mfn_frame_list, PAGE_SIZE);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/libxc/xc_load_aout9.c
--- a/tools/libxc/xc_load_aout9.c Thu Sep 8 15:18:40 2005
+++ b/tools/libxc/xc_load_aout9.c Fri Sep 9 16:30:54 2005
@@ -14,7 +14,8 @@
#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
-#define round_pgdown(_p) ((_p)&PAGE_MASK)
+#define KZERO 0x80000000
+#define KOFFSET(_p) ((_p)&~KZERO)
static int parseaout9image(char *, unsigned long, struct domain_setup_info *);
static int loadaout9image(char *, unsigned long, int, u32, unsigned long *,
struct domain_setup_info *);
@@ -47,7 +48,7 @@
struct domain_setup_info *dsi)
{
struct Exec ehdr;
- unsigned long start, txtsz, end;
+ unsigned long start, dstart, end;
if (!get_header(image, image_size, &ehdr)) {
ERROR("Kernel image does not have a a.out9 header.");
@@ -59,11 +60,11 @@
return -EINVAL;
}
- start = round_pgdown(ehdr.entry);
- txtsz = round_pgup(ehdr.text);
- end = start + txtsz + ehdr.data + ehdr.bss;
+ start = ehdr.entry;
+ dstart = round_pgup(start + ehdr.text);
+ end = dstart + ehdr.data + ehdr.bss;
- dsi->v_start = start;
+ dsi->v_start = KZERO;
dsi->v_kernstart = start;
dsi->v_kernend = end;
dsi->v_kernentry = ehdr.entry;
@@ -83,19 +84,18 @@
struct domain_setup_info *dsi)
{
struct Exec ehdr;
- unsigned long txtsz;
+ unsigned long start, dstart;
if (!get_header(image, image_size, &ehdr)) {
ERROR("Kernel image does not have a a.out9 header.");
return -EINVAL;
}
- txtsz = round_pgup(ehdr.text);
- copyout(xch, dom, parray,
- 0, image, sizeof ehdr + ehdr.text);
- copyout(xch, dom, parray,
- txtsz, image + sizeof ehdr + ehdr.text, ehdr.data);
- /* XXX zeroing of BSS needed? */
+ start = ehdr.entry;
+ dstart = round_pgup(start + ehdr.text);
+ copyout(xch, dom, parray, start, image + sizeof ehdr, ehdr.text);
+ copyout(xch, dom, parray, dstart,
+ image + sizeof ehdr + ehdr.text, ehdr.data);
/* XXX load symbols */
@@ -110,13 +110,14 @@
copyout(
int xch, u32 dom,
unsigned long *parray,
- unsigned long off,
+ unsigned long addr,
void *buf,
int sz)
{
- unsigned long pgoff, chunksz;
+ unsigned long pgoff, chunksz, off;
void *pg;
+ off = KOFFSET(addr);
while (sz > 0) {
pgoff = off & (PAGE_SIZE-1);
chunksz = sz;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/libxc/xc_private.c
--- a/tools/libxc/xc_private.c Thu Sep 8 15:18:40 2005
+++ b/tools/libxc/xc_private.c Fri Sep 9 16:30:54 2005
@@ -6,6 +6,7 @@
#include <zlib.h>
#include "xc_private.h"
+#include <xen/memory.h>
void *xc_map_foreign_batch(int xc_handle, u32 dom, int prot,
unsigned long *arr, int num )
@@ -115,7 +116,7 @@
if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
{
- fprintf(stderr, "Dom_mem operation failed (rc=%ld errno=%d)-- need to"
+ fprintf(stderr, "Dom_mmuext operation failed (rc=%ld errno=%d)-- need
to"
" rebuild the user-space tool set?\n",ret,errno);
}
@@ -171,7 +172,7 @@
}
int xc_add_mmu_update(int xc_handle, xc_mmu_t *mmu,
- unsigned long ptr, unsigned long val)
+ unsigned long long ptr, unsigned long long val)
{
mmu->updates[mmu->idx].ptr = ptr;
mmu->updates[mmu->idx].val = val;
@@ -187,38 +188,64 @@
return flush_mmu_updates(xc_handle, mmu);
}
-int xc_dom_mem_op(int xc_handle,
- unsigned int memop,
- unsigned int *extent_list,
- unsigned int nr_extents,
- unsigned int extent_order,
- domid_t domid)
+int xc_memory_op(int xc_handle,
+ int cmd,
+ void *arg)
{
privcmd_hypercall_t hypercall;
+ struct xen_memory_reservation *reservation = arg;
long ret = -EINVAL;
- hypercall.op = __HYPERVISOR_dom_mem_op;
- hypercall.arg[0] = (unsigned long)memop;
- hypercall.arg[1] = (unsigned long)extent_list;
- hypercall.arg[2] = (unsigned long)nr_extents;
- hypercall.arg[3] = (unsigned long)extent_order;
- hypercall.arg[4] = (unsigned long)domid;
-
- if ( (extent_list != NULL) &&
- (mlock(extent_list, nr_extents*sizeof(unsigned long)) != 0) )
- {
- PERROR("Could not lock memory for Xen hypercall");
- goto out1;
+ hypercall.op = __HYPERVISOR_memory_op;
+ hypercall.arg[0] = (unsigned long)cmd;
+ hypercall.arg[1] = (unsigned long)arg;
+
+ switch ( cmd )
+ {
+ case XENMEM_increase_reservation:
+ case XENMEM_decrease_reservation:
+ if ( mlock(reservation, sizeof(*reservation)) != 0 )
+ {
+ PERROR("Could not mlock");
+ goto out1;
+ }
+ if ( (reservation->extent_start != NULL) &&
+ (mlock(reservation->extent_start,
+ reservation->nr_extents * sizeof(unsigned long)) != 0) )
+ {
+ PERROR("Could not mlock");
+ safe_munlock(reservation, sizeof(*reservation));
+ goto out1;
+ }
+ break;
+ case XENMEM_maximum_ram_page:
+ if ( mlock(arg, sizeof(unsigned long)) != 0 )
+ {
+ PERROR("Could not mlock");
+ goto out1;
+ }
+ break;
}
if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
{
- fprintf(stderr, "Dom_mem operation failed (rc=%ld errno=%d)-- need to"
+ fprintf(stderr, "hypercall failed (rc=%ld errno=%d)-- need to"
" rebuild the user-space tool set?\n",ret,errno);
}
- if ( extent_list != NULL )
- safe_munlock(extent_list, nr_extents*sizeof(unsigned long));
+ switch ( cmd )
+ {
+ case XENMEM_increase_reservation:
+ case XENMEM_decrease_reservation:
+ safe_munlock(reservation, sizeof(*reservation));
+ if ( reservation->extent_start != NULL )
+ safe_munlock(reservation->extent_start,
+ reservation->nr_extents * sizeof(unsigned long));
+ break;
+ case XENMEM_maximum_ram_page:
+ safe_munlock(arg, sizeof(unsigned long));
+ break;
+ }
out1:
return ret;
@@ -395,3 +422,26 @@
{
return do_dom0_op(xc_handle, op);
}
+
+int xc_version(int xc_handle, int cmd, void *arg)
+{
+ return do_xen_version(xc_handle, cmd, arg);
+}
+
+unsigned long xc_make_page_below_4G(int xc_handle, u32 domid,
+ unsigned long mfn)
+{
+ unsigned long new_mfn;
+ if ( xc_domain_memory_decrease_reservation(
+ xc_handle, domid, 1, 0, &mfn ) != 1 )
+ {
+ fprintf(stderr,"xc_make_page_below_4G decrease failed. mfn=%lx\n",mfn);
+ return 0;
+ }
+ if ( xc_domain_memory_increase_reservation( xc_handle, domid, 1, 0, 32,
&new_mfn ) != 1 )
+ {
+ fprintf(stderr,"xc_make_page_below_4G increase failed. mfn=%lx\n",mfn);
+ return 0;
+ }
+ return new_mfn;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/libxc/xc_private.h
--- a/tools/libxc/xc_private.h Thu Sep 8 15:18:40 2005
+++ b/tools/libxc/xc_private.h Fri Sep 9 16:30:54 2005
@@ -59,6 +59,17 @@
(unsigned long)hypercall);
}
+static inline int do_xen_version(int xc_handle, int cmd, void *dest)
+{
+ privcmd_hypercall_t hypercall;
+
+ hypercall.op = __HYPERVISOR_xen_version;
+ hypercall.arg[0] = (unsigned long) cmd;
+ hypercall.arg[1] = (unsigned long) dest;
+
+ return do_xen_hypercall(xc_handle, &hypercall);
+}
+
static inline int do_dom0_op(int xc_handle, dom0_op_t *op)
{
int ret = -1;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/libxc/xc_vmx_build.c
--- a/tools/libxc/xc_vmx_build.c Thu Sep 8 15:18:40 2005
+++ b/tools/libxc/xc_vmx_build.c Fri Sep 9 16:30:54 2005
@@ -7,6 +7,7 @@
#define ELFSIZE 32
#include "xc_elf.h"
#include <stdlib.h>
+#include <unistd.h>
#include <zlib.h>
#include <xen/io/ioreq.h>
#include "linux_boot_params.h"
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h Thu Sep 8 15:18:40 2005
+++ b/tools/libxc/xenctrl.h Fri Sep 9 16:30:54 2005
@@ -23,6 +23,7 @@
#include <sys/ptrace.h>
#include <xen/xen.h>
#include <xen/dom0_ops.h>
+#include <xen/version.h>
#include <xen/event_channel.h>
#include <xen/sched_ctl.h>
#include <xen/acm.h>
@@ -386,7 +387,19 @@
int xc_domain_memory_increase_reservation(int xc_handle,
u32 domid,
- unsigned int mem_kb);
+ unsigned long nr_extents,
+ unsigned int extent_order,
+ unsigned int address_bits,
+ unsigned long *extent_start);
+
+int xc_domain_memory_decrease_reservation(int xc_handle,
+ u32 domid,
+ unsigned long nr_extents,
+ unsigned int extent_order,
+ unsigned long *extent_start);
+
+unsigned long xc_make_page_below_4G(int xc_handle, u32 domid,
+ unsigned long mfn);
typedef dom0_perfc_desc_t xc_perfc_desc_t;
/* IMPORTANT: The caller is responsible for mlock()'ing the @desc array. */
@@ -430,9 +443,7 @@
int xc_mmuext_op(int xc_handle, struct mmuext_op *op, unsigned int nr_ops,
domid_t dom);
-int xc_dom_mem_op(int xc_handle, unsigned int memop, unsigned int *extent_list,
- unsigned int nr_extents, unsigned int extent_order,
- domid_t domid);
+int xc_memory_op(int xc_handle, int cmd, void *arg);
int xc_get_pfn_type_batch(int xc_handle, u32 dom, int num, unsigned long *arr);
@@ -498,6 +509,8 @@
/* Execute a privileged dom0 operation. */
int xc_dom0_op(int xc_handle, dom0_op_t *op);
+
+int xc_version(int xc_handle, int cmd, void *arg);
/* Initializes the store (for dom0)
remote_port should be the remote end of a bound interdomain channel between
@@ -520,7 +533,7 @@
typedef struct xc_mmu xc_mmu_t;
xc_mmu_t *xc_init_mmu_updates(int xc_handle, domid_t dom);
int xc_add_mmu_update(int xc_handle, xc_mmu_t *mmu,
- unsigned long ptr, unsigned long val);
+ unsigned long long ptr, unsigned long long val);
int xc_finish_mmu_updates(int xc_handle, xc_mmu_t *mmu);
#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/libxc/xenguest.h
--- a/tools/libxc/xenguest.h Thu Sep 8 15:18:40 2005
+++ b/tools/libxc/xenguest.h Fri Sep 9 16:30:54 2005
@@ -6,13 +6,12 @@
* Copyright (c) 2003-2004, K A Fraser.
*/
-#ifndef XENBUILD_H
-#define XENBUILD_H
+#ifndef XENGUEST_H
+#define XENGUEST_H
-#define XCFLAGS_VERBOSE 1
-#define XCFLAGS_LIVE 2
-#define XCFLAGS_DEBUG 4
-#define XCFLAGS_CONFIGURE 8
+#define XCFLAGS_LIVE 1
+#define XCFLAGS_DEBUG 2
+
/**
* This function will save a domain running Linux.
@@ -22,7 +21,8 @@
* @parm dom the id of the domain
* @return 0 on success, -1 on failure
*/
-int xc_linux_save(int xc_handle, int fd, uint32_t dom);
+int xc_linux_save(int xc_handle, int fd, uint32_t dom, uint32_t max_iters,
+ uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */);
/**
* This function will restore a saved domain running Linux.
@@ -35,19 +35,22 @@
* @parm store_mfn returned with the mfn of the store page
* @return 0 on success, -1 on failure
*/
-int xc_linux_restore(int xc_handle, int io_fd, uint32_t dom, unsigned long
nr_pfns,
- unsigned int store_evtchn, unsigned long *store_mfn);
+int xc_linux_restore(int xc_handle, int io_fd, uint32_t dom,
+ unsigned long nr_pfns, unsigned int store_evtchn,
+ unsigned long *store_mfn, unsigned int console_evtchn,
+ unsigned long *console_mfn);
int xc_linux_build(int xc_handle,
uint32_t domid,
const char *image_name,
const char *ramdisk_name,
const char *cmdline,
- unsigned int control_evtchn,
unsigned long flags,
unsigned int vcpus,
unsigned int store_evtchn,
- unsigned long *store_mfn);
+ unsigned long *store_mfn,
+ unsigned int console_evtchn,
+ unsigned long *console_mfn);
struct mem_map;
int xc_vmx_build(int xc_handle,
@@ -63,4 +66,4 @@
unsigned int store_evtchn,
unsigned long *store_mfn);
-#endif
+#endif // XENGUEST_H
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/libxc/xg_private.c
--- a/tools/libxc/xg_private.c Thu Sep 8 15:18:40 2005
+++ b/tools/libxc/xg_private.c Fri Sep 9 16:30:54 2005
@@ -5,6 +5,7 @@
*/
#include <stdlib.h>
+#include <unistd.h>
#include <zlib.h>
#include "xg_private.h"
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/misc/cpuperf/cpuperf.c
--- a/tools/misc/cpuperf/cpuperf.c Thu Sep 8 15:18:40 2005
+++ b/tools/misc/cpuperf/cpuperf.c Fri Sep 9 16:30:54 2005
@@ -243,16 +243,12 @@
}
if (read) {
- while((cpu_mask&1)) {
- int i;
- for (i=0x300;i<0x312;i++) {
- printf("%010llu ",cpus_rdmsr( cpu_mask, i ) );
- }
- printf("\n");
- cpu_mask>>=1;
- }
+ int i;
+ for (i=0x300;i<0x312;i++)
+ printf("%010llu ",cpus_rdmsr( cpu_mask, i ) );
+ printf("\n");
exit(1);
- }
+ }
if (!escr) {
fprintf(stderr, "Need an ESCR.\n");
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/misc/mbootpack/Makefile
--- a/tools/misc/mbootpack/Makefile Thu Sep 8 15:18:40 2005
+++ b/tools/misc/mbootpack/Makefile Fri Sep 9 16:30:54 2005
@@ -20,8 +20,7 @@
INCS := -I. -I-
DEFS :=
LDFLAGS :=
-CC := gcc
-CFLAGS := -Wall -Wpointer-arith -Wcast-qual -Wno-unused -Wno-format
+CFLAGS := -Wall -Wpointer-arith -Wcast-qual -Wno-unused -Wno-format
CFLAGS += -Wmissing-prototypes
#CFLAGS += -pipe -g -O0 -Wcast-align
CFLAGS += -pipe -O3
@@ -34,7 +33,7 @@
DEPS = .*.d
mbootpack: $(OBJS)
- $(CC) -o $@ $(filter-out %.a, $^) $(LDFLAGS)
+ $(HOSTCC) -o $@ $(filter-out %.a, $^) $(LDFLAGS)
clean:
$(RM) mbootpack *.o $(DEPS) bootsect setup bzimage_header.c bin2c
@@ -48,7 +47,7 @@
$(LD) -m elf_i386 -Ttext 0x0 -s --oformat binary setup.o -o $@
bin2c: bin2c.o
- $(CC) -o $@ $^
+ $(HOSTCC) -o $@ $^
bzimage_header.c: bootsect setup bin2c
./bin2c -n 8 -b1 -a bzimage_bootsect bootsect > bzimage_header.c
@@ -58,10 +57,10 @@
@
%.o: %.S
- $(CC) $(DEPFLAGS) $(CFLAGS) $(INCS) $(DEFS) -c $< -o $@
+ $(HOSTCC) $(DEPFLAGS) $(CFLAGS) $(INCS) $(DEFS) -c $< -o $@
%.o: %.c
- $(CC) $(DEPFLAGS) $(CFLAGS) $(INCS) $(DEFS) -c $< -o $@
+ $(HOSTCC) $(DEPFLAGS) $(CFLAGS) $(INCS) $(DEFS) -c $< -o $@
.PHONY: all clean gdb
.PRECIOUS: $(OBJS) $(OBJS:.o=.c) $(DEPS)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/misc/mbootpack/buildimage.c
--- a/tools/misc/mbootpack/buildimage.c Thu Sep 8 15:18:40 2005
+++ b/tools/misc/mbootpack/buildimage.c Fri Sep 9 16:30:54 2005
@@ -42,6 +42,7 @@
#include "mbootpack.h"
#include "mb_header.h"
+
/* We will build an image that a bzImage-capable bootloader will load like
* this:
@@ -105,8 +106,8 @@
section_t *s;
/* Patch the kernel and mbi addresses into the setup code */
- *(address_t *)(bzimage_setup + BZ_ENTRY_OFFSET) = entry;
- *(address_t *)(bzimage_setup + BZ_MBI_OFFSET) = mbi;
+ *(address_t *)(bzimage_setup + BZ_ENTRY_OFFSET) = eswap(entry);
+ *(address_t *)(bzimage_setup + BZ_MBI_OFFSET) = eswap(mbi);
if (!quiet) printf("Kernel entry is %p, MBI is %p.\n", entry, mbi);
/* Write out header and trampoline */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/misc/mbootpack/mbootpack.c
--- a/tools/misc/mbootpack/mbootpack.c Thu Sep 8 15:18:40 2005
+++ b/tools/misc/mbootpack/mbootpack.c Fri Sep 9 16:30:54 2005
@@ -252,20 +252,21 @@
for (i = 0; i <= MIN(len - 12, MULTIBOOT_SEARCH - 12); i += 4)
{
mbh = (struct multiboot_header *)(headerbuf + i);
- if (mbh->magic != MULTIBOOT_MAGIC
- || ((mbh->magic+mbh->flags+mbh->checksum) & 0xffffffff))
+ if (eswap(mbh->magic) != MULTIBOOT_MAGIC
+ || ((eswap(mbh->magic)+eswap(mbh->flags)+eswap(mbh->checksum))
+ & 0xffffffff))
{
/* Not a multiboot header */
continue;
}
- if (mbh->flags & MULTIBOOT_UNSUPPORTED) {
+ if (eswap(mbh->flags) & MULTIBOOT_UNSUPPORTED) {
/* Requires options we don't support */
printf("Fatal: found a multiboot header, but it "
"requires multiboot options that I\n"
"don't understand. Sorry.\n");
exit(1);
}
- if (mbh->flags & MULTIBOOT_VIDEO_MODE) {
+ if (eswap(mbh->flags) & MULTIBOOT_VIDEO_MODE) {
/* Asked for screen mode information */
/* XXX carry on regardless */
printf("Warning: found a multiboot header which asks "
@@ -275,22 +276,22 @@
}
/* This kernel will do: place and load it */
- if (mbh->flags & MULTIBOOT_AOUT_KLUDGE) {
+ if (eswap(mbh->flags) & MULTIBOOT_AOUT_KLUDGE) {
/* Load using the offsets in the multiboot header */
if(!quiet)
printf("Loading %s using multiboot header.\n", filename);
/* How much is there? */
- start = mbh->load_addr;
- if (mbh->load_end_addr != 0)
- loadsize = mbh->load_end_addr - mbh->load_addr;
+ start = eswap(mbh->load_addr);
+ if (eswap(mbh->load_end_addr) != 0)
+ loadsize = eswap(mbh->load_end_addr) - eswap(mbh->load_addr);
else
loadsize = sb.st_size;
/* How much memory will it take up? */
- if (mbh->bss_end_addr != 0)
- size = mbh->bss_end_addr - mbh->load_addr;
+ if (eswap(mbh->bss_end_addr) != 0)
+ size = eswap(mbh->bss_end_addr) - eswap(mbh->load_addr);
else
size = loadsize;
@@ -335,32 +336,34 @@
/* Done. */
if (!quiet) printf("Loaded kernel from %s\n", filename);
- return mbh->entry_addr;
+ return eswap(mbh->entry_addr);
} else {
/* Now look for an ELF32 header */
ehdr = (Elf32_Ehdr *)headerbuf;
- if (*(unsigned long *)ehdr != 0x464c457f
+ if (*(unsigned long *)ehdr != eswap(0x464c457f)
|| ehdr->e_ident[EI_DATA] != ELFDATA2LSB
|| ehdr->e_ident[EI_CLASS] != ELFCLASS32
- || ehdr->e_machine != EM_386)
+ || eswap(ehdr->e_machine) != EM_386)
{
printf("Fatal: kernel has neither ELF32/x86 nor multiboot load"
" headers.\n");
exit(1);
}
- if (ehdr->e_phoff + ehdr->e_phnum*sizeof(*phdr) > HEADERBUF_SIZE) {
+ if (eswap(ehdr->e_phoff) + eswap(ehdr->e_phnum)*sizeof(*phdr)
+ > HEADERBUF_SIZE) {
/* Don't expect this will happen with sane kernels */
printf("Fatal: too much ELF for me. Try increasing "
"HEADERBUF_SIZE in mbootpack.\n");
exit(1);
}
- if (ehdr->e_phoff + ehdr->e_phnum*sizeof (*phdr) > len) {
+ if (eswap(ehdr->e_phoff) + eswap(ehdr->e_phnum)*sizeof (*phdr)
+ > len) {
printf("Fatal: malformed ELF header overruns EOF.\n");
exit(1);
}
- if (ehdr->e_phnum <= 0) {
+ if (eswap(ehdr->e_phnum) <= 0) {
printf("Fatal: ELF kernel has no program headers.\n");
exit(1);
}
@@ -368,22 +371,22 @@
if(!quiet)
printf("Loading %s using ELF header.\n", filename);
- if (ehdr->e_type != ET_EXEC
- || ehdr->e_version != EV_CURRENT
- || ehdr->e_phentsize != sizeof (Elf32_Phdr)) {
+ if (eswap(ehdr->e_type) != ET_EXEC
+ || eswap(ehdr->e_version) != EV_CURRENT
+ || eswap(ehdr->e_phentsize) != sizeof (Elf32_Phdr)) {
printf("Warning: funny-looking ELF header.\n");
}
- phdr = (Elf32_Phdr *)(headerbuf + ehdr->e_phoff);
+ phdr = (Elf32_Phdr *)(headerbuf + eswap(ehdr->e_phoff));
/* Obey the program headers to load the kernel */
- for(i = 0; i < ehdr->e_phnum; i++) {
-
- start = phdr[i].p_paddr;
- size = phdr[i].p_memsz;
- if (phdr[i].p_type != PT_LOAD)
+ for(i = 0; i < eswap(ehdr->e_phnum); i++) {
+
+ start = eswap(phdr[i].p_paddr);
+ size = eswap(phdr[i].p_memsz);
+ if (eswap(phdr[i].p_type) != PT_LOAD)
loadsize = 0;
else
- loadsize = MIN((long int)phdr[i].p_filesz, size);
+ loadsize = MIN((long int)eswap(phdr[i].p_filesz), size);
if ((buffer = malloc(size)) == NULL) {
printf("Fatal: malloc() for kernel load failed: %s\n",
@@ -396,7 +399,7 @@
/* Load section from file */
if (loadsize > 0) {
- if (fseek(fp, phdr[i].p_offset, SEEK_SET) != 0) {
+ if (fseek(fp, eswap(phdr[i].p_offset), SEEK_SET) != 0) {
printf("Fatal: seek failed in %s\n",
strerror(errno));
exit(1);
@@ -452,7 +455,7 @@
/* Done! */
if (!quiet) printf("Loaded kernel from %s\n", filename);
- return ehdr->e_entry;
+ return eswap(ehdr->e_entry);
}
}
@@ -568,12 +571,12 @@
/* Command line */
p = (char *)(mbi + 1);
sprintf(p, "%s %s", imagename, command_line);
- mbi->cmdline = ((address_t)p) + mbi_reloc_offset;
+ mbi->cmdline = eswap(((address_t)p) + mbi_reloc_offset);
p += command_line_len;
/* Bootloader ID */
sprintf(p, version_string);
- mbi->boot_loader_name = ((address_t)p) + mbi_reloc_offset;
+ mbi->boot_loader_name = eswap(((address_t)p) + mbi_reloc_offset);
p += strlen(version_string) + 1;
/* Next is space for the module command lines */
@@ -582,17 +585,17 @@
/* Last come the module info structs */
modp = (struct mod_list *)
((((address_t)p + mod_command_line_space) + 3) & ~3);
- mbi->mods_count = modules;
- mbi->mods_addr = ((address_t)modp) + mbi_reloc_offset;
+ mbi->mods_count = eswap(modules);
+ mbi->mods_addr = eswap(((address_t)modp) + mbi_reloc_offset);
/* Memory information will be added at boot time, by setup.S
* or trampoline.S. */
- mbi->flags = MB_INFO_CMDLINE | MB_INFO_BOOT_LOADER_NAME;
+ mbi->flags = eswap(MB_INFO_CMDLINE | MB_INFO_BOOT_LOADER_NAME);
/* Load the modules */
if (modules) {
- mbi->flags |= MB_INFO_MODS;
+ mbi->flags = eswap(eswap(mbi->flags) | MB_INFO_MODS);
/* Go back and parse the module command lines */
optind = opterr = 1;
@@ -652,10 +655,10 @@
if (p != NULL) *p = ' ';
/* Fill in the module info struct */
- modp->mod_start = start;
- modp->mod_end = start + size;
- modp->cmdline = (address_t)mod_clp + mbi_reloc_offset;
- modp->pad = 0;
+ modp->mod_start = eswap(start);
+ modp->mod_end = eswap(start + size);
+ modp->cmdline = eswap((address_t)mod_clp + mbi_reloc_offset);
+ modp->pad = eswap(0);
modp++;
/* Store the module command line */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/misc/mbootpack/mbootpack.h
--- a/tools/misc/mbootpack/mbootpack.h Thu Sep 8 15:18:40 2005
+++ b/tools/misc/mbootpack/mbootpack.h Fri Sep 9 16:30:54 2005
@@ -31,6 +31,24 @@
#undef NDEBUG
#include <stdio.h>
+
+#include <endian.h>
+#include <byteswap.h>
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define eswap(x) (x)
+#else
+#define eswap(x) \
+ ({ \
+ typeof(x) y = (x); \
+ switch(sizeof(y)) \
+ { \
+ case 2: y = __bswap_16(y); break; \
+ case 4: y = __bswap_32(y); break; \
+ case 8: y = __bswap_64(y); break; \
+ } \
+ y; \
+ })
+#endif
/* Flags */
extern int quiet;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/misc/xend
--- a/tools/misc/xend Thu Sep 8 15:18:40 2005
+++ b/tools/misc/xend Fri Sep 9 16:30:54 2005
@@ -25,11 +25,6 @@
import signal
import time
import commands
-
-XCS_PATH = "/var/lib/xen/xcs_socket"
-XCS_EXEC = "/usr/sbin/xcs"
-XCS_PIDFILE = "/var/run/xcs.pid"
-XCS_ARGS = (XCS_EXEC, "-p", XCS_PIDFILE)
# add fallback path for non-native python path installs if needed
sys.path.append('/usr/lib/python')
@@ -70,52 +65,6 @@
hline()
raise CheckError("invalid user")
-def xcs_running():
- """ See if the control switch is running.
- """
- s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
- try:
- s.connect( (XCS_PATH) )
- s.close()
- except:
- try:
- os.remove(XCS_PIDFILE)
- except:
- pass
- return 0
- return 1
-
-def start_xcs():
- if (not xcs_running()):
- if os.fork() == 0 :
- if not os.path.isdir(os.path.dirname(XCS_PATH)):
- os.makedirs(os.path.dirname(XCS_PATH))
- try:
- os.execvp(XCS_EXEC, XCS_ARGS)
- except:
- hline()
- msg("Tried to start xcs, but failed. Is it installed?")
- hline()
- raise CheckError("couldn't start xcs")
- for n in range(10) :
- if (xcs_running()):
- break
- time.sleep(0.1)
- else :
- hline()
- msg("Failed to start the control interface switch.")
- hline()
- raise CheckError("xcs not running")
-
-def stop_xcs():
- try:
- xcs_pidfile = open(XCS_PIDFILE)
- xcs_pid = int(xcs_pidfile.read().strip())
- os.kill(xcs_pid, signal.SIGTERM)
- xcs_pidfile.close()
- except:
- return
-
def start_xenstored():
XENSTORED_TRACE = os.getenv("XENSTORED_TRACE")
cmd = "/usr/sbin/xenstored --pid-file=/var/run/xenstore.pid"
@@ -141,21 +90,16 @@
pid, status = os.wait()
return status >> 8
elif sys.argv[1] == 'start':
- start_xcs()
start_xenstored()
start_consoled()
return daemon.start()
elif sys.argv[1] == 'trace_start':
- start_xcs()
start_xenstored()
start_consoled()
return daemon.start(trace=1)
elif sys.argv[1] == 'stop':
- stop_xcs()
return daemon.stop()
elif sys.argv[1] == 'restart':
- stop_xcs()
- start_xcs()
start_xenstored()
start_consoled()
return daemon.stop() or daemon.start()
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/setup.py
--- a/tools/python/setup.py Thu Sep 8 15:18:40 2005
+++ b/tools/python/setup.py Fri Sep 9 16:30:54 2005
@@ -7,10 +7,8 @@
extra_compile_args = [ "-fno-strict-aliasing", "-Wall", "-Werror" ]
-include_dirs = [ XEN_ROOT + "/tools/python/xen/lowlevel/xu",
- XEN_ROOT + "/tools/libxc",
+include_dirs = [ XEN_ROOT + "/tools/libxc",
XEN_ROOT + "/tools/xenstore",
- XEN_ROOT + "/tools/xcs",
]
library_dirs = [ XEN_ROOT + "/tools/libxc",
@@ -25,13 +23,6 @@
library_dirs = library_dirs,
libraries = libraries,
sources = [ "xen/lowlevel/xc/xc.c" ])
-
-xu = Extension("xu",
- extra_compile_args = extra_compile_args,
- include_dirs = include_dirs + [ "xen/lowlevel/xu" ],
- library_dirs = library_dirs,
- libraries = libraries,
- sources = [ "xen/lowlevel/xu/xu.c" ])
xs = Extension("xs",
extra_compile_args = extra_compile_args,
@@ -51,10 +42,10 @@
'xen.xend.xenstore',
'xen.xm',
'xen.web',
- 'xen.sv'
+ 'xen.sv'
],
ext_package = "xen.lowlevel",
- ext_modules = [ xc, xu, xs ]
+ ext_modules = [ xc, xs ]
)
os.chdir('logging')
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Thu Sep 8 15:18:40 2005
+++ b/tools/python/xen/lowlevel/xc/xc.c Fri Sep 9 16:30:54 2005
@@ -268,25 +268,33 @@
u32 dom;
char *image, *ramdisk = NULL, *cmdline = "";
int flags = 0, vcpus = 1;
- int control_evtchn, store_evtchn;
+ int store_evtchn, console_evtchn;
unsigned long store_mfn = 0;
-
- static char *kwd_list[] = { "dom", "control_evtchn", "store_evtchn",
- "image", "ramdisk", "cmdline", "flags",
+ unsigned long console_mfn = 0;
+
+ static char *kwd_list[] = { "dom", "store_evtchn",
+ "console_evtchn", "image",
+ /* optional */
+ "ramdisk", "cmdline", "flags",
"vcpus", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiis|ssii", kwd_list,
- &dom, &control_evtchn, &store_evtchn,
- &image, &ramdisk, &cmdline, &flags,
+ &dom, &store_evtchn,
+ &console_evtchn, &image,
+ /* optional */
+ &ramdisk, &cmdline, &flags,
&vcpus) )
return NULL;
if ( xc_linux_build(xc->xc_handle, dom, image,
- ramdisk, cmdline, control_evtchn, flags, vcpus,
- store_evtchn, &store_mfn) != 0 )
- return PyErr_SetFromErrno(xc_error);
-
- return Py_BuildValue("{s:i}", "store_mfn", store_mfn);
+ ramdisk, cmdline, flags, vcpus,
+ store_evtchn, &store_mfn,
+ console_evtchn, &console_mfn) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ return Py_BuildValue("{s:i,s:i}",
+ "store_mfn", store_mfn,
+ "console_mfn", console_mfn);
}
static PyObject *pyxc_vmx_build(PyObject *self,
@@ -682,6 +690,8 @@
{
XcObject *xc = (XcObject *)self;
xc_physinfo_t info;
+ char cpu_cap[128], *p=cpu_cap, *q=cpu_cap;
+ int i;
if ( !PyArg_ParseTuple(args, "") )
return NULL;
@@ -689,15 +699,72 @@
if ( xc_physinfo(xc->xc_handle, &info) != 0 )
return PyErr_SetFromErrno(xc_error);
- return Py_BuildValue("{s:i,s:i,s:i,s:i,s:l,s:l,s:i}",
+ *q=0;
+ for(i=0;i<sizeof(info.hw_cap)/4;i++)
+ {
+ p+=sprintf(p,"%08x:",info.hw_cap[i]);
+ if(info.hw_cap[i])
+ q=p;
+ }
+ if(q>cpu_cap)
+ *(q-1)=0;
+
+ return Py_BuildValue("{s:i,s:i,s:i,s:i,s:l,s:l,s:i,s:s}",
"threads_per_core", info.threads_per_core,
"cores_per_socket", info.cores_per_socket,
"sockets_per_node", info.sockets_per_node,
"nr_nodes", info.nr_nodes,
"total_pages", info.total_pages,
"free_pages", info.free_pages,
- "cpu_khz", info.cpu_khz);
-}
+ "cpu_khz", info.cpu_khz,
+ "hw_caps", cpu_cap);
+}
+
+static PyObject *pyxc_xeninfo(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+ xen_extraversion_t xen_extra;
+ xen_compile_info_t xen_cc;
+ xen_changeset_info_t xen_chgset;
+ xen_capabilities_info_t xen_caps;
+ xen_parameters_info_t xen_parms;
+ long xen_version;
+ char str[128];
+
+ xen_version = xc_version(xc->xc_handle, XENVER_version, NULL);
+
+ if ( xc_version(xc->xc_handle, XENVER_extraversion, &xen_extra) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ if ( xc_version(xc->xc_handle, XENVER_compile_info, &xen_cc) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ if ( xc_version(xc->xc_handle, XENVER_changeset, &xen_chgset) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ if ( xc_version(xc->xc_handle, XENVER_capabilities, &xen_caps) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ if ( xc_version(xc->xc_handle, XENVER_parameters, &xen_parms) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ sprintf(str,"virt_start=0x%lx",xen_parms.virt_start);
+
+ return Py_BuildValue("{s:i,s:i,s:s,s:s,s:s,s:s,s:s,s:s,s:s,s:s}",
+ "xen_major", xen_version >> 16,
+ "xen_minor", (xen_version & 0xffff),
+ "xen_extra", xen_extra,
+ "xen_caps", xen_caps.caps,
+ "xen_params", str,
+ "xen_changeset", xen_chgset,
+ "cc_compiler", xen_cc.compiler,
+ "cc_compile_by", xen_cc.compile_by,
+ "cc_compile_domain", xen_cc.compile_domain,
+ "cc_compile_date", xen_cc.compile_date);
+}
+
static PyObject *pyxc_sedf_domain_set(PyObject *self,
PyObject *args,
@@ -800,14 +867,21 @@
u32 dom;
unsigned long mem_kb;
-
- static char *kwd_list[] = { "dom", "mem_kb", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list,
- &dom, &mem_kb) )
- return NULL;
-
- if ( xc_domain_memory_increase_reservation(xc->xc_handle, dom, mem_kb) )
+ unsigned int extent_order = 0 , address_bits = 0;
+ unsigned long nr_extents;
+
+ static char *kwd_list[] = { "dom", "mem_kb", "extent_order",
"address_bits", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "il|ii", kwd_list,
+ &dom, &mem_kb, &extent_order,
&address_bits) )
+ return NULL;
+
+ /* round down to nearest power of 2. Assume callers using extent_order>0
+ know what they are doing */
+ nr_extents = (mem_kb / (XC_PAGE_SIZE/1024)) >> extent_order;
+ if ( xc_domain_memory_increase_reservation(xc->xc_handle, dom,
+ nr_extents, extent_order,
+ address_bits, NULL) )
return PyErr_SetFromErrno(xc_error);
Py_INCREF(zero);
@@ -1081,6 +1155,13 @@
"Returns [dict]: information about the hardware"
" [None]: on failure.\n" },
+ { "xeninfo",
+ (PyCFunction)pyxc_xeninfo,
+ METH_VARARGS, "\n"
+ "Get information about the Xen host\n"
+ "Returns [dict]: information about Xen"
+ " [None]: on failure.\n" },
+
{ "shadow_control",
(PyCFunction)pyxc_shadow_control,
METH_VARARGS | METH_KEYWORDS, "\n"
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/lowlevel/xs/xs.c
--- a/tools/python/xen/lowlevel/xs/xs.c Thu Sep 8 15:18:40 2005
+++ b/tools/python/xen/lowlevel/xs/xs.c Fri Sep 9 16:30:54 2005
@@ -15,6 +15,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Copyright (C) 2005 Mike Wray Hewlett-Packard
+ * Copyright (C) 2005 Christian Limpach <Christian.Limpach@xxxxxxxxxxxx>
*
*/
@@ -45,6 +46,7 @@
typedef struct XsHandle {
PyObject_HEAD;
struct xs_handle *xh;
+ PyObject *watches;
} XsHandle;
static inline struct xs_handle *xshandle(PyObject *self)
@@ -87,19 +89,21 @@
PyObject *val = NULL;
if (!xh)
- goto exit;
+ goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
&path))
goto exit;
+ Py_BEGIN_ALLOW_THREADS
xsval = xs_read(xh, path, &xsval_n);
- if (!xsval) {
- val = pyvalue_int(0);
+ Py_END_ALLOW_THREADS
+ if (!xsval) {
+ PyErr_SetFromErrno(PyExc_RuntimeError);
goto exit;
}
val = PyString_FromStringAndSize(xsval, xsval_n);
exit:
if (xsval)
- free(xsval);
+ free(xsval);
return val;
}
@@ -110,7 +114,7 @@
" create [int] : create flag, default 0.\n" \
" excl [int] : exclusive flag, default 0.\n" \
"\n" \
- "Returns: [int] 0 on success.\n" \
+ "Returns None on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
@@ -130,16 +134,23 @@
int xsval = 0;
if (!xh)
- goto exit;
+ goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
&path, &data, &data_n, &create, &excl))
goto exit;
if (create)
- flags |= O_CREAT;
+ flags |= O_CREAT;
if (excl)
- flags |= O_EXCL;
+ flags |= O_EXCL;
+ Py_BEGIN_ALLOW_THREADS
xsval = xs_write(xh, path, data, data_n, flags);
- val = pyvalue_int(xsval);
+ Py_END_ALLOW_THREADS
+ if (!xsval) {
+ PyErr_SetFromErrno(PyExc_RuntimeError);
+ goto exit;
+ }
+ Py_INCREF(Py_None);
+ val = Py_None;
exit:
return val;
}
@@ -165,12 +176,14 @@
int i;
if (!xh)
- goto exit;
+ goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
goto exit;
+ Py_BEGIN_ALLOW_THREADS
xsval = xs_directory(xh, path, &xsval_n);
- if (!xsval) {
- val = pyvalue_int(0);
+ Py_END_ALLOW_THREADS
+ if (!xsval) {
+ PyErr_SetFromErrno(PyExc_RuntimeError);
goto exit;
}
val = PyList_New(xsval_n);
@@ -184,7 +197,7 @@
"Make a directory.\n" \
" path [string]: path to directory to create.\n" \
"\n" \
- "Returns: [int] 0 on success.\n" \
+ "Returns None on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
@@ -199,11 +212,18 @@
int xsval = 0;
if (!xh)
- goto exit;
+ goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
goto exit;
+ Py_BEGIN_ALLOW_THREADS
xsval = xs_mkdir(xh, path);
- val = pyvalue_int(xsval);
+ Py_END_ALLOW_THREADS
+ if (!xsval) {
+ PyErr_SetFromErrno(PyExc_RuntimeError);
+ goto exit;
+ }
+ Py_INCREF(Py_None);
+ val = Py_None;
exit:
return val;
}
@@ -212,7 +232,7 @@
"Remove a path.\n" \
" path [string] : path to remove\n" \
"\n" \
- "Returns: [int] 0 on success.\n" \
+ "Returns None on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
@@ -227,11 +247,18 @@
int xsval = 0;
if (!xh)
- goto exit;
+ goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
goto exit;
+ Py_BEGIN_ALLOW_THREADS
xsval = xs_rm(xh, path);
- val = pyvalue_int(xsval);
+ Py_END_ALLOW_THREADS
+ if (!xsval) {
+ PyErr_SetFromErrno(PyExc_RuntimeError);
+ goto exit;
+ }
+ Py_INCREF(Py_None);
+ val = Py_None;
exit:
return val;
}
@@ -245,7 +272,7 @@
"\n"
static PyObject *xspy_get_permissions(PyObject *self, PyObject *args,
- PyObject *kwds)
+ PyObject *kwds)
{
static char *kwd_spec[] = { "path", NULL };
static char *arg_spec = "s|";
@@ -258,10 +285,12 @@
int i;
if (!xh)
- goto exit;
+ goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
goto exit;
+ Py_BEGIN_ALLOW_THREADS
perms = xs_get_permissions(xh, path, &perms_n);
+ Py_END_ALLOW_THREADS
if (!perms) {
PyErr_SetFromErrno(PyExc_RuntimeError);
goto exit;
@@ -283,12 +312,12 @@
" path [string] : xenstore path.\n" \
" perms : permissions.\n" \
"\n" \
- "Returns: [int] 0 on success.\n" \
+ "Returns None on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
static PyObject *xspy_set_permissions(PyObject *self, PyObject *args,
- PyObject *kwds)
+ PyObject *kwds)
{
static char *kwd_spec[] = { "path", "perms", NULL };
static char *arg_spec = "sO";
@@ -321,7 +350,7 @@
}
tuple0 = PyTuple_New(0);
if (!tuple0)
- goto exit;
+ goto exit;
for (i = 0; i < xsperms_n; i++) {
/* Domain the permissions apply to. */
int dom = 0;
@@ -329,20 +358,27 @@
int p_read = 0, p_write = 0;
PyObject *p = PyList_GetItem(perms, i);
if (!PyArg_ParseTupleAndKeywords(tuple0, p, perm_spec, perm_names,
- &dom, &p_read, &p_write))
+ &dom, &p_read, &p_write))
goto exit;
xsperms[i].id = dom;
if (p_read)
- xsperms[i].perms |= XS_PERM_READ;
+ xsperms[i].perms |= XS_PERM_READ;
if (p_write)
- xsperms[i].perms |= XS_PERM_WRITE;
- }
+ xsperms[i].perms |= XS_PERM_WRITE;
+ }
+ Py_BEGIN_ALLOW_THREADS
xsval = xs_set_permissions(xh, path, xsperms, xsperms_n);
- val = pyvalue_int(xsval);
+ Py_END_ALLOW_THREADS
+ if (!xsval) {
+ PyErr_SetFromErrno(PyExc_RuntimeError);
+ goto exit;
+ }
+ Py_INCREF(Py_None);
+ val = Py_None;
exit:
Py_XDECREF(tuple0);
if (xsperms)
- free(xsperms);
+ free(xsperms);
return val;
}
@@ -351,28 +387,53 @@
" path [string] : xenstore path.\n" \
" token [string] : returned in watch notification.\n" \
"\n" \
- "Returns: [int] 0 on success.\n" \
+ "Returns None on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
+/* Each 10 bits takes ~ 3 digits, plus one, plus one for nul terminator. */
+#define MAX_STRLEN(x) ((sizeof(x) * CHAR_BIT + CHAR_BIT-1) / 10 * 3 + 2)
+
static PyObject *xspy_watch(PyObject *self, PyObject *args, PyObject *kwds)
{
static char *kwd_spec[] = { "path", "token", NULL };
- static char *arg_spec = "s|is";
- char *path = NULL;
- char *token = "";
-
- struct xs_handle *xh = xshandle(self);
- PyObject *val = NULL;
- int xsval = 0;
-
- if (!xh)
- goto exit;
+ static char *arg_spec = "sO";
+ char *path = NULL;
+ PyObject *token;
+ char token_str[MAX_STRLEN(unsigned long) + 1];
+ int i;
+
+ XsHandle *xsh = (XsHandle *)self;
+ struct xs_handle *xh = xshandle(self);
+ PyObject *val = NULL;
+ int xsval = 0;
+
+ if (!xh)
+ goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
&path, &token))
goto exit;
- xsval = xs_watch(xh, path, token);
- val = pyvalue_int(xsval);
+ Py_INCREF(token);
+ sprintf(token_str, "%li", (unsigned long)token);
+ Py_BEGIN_ALLOW_THREADS
+ xsval = xs_watch(xh, path, token_str);
+ Py_END_ALLOW_THREADS
+ if (!xsval) {
+ PyErr_SetFromErrno(PyExc_RuntimeError);
+ Py_DECREF(token);
+ goto exit;
+ }
+
+ for (i = 0; i < PyList_Size(xsh->watches); i++) {
+ if (PyList_GetItem(xsh->watches, i) == Py_None) {
+ PyList_SetItem(xsh->watches, i, token);
+ break;
+ }
+ }
+ if (i == PyList_Size(xsh->watches))
+ PyList_Append(xsh->watches, token);
+ Py_INCREF(Py_None);
+ val = Py_None;
exit:
return val;
}
@@ -388,29 +449,46 @@
"\n"
static PyObject *xspy_read_watch(PyObject *self, PyObject *args,
- PyObject *kwds)
+ PyObject *kwds)
{
static char *kwd_spec[] = { NULL };
static char *arg_spec = "";
+ XsHandle *xsh = (XsHandle *)self;
struct xs_handle *xh = xshandle(self);
PyObject *val = NULL;
char **xsval = NULL;
-
- if (!xh)
- goto exit;
+ PyObject *token;
+ int i;
+
+ if (!xh)
+ goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
goto exit;
+ Py_BEGIN_ALLOW_THREADS
xsval = xs_read_watch(xh);
- if (!xsval) {
- val = PyErr_SetFromErrno(PyExc_RuntimeError);
- goto exit;
+ Py_END_ALLOW_THREADS
+ if (!xsval) {
+ PyErr_SetFromErrno(PyExc_RuntimeError);
+ goto exit;
+ }
+ if (sscanf(xsval[1], "%li", (unsigned long *)&token) != 1) {
+ PyErr_SetString(PyExc_RuntimeError, "invalid token");
+ goto exit;
+ }
+ for (i = 0; i < PyList_Size(xsh->watches); i++) {
+ if (token == PyList_GetItem(xsh->watches, i))
+ break;
+ }
+ if (i == PyList_Size(xsh->watches)) {
+ PyErr_SetString(PyExc_RuntimeError, "invalid token");
+ goto exit;
}
/* Create tuple (path, token). */
- val = Py_BuildValue("(ss)", xsval[0], xsval[1]);
+ val = Py_BuildValue("(sO)", xsval[0], token);
exit:
if (xsval)
- free(xsval);
+ free(xsval);
return val;
}
@@ -418,27 +496,36 @@
"Acknowledge a watch notification that has been read.\n" \
" token [string] : from the watch notification\n" \
"\n" \
- "Returns: [int] 0 on success.\n" \
+ "Returns None on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
static PyObject *xspy_acknowledge_watch(PyObject *self, PyObject *args,
- PyObject *kwds)
+ PyObject *kwds)
{
static char *kwd_spec[] = { "token", NULL };
- static char *arg_spec = "s";
- char *token;
-
- struct xs_handle *xh = xshandle(self);
- PyObject *val = NULL;
- int xsval = 0;
-
- if (!xh)
- goto exit;
+ static char *arg_spec = "O";
+ PyObject *token;
+ char token_str[MAX_STRLEN(unsigned long) + 1];
+
+ struct xs_handle *xh = xshandle(self);
+ PyObject *val = NULL;
+ int xsval = 0;
+
+ if (!xh)
+ goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &token))
goto exit;
- xsval = xs_acknowledge_watch(xh, token);
- val = pyvalue_int(xsval);
+ sprintf(token_str, "%li", (unsigned long)token);
+ Py_BEGIN_ALLOW_THREADS
+ xsval = xs_acknowledge_watch(xh, token_str);
+ Py_END_ALLOW_THREADS
+ if (!xsval) {
+ PyErr_SetFromErrno(PyExc_RuntimeError);
+ goto exit;
+ }
+ Py_INCREF(Py_None);
+ val = Py_None;
exit:
return val;
}
@@ -448,28 +535,46 @@
" path [string] : xenstore path.\n" \
" token [string] : token from the watch.\n" \
"\n" \
- "Returns: [int] 0 on success.\n" \
+ "Returns None on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
static PyObject *xspy_unwatch(PyObject *self, PyObject *args, PyObject *kwds)
{
static char *kwd_spec[] = { "path", "token", NULL };
- static char *arg_spec = "s|s";
- char *path = NULL;
- char *token = "";
-
- struct xs_handle *xh = xshandle(self);
- PyObject *val = NULL;
- int xsval = 0;
-
- if (!xh)
- goto exit;
+ static char *arg_spec = "sO";
+ char *path = NULL;
+ PyObject *token;
+ char token_str[MAX_STRLEN(unsigned long) + 1];
+ int i;
+
+ XsHandle *xsh = (XsHandle *)self;
+ struct xs_handle *xh = xshandle(self);
+ PyObject *val = NULL;
+ int xsval = 0;
+
+ if (!xh)
+ goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path,
- &token))
- goto exit;
- xsval = xs_unwatch(xh, path, token);
- val = pyvalue_int(xsval);
+ &token))
+ goto exit;
+ sprintf(token_str, "%li", (unsigned long)token);
+ Py_BEGIN_ALLOW_THREADS
+ xsval = xs_unwatch(xh, path, token_str);
+ Py_END_ALLOW_THREADS
+ if (!xsval)
+ PyErr_SetFromErrno(PyExc_RuntimeError);
+ else {
+ Py_INCREF(Py_None);
+ val = Py_None;
+ }
+ for (i = 0; i < PyList_Size(xsh->watches); i++) {
+ if (token == PyList_GetItem(xsh->watches, i)) {
+ Py_INCREF(Py_None);
+ PyList_SetItem(xsh->watches, i, Py_None);
+ break;
+ }
+ }
exit:
return val;
}
@@ -479,12 +584,12 @@
"Only one transaction can be active at a time.\n" \
" path [string]: xenstore path.\n" \
"\n" \
- "Returns: [int] 0 on success.\n" \
+ "Returns None on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
static PyObject *xspy_transaction_start(PyObject *self, PyObject *args,
- PyObject *kwds)
+ PyObject *kwds)
{
static char *kwd_spec[] = { "path", NULL };
static char *arg_spec = "s|";
@@ -495,11 +600,18 @@
int xsval = 0;
if (!xh)
- goto exit;
+ goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
goto exit;
+ Py_BEGIN_ALLOW_THREADS
xsval = xs_transaction_start(xh, path);
- val = pyvalue_int(xsval);
+ Py_END_ALLOW_THREADS
+ if (!xsval) {
+ PyErr_SetFromErrno(PyExc_RuntimeError);
+ goto exit;
+ }
+ Py_INCREF(Py_None);
+ val = Py_None;
exit:
return val;
}
@@ -509,12 +621,12 @@
"Attempts to commit the transaction unless abort is true.\n" \
" abort [int]: abort flag (default 0).\n" \
"\n" \
- "Returns: [int] 0 on success.\n" \
+ "Returns None on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
static PyObject *xspy_transaction_end(PyObject *self, PyObject *args,
- PyObject *kwds)
+ PyObject *kwds)
{
static char *kwd_spec[] = { "abort", NULL };
static char *arg_spec = "|i";
@@ -525,11 +637,18 @@
int xsval = 0;
if (!xh)
- goto exit;
+ goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &abort))
goto exit;
+ Py_BEGIN_ALLOW_THREADS
xsval = xs_transaction_end(xh, abort);
- val = pyvalue_int(xsval);
+ Py_END_ALLOW_THREADS
+ if (!xsval) {
+ PyErr_SetFromErrno(PyExc_RuntimeError);
+ goto exit;
+ }
+ Py_INCREF(Py_None);
+ val = Py_None;
exit:
return val;
}
@@ -541,12 +660,12 @@
" port [int] : port the domain is using for xenstore\n" \
" path [string]: path to the domain's data in xenstore\n" \
"\n" \
- "Returns: [int] 0 on success.\n" \
+ "Returns None on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
static PyObject *xspy_introduce_domain(PyObject *self, PyObject *args,
- PyObject *kwds)
+ PyObject *kwds)
{
static char *kwd_spec[] = { "dom", "page", "port", "path", NULL };
static char *arg_spec = "iiis|";
@@ -560,12 +679,19 @@
int xsval = 0;
if (!xh)
- goto exit;
+ goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
&dom, &page, &port, &path))
goto exit;
+ Py_BEGIN_ALLOW_THREADS
xsval = xs_introduce_domain(xh, dom, page, port, path);
- val = pyvalue_int(xsval);
+ Py_END_ALLOW_THREADS
+ if (!xsval) {
+ PyErr_SetFromErrno(PyExc_RuntimeError);
+ goto exit;
+ }
+ Py_INCREF(Py_None);
+ val = Py_None;
exit:
return val;
}
@@ -575,12 +701,12 @@
"Unless this is done the domain will not be released.\n" \
" dom [int]: domain id\n" \
"\n" \
- "Returns: [int] 0 on success.\n" \
+ "Returns None on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
static PyObject *xspy_release_domain(PyObject *self, PyObject *args,
- PyObject *kwds)
+ PyObject *kwds)
{
static char *kwd_spec[] = { "dom", NULL };
static char *arg_spec = "i|";
@@ -591,12 +717,19 @@
int xsval = 0;
if (!xh)
- goto exit;
+ goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
&dom))
goto exit;
+ Py_BEGIN_ALLOW_THREADS
xsval = xs_release_domain(xh, dom);
- val = pyvalue_int(xsval);
+ Py_END_ALLOW_THREADS
+ if (!xsval) {
+ PyErr_SetFromErrno(PyExc_RuntimeError);
+ goto exit;
+ }
+ Py_INCREF(Py_None);
+ val = Py_None;
exit:
return val;
}
@@ -604,7 +737,7 @@
#define xspy_close_doc "\n" \
"Close the connection to xenstore.\n" \
"\n" \
- "Returns: [int] 0 on success.\n" \
+ "Returns None on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
@@ -612,18 +745,25 @@
{
static char *kwd_spec[] = { NULL };
static char *arg_spec = "";
-
- struct xs_handle *xh = xshandle(self);
- PyObject *val = NULL;
- int xsval = 1;
-
- if (!xh)
- goto exit;
+ int i;
+
+ XsHandle *xsh = (XsHandle *)self;
+ struct xs_handle *xh = xshandle(self);
+ PyObject *val = NULL;
+
+ if (!xh)
+ goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
goto exit;
+ for (i = 0; i < PyList_Size(xsh->watches); i++) {
+ /* TODO: xs_unwatch watches */
+ Py_INCREF(Py_None);
+ PyList_SetItem(xsh->watches, i, Py_None);
+ }
xs_daemon_close(xh);
- ((XsHandle*)self)->xh = NULL;
- val = pyvalue_int(xsval);
+ xsh->xh = NULL;
+ Py_INCREF(Py_None);
+ val = Py_None;
exit:
return val;
}
@@ -631,7 +771,7 @@
#define xspy_shutdown_doc "\n" \
"Shutdown the xenstore daemon.\n" \
"\n" \
- "Returns: [int] 0 on success.\n" \
+ "Returns None on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
@@ -645,11 +785,18 @@
int xsval = 0;
if (!xh)
- goto exit;
+ goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
goto exit;
+ Py_BEGIN_ALLOW_THREADS
xsval = xs_shutdown(xh);
- val = pyvalue_int(xsval);
+ Py_END_ALLOW_THREADS
+ if (!xsval) {
+ PyErr_SetFromErrno(PyExc_RuntimeError);
+ goto exit;
+ }
+ Py_INCREF(Py_None);
+ val = Py_None;
exit:
return val;
}
@@ -750,20 +897,25 @@
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
&readonly))
- goto exit;
+ return NULL;
xsh = PyObject_New(XsHandle, &xshandle_type);
if (!xsh)
- goto exit;
+ return NULL;
+ xsh->watches = PyList_New(0);
+ if (!xsh->watches)
+ goto exit;
xsh->xh = (readonly ? xs_daemon_open_readonly() : xs_daemon_open());
if (!xsh->xh) {
- PyObject_Del(xsh);
- val = pyvalue_int(0);
+ Py_DECREF(xsh->watches);
+ PyErr_SetFromErrno(PyExc_RuntimeError);
goto exit;
}
val = (PyObject *)xsh;
- exit:
- return val;
+ return val;
+ exit:
+ PyObject_Del(xsh);
+ return NULL;
}
static PyMethodDef xs_methods[] = {
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/XendCheckpoint.py
--- a/tools/python/xen/xend/XendCheckpoint.py Thu Sep 8 15:18:40 2005
+++ b/tools/python/xen/xend/XendCheckpoint.py Fri Sep 9 16:30:54 2005
@@ -34,7 +34,7 @@
raise XendError(errmsg)
return buf
-def save(xd, fd, dominfo):
+def save(xd, fd, dominfo, live):
write_exact(fd, SIGNATURE, "could not write guest state file: signature")
config = sxp.to_string(dominfo.sxpr())
@@ -42,8 +42,13 @@
"could not write guest state file: config len")
write_exact(fd, config, "could not write guest state file: config")
+ # xc_save takes three customization parameters: maxit, max_f, and flags
+ # the last controls whether or not save is 'live', while the first two
+ # further customize behaviour when 'live' save is enabled. Passing "0"
+ # simply uses the defaults compiled into libxenguest; see the comments
+ # and/or code in xc_linux_save() for more information.
cmd = [PATH_XC_SAVE, str(xc.handle()), str(fd),
- str(dominfo.id)]
+ str(dominfo.id), "0", "0", str(int(live)) ]
log.info("[xc_save] " + join(cmd))
child = xPopen3(cmd, True, -1, [fd, xc.handle()])
@@ -51,7 +56,7 @@
p = select.poll()
p.register(child.fromchild.fileno())
p.register(child.childerr.fileno())
- while True:
+ while True:
r = p.poll()
for (fd, event) in r:
if not event & select.POLLIN:
@@ -65,15 +70,16 @@
if l.rstrip() == "suspend":
log.info("suspending %d" % dominfo.id)
xd.domain_shutdown(dominfo.id, reason='suspend')
+ dominfo.state_wait("suspended")
+ log.info("suspend %d done" % dominfo.id)
if dominfo.store_channel:
try:
dominfo.db.releaseDomain(dominfo.id)
except Exception, ex:
- log.warning("error in domain release on xenstore:
%s",
- ex)
+ log.warning(
+ "error in domain release on xenstore: %s",
+ ex)
pass
- dominfo.state_wait("suspended")
- log.info("suspend %d done" % dominfo.id)
child.tochild.write("done\n")
child.tochild.flush()
if filter(lambda (fd, event): event & select.POLLHUP, r):
@@ -121,12 +127,18 @@
"not a valid guest state file: pfn count out of range")
if dominfo.store_channel:
- evtchn = dominfo.store_channel.port2
+ store_evtchn = dominfo.store_channel.port2
else:
- evtchn = 0
+ store_evtchn = 0
+
+ if dominfo.console_channel:
+ console_evtchn = dominfo.console_channel.port2
+ else:
+ console_evtchn = 0
cmd = [PATH_XC_RESTORE, str(xc.handle()), str(fd),
- str(dominfo.id), str(nr_pfns), str(evtchn)]
+ str(dominfo.id), str(nr_pfns),
+ str(store_evtchn), str(console_evtchn)]
log.info("[xc_restore] " + join(cmd))
child = xPopen3(cmd, True, -1, [fd, xc.handle()])
child.tochild.close()
@@ -147,6 +159,7 @@
if fd == child.fromchild.fileno():
l = child.fromchild.readline()
while l:
+ log.info(l.rstrip())
m = re.match(r"^(store-mfn) (\d+)\n$", l)
if m:
if dominfo.store_channel:
@@ -156,7 +169,10 @@
dominfo.store_mfn,
dominfo.store_channel)
dominfo.exportToDB(save=True, sync=True)
- log.info(l.rstrip())
+ m = re.match(r"^(console-mfn) (\d+)\n$", l)
+ if m:
+ dominfo.console_mfn = int(m.group(2))
+ dominfo.exportToDB(save=True, sync=True)
try:
l = child.fromchild.readline()
except:
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/XendDomain.py
--- a/tools/python/xen/xend/XendDomain.py Thu Sep 8 15:18:40 2005
+++ b/tools/python/xen/xend/XendDomain.py Fri Sep 9 16:30:54 2005
@@ -36,7 +36,6 @@
from xen.xend.XendError import XendError
from xen.xend.XendLogging import log
from xen.xend import scheduler
-from xen.xend.server import channel
from xen.xend.server import relocate
from xen.xend.uuid import getUuid
from xen.xend.xenstore import XenNode, DBMap
@@ -67,7 +66,7 @@
xroot.add_component("xen.xend.XendDomain", self)
self.domains = XendDomainDict()
self.dbmap = DBMap(db=XenNode("/domain"))
- eserver.subscribe('xend.virq', self.onVirq)
+ self.watchReleaseDomain()
self.initial_refresh()
def list(self):
@@ -75,12 +74,32 @@
@return: domain objects
"""
+ self.refresh()
return self.domains.values()
-
- def onVirq(self, event, val):
- """Event handler for virq.
- """
+
+ def list_sorted(self):
+ """Get list of domain objects, sorted by name.
+
+ @return: domain objects
+ """
+ doms = self.list()
+ doms.sort(lambda x, y: cmp(x.name, y.name))
+ return doms
+
+ def list_names(self):
+ """Get list of domain names.
+
+ @return: domain names
+ """
+ doms = self.list_sorted()
+ return map(lambda x: x.name, doms)
+
+ def onReleaseDomain(self):
self.refresh(cleanup=True)
+
+ def watchReleaseDomain(self):
+ from xen.xend.xenstore.xswatch import xswatch
+ self.releaseDomain = xswatch("@releaseDomain", self.onReleaseDomain)
def xen_domains(self):
"""Get table of domains indexed by id from xc.
@@ -265,24 +284,6 @@
else:
self._delete_domain(id)
- def domain_ls(self):
- """Get list of domain names.
-
- @return: domain names
- """
- self.refresh()
- doms = self.domains.values()
- doms.sort(lambda x, y: cmp(x.name, y.name))
- return map(lambda x: x.name, doms)
-
- def domain_ls_ids(self):
- """Get list of domain ids.
-
- @return: domain names
- """
- self.refresh()
- return self.domains.keys()
-
def domain_create(self, config):
"""Create a domain from a configuration.
@@ -542,7 +543,7 @@
dominfo.name = "tmp-" + dominfo.name
try:
- XendCheckpoint.save(self, sock.fileno(), dominfo)
+ XendCheckpoint.save(self, sock.fileno(), dominfo, live)
except:
if dst == "localhost":
dominfo.name = string.replace(dominfo.name, "tmp-", "", 1)
@@ -563,7 +564,8 @@
fd = os.open(dst, os.O_WRONLY | os.O_CREAT | os.O_TRUNC)
- return XendCheckpoint.save(self, fd, dominfo)
+ # For now we don't support 'live checkpoint'
+ return XendCheckpoint.save(self, fd, dominfo, False)
except OSError, ex:
raise XendError("can't write guest state file %s: %s" %
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py Thu Sep 8 15:18:40 2005
+++ b/tools/python/xen/xend/XendDomainInfo.py Fri Sep 9 16:30:54 2005
@@ -34,8 +34,7 @@
from xen.xend.server import controller
from xen.xend.server import SrvDaemon; xend = SrvDaemon.instance()
-from xen.xend.server import messages
-from xen.xend.server.channel import EventChannel, channelFactory
+from xen.xend.server.channel import EventChannel
from xen.util.blkif import blkdev_name_to_number, expand_dev_name
from xen.xend import sxp
@@ -47,7 +46,7 @@
from xen.xend.XendRoot import get_component
from xen.xend.uuid import getUuid
-from xen.xend.xenstore import DBVar
+from xen.xend.xenstore import DBVar, XenNode, DBMap
"""Shutdown code for poweroff."""
DOMAIN_POWEROFF = 0
@@ -231,6 +230,7 @@
DBVar('start_time', ty='float'),
DBVar('state', ty='str'),
DBVar('store_mfn', ty='long'),
+ DBVar('console_mfn', ty='long', path="console/ring-ref"),
DBVar('restart_mode', ty='str'),
DBVar('restart_state', ty='str'),
DBVar('restart_time', ty='float'),
@@ -257,15 +257,17 @@
self.target = None
- self.channel = None
self.store_channel = None
self.store_mfn = None
+ self.console_channel = None
+ self.console_mfn = None
self.controllers = {}
self.info = None
self.blkif_backend = False
self.netif_backend = False
self.netif_idx = 0
+ self.tpmif_backend = False
#todo: state: running, suspended
self.state = STATE_VM_OK
@@ -292,18 +294,18 @@
self.db.saveDB(save=save, sync=sync)
def exportToDB(self, save=False, sync=False):
- if self.channel:
- self.channel.saveToDB(self.db.addChild("channel"), save=save)
if self.store_channel:
self.store_channel.saveToDB(self.db.addChild("store_channel"),
save=save)
+ if self.console_channel:
+ self.db['console/port'] = "%i" % self.console_channel.port1
if self.image:
self.image.exportToDB(save=save, sync=sync)
self.db.exportToDB(self, fields=self.__exports__, save=save, sync=sync)
def importFromDB(self):
self.db.importFromDB(self, fields=self.__exports__)
- self.store_channel = self.eventChannel("store_channel")
+ self.store_channel = self.eventChannelOld("store_channel")
def setdom(self, dom):
"""Set the domain id.
@@ -323,16 +325,16 @@
def getName(self):
return self.name
- def getChannel(self):
- return self.channel
-
def getStoreChannel(self):
return self.store_channel
- def update(self, info):
+ def getConsoleChannel(self):
+ return self.console_channel
+
+ def update(self, info=None):
"""Update with info from xc.domain_getinfo().
"""
- self.info = info
+ self.info = info or dom_get(self.id)
self.memory = self.info['mem_kb'] / 1024
self.ssidref = self.info['ssidref']
self.target = self.info['mem_kb'] * 1024
@@ -384,6 +386,8 @@
return ctrl
def createDevice(self, type, devconfig, change=False):
+ if self.recreate:
+ return
if type == 'vbd':
typedev = sxp.child_value(devconfig, 'dev')
if re.match('^ioemu:', typedev):
@@ -420,6 +424,15 @@
return
if type == 'vif':
+ from xen.xend import XendRoot
+ xroot = XendRoot.instance()
+
+ def _get_config_ipaddr(config):
+ val = []
+ for ipaddr in sxp.children(config, elt='ip'):
+ val.append(sxp.child0(ipaddr))
+ return val
+
backdom = domain_exists(sxp.child_value(devconfig, 'backend', '0'))
log.error(devconfig)
@@ -427,6 +440,14 @@
devnum = self.netif_idx
self.netif_idx += 1
+ script = sxp.child_value(devconfig, 'script',
+ xroot.get_vif_script())
+ script = os.path.join(xroot.network_script_dir, script)
+ bridge = sxp.child_value(devconfig, 'bridge',
+ xroot.get_vif_bridge())
+ mac = sxp.child_value(devconfig, 'mac')
+ ipaddr = _get_config_ipaddr(devconfig)
+
# create backend db
backdb = backdom.db.addChild("/backend/%s/%s/%d" %
(type, self.uuid, devnum))
@@ -434,6 +455,12 @@
# create frontend db
db = self.db.addChild("/device/%s/%d" % (type, devnum))
+ backdb['script'] = script
+ backdb['domain'] = self.name
+ backdb['mac'] = mac
+ backdb['bridge'] = bridge
+ if ipaddr:
+ backdb['ip'] = ' '.join(ipaddr)
backdb['frontend'] = db.getPath()
backdb['frontend-id'] = "%i" % self.id
backdb['handle'] = "%i" % devnum
@@ -442,13 +469,37 @@
db['backend'] = backdb.getPath()
db['backend-id'] = "%i" % backdom.id
db['handle'] = "%i" % devnum
- log.error(sxp.child_value(devconfig, 'mac'))
- db['mac'] = sxp.child_value(devconfig, 'mac')
+ db['mac'] = mac
db.saveDB(save=True)
return
+ if type == 'vtpm':
+ backdom = domain_exists(sxp.child_value(devconfig, 'backend', '0'))
+
+ devnum = int(sxp.child_value(devconfig, 'instance', '0'))
+ log.error("The domain has a TPM with instance %d." % devnum)
+
+ # create backend db
+ backdb = backdom.db.addChild("/backend/%s/%s/%d" %
+ (type, self.uuid, devnum))
+ # create frontend db
+ db = self.db.addChild("/device/%s/%d" % (type, devnum))
+
+ backdb['frontend'] = db.getPath()
+ backdb['frontend-id'] = "%i" % self.id
+ backdb['instance'] = sxp.child_value(devconfig, 'instance', '0')
+ backdb.saveDB(save=True)
+
+ db['handle'] = "%i" % devnum
+ db['backend'] = backdb.getPath()
+ db['backend-id'] = "%i" % int(sxp.child_value(devconfig,
+ 'backend', '0'))
+ db.saveDB(save=True)
+
+ return
+
ctrl = self.findDeviceController(type)
return ctrl.createDevice(devconfig, recreate=self.recreate,
change=change)
@@ -512,12 +563,18 @@
sxpr.append(['up_time', str(up_time) ])
sxpr.append(['start_time', str(self.start_time) ])
- if self.channel:
- sxpr.append(self.channel.sxpr())
if self.store_channel:
sxpr.append(self.store_channel.sxpr())
if self.store_mfn:
sxpr.append(['store_mfn', self.store_mfn])
+ if self.console_channel:
+ sxpr.append(['console_channel', self.console_channel.sxpr()])
+ if self.console_mfn:
+ sxpr.append(['console_mfn', self.console_mfn])
+# already in (devices)
+# console = self.getConsole()
+# if console:
+# sxpr.append(console.sxpr())
if self.restart_count:
sxpr.append(['restart_count', self.restart_count])
@@ -695,12 +752,6 @@
"""
self.state = STATE_VM_TERMINATED
self.release_devices()
- if self.channel:
- try:
- self.channel.close()
- self.channel = None
- except:
- pass
if self.store_channel:
try:
self.store_channel.close()
@@ -712,6 +763,13 @@
except Exception, ex:
log.warning("error in domain release on xenstore: %s", ex)
pass
+ if self.console_channel:
+ # notify processes using this cosole?
+ try:
+ self.console_channel.close()
+ self.console_channel = None
+ except:
+ pass
if self.image:
try:
self.device_model_pid = 0
@@ -723,8 +781,8 @@
def destroy(self):
"""Clenup vm and destroy domain.
"""
+ self.destroy_domain()
self.cleanup()
- self.destroy_domain()
self.saveToDB()
return 0
@@ -755,6 +813,11 @@
for dev in typedb.keys():
typedb[dev].delete()
typedb.saveDB(save=True)
+ if type == 'vtpm':
+ typedb = ddb.addChild(type)
+ for dev in typedb.keys():
+ typedb[dev].delete()
+ typedb.saveDB(save=True)
def show(self):
"""Print virtual machine info.
@@ -780,21 +843,7 @@
id, self.name, self.memory)
self.setdom(id)
- def openChannel(self, key, local, remote):
- """Create a control channel to the domain.
- If saved info is available recreate the channel.
-
- @param key db key for the saved data (if any)
- @param local default local port
- @param remote default remote port
- """
- db = self.db.addChild(key)
- chan = channelFactory().restoreFromDB(db, self.id, local, remote)
- #todo: save here?
- #chan.saveToDB(db)
- return chan
-
- def eventChannel(self, key):
+ def eventChannelOld(self, key):
"""Create an event channel to the domain.
If saved info is available recreate the channel.
@@ -803,11 +852,27 @@
db = self.db.addChild(key)
return EventChannel.restoreFromDB(db, 0, self.id)
+ def eventChannel(self, path=None, key=None):
+ """Create an event channel to the domain.
+
+ @param path under which port is stored in db
+ """
+ port = 0
+ try:
+ if path and key:
+ if path:
+ db = self.db.addChild(path)
+ else:
+ db = self.db
+ port = int(db[key].getData())
+ except: pass
+ return EventChannel.interdomain(0, self.id, port1=port, port2=0)
+
def create_channel(self):
"""Create the channels to the domain.
"""
- self.channel = self.openChannel("channel", 0, 1)
- self.store_channel = self.eventChannel("store_channel")
+ self.store_channel = self.eventChannelOld("store_channel")
+ self.console_channel = self.eventChannel("console", "port")
def create_configured_devices(self):
devices = sxp.children(self.config, 'device')
@@ -950,6 +1015,7 @@
"""
try:
+ self.clear_shutdown()
self.state = STATE_VM_OK
self.shutdown_pending = None
self.restart_check()
@@ -993,6 +1059,8 @@
self.netif_backend = True
elif name == 'usbif':
self.usbif_backend = True
+ elif name == 'tpmif':
+ self.tpmif_backend = True
else:
raise VmError('invalid backend type:' + str(name))
@@ -1084,7 +1152,7 @@
def dom0_init_store(self):
if not self.store_channel:
- self.store_channel = self.eventChannel("store_channel")
+ self.store_channel = self.eventChannelOld("store_channel")
self.store_mfn = xc.init_store(self.store_channel.port2)
if self.store_mfn >= 0:
self.db.introduceDomain(self.id, self.store_mfn,
@@ -1158,6 +1226,10 @@
controller.addDevControllerClass("vif", netif.NetifController)
add_device_handler("vif", "vif")
+from server import tpmif
+controller.addDevControllerClass("vtpm", tpmif.TPMifController)
+add_device_handler("vtpm", "vtpm")
+
from server import pciif
controller.addDevControllerClass("pci", pciif.PciController)
add_device_handler("pci", "pci")
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/XendNode.py
--- a/tools/python/xen/xend/XendNode.py Thu Sep 8 15:18:40 2005
+++ b/tools/python/xen/xend/XendNode.py Fri Sep 9 16:30:54 2005
@@ -46,7 +46,7 @@
return self.xc.bvtsched_global_get()
def info(self):
- return self.nodeinfo() + self.physinfo()
+ return self.nodeinfo() + self.physinfo() + self.xeninfo()
def nodeinfo(self):
(sys, host, rel, ver, mch) = os.uname()
@@ -58,14 +58,29 @@
def physinfo(self):
pinfo = self.xc.physinfo()
- info = [['cores_per_socket', pinfo['cores_per_socket']],
+ info = [['nr_cpus',
pinfo['nr_nodes']*pinfo['sockets_per_node']*pinfo['cores_per_socket']*pinfo['threads_per_core']],
+ ['nr_nodes', pinfo['nr_nodes']],
+ ['sockets_per_node', pinfo['sockets_per_node']],
+ ['cores_per_socket', pinfo['cores_per_socket']],
['threads_per_core', pinfo['threads_per_core']],
- ['cpu_mhz', pinfo['cpu_khz']/1000],
- ['memory', pinfo['total_pages']/256],
- ['free_memory', pinfo['free_pages']/256]]
+ ['cpu_mhz', pinfo['cpu_khz']/1000],
+ ['hw_caps', pinfo['hw_caps']],
+ ['memory', pinfo['total_pages']/256],
+ ['free_memory', pinfo['free_pages']/256]]
return info
-
+ def xeninfo(self):
+ xinfo = self.xc.xeninfo()
+ return [['xen_major', xinfo['xen_major']],
+ ['xen_minor', xinfo['xen_minor']],
+ ['xen_extra', xinfo['xen_extra']],
+ ['xen_caps', xinfo['xen_caps']],
+ ['xen_params',xinfo['xen_params']],
+ ['xen_changeset', xinfo['xen_changeset']],
+ ['cc_compiler', xinfo['cc_compiler']],
+ ['cc_compile_by', xinfo['cc_compile_by']],
+ ['cc_compile_domain', xinfo['cc_compile_domain']],
+ ['cc_compile_date', xinfo['cc_compile_date']]]
def instance():
global inst
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py Thu Sep 8 15:18:40 2005
+++ b/tools/python/xen/xend/image.py Fri Sep 9 16:30:54 2005
@@ -32,6 +32,9 @@
"""Flag for a net device backend domain."""
SIF_NET_BE_DOMAIN = (1<<5)
+"""Flag for a TPM device backend domain."""
+SIF_TPM_BE_DOMAIN = (1<<7)
+
class ImageHandler:
"""Abstract base class for image handlers.
@@ -156,7 +159,12 @@
xc.domain_setmaxmem(dom, mem_kb)
try:
- xc.domain_memory_increase_reservation(dom, mem_kb)
+ # Give the domain some memory below 4GB
+ lmem_kb = 0
+ if lmem_kb > 0:
+ xc.domain_memory_increase_reservation(dom,
min(lmem_kb,mem_kb), 0, 32)
+ if mem_kb > lmem_kb:
+ xc.domain_memory_increase_reservation(dom, mem_kb-lmem_kb, 0,
0)
except:
xc.domain_destroy(dom)
raise
@@ -194,6 +202,7 @@
self.flags = 0
if self.vm.netif_backend: self.flags |= SIF_NET_BE_DOMAIN
if self.vm.blkif_backend: self.flags |= SIF_BLK_BE_DOMAIN
+ if self.vm.tpmif_backend: self.flags |= SIF_TPM_BE_DOMAIN
if self.vm.recreate or self.vm.restore:
return
@@ -238,16 +247,31 @@
store_evtchn = self.vm.store_channel.port2
else:
store_evtchn = 0
+ if self.vm.console_channel:
+ console_evtchn = self.vm.console_channel.port2
+ else:
+ console_evtchn = 0
+
+ log.debug("dom = %d", self.vm.getDomain())
+ log.debug("image = %s", self.kernel)
+ log.debug("store_evtchn = %d", store_evtchn)
+ log.debug("console_evtchn = %d", console_evtchn)
+ log.debug("cmdline = %s", self.cmdline)
+ log.debug("ramdisk = %s", self.ramdisk)
+ log.debug("flags = %d", self.flags)
+ log.debug("vcpus = %d", self.vm.vcpus)
+
ret = xc.linux_build(dom = self.vm.getDomain(),
image = self.kernel,
- control_evtchn = self.vm.channel.getRemotePort(),
store_evtchn = store_evtchn,
+ console_evtchn = console_evtchn,
cmdline = self.cmdline,
ramdisk = self.ramdisk,
flags = self.flags,
vcpus = self.vm.vcpus)
if isinstance(ret, dict):
self.vm.store_mfn = ret.get('store_mfn')
+ self.vm.console_mfn = ret.get('console_mfn')
return 0
return ret
@@ -349,6 +373,11 @@
mac = sxp.child_value(vifinfo, 'mac')
ret.append("-macaddr")
ret.append("%s" % mac)
+ if name == 'vtpm':
+ vtpminfo = sxp.child(device, 'vtpm')
+ instance = sxp.child_value(vtpminfo, 'instance')
+ ret.append("-instance")
+ ret.append("%s" % instance)
# Handle graphics library related options
vnc = sxp.child_value(self.vm.config, 'vnc')
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/server/SrvDaemon.py
--- a/tools/python/xen/xend/server/SrvDaemon.py Thu Sep 8 15:18:40 2005
+++ b/tools/python/xen/xend/server/SrvDaemon.py Fri Sep 9 16:30:54 2005
@@ -17,8 +17,6 @@
import time
import glob
-from xen.lowlevel import xu
-
from xen.xend import sxp
from xen.xend import PrettyPrint
from xen.xend import EventServer; eserver = EventServer.instance()
@@ -27,7 +25,6 @@
from xen.xend.XendLogging import log
from xen.xend import XendRoot; xroot = XendRoot.instance()
-import channel
import controller
import event
import relocate
@@ -37,12 +34,12 @@
"""The xend daemon.
"""
def __init__(self):
- self.channelF = None
self.shutdown = 0
self.traceon = 0
self.tracefile = None
self.traceindent = 0
-
+ self.child = 0
+
def daemon_pids(self):
pids = []
pidex = '(?P<pid>\d+)'
@@ -140,15 +137,12 @@
else:
return 0
- def install_child_reaper(self):
- #signal.signal(signal.SIGCHLD, self.onSIGCHLD)
- # Ensure that zombie children are automatically reaped.
- xu.autoreap()
-
def onSIGCHLD(self, signum, frame):
- code = 1
- while code > 0:
- code = os.waitpid(-1, os.WNOHANG)
+ if self.child > 0:
+ try:
+ pid, sts = os.waitpid(self.child, os.WNOHANG)
+ except os.error, ex:
+ pass
def fork_pid(self, pidfile):
"""Fork and write the pid of the child to 'pidfile'.
@@ -156,13 +150,16 @@
@param pidfile: pid file
@return: pid of child in parent, 0 in child
"""
- pid = os.fork()
- if pid:
+
+ self.child = os.fork()
+
+ if self.child:
# Parent
pidfile = open(pidfile, 'w')
- pidfile.write(str(pid))
+ pidfile.write(str(self.child))
pidfile.close()
- return pid
+
+ return self.child
def daemonize(self):
if not XEND_DAEMONIZE: return
@@ -203,8 +200,7 @@
# Trying to run an already-running service is a success.
return 0
- self.install_child_reaper()
-
+ signal.signal(signal.SIGCHLD, self.onSIGCHLD)
if self.fork_pid(XEND_PID_FILE):
#Parent. Sleep to give child time to start.
time.sleep(1)
@@ -298,10 +294,8 @@
_enforce_dom0_cpus()
try:
log.info("Xend Daemon started")
- self.createFactories()
event.listenEvent(self)
relocate.listenRelocation()
- self.listenChannels()
servers = SrvServer.create()
self.daemonize()
servers.start()
@@ -309,22 +303,10 @@
print >>sys.stderr, 'Exception starting xend:', ex
if XEND_DEBUG:
traceback.print_exc()
- log.exception("Exception starting xend")
+ log.exception("Exception starting xend (%s)" % ex)
self.exit(1)
- def createFactories(self):
- self.channelF = channel.channelFactory()
-
- def listenChannels(self):
- def virqReceived(virq):
- eserver.inject('xend.virq', virq)
-
- self.channelF.setVirqHandler(virqReceived)
- self.channelF.start()
-
def exit(self, rc=0):
- if self.channelF:
- self.channelF.stop()
# Calling sys.exit() raises a SystemExit exception, which only
# kills the current thread. Calling os._exit() makes the whole
# Python process exit immediately. There doesn't seem to be another
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/server/SrvDomain.py
--- a/tools/python/xen/xend/server/SrvDomain.py Thu Sep 8 15:18:40 2005
+++ b/tools/python/xen/xend/server/SrvDomain.py Fri Sep 9 16:30:54 2005
@@ -221,6 +221,7 @@
#
# if op and op[0] in ['vifs', 'vif', 'vbds', 'vbd', 'mem_target_set']:
# return self.perform(req)
+ self.dom.update()
if self.use_sxp(req):
req.setHeader("Content-Type", sxp.mime_type)
sxp.show(self.dom.sxpr(), out=req)
diff -r 10b1d30d3f66 -r b2f4823b6ff0
tools/python/xen/xend/server/SrvDomainDir.py
--- a/tools/python/xen/xend/server/SrvDomainDir.py Thu Sep 8 15:18:40 2005
+++ b/tools/python/xen/xend/server/SrvDomainDir.py Fri Sep 9 16:30:54 2005
@@ -146,11 +146,10 @@
if not url.endswith('/'):
url += '/'
if use_sxp:
- domains = self.xd.domain_ls()
+ domains = self.xd.list_names()
sxp.show(domains, out=req)
else:
- domains = self.xd.list()
- domains.sort(lambda x, y: cmp(x.name, y.name))
+ domains = self.xd.list_sorted()
req.write('<ul>')
for d in domains:
req.write('<li><a href="%s%s"> Domain %s</a>'
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/server/SrvServer.py
--- a/tools/python/xen/xend/server/SrvServer.py Thu Sep 8 15:18:40 2005
+++ b/tools/python/xen/xend/server/SrvServer.py Fri Sep 9 16:30:54 2005
@@ -61,9 +61,14 @@
def start(self):
Vifctl.network('start')
+ threads = []
for server in self.servers:
thread = Thread(target=server.run)
thread.start()
+ threads.append(thread)
+
+ for t in threads:
+ t.join()
def create():
root = SrvDir()
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/server/blkif.py
--- a/tools/python/xen/xend/server/blkif.py Thu Sep 8 15:18:40 2005
+++ b/tools/python/xen/xend/server/blkif.py Fri Sep 9 16:30:54 2005
@@ -27,9 +27,7 @@
from xen.xend import Blkctl
from xen.xend.xenstore import DBVar
-from xen.xend.server import channel
-from xen.xend.server.controller import CtrlMsgRcvr, Dev, DevController
-from xen.xend.server.messages import *
+from xen.xend.server.controller import Dev, DevController
class BlkifBackend:
""" Handler for the 'back-end' channel to a block device driver domain
@@ -41,21 +39,15 @@
self.controller = controller
self.id = id
self.frontendDomain = self.controller.getDomain()
- self.frontendChannel = None
self.backendDomain = dom
- self.backendChannel = None
self.destroyed = False
self.connected = False
- self.evtchn = None
self.status = None
def init(self, recreate=False, reboot=False):
self.destroyed = False
self.status = BLKIF_INTERFACE_STATUS_DISCONNECTED
self.frontendDomain = self.controller.getDomain()
- self.frontendChannel = self.controller.getChannel()
- cf = channel.channelFactory()
- self.backendChannel = cf.openChannel(self.backendDomain)
def __str__(self):
return ('<BlkifBackend frontend=%d backend=%d id=%d>'
@@ -66,29 +58,6 @@
def getId(self):
return self.id
- def getEvtchn(self):
- return self.evtchn
-
- def closeEvtchn(self):
- if self.evtchn:
- channel.eventChannelClose(self.evtchn)
- self.evtchn = None
-
- def openEvtchn(self):
- self.evtchn = channel.eventChannel(self.backendDomain,
self.frontendDomain)
-
- def getEventChannelBackend(self):
- val = 0
- if self.evtchn:
- val = self.evtchn['port1']
- return val
-
- def getEventChannelFrontend(self):
- val = 0
- if self.evtchn:
- val = self.evtchn['port2']
- return val
-
def connect(self, recreate=False):
"""Connect to the blkif control interface.
@@ -98,83 +67,19 @@
if recreate or self.connected:
self.connected = True
pass
- else:
- self.send_be_create()
-
- def send_be_create(self):
- log.debug("send_be_create %s", str(self))
- msg = packMsg('blkif_be_create_t',
- { 'domid' : self.frontendDomain,
- 'blkif_handle' : self.id })
- msg = self.backendChannel.requestResponse(msg)
- #todo: check return status
- self.connected = True
-
+
def destroy(self, change=False, reboot=False):
"""Disconnect from the blkif control interface and destroy it.
"""
- self.send_be_disconnect()
- self.send_be_destroy()
- self.closeEvtchn()
self.destroyed = True
# For change true need to notify front-end, or back-end will do it?
- def send_be_disconnect(self):
- msg = packMsg('blkif_be_disconnect_t',
- { 'domid' : self.frontendDomain,
- 'blkif_handle' : self.id })
- self.backendChannel.requestResponse(msg)
- #todo: check return status
- self.connected = False
-
- def send_be_destroy(self):
- msg = packMsg('blkif_be_destroy_t',
- { 'domid' : self.frontendDomain,
- 'blkif_handle' : self.id })
- self.backendChannel.requestResponse(msg)
- #todo: check return status
-
def connectInterface(self, val):
- self.openEvtchn()
- log.debug("Connecting blkif to event channel %s ports=%d:%d",
- str(self), self.evtchn['port1'], self.evtchn['port2'])
- msg = packMsg('blkif_be_connect_t',
- { 'domid' : self.frontendDomain,
- 'blkif_handle' : self.id,
- 'evtchn' : self.getEventChannelBackend(),
- 'shmem_frame' : val['shmem_frame'],
- 'shmem_ref' : val['shmem_ref'] })
- msg = self.backendChannel.requestResponse(msg)
- #todo: check return status
- val = unpackMsg('blkif_be_connect_t', msg)
self.status = BLKIF_INTERFACE_STATUS_CONNECTED
- self.send_fe_interface_status()
- def send_fe_interface_status(self):
- msg = packMsg('blkif_fe_interface_status_t',
- { 'handle' : self.id,
- 'status' : self.status,
- 'domid' : self.backendDomain,
- 'evtchn' : self.getEventChannelFrontend() })
- self.frontendChannel.writeRequest(msg)
-
def interfaceDisconnected(self):
self.status = BLKIF_INTERFACE_STATUS_DISCONNECTED
- #todo?: Close evtchn:
- #self.closeEvtchn()
- self.send_fe_interface_status()
-
- def interfaceChanged(self):
- """Notify the front-end that devices have been added or removed.
- The front-end should then probe for devices.
- """
- msg = packMsg('blkif_fe_interface_status_t',
- { 'handle' : self.id,
- 'status' : BLKIF_INTERFACE_STATUS_CHANGED,
- 'domid' : self.backendDomain,
- 'evtchn' : 0 })
- self.frontendChannel.writeRequest(msg)
-
+
class BlkDev(Dev):
"""Info record for a block device.
"""
@@ -207,24 +112,17 @@
self.nr_sectors = None
self.frontendDomain = self.getDomain()
- self.frontendChannel = None
self.backendDomain = None
- self.backendChannel = None
self.backendId = 0
self.configure(self.config, recreate=recreate)
def exportToDB(self, save=False):
Dev.exportToDB(self, save=save)
backend = self.getBackend()
- if backend and backend.evtchn:
- db = self.db.addChild("evtchn")
- backend.evtchn.saveToDB(db, save=save)
def init(self, recreate=False, reboot=False):
self.frontendDomain = self.getDomain()
- self.frontendChannel = self.getChannel()
backend = self.getBackend()
- self.backendChannel = backend.backendChannel
self.backendId = backend.id
def configure(self, config, change=False, recreate=False):
@@ -351,7 +249,6 @@
self.destroyed = True
log.debug("Destroying vbd domain=%d id=%s", self.frontendDomain,
self.id)
- self.send_be_vbd_destroy()
if change:
self.interfaceChanged()
self.unbind()
@@ -367,30 +264,6 @@
"""
self.getBackend().connect()
- self.send_be_vbd_create()
-
- def send_be_vbd_create(self):
- msg = packMsg('blkif_be_vbd_create_t',
- { 'domid' : self.frontendDomain,
- 'blkif_handle' : self.backendId,
- 'pdevice' : self.device,
- 'dev_handle' : self.dev_handle,
- 'vdevice' : self.vdev,
- 'readonly' : self.readonly() })
- msg = self.backendChannel.requestResponse(msg)
-
- val = unpackMsg('blkif_be_vbd_create_t', msg)
- status = val['status']
- if status != BLKIF_BE_STATUS_OKAY:
- raise XendError("Creating vbd failed: device %s, error %d"
- % (sxp.to_string(self.config), status))
-
- def send_be_vbd_destroy(self):
- msg = packMsg('blkif_be_vbd_destroy_t',
- { 'domid' : self.frontendDomain,
- 'blkif_handle' : self.backendId,
- 'vdevice' : self.vdev })
- return self.backendChannel.writeRequest(msg)
class BlkifController(DevController):
"""Block device interface controller. Handles all block devices
@@ -403,19 +276,9 @@
DevController.__init__(self, vm, recreate=recreate)
self.backends = {}
self.backendId = 0
- self.rcvr = None
def initController(self, recreate=False, reboot=False):
self.destroyed = False
- # Add our handlers for incoming requests.
- self.rcvr = CtrlMsgRcvr(self.getChannel())
- self.rcvr.addHandler(CMSG_BLKIF_FE,
- CMSG_BLKIF_FE_DRIVER_STATUS,
- self.recv_fe_driver_status)
- self.rcvr.addHandler(CMSG_BLKIF_FE,
- CMSG_BLKIF_FE_INTERFACE_CONNECT,
- self.recv_fe_interface_connect)
- self.rcvr.registerChannel()
if reboot:
self.rebootBackends()
self.rebootDevices()
@@ -465,26 +328,7 @@
log.debug("Destroying blkif domain=%d", self.getDomain())
self.destroyDevices(reboot=reboot)
self.destroyBackends(reboot=reboot)
- self.rcvr.deregisterChannel()
def destroyBackends(self, reboot=False):
for backend in self.backends.values():
backend.destroy(reboot=reboot)
-
- def recv_fe_driver_status(self, msg):
- val = unpackMsg('blkif_fe_driver_status_t', msg)
- for backend in self.backends.values():
- backend.interfaceDisconnected()
-
- def recv_fe_interface_connect(self, msg):
- val = unpackMsg('blkif_fe_interface_connect_t', msg)
- id = val['handle']
- backend = self.getBackendById(id)
- if backend:
- try:
- backend.connectInterface(val)
- except IOError, ex:
- log.error("Exception connecting backend: %s", ex)
- else:
- log.error('interface connect on unknown interface: id=%d', id)
-
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/server/channel.py
--- a/tools/python/xen/xend/server/channel.py Thu Sep 8 15:18:40 2005
+++ b/tools/python/xen/xend/server/channel.py Fri Sep 9 16:30:54 2005
@@ -19,11 +19,8 @@
import select
import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
-from xen.lowlevel import xu
from xen.xend.XendLogging import log
-
-from messages import *
DEBUG = 0
@@ -132,501 +129,3 @@
"""
if not evtchn: return
evtchn.close()
-
-class ChannelFactory:
- """Factory for creating control channels.
- Maintains a table of channels.
- """
-
- """ Channels indexed by index. """
- channels = None
-
- thread = None
-
- notifier = None
-
- """Map of ports to the virq they signal."""
- virqPorts = None
-
- def __init__(self):
- """Constructor - do not use. Use the channelFactory function."""
- self.channels = {}
- self.virqPorts = {}
- self.notifier = xu.notifier()
- # Register interest in virqs.
- self.bind_virq(xen.lowlevel.xc.VIRQ_DOM_EXC)
- self.virqHandler = None
-
- def bind_virq(self, virq):
- port = self.notifier.bind_virq(virq)
- self.virqPorts[port] = virq
- log.info("Virq %s on port %s", virq, port)
-
- def start(self):
- """Fork a thread to read messages.
- """
- if self.thread: return
- self.thread = threading.Thread(name="ChannelFactory",
- target=self.main)
- self.thread.setDaemon(True)
- self.thread.start()
-
- def stop(self):
- """Signal the thread to stop.
- """
- self.thread = None
-
- def main(self):
- """Main routine for the thread.
- Reads the notifier and dispatches to channels.
- """
- while True:
- if self.thread == None: return
- port = self.notifier.read()
- if port:
- virq = self.virqPorts.get(port)
- if virq is not None:
- self.virqReceived(virq)
- else:
- self.msgReceived(port)
- else:
- select.select([self.notifier], [], [], 1.0)
-
- def msgReceived(self, port):
- # We run the message handlers in their own threads.
- # Note we use keyword args to lambda to save the values -
- # otherwise lambda will use the variables, which will get
- # assigned by the loop and the lambda will get the changed values.
- received = 0
- for chan in self.channels.values():
- if self.thread == None: return
- msg = chan.readResponse()
- if msg:
- received += 1
- chan.responseReceived(msg)
- for chan in self.channels.values():
- if self.thread == None: return
- msg = chan.readRequest()
- if msg:
- received += 1
- self.runInThread(lambda chan=chan, msg=msg:
chan.requestReceived(msg))
- if port and received == 0:
- log.warning("Port %s notified, but no messages found", port)
-
- def runInThread(self, thunk):
- thread = threading.Thread(target = thunk)
- thread.setDaemon(True)
- thread.start()
-
- def setVirqHandler(self, virqHandler):
- self.virqHandler = virqHandler
-
- def virqReceived(self, virq):
- if DEBUG:
- print 'virqReceived>', virq
- if not self.virqHandler: return
- self.runInThread(lambda virq=virq: self.virqHandler(virq))
-
- def newChannel(self, dom, local_port, remote_port):
- """Create a new channel.
- """
- return self.addChannel(Channel(self, dom, local_port, remote_port))
-
- def addChannel(self, channel):
- """Add a channel.
- """
- self.channels[channel.getKey()] = channel
- return channel
-
- def delChannel(self, channel):
- """Remove the channel.
- """
- key = channel.getKey()
- if key in self.channels:
- del self.channels[key]
-
- def getChannel(self, dom, local_port, remote_port):
- """Get the channel with the given domain and ports (if any).
- """
- key = (dom, local_port, remote_port)
- return self.channels.get(key)
-
- def findChannel(self, dom, local_port=0, remote_port=0):
- """Find a channel. Ports given as zero are wildcards.
-
- dom domain
-
- returns channel
- """
- chan = self.getChannel(dom, local_port, remote_port)
- if chan: return chan
- if local_port and remote_port:
- return None
- for c in self.channels.values():
- if c.dom != dom: continue
- if local_port and local_port != c.getLocalPort(): continue
- if remote_port and remote_port != c.getRemotePort(): continue
- return c
- return None
-
- def openChannel(self, dom, local_port=0, remote_port=0):
- chan = self.findChannel(dom, local_port=local_port,
- remote_port=remote_port)
- if chan:
- return chan
- chan = self.newChannel(dom, local_port, remote_port)
- return chan
-
-
- def createPort(self, dom, local_port=0, remote_port=0):
- """Create a port for a channel to the given domain.
- If only the domain is specified, a new channel with new port ids is
- created. If one port id is specified and the given port id is in use,
- the other port id is filled. If one port id is specified and the
- given port id is not in use, a new channel is created with one port
- id equal to the given id and a new id for the other end. If both
- port ids are specified, a port is reconnected using the given port
- ids.
-
- @param dom: domain
- @param local: local port id to use
- @type local: int
- @param remote: remote port id to use
- @type remote: int
- @return: port object
- """
- return xu.port(dom, local_port=local_port, remote_port=remote_port)
-
- def restoreFromDB(self, db, dom, local, remote):
- """Create a channel using ports restored from the db (if available).
- Otherwise use the given ports. This is the inverse operation to
- saveToDB() on a channel.
-
- @param db db
- @param dom domain the channel connects to
- @param local default local port
- @param remote default remote port
- """
- try:
- local_port = int(db['local_port'])
- except:
- local_port = local
- try:
- remote_port = int(db['remote_port'])
- except:
- remote_port = remote
- try:
- chan = self.openChannel(dom, local_port, remote_port)
- except:
- return None
- return chan
-
-def channelFactory():
- """Singleton constructor for the channel factory.
- Use this instead of the class constructor.
- """
- global inst
- try:
- inst
- except:
- inst = ChannelFactory()
- return inst
-
-class Channel:
- """Control channel to a domain.
- Maintains a list of device handlers to dispatch requests to, based
- on the request type.
- """
-
- def __init__(self, factory, dom, local_port, remote_port):
- self.factory = factory
- self.dom = int(dom)
- # Registered device handlers.
- self.devs = []
- # Handlers indexed by the message types they handle.
- self.devs_by_type = {}
- self.port = self.factory.createPort(self.dom,
- local_port=local_port,
- remote_port=remote_port)
- self.closed = False
- # Queue of waiters for responses to requests.
- self.queue = ResponseQueue(self)
- # Make sure the port will deliver all the messages.
- self.port.register(TYPE_WILDCARD)
-
- def saveToDB(self, db, save=False):
- """Save the channel ports to the db so the channel can be restored
later,
- using restoreFromDB() on the factory.
-
- @param db db
- """
- if self.closed: return
- db['local_port'] = str(self.getLocalPort())
- db['remote_port'] = str(self.getRemotePort())
- db.saveDB(save=save)
-
- def getKey(self):
- """Get the channel key.
- """
- return (self.dom, self.getLocalPort(), self.getRemotePort())
-
- def sxpr(self):
- val = ['channel']
- val.append(['domain', self.dom])
- if self.port:
- val.append(['local_port', self.port.local_port])
- val.append(['remote_port', self.port.remote_port])
- return val
-
- def close(self):
- """Close the channel.
- """
- if DEBUG:
- print 'Channel>close>', self
- if self.closed: return
- self.closed = True
- self.factory.delChannel(self)
- for d in self.devs[:]:
- d.lostChannel(self)
- self.devs = []
- self.devs_by_type = {}
- if self.port:
- self.port.close()
- #self.port = None
-
- def getDomain(self):
- return self.dom
-
- def getLocalPort(self):
- """Get the local port.
-
- @return: local port
- @rtype: int
- """
- if self.closed: return -1
- return self.port.local_port
-
- def getRemotePort(self):
- """Get the remote port.
-
- @return: remote port
- @rtype: int
- """
- if self.closed: return -1
- return self.port.remote_port
-
- def __repr__(self):
- return ('<Channel dom=%d ports=%d:%d>'
- % (self.dom,
- self.getLocalPort(),
- self.getRemotePort()))
-
-
- def registerDevice(self, types, dev):
- """Register a device message handler.
-
- @param types: message types handled
- @type types: array of ints
- @param dev: device handler
- """
- if self.closed: return
- self.devs.append(dev)
- for ty in types:
- self.devs_by_type[ty] = dev
-
- def deregisterDevice(self, dev):
- """Remove the registration for a device handler.
-
- @param dev: device handler
- """
- if dev in self.devs:
- self.devs.remove(dev)
- types = [ ty for (ty, d) in self.devs_by_type.items() if d == dev ]
- for ty in types:
- del self.devs_by_type[ty]
-
- def getDevice(self, type):
- """Get the handler for a message type.
-
- @param type: message type
- @type type: int
- @return: controller or None
- @rtype: device handler
- """
- return self.devs_by_type.get(type)
-
- def requestReceived(self, msg):
- """A request has been received on the channel.
- Disptach it to the device handlers.
- Called from the channel factory thread.
- """
- if DEBUG:
- print 'Channel>requestReceived>', self,
- printMsg(msg)
- (ty, subty) = getMessageType(msg)
- responded = False
- dev = self.getDevice(ty)
- if dev:
- responded = dev.requestReceived(msg, ty, subty)
- elif DEBUG:
- print "Channel>requestReceived> No device handler", self,
- printMsg(msg)
- else:
- pass
- if not responded:
- self.writeResponse(msg)
-
- def writeRequest(self, msg):
- """Write a request to the channel.
- """
- if DEBUG:
- print 'Channel>writeRequest>', self,
- printMsg(msg, all=True)
- if self.closed: return -1
- self.port.write_request(msg)
- return 1
-
- def writeResponse(self, msg):
- """Write a response to the channel.
- """
- if DEBUG:
- print 'Channel>writeResponse>', self,
- printMsg(msg, all=True)
- if self.port:
- self.port.write_response(msg)
- return 1
-
- def readRequest(self):
- """Read a request from the channel.
- Called internally.
- """
- if self.closed:
- val = None
- else:
- val = self.port.read_request()
- return val
-
- def readResponse(self):
- """Read a response from the channel.
- Called internally.
- """
- if self.closed:
- val = None
- else:
- val = self.port.read_response()
- if DEBUG and val:
- print 'Channel>readResponse>', self,
- printMsg(val, all=True)
- return val
-
- def requestResponse(self, msg, timeout=None):
- """Write a request and wait for a response.
- Raises IOError on timeout.
-
- @param msg request message
- @param timeout timeout (0 is forever)
- @return response message
- """
- if self.closed:
- raise IOError("closed")
- if self.closed:
- return None
- if timeout is None:
- timeout = RESPONSE_TIMEOUT
- elif timeout <= 0:
- timeout = None
- return self.queue.call(msg, timeout)
-
- def responseReceived(self, msg):
- """A response has been received, look for a waiter to
- give it to.
- Called internally.
- """
- if DEBUG:
- print 'Channel>responseReceived>', self,
- printMsg(msg)
- self.queue.response(getMessageId(msg), msg)
-
- def virq(self):
- self.factory.virq()
-
-class Response:
- """Entry in the response queue.
- Used to signal a response to a message.
- """
-
- def __init__(self, mid):
- self.mid = mid
- self.msg = None
- self.ready = threading.Event()
-
- def response(self, msg):
- """Signal arrival of a response to a waiting thread.
- Passing msg None cancels the wait with an IOError.
- """
- if msg:
- self.msg = msg
- else:
- self.mid = -1
- self.ready.set()
-
- def wait(self, timeout):
- """Wait up to 'timeout' seconds for a response.
- Returns the response or raises an IOError.
- """
- self.ready.wait(timeout)
- if self.mid < 0:
- raise IOError("wait canceled")
- if self.msg is None:
- raise IOError("response timeout")
- return self.msg
-
-class ResponseQueue:
- """Response queue. Manages waiters for responses to messages.
- """
-
- def __init__(self, channel):
- self.channel = channel
- self.lock = threading.Lock()
- self.responses = {}
-
- def add(self, mid):
- r = Response(mid)
- self.responses[mid] = r
- return r
-
- def get(self, mid):
- return self.responses.get(mid)
-
- def remove(self, mid):
- r = self.responses.get(mid)
- if r:
- del self.responses[mid]
- return r
-
- def response(self, mid, msg):
- """Process a response - signals any waiter that a response
- has arrived.
- """
- try:
- self.lock.acquire()
- r = self.remove(mid)
- finally:
- self.lock.release()
- if r:
- r.response(msg)
-
- def call(self, msg, timeout):
- """Send the message and wait for 'timeout' seconds for a response.
- Returns the response.
- Raises IOError on timeout.
- """
- mid = getMessageId(msg)
- try:
- self.lock.acquire()
- r = self.add(mid)
- finally:
- self.lock.release()
- self.channel.writeRequest(msg)
- return r.wait(timeout)
-
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/server/controller.py
--- a/tools/python/xen/xend/server/controller.py Thu Sep 8 15:18:40 2005
+++ b/tools/python/xen/xend/server/controller.py Fri Sep 9 16:30:54 2005
@@ -21,106 +21,8 @@
from xen.xend.XendError import XendError
from xen.xend.xenstore import DBVar
-from xen.xend.server.messages import msgTypeName, printMsg, getMessageType
DEBUG = 0
-
-class CtrlMsgRcvr:
- """Utility class to dispatch messages on a control channel.
- Once I{registerChannel} has been called, our message types are registered
- with the channel. The channel will call I{requestReceived}
- when a request arrives if it has one of our message types.
-
- @ivar channel: channel to a domain
- @type channel: Channel
- @ivar majorTypes: major message types we are interested in
- @type majorTypes: {int:{int:method}}
-
- """
-
- def __init__(self, channel):
- self.majorTypes = {}
- self.channel = channel
-
- def getHandler(self, type, subtype):
- """Get the method for a type and subtype.
-
- @param type: major message type
- @param subtype: minor message type
- @return: method or None
- """
- method = None
- subtypes = self.majorTypes.get(type)
- if subtypes:
- method = subtypes.get(subtype)
- return method
-
- def addHandler(self, type, subtype, method):
- """Add a method to handle a message type and subtype.
-
- @param type: major message type
- @param subtype: minor message type
- @param method: method
- """
- subtypes = self.majorTypes.get(type)
- if not subtypes:
- subtypes = {}
- self.majorTypes[type] = subtypes
- subtypes[subtype] = method
-
- def getMajorTypes(self):
- """Get the list of major message types handled.
- """
- return self.majorTypes.keys()
-
- def requestReceived(self, msg, type, subtype):
- """Dispatch a request message to handlers.
- Called by the channel for requests with one of our types.
-
- @param msg: message
- @type msg: xu message
- @param type: major message type
- @type type: int
- @param subtype: minor message type
- @type subtype: int
- """
- if DEBUG:
- print 'requestReceived>',
- printMsg(msg, all=True)
- responded = 0
- method = self.getHandler(type, subtype)
- if method:
- responded = method(msg)
- elif DEBUG:
- print ('requestReceived> No handler: Message type %s %d:%d'
- % (msgTypeName(type, subtype), type, subtype)), self
- return responded
-
-
- def lostChannel(self):
- """Called when the channel to the domain is lost.
- """
- if DEBUG:
- print 'CtrlMsgRcvr>lostChannel>',
- self.channel = None
-
- def registerChannel(self):
- """Register interest in our major message types with the
- channel to our domain. Once we have registered, the channel
- will call requestReceived for our messages.
- """
- if DEBUG:
- print 'CtrlMsgRcvr>registerChannel>', self.channel,
self.getMajorTypes()
- if self.channel:
- self.channel.registerDevice(self.getMajorTypes(), self)
-
- def deregisterChannel(self):
- """Deregister interest in our major message types with the
- channel to our domain. After this the channel won't call
- us any more.
- """
- if self.channel:
- self.channel.deregisterDevice(self)
class DevControllerTable:
"""Table of device controller classes, indexed by type name.
@@ -232,10 +134,6 @@
def getDomainName(self):
return self.vm.getName()
- def getChannel(self):
- chan = self.vm.getChannel()
- return chan
-
def getDomainInfo(self):
return self.vm
@@ -433,9 +331,6 @@
def getDomainName(self):
return self.controller.getDomainName()
- def getChannel(self):
- return self.controller.getChannel()
-
def getDomainInfo(self):
return self.controller.getDomainInfo()
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/server/event.py
--- a/tools/python/xen/xend/server/event.py Thu Sep 8 15:18:40 2005
+++ b/tools/python/xen/xend/server/event.py Fri Sep 9 16:30:54 2005
@@ -174,11 +174,6 @@
else:
logging.removeLogStderr()
- def op_debug_msg(self, name, v):
- mode = v[1]
- import messages
- messages.DEBUG = (mode == 'on')
-
def op_debug_controller(self, name, v):
mode = v[1]
import controller
@@ -186,7 +181,7 @@
def op_domain_ls(self, name, v):
xd = xroot.get_component("xen.xend.XendDomain")
- return xd.domain_ls()
+ return xd.list_names()
def op_domain_configure(self, name, v):
domid = sxp.child_value(v, "dom")
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/server/netif.py
--- a/tools/python/xen/xend/server/netif.py Thu Sep 8 15:18:40 2005
+++ b/tools/python/xen/xend/server/netif.py Fri Sep 9 16:30:54 2005
@@ -30,9 +30,7 @@
from xen.xend.XendRoot import get_component
from xen.xend.xenstore import DBVar
-from xen.xend.server import channel
-from xen.xend.server.controller import CtrlMsgRcvr, Dev, DevController
-from xen.xend.server.messages import *
+from xen.xend.server.controller import Dev, DevController
class NetDev(Dev):
"""A network device.
@@ -90,12 +88,9 @@
def __init__(self, controller, id, config, recreate=False):
Dev.__init__(self, controller, id, config, recreate=recreate)
self.vif = int(self.id)
- self.evtchn = None
self.status = None
self.frontendDomain = self.getDomain()
- self.frontendChannel = None
self.backendDomain = None
- self.backendChannel = None
self.credit = None
self.period = None
self.mac = None
@@ -109,17 +104,11 @@
def exportToDB(self, save=False):
Dev.exportToDB(self, save=save)
- if self.evtchn:
- db = self.db.addChild("evtchn")
- self.evtchn.saveToDB(db, save=save)
def init(self, recreate=False, reboot=False):
self.destroyed = False
self.status = NETIF_INTERFACE_STATUS_DISCONNECTED
self.frontendDomain = self.getDomain()
- self.frontendChannel = self.getChannel()
- cf = channel.channelFactory()
- self.backendChannel = cf.openChannel(self.backendDomain)
def _get_config_mac(self, config):
vmac = sxp.child_value(config, 'mac')
@@ -287,10 +276,6 @@
val.append(['credit', self.credit])
if self.period:
val.append(['period', self.period])
- if self.evtchn:
- val.append(['evtchn',
- self.evtchn['port1'],
- self.evtchn['port2']])
return val
def get_vifname(self):
@@ -348,42 +333,11 @@
if recreate:
pass
else:
- self.send_be_create()
if self.credit and self.period:
- self.send_be_creditlimit(self.credit, self.period)
+ #self.send_be_creditlimit(self.credit, self.period)
+ pass
self.vifctl('up', vmname=self.getDomainName())
- def closeEvtchn(self):
- if self.evtchn:
- channel.eventChannelClose(self.evtchn)
- self.evtchn = None
-
- def openEvtchn(self):
- self.evtchn = channel.eventChannel(self.backendDomain,
self.frontendDomain)
-
- def getEventChannelBackend(self):
- val = 0
- if self.evtchn:
- val = self.evtchn['port1']
- return val
-
- def getEventChannelFrontend(self):
- val = 0
- if self.evtchn:
- val = self.evtchn['port2']
- return val
-
- def send_be_create(self):
- msg = packMsg('netif_be_create_t',
- { 'domid' : self.frontendDomain,
- 'netif_handle' : self.vif,
- 'be_mac' : self.be_mac or [0, 0, 0, 0, 0, 0],
- 'mac' : self.mac,
- #'vifname' : self.vifname
- })
- msg = self.backendChannel.requestResponse(msg)
- # todo: check return status
-
def destroy(self, change=False, reboot=False):
"""Destroy the device's resources and disconnect from the back-end
device controller. If 'change' is true notify the front-end interface.
@@ -393,47 +347,14 @@
self.destroyed = True
self.status = NETIF_INTERFACE_STATUS_CLOSED
log.debug("Destroying vif domain=%d vif=%d", self.frontendDomain,
self.vif)
- self.closeEvtchn()
self.vifctl('down')
- self.send_be_disconnect()
- self.send_be_destroy()
if change:
self.reportStatus()
-
- def send_be_disconnect(self):
- msg = packMsg('netif_be_disconnect_t',
- { 'domid' : self.frontendDomain,
- 'netif_handle' : self.vif })
- self.backendChannel.requestResponse(msg)
- #todo: check return status
-
- def send_be_destroy(self, response=None):
- msg = packMsg('netif_be_destroy_t',
- { 'domid' : self.frontendDomain,
- 'netif_handle' : self.vif })
- self.backendChannel.requestResponse(msg)
- #todo: check return status
-
- def recv_fe_interface_connect(self, val):
- self.openEvtchn()
- msg = packMsg('netif_be_connect_t',
- { 'domid' : self.frontendDomain,
- 'netif_handle' : self.vif,
- 'evtchn' : self.getEventChannelBackend(),
- 'tx_shmem_frame' : val['tx_shmem_frame'],
- 'tx_shmem_ref' : val['tx_shmem_ref'],
- 'rx_shmem_frame' : val['rx_shmem_frame'],
- 'rx_shmem_ref' : val['rx_shmem_ref'] })
- msg = self.backendChannel.requestResponse(msg)
- #todo: check return status
- self.status = NETIF_INTERFACE_STATUS_CONNECTED
- self.reportStatus()
def setCreditLimit(self, credit, period):
#todo: these params should be in sxpr and vif config.
self.credit = credit
self.period = period
- self.send_be_creditlimit(credit, period)
def getCredit(self):
return self.credit
@@ -441,31 +362,10 @@
def getPeriod(self):
return self.period
- def send_be_creditlimit(self, credit, period):
- msg = packMsg('netif_be_creditlimit_t',
- { 'domid' : self.frontendDomain,
- 'netif_handle' : self.vif,
- 'credit_bytes' : credit,
- 'period_usec' : period })
- msg = self.backendChannel.requestResponse(msg)
- # todo: check return status
-
- def reportStatus(self, resp=False):
- msg = packMsg('netif_fe_interface_status_t',
- { 'handle' : self.vif,
- 'status' : self.status,
- 'evtchn' : self.getEventChannelFrontend(),
- 'domid' : self.backendDomain,
- 'mac' : self.mac })
- if resp:
- self.frontendChannel.writeResponse(msg)
- else:
- self.frontendChannel.writeRequest(msg)
-
def interfaceChanged(self):
"""Notify the front-end that a device has been added or removed.
"""
- self.reportStatus()
+ pass
class NetifController(DevController):
"""Network interface controller. Handles all network devices for a domain.
@@ -473,25 +373,9 @@
def __init__(self, vm, recreate=False):
DevController.__init__(self, vm, recreate=recreate)
- self.channel = None
- self.rcvr = None
- self.channel = None
def initController(self, recreate=False, reboot=False):
self.destroyed = False
- self.channel = self.getChannel()
- # Register our handlers for incoming requests.
- self.rcvr = CtrlMsgRcvr(self.channel)
- self.rcvr.addHandler(CMSG_NETIF_FE,
- CMSG_NETIF_FE_DRIVER_STATUS,
- self.recv_fe_driver_status)
- self.rcvr.addHandler(CMSG_NETIF_FE,
- CMSG_NETIF_FE_INTERFACE_STATUS,
- self.recv_fe_interface_status)
- self.rcvr.addHandler(CMSG_NETIF_FE,
- CMSG_NETIF_FE_INTERFACE_CONNECT,
- self.recv_fe_interface_connect)
- self.rcvr.registerChannel()
if reboot:
self.rebootDevices()
@@ -501,8 +385,6 @@
self.destroyed = True
log.debug("Destroying netif domain=%d", self.getDomain())
self.destroyDevices(reboot=reboot)
- if self.rcvr:
- self.rcvr.deregisterChannel()
def sxpr(self):
val = ['netif', ['dom', self.getDomain()]]
@@ -524,57 +406,3 @@
dev = self.devices[vif]
return dev.setCreditLimit(credit, period)
-
- def recv_fe_driver_status(self, msg):
- msg = packMsg('netif_fe_driver_status_t',
- { 'status' : NETIF_DRIVER_STATUS_UP,
- ## FIXME: max_handle should be max active interface id
- 'max_handle' : self.getDeviceCount()
- #'max_handle' : self.getMaxDeviceId()
- })
- # Two ways of doing it:
- # 1) front-end requests driver status, we reply with the interface
count,
- # front-end polls the interfaces,
- # front-end checks they are all up
- # 2) front-end requests driver status, we reply (with anything),
- # we notify the interfaces,
- # we notify driver status up with the count
- # front-end checks they are all up
- #
- # We really want to use 1), but at the moment the xenU kernel panics
- # in that mode, so we're sticking to 2) for now.
- resp = False
- if resp:
- self.channel.writeResponse(msg)
- else:
- for dev in self.devices.values():
- dev.reportStatus()
- self.channel.writeRequest(msg)
- return resp
-
- def recv_fe_interface_status(self, msg):
- val = unpackMsg('netif_fe_interface_status_t', msg)
- vif = val['handle']
- dev = self.findDevice(vif)
- if dev:
- dev.reportStatus(resp=True)
- else:
- log.error('Received netif_fe_interface_status for unknown vif:
dom=%d vif=%d',
- self.getDomain(), vif)
- msg = packMsg('netif_fe_interface_status_t',
- { 'handle' : -1,
- 'status' : NETIF_INTERFACE_STATUS_CLOSED,
- });
- self.channel.writeResponse(msg)
- return True
-
- def recv_fe_interface_connect(self, msg):
- val = unpackMsg('netif_fe_interface_connect_t', msg)
- vif = val['handle']
- dev = self.getDevice(vif)
- if dev:
- dev.recv_fe_interface_connect(val)
- else:
- log.error('Received netif_fe_interface_connect for unknown vif:
dom=%d vif=%d',
- self.getDomain(), vif)
-
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/server/usbif.py
--- a/tools/python/xen/xend/server/usbif.py Thu Sep 8 15:18:40 2005
+++ b/tools/python/xen/xend/server/usbif.py Fri Sep 9 16:30:54 2005
@@ -9,9 +9,7 @@
from xen.xend.XendError import XendError
from xen.xend.xenstore import DBVar
-from xen.xend.server import channel
from xen.xend.server.controller import Dev, DevController
-from xen.xend.server.messages import *
class UsbBackend:
"""Handler for the 'back-end' channel to a USB device driver domain
@@ -25,39 +23,15 @@
self.connecting = False
self.frontendDomain = self.controller.getDomain()
self.backendDomain = dom
- self.frontendChannel = None
- self.backendChannel = None
def init(self, recreate=False, reboot=False):
- self.frontendChannel = self.controller.getChannel()
- cf = channel.channelFactory()
- self.backendChannel = cf.openChannel(self.backendDomain)
-
+ pass
+
def __str__(self):
return ('<UsbifBackend frontend=%d backend=%d id=%d>'
% (self.frontendDomain,
self.backendDomain,
self.id))
-
- def closeEvtchn(self):
- if self.evtchn:
- channel.eventChannelClose(self.evtchn)
- self.evtchn = None
-
- def openEvtchn(self):
- self.evtchn = channel.eventChannel(self.backendDomain,
self.frontendDomain)
-
- def getEventChannelBackend(self):
- val = 0
- if self.evtchn:
- val = self.evtchn['port1']
- return val
-
- def getEventChannelFrontend(self):
- val = 0
- if self.evtchn:
- val = self.evtchn['port2']
- return val
def connect(self, recreate=False):
"""Connect the controller to the usbif control interface.
@@ -67,78 +41,14 @@
log.debug("Connecting usbif %s", str(self))
if recreate or self.connected or self.connecting:
pass
- else:
- self.send_be_create()
- def send_be_create(self):
- msg = packMsg('usbif_be_create_t',
- { 'domid' : self.frontendDomain })
- msg = self.backendChannel.requestResponse(msg)
- val = unpackMsg('usbif_be_create_t', msg)
- log.debug('>UsbifBackendController>respond_be_create> %s', str(val))
- self.connected = True
-
def destroy(self, reboot=False):
"""Disconnect from the usbif control interface and destroy it.
"""
self.destroyed = True
- self.send_be_disconnect()
- self.send_be_destroy()
- self.closeEvtchn()
- def send_be_disconnect(self):
- log.debug('>UsbifBackendController>send_be_disconnect> %s', str(self))
- msg = packMsg('usbif_be_disconnect_t',
- { 'domid' : self.frontendDomain })
- self.backendChannel.requestResponse(msg)
-
- def send_be_destroy(self, response=None):
- log.debug('>UsbifBackendController>send_be_destroy> %s', str(self))
- msg = packMsg('usbif_be_destroy_t',
- { 'domid' : self.frontendDomain })
- self.backendChannel.requestResponse(msg)
- #todo: check return status
-
-
- def connectInterface(self, val):
- self.openEvtchn()
- log.debug(">UsbifBackendController>connectInterface> connecting usbif
to event channel %s ports=%d:%d",
- str(self),
- self.getEventChannelBackend(),
- self.getEventChannelFrontend())
- msg = packMsg('usbif_be_connect_t',
- { 'domid' : self.frontendDomain,
- 'evtchn' : self.getEventChannelBackend(),
- 'shmem_frame' : val['shmem_frame'],
- 'bandwidth' : 500 # XXX fix bandwidth!
- })
- msg = self.backendChannel.requestResponse(msg)
- self.respond_be_connect(msg)
-
- def respond_be_connect(self, msg):
- """Response handler for a be_connect message.
-
- @param msg: message
- @type msg: xu message
- """
- val = unpackMsg('usbif_be_connect_t', msg)
- log.debug('>UsbifBackendController>respond_be_connect> %s, %s',
str(self), str(val))
- self.send_fe_interface_status_changed()
- log.debug(">UsbifBackendController> Successfully connected USB
interface for domain %d" % self.frontendDomain)
- self.controller.claim_ports()
-
- def send_fe_interface_status_changed(self):
- msg = packMsg('usbif_fe_interface_status_changed_t',
- { 'status' : USBIF_INTERFACE_STATUS_CONNECTED,
- 'domid' : self.backendDomain,
- 'evtchn' : self.getEventChannelFrontend(),
- 'bandwidth' : 500,
- 'num_ports' : len(self.controller.devices)
- })
- self.frontendChannel.writeRequest(msg)
-
def interfaceChanged(self):
- self.send_fe_interface_status_changed()
+ pass
class UsbDev(Dev):
@@ -153,17 +63,12 @@
self.port = id
self.path = None
self.frontendDomain = self.getDomain()
- self.frontendChannel = None
self.backendDomain = 0
- self.backendChannel = None
self.configure(self.config, recreate=recreate)
def init(self, recreate=False, reboot=False):
self.destroyed = False
self.frontendDomain = self.getDomain()
- self.frontendChannel = self.getChannel()
- backend = self.getBackend()
- self.backendChannel = backend.backendChannel
def configure(self, config, change=False, recreate=False):
if change:
@@ -204,7 +109,6 @@
"""
self.destroyed = True
log.debug("Destroying usb domain=%d id=%s", self.frontendDomain,
self.id)
- self.send_be_release_port()
if change:
self.interfaceChanged()
@@ -220,27 +124,6 @@
"""
self.getBackend().connect()
- def send_be_claim_port(self):
- log.debug(">UsbifBackendController>send_be_claim_port> about to claim
port %s" % self.path)
- msg = packMsg('usbif_be_claim_port_t',
- { 'domid' : self.frontendDomain,
- 'path' : self.path,
- 'usbif_port' : self.port,
- 'status' : 0})
- self.backendChannel.writeRequest(msg)
- log.debug(">UsbifBackendController> Claim port completed")
- # No need to add any callbacks, since the guest polls its virtual ports
- # anyhow, somewhat like a UHCI controller ;-)
-
- def send_be_release_port(self):
- msg = packMsg('usbif_be_release_port_t',
- { 'domid' : self.frontendDomain,
- 'path' : self.path })
- self.backendChannel.writeRequest(msg)
- log.debug(">UsbifBackendController> Release port completed")
- # No need to add any callbacks, since the guest polls its virtual ports
- # anyhow, somewhat like a UHCI controller ;-)
-
class UsbifController(DevController):
"""USB device interface controller. Handles all USB devices
for a domain.
@@ -252,18 +135,9 @@
DevController.__init__(self, vm, recreate=recreate)
self.backends = {}
self.backendId = 0
- self.rcvr = None
def init(self, recreate=False, reboot=False):
self.destroyed = False
- self.rcvr = CtrlMsgRcvr(self.getChannel())
- self.rcvr.addHandler(CMSG_USBIF_FE,
- CMSG_USBIF_FE_DRIVER_STATUS_CHANGED,
- self.recv_fe_driver_status_changed)
- self.rcvr.addHandler(CMSG_USBIF_FE,
- CMSG_USBIF_FE_INTERFACE_CONNECT,
- self.recv_fe_interface_connect)
- self.rcvr.registerChannel()
if reboot:
self.rebootBackends()
self.rebootDevices()
@@ -283,8 +157,6 @@
log.debug("Destroying blkif domain=%d", self.getDomain())
self.destroyDevices(reboot=reboot)
self.destroyBackends(reboot=reboot)
- if self.rcvr:
- self.rcvr.deregisterChannel()
def rebootBackends(self):
for backend in self.backends.values():
@@ -311,40 +183,3 @@
def destroyBackends(self, reboot=False):
for backend in self.backends.values():
backend.destroy(reboot=reboot)
-
- def recv_fe_driver_status_changed(self, msg):
- val = unpackMsg('usbif_fe_driver_status_changed_t', msg)
- log.debug('>UsbifController>recv_fe_driver_status_changed> %s',
str(val))
- #todo: FIXME: For each backend?
- msg = packMsg('usbif_fe_interface_status_changed_t',
- { 'status' : USBIF_INTERFACE_STATUS_DISCONNECTED,
- 'domid' : 0, #todo: FIXME: should be domid of backend
- 'evtchn' : 0 })
- msg = self.getChannel().requestResponse(msg)
- self.disconnected_resp(msg)
-
- def disconnected_resp(self, msg):
- val = unpackMsg('usbif_fe_interface_status_changed_t', msg)
- if val['status'] != USBIF_INTERFACE_STATUS_DISCONNECTED:
- log.error(">UsbifController>disconnected_resp> unexpected status
change")
- else:
- log.debug(">UsbifController>disconnected_resp> interface
disconnected OK")
-
- def recv_fe_interface_connect(self, msg):
- val = unpackMsg('usbif_fe_interface_status_changed_t', msg)
- log.debug(">UsbifController>recv_fe_interface_connect> notifying
backend")
- #todo: FIXME: generalise to more than one backend.
- id = 0
- backend = self.getBackendById(id)
- if backend:
- try:
- backend.connectInterface(val)
- except IOError, ex:
- log.error("Exception connecting backend: %s", ex)
- else:
- log.error('interface connect on unknown interface: id=%d', id)
-
- def claim_ports(self):
- for dev in self.devices.values():
- dev.send_be_claim_port()
-
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/xenstore/xsobj.py
--- a/tools/python/xen/xend/xenstore/xsobj.py Thu Sep 8 15:18:40 2005
+++ b/tools/python/xen/xend/xenstore/xsobj.py Fri Sep 9 16:30:54 2005
@@ -543,10 +543,10 @@
if not isinstance(node, DBMap): continue
node.saveDB(sync=sync, save=save)
# Remove db nodes not in children.
- if sync:
- for name in self.__db__.ls():
- if name not in self:
- self.__db__.delete(name)
+ ###if sync:
+ ### for name in self.__db__.ls():
+ ### if name not in self:
+ ### self.__db__.delete(name)
def importFromDB(self, obj, fields):
"""Set fields in obj from db fields.
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py Thu Sep 8 15:18:40 2005
+++ b/tools/python/xen/xm/create.py Fri Sep 9 16:30:54 2005
@@ -103,12 +103,13 @@
fn=set_true, default=0,
use="Connect to the console after the domain is created.")
-gopts.var('vnc', val='no|yes',
+gopts.var('vncviewer', val='no|yes',
fn=set_bool, default=None,
use="""Spawn a vncviewer listening for a vnc server in the domain.
The address of the vncviewer is passed to the domain on the kernel
command
line using 'VNC_SERVER=<host>:<port>'. The port used by vnc is 5500
+ DISPLAY.
A display value with a free port is chosen if possible.
+ Only valid when vnc=1.
""")
gopts.var('name', val='NAME',
@@ -174,6 +175,12 @@
gopts.var('netif', val='no|yes',
fn=set_bool, default=0,
use="Make the domain a network interface backend.")
+
+gopts.var('tpmif', val='frontend=DOM',
+ fn=append_value, default=[],
+ use="""Make the domain a TPM interface backend. If frontend is given,
+ the frontend in that domain is connected to this backend (not
+ completely implemented, yet)""")
gopts.var('disk', val='phy:DEV,VDEV,MODE[,DOM]',
fn=append_value, default=[],
@@ -213,6 +220,12 @@
This option may be repeated to add more than one vif.
Specifying vifs will increase the number of interfaces as needed.""")
+gopts.var('vtpm', val="instance=INSTANCE,backend=DOM",
+ fn=append_value, default=[],
+ use="""Add a tpm interface. On the backend side us the the given
+ instance as virtual TPM instance. Use the backend in the given
+ domain.""")
+
gopts.var('nics', val="NUM",
fn=set_int, default=1,
use="""Set the number of network interfaces.
@@ -308,6 +321,10 @@
gopts.var('nographic', val='no|yes',
fn=set_bool, default=0,
use="Should device models use graphics?")
+
+gopts.var('vnc', val='',
+ fn=set_value, default=None,
+ use="""Should the device model use VNC?""")
gopts.var('sdl', val='',
fn=set_value, default=None,
@@ -368,6 +385,46 @@
for path in vals.usb:
config_usb = ['usb', ['path', path]]
config_devs.append(['device', config_usb])
+
+def configure_vtpm(opts, config_devs, vals):
+ """Create the config for virtual TPM interfaces.
+ """
+ vtpm = vals.vtpm
+ vtpm_n = 1
+ for idx in range(0, vtpm_n):
+ if idx < len(vtpm):
+ d = vtpm[idx]
+ instance = d.get('instance')
+ if instance == "VTPMD":
+ instance = "0"
+ else:
+ try:
+ if int(instance) == 0:
+ opts.err('VM config error: vTPM instance must not be
0.')
+ except ValueError:
+ opts.err('Vm config error: could not parse instance
number.')
+ backend = d.get('backend')
+ config_vtpm = ['vtpm']
+ if instance:
+ config_vtpm.append(['instance', instance])
+ if backend:
+ config_vtpm.append(['backend', backend])
+ config_devs.append(['device', config_vtpm])
+
+def configure_tpmif(opts, config_devs, vals):
+ """Create the config for virtual TPM interfaces.
+ """
+ tpmif = vals.tpmif
+ tpmif_n = 1
+ for idx in range(0, tpmif_n):
+ if idx < len(tpmif):
+ d = tpmif[idx]
+ frontend = d.get('frontend')
+ config_tpmif = ['tpmif']
+ if frontend:
+ config_tpmif.append(['frontend', frontend])
+ config_devs.append(['device', config_tpmif])
+
def randomMAC():
"""Generate a random MAC address.
@@ -442,7 +499,7 @@
"""
args = [ 'memmap', 'device_model', 'cdrom',
'boot', 'fda', 'fdb', 'localtime', 'serial', 'macaddr', 'stdvga',
- 'isa', 'nographic', 'vnc', 'sdl', 'display']
+ 'isa', 'nographic', 'vnc', 'vncviewer', 'sdl', 'display']
for a in args:
if (vals.__dict__[a]):
config_devs.append([a, vals.__dict__[a]])
@@ -479,6 +536,8 @@
config.append(['backend', ['blkif']])
if vals.netif:
config.append(['backend', ['netif']])
+ if vals.tpmif:
+ config.append(['backend', ['tpmif']])
if vals.restart:
config.append(['restart', vals.restart])
@@ -491,6 +550,7 @@
configure_pci(opts, config_devs, vals)
configure_vifs(opts, config_devs, vals)
configure_usb(opts, config_devs, vals)
+ configure_vtpm(opts, config_devs, vals)
configure_vmx(opts, config_devs, vals)
config += config_devs
@@ -539,6 +599,38 @@
vifs.append(d)
vals.vif = vifs
+def preprocess_vtpm(opts, vals):
+ if not vals.vtpm: return
+ vtpms = []
+ for vtpm in vals.vtpm:
+ d = {}
+ a = vtpm.split(',')
+ for b in a:
+ (k, v) = b.strip().split('=', 1)
+ k = k.strip()
+ v = v.strip()
+ if k not in ['backend', 'instance']:
+ opts.err('Invalid vtpm specifier: ' + vtpm)
+ d[k] = v
+ vtpms.append(d)
+ vals.vtpm = vtpms
+
+def preprocess_tpmif(opts, vals):
+ if not vals.tpmif: return
+ tpmifs = []
+ for tpmif in vals.tpmif:
+ d = {}
+ a = tpmif.split(',')
+ for b in a:
+ (k, v) = b.strip().split('=', 1)
+ k = k.strip()
+ v = v.strip()
+ if k not in ['frontend']:
+ opts.err('Invalid tpmif specifier: ' + vtpm)
+ d[k] = v
+ tpmifs.append(d)
+ vals.tpmif = tpmifs
+
def preprocess_ip(opts, vals):
if vals.ip or vals.dhcp != 'off':
dummy_nfs_server = '1.2.3.4'
@@ -606,7 +698,7 @@
"""If vnc was specified, spawn a vncviewer in listen mode
and pass its address to the domain on the kernel command line.
"""
- if not vals.vnc or vals.dryrun: return
+ if not (vals.vnc and vals.vncviewer) or vals.dryrun: return
vnc_display = choose_vnc_display()
if not vnc_display:
opts.warn("No free vnc display")
@@ -627,6 +719,8 @@
preprocess_ip(opts, vals)
preprocess_nfs(opts, vals)
preprocess_vnc(opts, vals)
+ preprocess_vtpm(opts, vals)
+ preprocess_tpmif(opts, vals)
def make_domain(opts, config):
"""Create, build and start a domain.
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py Thu Sep 8 15:18:40 2005
+++ b/tools/python/xen/xm/main.py Fri Sep 9 16:30:54 2005
@@ -715,9 +715,9 @@
err("Most commands need root access. Please try again as root")
sys.exit(1)
except XendError, ex:
- if args[0] == "bogus":
- args.remove("bogus")
if len(args) > 0:
+ if args[0] == "bogus":
+ args.remove("bogus")
handle_xend_error(argv[1], args[0], ex)
else:
print "Unexpected error:", sys.exc_info()[0]
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/security/Makefile
--- a/tools/security/Makefile Thu Sep 8 15:18:40 2005
+++ b/tools/security/Makefile Fri Sep 9 16:30:54 2005
@@ -45,6 +45,7 @@
$(MAKE) secpol_xml2bin
chmod 700 ./setlabel.sh
chmod 700 ./updategrub.sh
+ chmod 700 ./getlabel.sh
secpol_tool : secpol_tool.c secpol_compat.h
$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $<
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/security/secpol_tool.c
--- a/tools/security/secpol_tool.c Thu Sep 8 15:18:40 2005
+++ b/tools/security/secpol_tool.c Fri Sep 9 16:30:54 2005
@@ -25,6 +25,7 @@
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
+#include <getopt.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -40,6 +41,17 @@
#define PERROR(_m, _a...) \
fprintf(stderr, "ERROR: " _m " (%d = %s)\n" , ## _a , \
errno, strerror(errno))
+
+void usage(char *progname)
+{
+ printf("Use: %s \n"
+ "\t getpolicy\n"
+ "\t dumpstats\n"
+ "\t loadpolicy <binary policy file>\n"
+ "\t getssid -d <domainid> [-f]\n"
+ "\t getssid -s <ssidref> [-f]\n", progname);
+ exit(-1);
+}
static inline int do_policycmd(int xc_handle, unsigned int cmd,
unsigned long data)
@@ -320,7 +332,7 @@
if (ret)
printf
- ("ERROR setting policy. Use 'xm dmesg' to see details.\n");
+ ("ERROR setting policy. Try 'xm dmesg' to see details.\n");
else
printf("Successfully changed policy.\n");
@@ -370,7 +382,7 @@
if (ret < 0)
{
- printf("ERROR dumping policy stats. Use 'xm dmesg' to see details.\n");
+ printf("ERROR dumping policy stats. Try 'xm dmesg' to see details.\n");
return ret;
}
stats = (struct acm_stats_buffer *) stats_buffer;
@@ -421,17 +433,121 @@
}
return ret;
}
+/************************ get ssidref & types ******************************/
+/*
+ * the ssid (types) can be looked up either by domain id or by ssidref
+ */
+int acm_domain_getssid(int xc_handle, int argc, char * const argv[])
+{
+ /* this includes header and a set of types */
+ #define MAX_SSIDBUFFER 2000
+ int ret, i;
+ acm_op_t op;
+ struct acm_ssid_buffer *hdr;
+ unsigned char *buf;
+ int nice_print = 1;
+
+ op.cmd = ACM_GETSSID;
+ op.interface_version = ACM_INTERFACE_VERSION;
+ op.u.getssid.get_ssid_by = UNSET;
+ /* arguments
+ -d ... domain id to look up
+ -s ... ssidref number to look up
+ -f ... formatted print (scripts depend on this format)
+ */
+ while (1)
+ {
+ int c = getopt(argc, argv, "d:s:f");
+ if (c == -1)
+ break;
+ if (c == 'd')
+ {
+ if (op.u.getssid.get_ssid_by != UNSET)
+ usage(argv[0]);
+ op.u.getssid.get_ssid_by = DOMAINID;
+ op.u.getssid.id.domainid = strtoul(optarg, NULL, 0);
+ }
+ else if (c== 's')
+ {
+ if (op.u.getssid.get_ssid_by != UNSET)
+ usage(argv[0]);
+ op.u.getssid.get_ssid_by = SSIDREF;
+ op.u.getssid.id.ssidref = strtoul(optarg, NULL, 0);
+ }
+ else if (c== 'f')
+ {
+ nice_print = 0;
+ }
+ else
+ usage(argv[0]);
+ }
+ if (op.u.getssid.get_ssid_by == UNSET)
+ usage(argv[0]);
+
+ buf = malloc(MAX_SSIDBUFFER);
+ if (!buf)
+ return -ENOMEM;
+
+ /* dump it and then push it down into xen/acm */
+ op.u.getssid.ssidbuf = buf; /* out */
+ op.u.getssid.ssidbuf_size = MAX_SSIDBUFFER;
+ ret = do_acm_op(xc_handle, &op);
+
+ if (ret)
+ {
+ printf("ERROR getting ssidref. Try 'xm dmesg' to see details.\n");
+ goto out;
+ }
+ hdr = (struct acm_ssid_buffer *)buf;
+ if (hdr->len > MAX_SSIDBUFFER)
+ {
+ printf("ERROR: Buffer length inconsistent (ret=%d, hdr->len=%d)!\n",
+ ret, hdr->len);
+ return -EIO;
+ }
+ if (nice_print)
+ {
+ printf("SSID: ssidref = 0x%08x \n", hdr->ssidref);
+ printf(" P: %s, max_types = %d\n",
+ ACM_POLICY_NAME(hdr->primary_policy_code),
hdr->primary_max_types);
+ printf(" Types: ");
+ for (i=0; i< hdr->primary_max_types; i++)
+ if (buf[hdr->primary_types_offset + i])
+ printf("%02x ", i);
+ else
+ printf("-- ");
+ printf("\n");
+
+ printf(" S: %s, max_types = %d\n",
+ ACM_POLICY_NAME(hdr->secondary_policy_code),
hdr->secondary_max_types);
+ printf(" Types: ");
+ for (i=0; i< hdr->secondary_max_types; i++)
+ if (buf[hdr->secondary_types_offset + i])
+ printf("%02x ", i);
+ else
+ printf("-- ");
+ printf("\n");
+ }
+ else
+ {
+ /* formatted print for use with scripts (.sh)
+ * update scripts when updating here (usually
+ * used in combination with -d to determine a
+ * running domain's label
+ */
+ printf("SSID: ssidref = 0x%08x \n", hdr->ssidref);
+ }
+
+ /* return ste ssidref */
+ if (hdr->primary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
+ ret = (hdr->ssidref) & 0xffff;
+ else if (hdr->secondary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
+ ret = (hdr->ssidref) >> 16;
+ out:
+ return ret;
+}
/***************************** main **************************************/
-
-void usage(char *progname)
-{
- printf("Use: %s \n"
- "\t getpolicy\n"
- "\t dumpstats\n"
- "\t loadpolicy <binary policy file>\n", progname);
- exit(-1);
-}
int main(int argc, char **argv)
{
@@ -459,6 +575,8 @@
if (argc != 2)
usage(argv[0]);
ret = acm_domain_dumpstats(acm_cmd_fd);
+ } else if (!strcmp(argv[1], "getssid")) {
+ ret = acm_domain_getssid(acm_cmd_fd, argc, argv);
} else
usage(argv[0]);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/security/setlabel.sh
--- a/tools/security/setlabel.sh Thu Sep 8 15:18:40 2005
+++ b/tools/security/setlabel.sh Fri Sep 9 16:30:54 2005
@@ -34,275 +34,27 @@
exec sh -c "bash $0 $*"
fi
+export PATH=$PATH:.
+source labelfuncs.sh
usage ()
{
- echo "Usage: $0 [Option] <vmfile> <label> <policy name> "
- echo " or $0 -l <policy name>"
+ echo "Usage: $0 [Option] <vmfile> <label> [<policy name>]"
+ echo " or $0 -l [<policy name>]"
echo ""
- echo "Valid Options are:"
+ echo "Valid options are:"
echo "-r : to relabel a file without being prompted"
echo ""
echo "vmfile : XEN vm configuration file"
- echo "label : the label to map"
+ echo "label : the label to map to an ssidref"
echo "policy name : the name of the policy, i.e. 'chwall'"
+ echo " If the policy name is omitted, it is attempted"
+ echo " to find the current policy's name in grub.conf."
echo ""
- echo "-l <policy name> is used to show valid labels in the map file"
+ echo "-l [<policy name>] is used to show valid labels in the map file
of"
+ echo " the given or current policy."
echo ""
}
-
-
-findMapFile ()
-{
- mapfile="./$1.map"
- if [ -r "$mapfile" ]; then
- return 1
- fi
-
- mapfile="./policies/$1/$1.map"
- if [ -r "$mapfile" ]; then
- return 1
- fi
-
- return 0
-}
-
-showLabels ()
-{
- mapfile=$1
- if [ ! -r "$mapfile" -o "$mapfile" == "" ]; then
- echo "Cannot read from vm configuration file $vmfile."
- return -1
- fi
-
- getPrimaryPolicy $mapfile
- getSecondaryPolicy $mapfile
-
- echo "The following labels are available:"
- let line=1
- while [ 1 ]; do
- ITEM=`cat $mapfile | \
- awk -vline=$line \
- -vprimary=$primary \
- '{ \
- if ($1 == "LABEL->SSID" && \
- $2 == "VM" && \
- $3 == primary ) { \
- ctr++; \
- if (ctr == line) { \
- print $4; \
- } \
- } \
- } END { \
- }'`
-
- if [ "$ITEM" == "" ]; then
- break
- fi
- if [ "$secondary" != "NULL" ]; then
- LABEL=`cat $mapfile | \
- awk -vitem=$ITEM \
- '{
- if ($1 == "LABEL->SSID" && \
- $2 == "VM" && \
- $3 == "CHWALL" && \
- $4 == item ) { \
- result = item; \
- } \
- } END { \
- print result \
- }'`
- else
- LABEL=$ITEM
- fi
-
- if [ "$LABEL" != "" ]; then
- echo "$LABEL"
- found=1
- fi
- let line=line+1
- done
- if [ "$found" != "1" ]; then
- echo "No labels found."
- fi
-}
-
-getPrimaryPolicy ()
-{
- mapfile=$1
- primary=`cat $mapfile | \
- awk ' \
- { \
- if ( $1 == "PRIMARY" ) { \
- res=$2; \
- } \
- } END { \
- print res; \
- } '`
-}
-
-getSecondaryPolicy ()
-{
- mapfile=$1
- secondary=`cat $mapfile | \
- awk ' \
- { \
- if ( $1 == "SECONDARY" ) { \
- res=$2; \
- } \
- } END { \
- print res; \
- } '`
-}
-
-
-getDefaultSsid ()
-{
- mapfile=$1
- pol=$2
- RES=`cat $mapfile \
- awk -vpol=$pol \
- { \
- if ($1 == "LABEL->SSID" && \
- $2 == "ANY" && \
- $3 == pol && \
- $4 == "DEFAULT" ) {\
- res=$5; \
- } \
- } END { \
- printf "%04x", strtonum(res) \
- }'`
- echo "default NULL mapping is $RES"
- defaultssid=$RES
-}
-
-relabel ()
-{
- vmfile=$1
- label=$2
- mapfile=$3
- mode=$4
-
- if [ ! -r "$vmfile" ]; then
- echo "Cannot read from vm configuration file $vmfile."
- return -1
- fi
-
- if [ ! -w "$vmfile" ]; then
- echo "Cannot write to vm configuration file $vmfile."
- return -1
- fi
-
- if [ ! -r "$mapfile" ] ; then
- echo "Cannot read mapping file $mapfile."
- return -1
- fi
-
- # Determine which policy is primary, which sec.
- getPrimaryPolicy $mapfile
- getSecondaryPolicy $mapfile
-
- # Calculate the primary policy's SSIDREF
- if [ "$primary" == "NULL" ]; then
- SSIDLO="0000"
- else
- SSIDLO=`cat $mapfile | \
- awk -vlabel=$label \
- -vprimary=$primary \
- '{ \
- if ( $1 == "LABEL->SSID" && \
- $2 == "VM" && \
- $3 == primary && \
- $4 == label ) { \
- result=$5 \
- } \
- } END { \
- if (result != "" ) \
- {printf "%04x", strtonum(result)}\
- }'`
- fi
-
- # Calculate the secondary policy's SSIDREF
- if [ "$secondary" == "NULL" ]; then
- SSIDHI="0000"
- else
- SSIDHI=`cat $mapfile | \
- awk -vlabel=$label \
- -vsecondary=$secondary \
- '{ \
- if ( $1 == "LABEL->SSID" && \
- $2 == "VM" && \
- $3 == secondary && \
- $4 == label ) { \
- result=$5 \
- } \
- } END { \
- if (result != "" ) \
- {printf "%04x", strtonum(result)}\
- }'`
- fi
-
- if [ "$SSIDLO" == "" -o \
- "$SSIDHI" == "" ]; then
- echo "Could not map the given label '$label'."
- return -1
- fi
-
- ACM_POLICY=`cat $mapfile | \
- awk ' { if ( $1 == "POLICY" ) { \
- result=$2 \
- } \
- } \
- END { \
- if (result != "") { \
- printf result \
- } \
- }'`
-
- if [ "$ACM_POLICY" == "" ]; then
- echo "Could not find 'POLICY' entry in map file."
- return -1
- fi
-
- SSIDREF="0x$SSIDHI$SSIDLO"
-
- if [ "$mode" != "relabel" ]; then
- RES=`cat $vmfile | \
- awk '{ \
- if ( substr($1,0,7) == "ssidref" ) {\
- print $0; \
- } \
- }'`
- if [ "$RES" != "" ]; then
- echo "Do you want to overwrite the existing mapping
($RES)? (y/N)"
- read user
- if [ "$user" != "y" -a "$user" != "Y" ]; then
- echo "Aborted."
- return 0
- fi
- fi
- fi
-
- #Write the output
- vmtmp1="/tmp/__setlabel.tmp1"
- vmtmp2="/tmp/__setlabel.tmp2"
- touch $vmtmp1
- touch $vmtmp2
- if [ ! -w "$vmtmp1" -o ! -w "$vmtmp2" ]; then
- echo "Cannot create temporary files. Aborting."
- return -1
- fi
- RES=`sed -e '/^#ACM_POLICY/d' $vmfile > $vmtmp1`
- RES=`sed -e '/^#ACM_LABEL/d' $vmtmp1 > $vmtmp2`
- RES=`sed -e '/^ssidref/d' $vmtmp2 > $vmtmp1`
- echo "#ACM_POLICY=$ACM_POLICY" >> $vmtmp1
- echo "#ACM_LABEL=$label" >> $vmtmp1
- echo "ssidref = $SSIDREF" >> $vmtmp1
- mv -f $vmtmp1 $vmfile
- rm -rf $vmtmp1 $vmtmp2
- echo "Mapped label '$label' to ssidref '$SSIDREF'."
-}
-
if [ "$1" == "-r" ]; then
@@ -317,10 +69,25 @@
if [ "$mode" == "show" ]; then
if [ "$1" == "" ]; then
- usage
- exit -1;
+ findGrubConf
+ ret=$?
+ if [ $ret -eq 0 ]; then
+ echo "Could not find grub.conf"
+ exit -1;
+ fi
+ findPolicyInGrub $grubconf
+ if [ "$policy" != "" ]; then
+ echo "Assuming policy to be '$policy'.";
+ else
+ echo "Could not find policy."
+ exit -1;
+ fi
+ else
+ policy=$3;
fi
- findMapFile $1
+
+
+ findMapFile $policy
res=$?
if [ "$res" != "0" ]; then
showLabels $mapfile
@@ -330,11 +97,29 @@
elif [ "$mode" == "usage" ]; then
usage
else
+ if [ "$2" == "" ]; then
+ usage
+ exit -1
+ fi
if [ "$3" == "" ]; then
- usage
- exit -1;
+ findGrubConf
+ ret=$?
+ if [ $ret -eq 0 ]; then
+ echo "Could not find grub.conf"
+ exit -1;
+ fi
+ findPolicyInGrub $grubconf
+ if [ "$policy" != "" ]; then
+ echo "Assuming policy to be '$policy'.";
+ else
+ echo "Could not find policy."
+ exit -1;
+ fi
+
+ else
+ policy=$3;
fi
- findMapFile $3
+ findMapFile $policy
res=$?
if [ "$res" != "0" ]; then
relabel $1 $2 $mapfile $mode
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcutils/Makefile
--- a/tools/xcutils/Makefile Thu Sep 8 15:18:40 2005
+++ b/tools/xcutils/Makefile Fri Sep 9 16:30:54 2005
@@ -18,8 +18,6 @@
PROGRAMS_INSTALL_DIR = /usr/libexec/xen
INCLUDES += -I $(XEN_LIBXC)
-
-CC := gcc
CFLAGS += -Wall -Werror -O3 -fno-strict-aliasing
CFLAGS += $(INCLUDES)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcutils/xc_restore.c
--- a/tools/xcutils/xc_restore.c Thu Sep 8 15:18:40 2005
+++ b/tools/xcutils/xc_restore.c Fri Sep 9 16:30:54 2005
@@ -17,22 +17,27 @@
int
main(int argc, char **argv)
{
- unsigned int xc_fd, io_fd, domid, nr_pfns, evtchn;
+ unsigned int xc_fd, io_fd, domid, nr_pfns, store_evtchn, console_evtchn;
int ret;
- unsigned long mfn;
+ unsigned long store_mfn, console_mfn;
- if (argc != 6)
- errx(1, "usage: %s xcfd iofd domid nr_pfns evtchn", argv[0]);
+ if (argc != 7)
+ errx(1,
+ "usage: %s xcfd iofd domid nr_pfns store_evtchn console_evtchn",
+ argv[0]);
xc_fd = atoi(argv[1]);
io_fd = atoi(argv[2]);
domid = atoi(argv[3]);
nr_pfns = atoi(argv[4]);
- evtchn = atoi(argv[5]);
+ store_evtchn = atoi(argv[5]);
+ console_evtchn = atoi(argv[6]);
- ret = xc_linux_restore(xc_fd, io_fd, domid, nr_pfns, evtchn, &mfn);
+ ret = xc_linux_restore(xc_fd, io_fd, domid, nr_pfns, store_evtchn,
+ &store_mfn, console_evtchn, &console_mfn);
if (ret == 0) {
- printf("store-mfn %li\n", mfn);
+ printf("store-mfn %li\n", store_mfn);
+ printf("console-mfn %li\n", console_mfn);
fflush(stdout);
}
return ret;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcutils/xc_save.c
--- a/tools/xcutils/xc_save.c Thu Sep 8 15:18:40 2005
+++ b/tools/xcutils/xc_save.c Fri Sep 9 16:30:54 2005
@@ -17,14 +17,17 @@
int
main(int argc, char **argv)
{
- unsigned int xc_fd, io_fd, domid;
+ unsigned int xc_fd, io_fd, domid, maxit, max_f, flags;
- if (argc != 4)
- errx(1, "usage: %s xcfd iofd domid", argv[0]);
+ if (argc != 7)
+ errx(1, "usage: %s xcfd iofd domid maxit maxf flags", argv[0]);
xc_fd = atoi(argv[1]);
io_fd = atoi(argv[2]);
domid = atoi(argv[3]);
+ maxit = atoi(argv[4]);
+ max_f = atoi(argv[5]);
+ flags = atoi(argv[6]);
- return xc_linux_save(xc_fd, io_fd, domid);
+ return xc_linux_save(xc_fd, io_fd, domid, maxit, max_f, flags);
}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xenstat/Makefile
--- a/tools/xenstat/Makefile Thu Sep 8 15:18:40 2005
+++ b/tools/xenstat/Makefile Fri Sep 9 16:30:54 2005
@@ -3,7 +3,11 @@
SUBDIRS :=
SUBDIRS += libxenstat
+
+# This doesn't cross-compile (cross-compile environments rarely have curses)
+ifeq ($(XEN_COMPILE_ARCH),$(XEN_TARGET_ARCH))
SUBDIRS += xentop
+endif
.PHONY: all install clean
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xenstore/Makefile
--- a/tools/xenstore/Makefile Thu Sep 8 15:18:40 2005
+++ b/tools/xenstore/Makefile Fri Sep 9 16:30:54 2005
@@ -8,15 +8,16 @@
INSTALL_DIR = $(INSTALL) -d -m0755
PROFILE=#-pg
-BASECFLAGS=-Wall -W -g
+BASECFLAGS=-Wall -W -g -Werror
# Make gcc generate dependencies.
BASECFLAGS += -Wp,-MD,.$(@F).d
PROG_DEP = .*.d
-#BASECFLAGS+= -O3 $(PROFILE)
+BASECFLAGS+= -O3 $(PROFILE)
#BASECFLAGS+= -I$(XEN_ROOT)/tools
BASECFLAGS+= -I$(XEN_ROOT)/tools/libxc
BASECFLAGS+= -I$(XEN_ROOT)/xen/include/public
BASECFLAGS+= -I.
+BASECFLAGS+= -I$(XEN_ROOT)/linux-2.6-xen-sparse/include/asm-xen/linux-public
CFLAGS += $(BASECFLAGS)
LDFLAGS += $(PROFILE) -L$(XEN_LIBXC)
@@ -24,15 +25,22 @@
TESTFLAGS= -DTESTING
TESTENV = XENSTORED_ROOTDIR=$(TESTDIR) XENSTORED_RUNDIR=$(TESTDIR)
-all: xen xenstored libxenstore.so
+CLIENTS := xenstore-read xenstore-rm xenstore-write
+CLIENTS_OBJS := $(patsubst xenstore-%,xenstore_%.o,$(CLIENTS))
-testcode: xen xs_test xenstored_test xs_random xs_dom0_test
+all: libxenstore.so xenstored $(CLIENTS)
-xen:
- ln -sf $(XEN_ROOT)/xen/include/public $@
+testcode: xs_test xenstored_test xs_random xs_dom0_test
xenstored: xenstored_core.o xenstored_watch.o xenstored_domain.o
xenstored_transaction.o xs_lib.o talloc.o utils.o
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -lxenctrl -o $@
+
+$(CLIENTS): libxenstore.so
+$(CLIENTS): xenstore-%: xenstore_%.o
+ $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -lxenctrl -L. -lxenstore -o $@
+
+$(CLIENTS_OBJS): xenstore_%.o: xenstore_client.c
+ $(COMPILE.c) -DCLIENT_$(*F) -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
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
@@ -58,7 +66,7 @@
clean: testsuite-clean
rm -f *.o *.opic *.so
- rm -f xen xenstored xs_random xs_stress xs_crashme
+ rm -f xenstored xs_random xs_stress xs_crashme
rm -f xs_test xenstored_test xs_dom0_test
$(RM) $(PROG_DEP)
@@ -72,10 +80,10 @@
fullcheck: testsuite-run randomcheck stresstest
-testsuite-run: xen xenstored_test xs_test
+testsuite-run: xenstored_test xs_test
$(TESTENV) testsuite/test.sh && echo
-testsuite-fast: xen xenstored_test xs_test
+testsuite-fast: xenstored_test xs_test
@$(TESTENV) testsuite/test.sh --fast
testsuite-clean:
@@ -111,12 +119,14 @@
tarball: clean
cd .. && tar -c -j -v -h -f xenstore.tar.bz2 xenstore/
-install: xenstored libxenstore.so
+install: libxenstore.so xenstored $(CLIENTS)
$(INSTALL_DIR) -p $(DESTDIR)/var/run/xenstored
$(INSTALL_DIR) -p $(DESTDIR)/var/lib/xenstored
+ $(INSTALL_DIR) -p $(DESTDIR)/usr/bin
$(INSTALL_DIR) -p $(DESTDIR)/usr/sbin
$(INSTALL_DIR) -p $(DESTDIR)/usr/include
$(INSTALL_PROG) xenstored $(DESTDIR)/usr/sbin
+ $(INSTALL_PROG) $(CLIENTS) $(DESTDIR)/usr/bin
$(INSTALL_DIR) -p $(DESTDIR)/usr/$(LIBDIR)
$(INSTALL_DATA) libxenstore.so $(DESTDIR)/usr/$(LIBDIR)
$(INSTALL_DATA) xs.h $(DESTDIR)/usr/include
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xenstore/xenstored.h
--- a/tools/xenstore/xenstored.h Thu Sep 8 15:18:40 2005
+++ b/tools/xenstore/xenstored.h Fri Sep 9 16:30:54 2005
@@ -42,7 +42,7 @@
XS_OP_READ_ONLY = XS_TRANSACTION_END,
XS_INTRODUCE,
XS_RELEASE,
- XS_GETDOMAINPATH,
+ XS_GET_DOMAIN_PATH,
XS_WRITE,
XS_MKDIR,
XS_RM,
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xenstore/xenstored_core.c
--- a/tools/xenstore/xenstored_core.c Thu Sep 8 15:18:40 2005
+++ b/tools/xenstore/xenstored_core.c Fri Sep 9 16:30:54 2005
@@ -49,6 +49,8 @@
#include "xenstored_watch.h"
#include "xenstored_transaction.h"
#include "xenstored_domain.h"
+#include "xenctrl.h"
+#include "xen/io/domain_controller.h"
static bool verbose;
LIST_HEAD(connections);
@@ -140,7 +142,7 @@
case XS_TRANSACTION_END: return "TRANSACTION_END";
case XS_INTRODUCE: return "INTRODUCE";
case XS_RELEASE: return "RELEASE";
- case XS_GETDOMAINPATH: return "GETDOMAINPATH";
+ case XS_GET_DOMAIN_PATH: return "GET_DOMAIN_PATH";
case XS_WRITE: return "WRITE";
case XS_MKDIR: return "MKDIR";
case XS_RM: return "RM";
@@ -719,7 +721,7 @@
char *slash = strrchr(node + 1, '/');
if (!slash)
return talloc_strdup(node, "/");
- return talloc_asprintf(node, "%.*s", slash - node, node);
+ return talloc_asprintf(node, "%.*s", (int)(slash - node), node);
}
static enum xs_perm_type perm_for_id(domid_t id,
@@ -828,6 +830,15 @@
return false;
}
+bool check_event_node(const char *node)
+{
+ if (!node || !strstarts(node, "@")) {
+ errno = EINVAL;
+ return false;
+ }
+ return true;
+}
+
static void send_directory(struct connection *conn, const char *node)
{
char *path, *reply;
@@ -901,7 +912,7 @@
if (slash)
*slash = '\0';
- dest = talloc_asprintf(dir, "%.*s", dot - dir, dir);
+ dest = talloc_asprintf(dir, "%.*s", (int)(dot - dir), dir);
return rename(dir, dest) == 0;
}
@@ -1277,7 +1288,7 @@
do_release(conn, onearg(in));
break;
- case XS_GETDOMAINPATH:
+ case XS_GET_DOMAIN_PATH:
do_get_domain_path(conn, onearg(in));
break;
@@ -1295,8 +1306,12 @@
static void consider_message(struct connection *conn)
{
- struct buffered_data *in = NULL;
- enum xsd_sockmsg_type type = conn->in->hdr.msg.type;
+ /*
+ * 'volatile' qualifier prevents register allocation which fixes:
+ * warning: variable 'xxx' might be clobbered by 'longjmp' or 'vfork'
+ */
+ struct buffered_data *volatile in = NULL;
+ enum xsd_sockmsg_type volatile type = conn->in->hdr.msg.type;
jmp_buf talloc_fail;
assert(conn->state == OK);
@@ -1434,7 +1449,11 @@
struct connection *new_connection(connwritefn_t *write, connreadfn_t *read)
{
- struct connection *new;
+ /*
+ * 'volatile' qualifier prevents register allocation which fixes:
+ * warning: variable 'xxx' might be clobbered by 'longjmp' or 'vfork'
+ */
+ struct connection *volatile new;
jmp_buf talloc_fail;
new = talloc(talloc_autofree_context(), struct connection);
@@ -1628,12 +1647,13 @@
}
-static struct option options[] = { { "no-fork", 0, NULL, 'N' },
- { "verbose", 0, NULL, 'V' },
- { "output-pid", 0, NULL, 'P' },
- { "trace-file", 1, NULL, 'T' },
- { "pid-file", 1, NULL, 'F' },
- { NULL, 0, NULL, 0 } };
+static struct option options[] = {
+ { "pid-file", 1, NULL, 'F' },
+ { "no-fork", 0, NULL, 'N' },
+ { "output-pid", 0, NULL, 'P' },
+ { "trace-file", 1, NULL, 'T' },
+ { "verbose", 0, NULL, 'V' },
+ { NULL, 0, NULL, 0 } };
int main(int argc, char *argv[])
{
@@ -1644,13 +1664,14 @@
bool outputpid = false;
const char *pidfile = NULL;
- while ((opt = getopt_long(argc, argv, "DVT:", options, NULL)) != -1) {
+ while ((opt = getopt_long(argc, argv, "F:NPT:V", options,
+ NULL)) != -1) {
switch (opt) {
+ case 'F':
+ pidfile = optarg;
+ break;
case 'N':
dofork = false;
- break;
- case 'V':
- verbose = true;
break;
case 'P':
outputpid = true;
@@ -1662,8 +1683,9 @@
optarg);
write(tracefd, "\n***\n", strlen("\n***\n"));
break;
- case 'F':
- pidfile = optarg;
+ case 'V':
+ verbose = true;
+ break;
}
}
if (optind != argc)
@@ -1812,6 +1834,7 @@
/* If transactions ended, we might be able to do more work. */
unblock_connections();
- max = initialize_set(&inset, &outset, *sock,*ro_sock,event_fd);
- }
-}
+ max = initialize_set(&inset, &outset, *sock, *ro_sock,
+ event_fd);
+ }
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xenstore/xenstored_core.h
--- a/tools/xenstore/xenstored_core.h Thu Sep 8 15:18:40 2005
+++ b/tools/xenstore/xenstored_core.h Fri Sep 9 16:30:54 2005
@@ -133,6 +133,9 @@
bool check_node_perms(struct connection *conn, const char *node,
enum xs_perm_type perm);
+/* Check if node is an event node. */
+bool check_event_node(const char *node);
+
/* Path to this node outside transaction. */
char *node_dir_outside_transaction(const char *node);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xenstore/xenstored_domain.c
--- a/tools/xenstore/xenstored_domain.c Thu Sep 8 15:18:40 2005
+++ b/tools/xenstore/xenstored_domain.c Fri Sep 9 16:30:54 2005
@@ -1,4 +1,4 @@
-/*
+/*
Domain communications for Xen Store Daemon.
Copyright (C) 2005 Rusty Russell IBM Corporation
@@ -33,10 +33,12 @@
#include "talloc.h"
#include "xenstored_core.h"
#include "xenstored_domain.h"
+#include "xenstored_watch.h"
#include "xenstored_test.h"
static int *xc_handle;
static int eventchn_fd;
+static int virq_port;
static unsigned int ringbuf_datasize;
struct domain
@@ -216,17 +218,6 @@
return 0;
}
-static struct domain *find_domain(u16 port)
-{
- struct domain *i;
-
- list_for_each_entry(i, &domains, list) {
- if (i->port == port)
- return i;
- }
- return NULL;
-}
-
/* We scan all domains rather than use the information given here. */
void handle_event(int event_fd)
{
@@ -234,6 +225,10 @@
if (read(event_fd, &port, sizeof(port)) != sizeof(port))
barf_perror("Failed to read from event fd");
+
+ if (port == virq_port)
+ domain_cleanup();
+
#ifndef TESTING
if (write(event_fd, &port, sizeof(port)) != sizeof(port))
barf_perror("Failed to write to event fd");
@@ -319,6 +314,9 @@
/* Now domain belongs to its connection. */
talloc_steal(domain->conn, domain);
+
+ fire_watches(conn, "@introduceDomain", false);
+
send_ack(conn, XS_INTRODUCE);
}
@@ -367,7 +365,30 @@
}
talloc_free(domain->conn);
+
+ fire_watches(NULL, "@releaseDomain", false);
+
send_ack(conn, XS_RELEASE);
+}
+
+void domain_cleanup(void)
+{
+ xc_dominfo_t dominfo;
+ struct domain *domain, *tmp;
+ int released = 0;
+
+ list_for_each_entry_safe(domain, tmp, &domains, list) {
+ if (xc_domain_getinfo(*xc_handle, domain->domid, 1,
+ &dominfo) == 1 &&
+ dominfo.domid == domain->domid &&
+ !dominfo.dying && !dominfo.crashed && !dominfo.shutdown)
+ continue;
+ talloc_free(domain->conn);
+ released++;
+ }
+
+ if (released)
+ fire_watches(NULL, "@releaseDomain", false);
}
void do_get_domain_path(struct connection *conn, const char *domid_str)
@@ -386,10 +407,10 @@
else
domain = find_domain_by_domid(domid);
- if (!domain)
+ if (!domain)
send_error(conn, ENOENT);
else
- send_reply(conn, XS_GETDOMAINPATH, domain->path,
+ send_reply(conn, XS_GET_DOMAIN_PATH, domain->path,
strlen(domain->path) + 1);
}
@@ -412,26 +433,55 @@
{
}
+#define EVTCHN_DEV_NAME "/dev/xen/evtchn"
+#define EVTCHN_DEV_MAJOR 10
+#define EVTCHN_DEV_MINOR 201
+
/* Returns the event channel handle. */
int domain_init(void)
{
+ struct stat st;
+
/* The size of the ringbuffer: half a page minus head structure. */
ringbuf_datasize = getpagesize() / 2 - sizeof(struct ringbuf_head);
xc_handle = talloc(talloc_autofree_context(), int);
if (!xc_handle)
barf_perror("Failed to allocate domain handle");
+
*xc_handle = xc_interface_open();
if (*xc_handle < 0)
barf_perror("Failed to open connection to hypervisor");
+
talloc_set_destructor(xc_handle, close_xc_handle);
#ifdef TESTING
eventchn_fd = fake_open_eventchn();
#else
- eventchn_fd = open("/dev/xen/evtchn", O_RDWR);
+ /* Make sure any existing device file links to correct device. */
+ if ((lstat(EVTCHN_DEV_NAME, &st) != 0) || !S_ISCHR(st.st_mode) ||
+ (st.st_rdev != makedev(EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR)))
+ (void)unlink(EVTCHN_DEV_NAME);
+
+ reopen:
+ eventchn_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR);
+ if (eventchn_fd == -1) {
+ if ((errno == ENOENT) &&
+ ((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) &&
+ (mknod(EVTCHN_DEV_NAME, S_IFCHR|0600,
+ makedev(EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR)) == 0))
+ goto reopen;
+ return -errno;
+ }
#endif
if (eventchn_fd < 0)
- barf_perror("Failed to open connection to hypervisor");
+ barf_perror("Failed to open evtchn device");
+
+ if (xc_evtchn_bind_virq(*xc_handle, VIRQ_DOM_EXC, &virq_port))
+ barf_perror("Failed to bind to domain exception virq");
+
+ if (ioctl(eventchn_fd, EVENTCHN_BIND, virq_port) != 0)
+ barf_perror("Failed to bind to domain exception virq port");
+
return eventchn_fd;
}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xenstore/xenstored_domain.h
--- a/tools/xenstore/xenstored_domain.h Thu Sep 8 15:18:40 2005
+++ b/tools/xenstore/xenstored_domain.h Fri Sep 9 16:30:54 2005
@@ -28,6 +28,10 @@
/* domid */
void do_release(struct connection *conn, const char *domid_str);
+/* Enumerate domains and release connections for non-existant or dying
+ * domains. */
+void domain_cleanup(void);
+
/* domid */
void do_get_domain_path(struct connection *conn, const char *domid_str);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xenstore/xenstored_watch.c
--- a/tools/xenstore/xenstored_watch.c Thu Sep 8 15:18:40 2005
+++ b/tools/xenstore/xenstored_watch.c Fri Sep 9 16:30:54 2005
@@ -103,7 +103,8 @@
/* Check read permission: no permission, no watch event.
* If it doesn't exist, we need permission to read parent.
*/
- if (!check_node_perms(conn, node, XS_PERM_READ|XS_PERM_ENOENT_OK)) {
+ if (!check_node_perms(conn, node, XS_PERM_READ|XS_PERM_ENOENT_OK) &&
+ !check_event_node(node)) {
fprintf(stderr, "No permission for %s\n", node);
return;
}
@@ -131,7 +132,7 @@
struct watch *watch;
/* During transactions, don't fire watches. */
- if (conn->transaction)
+ if (conn && conn->transaction)
return;
/* Create an event for each watch. Don't send to self. */
@@ -213,11 +214,16 @@
return;
}
- relative = !strstarts(vec[0], "/");
- vec[0] = canonicalize(conn, vec[0]);
- if (!is_valid_nodename(vec[0])) {
- send_error(conn, errno);
- return;
+ if (strstarts(vec[0], "@")) {
+ relative = false;
+ /* check if valid event */
+ } else {
+ relative = !strstarts(vec[0], "/");
+ vec[0] = canonicalize(conn, vec[0]);
+ if (!is_valid_nodename(vec[0])) {
+ send_error(conn, errno);
+ return;
+ }
}
watch = talloc(conn, struct watch);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xenstore/xs.c
--- a/tools/xenstore/xs.c Thu Sep 8 15:18:40 2005
+++ b/tools/xenstore/xs.c Fri Sep 9 16:30:54 2005
@@ -31,14 +31,17 @@
#include <signal.h>
#include <stdint.h>
#include <errno.h>
+#include <sys/ioctl.h>
#include "xs.h"
#include "xenstored.h"
#include "xs_lib.h"
#include "utils.h"
+#include "xenbus_dev.h"
struct xs_handle
{
int fd;
+ enum { SOCK, DEV } type;
};
/* Get the socket from the store daemon handle.
@@ -65,17 +68,39 @@
h = malloc(sizeof(*h));
if (h) {
h->fd = sock;
+ h->type = SOCK;
return h;
}
}
saved_errno = errno;
close(sock);
- free(h);
errno = saved_errno;
return NULL;
}
+static struct xs_handle *get_dev(const char *connect_to)
+{
+ int fd, saved_errno;
+ struct xs_handle *h = NULL;
+
+ fd = open(connect_to, O_RDONLY);
+ if (fd < 0)
+ return NULL;
+
+ h = malloc(sizeof(*h));
+ if (h) {
+ h->fd = fd;
+ h->type = DEV;
+ return h;
+ }
+
+ saved_errno = errno;
+ close(fd);
+ errno = saved_errno;
+ return NULL;
+}
+
struct xs_handle *xs_daemon_open(void)
{
return get_socket(xs_daemon_socket());
@@ -84,6 +109,11 @@
struct xs_handle *xs_daemon_open_readonly(void)
{
return get_socket(xs_daemon_socket_ro());
+}
+
+struct xs_handle *xs_domain_open(void)
+{
+ return get_dev(xs_domain_dev());
}
void xs_daemon_close(struct xs_handle *h)
@@ -160,9 +190,9 @@
}
/* Send message to xs, get malloc'ed reply. NULL and set errno on error. */
-static void *xs_talkv(struct xs_handle *h, enum xsd_sockmsg_type type,
- const struct iovec *iovec, unsigned int num_vecs,
- unsigned int *len)
+static void *xs_talkv_sock(struct xs_handle *h, enum xsd_sockmsg_type type,
+ const struct iovec *iovec, unsigned int num_vecs,
+ unsigned int *len)
{
struct xsd_sockmsg msg;
void *ret = NULL;
@@ -220,6 +250,54 @@
close(h->fd);
h->fd = -1;
errno = saved_errno;
+ return NULL;
+}
+
+/* Send message to xs, get malloc'ed reply. NULL and set errno on error. */
+static void *xs_talkv_dev(struct xs_handle *h, enum xsd_sockmsg_type type,
+ const struct iovec *iovec, unsigned int num_vecs,
+ unsigned int *len)
+{
+ struct xenbus_dev_talkv dt;
+ char *buf;
+ int err, buflen = 1024;
+
+ again:
+ buf = malloc(buflen);
+ if (buf == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ dt.type = type;
+ dt.iovec = (struct kvec *)iovec;
+ dt.num_vecs = num_vecs;
+ dt.buf = buf;
+ dt.len = buflen;
+ err = ioctl(h->fd, IOCTL_XENBUS_DEV_TALKV, &dt);
+ if (err < 0) {
+ free(buf);
+ errno = err;
+ return NULL;
+ }
+ if (err > buflen) {
+ free(buf);
+ buflen = err;
+ goto again;
+ }
+ if (len)
+ *len = err;
+ return buf;
+}
+
+/* Send message to xs, get malloc'ed reply. NULL and set errno on error. */
+static void *xs_talkv(struct xs_handle *h, enum xsd_sockmsg_type type,
+ const struct iovec *iovec, unsigned int num_vecs,
+ unsigned int *len)
+{
+ if (h->type == SOCK)
+ return xs_talkv_sock(h, type, iovec, num_vecs, len);
+ if (h->type == DEV)
+ return xs_talkv_dev(h, type, iovec, num_vecs, len);
return NULL;
}
@@ -535,13 +613,23 @@
return xs_bool(xs_single(h, XS_RELEASE, domid_str, NULL));
}
+char *xs_get_domain_path(struct xs_handle *h, domid_t domid)
+{
+ char domid_str[MAX_STRLEN(domid)];
+
+ sprintf(domid_str, "%u", domid);
+
+ return xs_single(h, XS_GET_DOMAIN_PATH, domid_str, NULL);
+}
+
bool xs_shutdown(struct xs_handle *h)
{
bool ret = xs_bool(xs_single(h, XS_SHUTDOWN, "", NULL));
if (ret) {
char c;
/* Wait for it to actually shutdown. */
- read(h->fd, &c, 1);
+ while ((read(h->fd, &c, 1) < 0) && (errno == EINTR))
+ continue;
}
return ret;
}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xenstore/xs.h
--- a/tools/xenstore/xs.h Thu Sep 8 15:18:40 2005
+++ b/tools/xenstore/xs.h Fri Sep 9 16:30:54 2005
@@ -30,6 +30,7 @@
* Returns a handle or NULL.
*/
struct xs_handle *xs_daemon_open(void);
+struct xs_handle *xs_domain_open(void);
/* Connect to the xs daemon (readonly for non-root clients).
* Returns a handle or NULL.
@@ -133,6 +134,10 @@
*/
bool xs_release_domain(struct xs_handle *h, domid_t domid);
+/* Query the home path of a domain.
+ */
+char *xs_get_domain_path(struct xs_handle *h, domid_t domid);
+
/* Only useful for DEBUG versions */
char *xs_debug_command(struct xs_handle *h, const char *cmd,
void *data, unsigned int len);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xenstore/xs_lib.c
--- a/tools/xenstore/xs_lib.c Thu Sep 8 15:18:40 2005
+++ b/tools/xenstore/xs_lib.c Fri Sep 9 16:30:54 2005
@@ -64,6 +64,12 @@
static char buf[PATH_MAX];
sprintf(buf, "%s/transactions", xs_daemon_rootdir());
return buf;
+}
+
+const char *xs_domain_dev(void)
+{
+ char *s = getenv("XENSTORED_DOMAIN_DEV");
+ return (s ? s : "/proc/xen/xenbus");
}
/* Simple routines for writing to sockets, etc. */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xenstore/xs_lib.h
--- a/tools/xenstore/xs_lib.h Thu Sep 8 15:18:40 2005
+++ b/tools/xenstore/xs_lib.h Fri Sep 9 16:30:54 2005
@@ -48,6 +48,7 @@
const char *xs_daemon_socket_ro(void);
const char *xs_daemon_store(void);
const char *xs_daemon_transactions(void);
+const char *xs_domain_dev(void);
/* Simple write function: loops for you. */
bool xs_write_all(int fd, const void *data, unsigned int len);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xentrace/formats
--- a/tools/xentrace/formats Thu Sep 8 15:18:40 2005
+++ b/tools/xentrace/formats Fri Sep 9 16:30:54 2005
@@ -15,3 +15,7 @@
0x00080001 CPU%(cpu)d %(tsc)d VMX_VMEXIT [ domid
= 0x%(1)08x, eip = 0x%(2)08x, reason = 0x%(3)08x ]
0x00080002 CPU%(cpu)d %(tsc)d VMX_VECTOR [ domid
= 0x%(1)08x, eip = 0x%(2)08x, vector = 0x%(3)08x ]
0x00080003 CPU%(cpu)d %(tsc)d VMX_INT [ domid
= 0x%(1)08x, trap = 0x%(2)08x, va = 0x%(3)08x ]
+
+0x00090001 CPU%(cpu)d %(tsc)d VMENTRY
0x%(1)08x 0x%(2)08x 0x%(3)08x 0x%(4)08x 0x%(5)08x
+0x00090002 CPU%(cpu)d %(tsc)d VMEXIT
0x%(1)08x 0x%(2)08x 0x%(3)08x
+
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xentrace/xentrace.c
--- a/tools/xentrace/xentrace.c Thu Sep 8 15:18:40 2005
+++ b/tools/xentrace/xentrace.c Fri Sep 9 16:30:54 2005
@@ -525,7 +525,7 @@
}
if (opts.cpu_mask != 0) {
- set_mask(opts.evt_mask, 1);
+ set_mask(opts.cpu_mask, 1);
}
if ( opts.outfile )
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/Rules.mk
--- a/xen/Rules.mk Thu Sep 8 15:18:40 2005
+++ b/xen/Rules.mk Fri Sep 9 16:30:54 2005
@@ -7,7 +7,6 @@
perfc ?= n
perfc_arrays?= n
trace ?= n
-optimize ?= y
domu_debug ?= n
crash_debug ?= n
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/acm/acm_chinesewall_hooks.c
--- a/xen/acm/acm_chinesewall_hooks.c Thu Sep 8 15:18:40 2005
+++ b/xen/acm/acm_chinesewall_hooks.c Fri Sep 9 16:30:54 2005
@@ -310,6 +310,28 @@
return 0;
}
+static int
+chwall_dump_ssid_types(ssidref_t ssidref, u8 *buf, u16 len)
+{
+ int i;
+
+ /* fill in buffer */
+ if (chwall_bin_pol.max_types > len)
+ return -EFAULT;
+
+ if (ssidref >= chwall_bin_pol.max_ssidrefs)
+ return -EFAULT;
+
+ /* read types for chwall ssidref */
+ for(i=0; i< chwall_bin_pol.max_types; i++) {
+ if (chwall_bin_pol.ssidrefs[ssidref * chwall_bin_pol.max_types + i])
+ buf[i] = 1;
+ else
+ buf[i] = 0;
+ }
+ return chwall_bin_pol.max_types;
+}
+
/***************************
* Authorization functions
***************************/
@@ -492,6 +514,7 @@
.dump_binary_policy = chwall_dump_policy,
.set_binary_policy = chwall_set_policy,
.dump_statistics = chwall_dump_stats,
+ .dump_ssid_types = chwall_dump_ssid_types,
/* domain management control hooks */
.pre_domain_create = chwall_pre_domain_create,
.post_domain_create = chwall_post_domain_create,
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/acm/acm_core.c
--- a/xen/acm/acm_core.c Thu Sep 8 15:18:40 2005
+++ b/xen/acm/acm_core.c Fri Sep 9 16:30:54 2005
@@ -64,16 +64,17 @@
void acm_set_endian(void)
{
u32 test = 1;
- if (*((u8 *)&test) == 1) {
+ if (*((u8 *)&test) == 1)
+ {
printk("ACM module running in LITTLE ENDIAN.\n");
- little_endian = 1;
- } else {
- printk("ACM module running in BIG ENDIAN.\n");
- little_endian = 0;
- }
-}
-
-#if (ACM_USE_SECURITY_POLICY != ACM_NULL_POLICY)
+ little_endian = 1;
+ }
+ else
+ {
+ printk("ACM module running in BIG ENDIAN.\n");
+ little_endian = 0;
+ }
+}
/* initialize global security policy for Xen; policy write-locked already */
static void
@@ -101,7 +102,8 @@
* Try all modules and see whichever could be the binary policy.
* Adjust the initrdidx if module[1] is the binary policy.
*/
- for (i = mbi->mods_count-1; i >= 1; i--) {
+ for (i = mbi->mods_count-1; i >= 1; i--)
+ {
struct acm_policy_buffer *pol;
char *_policy_start;
unsigned long _policy_len;
@@ -117,23 +119,32 @@
continue; /* not a policy */
pol = (struct acm_policy_buffer *)_policy_start;
- if (ntohl(pol->magic) == ACM_MAGIC) {
+ if (ntohl(pol->magic) == ACM_MAGIC)
+ {
rc = acm_set_policy((void *)_policy_start,
(u16)_policy_len,
0);
- if (rc == ACM_OK) {
+ if (rc == ACM_OK)
+ {
printf("Policy len 0x%lx, start at
%p.\n",_policy_len,_policy_start);
- if (i == 1) {
- if (mbi->mods_count > 2) {
+ if (i == 1)
+ {
+ if (mbi->mods_count > 2)
+ {
*initrdidx = 2;
- } else {
+ }
+ else {
*initrdidx = 0;
}
- } else {
+ }
+ else
+ {
*initrdidx = 1;
}
break;
- } else {
+ }
+ else
+ {
printk("Invalid policy. %d.th module line.\n", i+1);
}
} /* end if a binary policy definition, i.e., (ntohl(pol->magic) ==
ACM_MAGIC ) */
@@ -147,56 +158,84 @@
const multiboot_info_t *mbi,
unsigned long initial_images_start)
{
- int ret = -EINVAL;
-
- acm_set_endian();
+ int ret = ACM_OK;
+
+ acm_set_endian();
write_lock(&acm_bin_pol_rwlock);
-
- if (ACM_USE_SECURITY_POLICY == ACM_CHINESE_WALL_POLICY) {
- acm_init_binary_policy(NULL, NULL);
- acm_init_chwall_policy();
+ acm_init_binary_policy(NULL, NULL);
+
+ /* set primary policy component */
+ switch ((ACM_USE_SECURITY_POLICY) & 0x0f)
+ {
+
+ case ACM_CHINESE_WALL_POLICY:
+ acm_init_chwall_policy();
acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY;
acm_primary_ops = &acm_chinesewall_ops;
+ break;
+
+ case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
+ acm_init_ste_policy();
+ acm_bin_pol.primary_policy_code =
ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
+ acm_primary_ops = &acm_simple_type_enforcement_ops;
+ break;
+
+ default:
+ /* NULL or Unknown policy not allowed primary;
+ * NULL/NULL will not compile this code */
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* secondary policy component part */
+ switch ((ACM_USE_SECURITY_POLICY) >> 4) {
+ case ACM_NULL_POLICY:
acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
acm_secondary_ops = &acm_null_ops;
- ret = ACM_OK;
- } else if (ACM_USE_SECURITY_POLICY ==
ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) {
- acm_init_binary_policy(NULL, NULL);
+ break;
+
+ case ACM_CHINESE_WALL_POLICY:
+ if (acm_bin_pol.primary_policy_code == ACM_CHINESE_WALL_POLICY)
+ { /* not a valid combination */
+ ret = -EINVAL;
+ goto out;
+ }
+ acm_init_chwall_policy();
+ acm_bin_pol.secondary_policy_code = ACM_CHINESE_WALL_POLICY;
+ acm_secondary_ops = &acm_chinesewall_ops;
+ break;
+
+ case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
+ if (acm_bin_pol.primary_policy_code ==
ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
+ { /* not a valid combination */
+ ret = -EINVAL;
+ goto out;
+ }
acm_init_ste_policy();
- acm_bin_pol.primary_policy_code =
ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
- acm_primary_ops = &acm_simple_type_enforcement_ops;
- acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
- acm_secondary_ops = &acm_null_ops;
- ret = ACM_OK;
- } else if (ACM_USE_SECURITY_POLICY ==
ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY) {
- acm_init_binary_policy(NULL, NULL);
- acm_init_chwall_policy();
- acm_init_ste_policy();
- acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY;
- acm_primary_ops = &acm_chinesewall_ops;
acm_bin_pol.secondary_policy_code =
ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
acm_secondary_ops = &acm_simple_type_enforcement_ops;
- ret = ACM_OK;
- } else if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY) {
- acm_init_binary_policy(NULL, NULL);
- acm_bin_pol.primary_policy_code = ACM_NULL_POLICY;
- acm_primary_ops = &acm_null_ops;
- acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
- acm_secondary_ops = &acm_null_ops;
- ret = ACM_OK;
+ break;
+
+ default:
+ ret = -EINVAL;
+ goto out;
+ }
+
+ out:
+ write_unlock(&acm_bin_pol_rwlock);
+
+ if (ret != ACM_OK)
+ {
+ printk("%s: Error setting policies.\n", __func__);
+ /* here one could imagine a clean panic */
+ return -EINVAL;
}
- write_unlock(&acm_bin_pol_rwlock);
-
- if (ret != ACM_OK)
- return -EINVAL;
acm_setup(initrdidx, mbi, initial_images_start);
printk("%s: Enforcing Primary %s, Secondary %s.\n", __func__,
- ACM_POLICY_NAME(acm_bin_pol.primary_policy_code),
ACM_POLICY_NAME(acm_bin_pol.secondary_policy_code));
+ ACM_POLICY_NAME(acm_bin_pol.primary_policy_code),
+ ACM_POLICY_NAME(acm_bin_pol.secondary_policy_code));
return ret;
}
-
-
-#endif
int
acm_init_domain_ssid(domid_t id, ssidref_t ssidref)
@@ -205,7 +244,8 @@
struct domain *subj = find_domain_by_id(id);
int ret1, ret2;
- if (subj == NULL) {
+ if (subj == NULL)
+ {
printk("%s: ACM_NULL_POINTER ERROR (id=%x).\n", __func__, id);
return ACM_NULL_POINTER_ERROR;
}
@@ -235,14 +275,16 @@
else
ret2 = ACM_OK;
- if ((ret1 != ACM_OK) || (ret2 != ACM_OK)) {
+ if ((ret1 != ACM_OK) || (ret2 != ACM_OK))
+ {
printk("%s: ERROR instantiating individual ssids for domain
0x%02x.\n",
__func__, subj->domain_id);
acm_free_domain_ssid(ssid);
put_domain(subj);
return ACM_INIT_SSID_ERROR;
}
- printk("%s: assigned domain %x the ssidref=%x.\n", __func__, id,
ssid->ssidref);
+ printk("%s: assigned domain %x the ssidref=%x.\n",
+ __func__, id, ssid->ssidref);
put_domain(subj);
return ACM_OK;
}
@@ -254,11 +296,12 @@
domid_t id;
/* domain is already gone, just ssid is left */
- if (ssid == NULL) {
+ if (ssid == NULL)
+ {
printk("%s: ACM_NULL_POINTER ERROR.\n", __func__);
return ACM_NULL_POINTER_ERROR;
}
- id = ssid->domainid;
+ id = ssid->domainid;
ssid->subject = NULL;
if (acm_primary_ops->free_domain_ssid != NULL) /* null policy */
@@ -268,6 +311,7 @@
acm_secondary_ops->free_domain_ssid(ssid->secondary_ssid);
ssid->secondary_ssid = NULL;
xfree(ssid);
- printkd("%s: Freed individual domain ssid (domain=%02x).\n",__func__,
id);
+ printkd("%s: Freed individual domain ssid (domain=%02x).\n",
+ __func__, id);
return ACM_OK;
}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/acm/acm_null_hooks.c
--- a/xen/acm/acm_null_hooks.c Thu Sep 8 15:18:40 2005
+++ b/xen/acm/acm_null_hooks.c Fri Sep 9 16:30:54 2005
@@ -14,13 +14,13 @@
#include <acm/acm_hooks.h>
static int
-null_init_domain_ssid(void **chwall_ssid, ssidref_t ssidref)
+null_init_domain_ssid(void **ssid, ssidref_t ssidref)
{
return ACM_OK;
}
static void
-null_free_domain_ssid(void *chwall_ssid)
+null_free_domain_ssid(void *ssid)
{
return;
}
@@ -44,6 +44,14 @@
return 0;
}
+static int
+null_dump_ssid_types(ssidref_t ssidref, u8 *buffer, u16 buf_size)
+{
+ /* no types */
+ return 0;
+}
+
+
/* now define the hook structure similarly to LSM */
struct acm_operations acm_null_ops = {
.init_domain_ssid = null_init_domain_ssid,
@@ -51,6 +59,7 @@
.dump_binary_policy = null_dump_binary_policy,
.set_binary_policy = null_set_binary_policy,
.dump_statistics = null_dump_stats,
+ .dump_ssid_types = null_dump_ssid_types,
/* domain management control hooks */
.pre_domain_create = NULL,
.post_domain_create = NULL,
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/acm/acm_policy.c
--- a/xen/acm/acm_policy.c Thu Sep 8 15:18:40 2005
+++ b/xen/acm/acm_policy.c Fri Sep 9 16:30:54 2005
@@ -26,8 +26,8 @@
#include <xen/lib.h>
#include <xen/delay.h>
#include <xen/sched.h>
+#include <acm/acm_core.h>
#include <public/acm_ops.h>
-#include <acm/acm_core.h>
#include <acm/acm_hooks.h>
#include <acm/acm_endian.h>
@@ -37,14 +37,16 @@
u8 *policy_buffer = NULL;
struct acm_policy_buffer *pol;
- if (buf_size < sizeof(struct acm_policy_buffer))
+ if (buf_size < sizeof(struct acm_policy_buffer))
return -EFAULT;
/* 1. copy buffer from domain */
if ((policy_buffer = xmalloc_array(u8, buf_size)) == NULL)
- goto error_free;
+ return -ENOMEM;
+
if (isuserbuffer) {
- if (copy_from_user(policy_buffer, buf, buf_size)) {
+ if (copy_from_user(policy_buffer, buf, buf_size))
+ {
printk("%s: Error copying!\n",__func__);
goto error_free;
}
@@ -57,11 +59,13 @@
if ((ntohl(pol->magic) != ACM_MAGIC) ||
(ntohl(pol->policy_version) != ACM_POLICY_VERSION) ||
(ntohl(pol->primary_policy_code) !=
acm_bin_pol.primary_policy_code) ||
- (ntohl(pol->secondary_policy_code) !=
acm_bin_pol.secondary_policy_code)) {
+ (ntohl(pol->secondary_policy_code) !=
acm_bin_pol.secondary_policy_code))
+ {
printkd("%s: Wrong policy magics or versions!\n", __func__);
goto error_free;
}
- if (buf_size != ntohl(pol->len)) {
+ if (buf_size != ntohl(pol->len))
+ {
printk("%s: ERROR in buf size.\n", __func__);
goto error_free;
}
@@ -72,27 +76,25 @@
/* 3. set primary policy data */
if (acm_primary_ops->set_binary_policy(buf +
ntohl(pol->primary_buffer_offset),
ntohl(pol->secondary_buffer_offset) -
-
ntohl(pol->primary_buffer_offset))) {
+
ntohl(pol->primary_buffer_offset)))
goto error_lock_free;
- }
+
/* 4. set secondary policy data */
if (acm_secondary_ops->set_binary_policy(buf +
ntohl(pol->secondary_buffer_offset),
ntohl(pol->len) -
-
ntohl(pol->secondary_buffer_offset))) {
+
ntohl(pol->secondary_buffer_offset)))
goto error_lock_free;
- }
+
write_unlock(&acm_bin_pol_rwlock);
- if (policy_buffer != NULL)
- xfree(policy_buffer);
+ xfree(policy_buffer);
return ACM_OK;
error_lock_free:
write_unlock(&acm_bin_pol_rwlock);
error_free:
printk("%s: Error setting policy.\n", __func__);
- if (policy_buffer != NULL)
- xfree(policy_buffer);
- return -ENOMEM;
+ xfree(policy_buffer);
+ return -EFAULT;
}
int
@@ -102,11 +104,14 @@
int ret;
struct acm_policy_buffer *bin_pol;
+ if (buf_size < sizeof(struct acm_policy_buffer))
+ return -EFAULT;
+
if ((policy_buffer = xmalloc_array(u8, buf_size)) == NULL)
return -ENOMEM;
read_lock(&acm_bin_pol_rwlock);
- /* future: read policy from file and set it */
+
bin_pol = (struct acm_policy_buffer *)policy_buffer;
bin_pol->magic = htonl(ACM_MAGIC);
bin_pol->primary_policy_code = htonl(acm_bin_pol.primary_policy_code);
@@ -118,27 +123,30 @@
ret = acm_primary_ops->dump_binary_policy (policy_buffer +
ntohl(bin_pol->primary_buffer_offset),
buf_size -
ntohl(bin_pol->primary_buffer_offset));
- if (ret < 0) {
- printk("%s: ERROR creating chwallpolicy buffer.\n", __func__);
- read_unlock(&acm_bin_pol_rwlock);
- return -1;
- }
+ if (ret < 0)
+ goto error_free_unlock;
+
bin_pol->len = htonl(ntohl(bin_pol->len) + ret);
bin_pol->secondary_buffer_offset = htonl(ntohl(bin_pol->len));
ret = acm_secondary_ops->dump_binary_policy(policy_buffer +
ntohl(bin_pol->secondary_buffer_offset),
buf_size -
ntohl(bin_pol->secondary_buffer_offset));
- if (ret < 0) {
- printk("%s: ERROR creating chwallpolicy buffer.\n", __func__);
- read_unlock(&acm_bin_pol_rwlock);
- return -1;
- }
+ if (ret < 0)
+ goto error_free_unlock;
+
bin_pol->len = htonl(ntohl(bin_pol->len) + ret);
- read_unlock(&acm_bin_pol_rwlock);
if (copy_to_user(buf, policy_buffer, ntohl(bin_pol->len)))
- return -EFAULT;
+ goto error_free_unlock;
+
+ read_unlock(&acm_bin_pol_rwlock);
xfree(policy_buffer);
return ACM_OK;
+
+ error_free_unlock:
+ read_unlock(&acm_bin_pol_rwlock);
+ printk("%s: Error getting policy.\n", __func__);
+ xfree(policy_buffer);
+ return -EFAULT;
}
int
@@ -185,4 +193,62 @@
return -EFAULT;
}
+
+int
+acm_get_ssid(ssidref_t ssidref, u8 *buf, u16 buf_size)
+{
+ /* send stats to user space */
+ u8 *ssid_buffer;
+ int ret;
+ struct acm_ssid_buffer *acm_ssid;
+ if (buf_size < sizeof(struct acm_ssid_buffer))
+ return -EFAULT;
+
+ if ((ssid_buffer = xmalloc_array(u8, buf_size)) == NULL)
+ return -ENOMEM;
+
+ read_lock(&acm_bin_pol_rwlock);
+
+ acm_ssid = (struct acm_ssid_buffer *)ssid_buffer;
+ acm_ssid->len = sizeof(struct acm_ssid_buffer);
+ acm_ssid->ssidref = ssidref;
+ acm_ssid->primary_policy_code = acm_bin_pol.primary_policy_code;
+ acm_ssid->secondary_policy_code = acm_bin_pol.secondary_policy_code;
+ acm_ssid->primary_types_offset = acm_ssid->len;
+
+ /* ret >= 0 --> ret == max_types */
+ ret = acm_primary_ops->dump_ssid_types(ACM_PRIMARY(ssidref),
+ ssid_buffer +
acm_ssid->primary_types_offset,
+ buf_size -
acm_ssid->primary_types_offset);
+ if (ret < 0)
+ goto error_free_unlock;
+
+ acm_ssid->len += ret;
+ acm_ssid->primary_max_types = ret;
+
+ acm_ssid->secondary_types_offset = acm_ssid->len;
+
+ ret = acm_secondary_ops->dump_ssid_types(ACM_SECONDARY(ssidref),
+ ssid_buffer +
acm_ssid->secondary_types_offset,
+ buf_size -
acm_ssid->secondary_types_offset);
+ if (ret < 0)
+ goto error_free_unlock;
+
+ acm_ssid->len += ret;
+ acm_ssid->secondary_max_types = ret;
+
+ if (copy_to_user(buf, ssid_buffer, acm_ssid->len))
+ goto error_free_unlock;
+
+ read_unlock(&acm_bin_pol_rwlock);
+ xfree(ssid_buffer);
+ return ACM_OK;
+
+ error_free_unlock:
+ read_unlock(&acm_bin_pol_rwlock);
+ printk("%s: Error getting ssid.\n", __func__);
+ xfree(ssid_buffer);
+ return -ENOMEM;
+}
+
/*eof*/
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/acm/acm_simple_type_enforcement_hooks.c
--- a/xen/acm/acm_simple_type_enforcement_hooks.c Thu Sep 8 15:18:40 2005
+++ b/xen/acm/acm_simple_type_enforcement_hooks.c Fri Sep 9 16:30:54 2005
@@ -383,6 +383,27 @@
return sizeof(struct acm_ste_stats_buffer);
}
+static int
+ste_dump_ssid_types(ssidref_t ssidref, u8 *buf, u16 len)
+{
+ int i;
+
+ /* fill in buffer */
+ if (ste_bin_pol.max_types > len)
+ return -EFAULT;
+
+ if (ssidref >= ste_bin_pol.max_ssidrefs)
+ return -EFAULT;
+
+ /* read types for chwall ssidref */
+ for(i=0; i< ste_bin_pol.max_types; i++) {
+ if (ste_bin_pol.ssidrefs[ssidref * ste_bin_pol.max_types + i])
+ buf[i] = 1;
+ else
+ buf[i] = 0;
+ }
+ return ste_bin_pol.max_types;
+}
/* we need to go through this before calling the hooks,
* returns 1 == cache hit */
@@ -625,22 +646,23 @@
/* policy management services */
.init_domain_ssid = ste_init_domain_ssid,
.free_domain_ssid = ste_free_domain_ssid,
- .dump_binary_policy = ste_dump_policy,
- .set_binary_policy = ste_set_policy,
+ .dump_binary_policy = ste_dump_policy,
+ .set_binary_policy = ste_set_policy,
.dump_statistics = ste_dump_stats,
+ .dump_ssid_types = ste_dump_ssid_types,
/* domain management control hooks */
.pre_domain_create = ste_pre_domain_create,
- .post_domain_create = NULL,
- .fail_domain_create = NULL,
- .post_domain_destroy = ste_post_domain_destroy,
+ .post_domain_create = NULL,
+ .fail_domain_create = NULL,
+ .post_domain_destroy = ste_post_domain_destroy,
/* event channel control hooks */
- .pre_eventchannel_unbound = ste_pre_eventchannel_unbound,
+ .pre_eventchannel_unbound = ste_pre_eventchannel_unbound,
.fail_eventchannel_unbound = NULL,
.pre_eventchannel_interdomain = ste_pre_eventchannel_interdomain,
.fail_eventchannel_interdomain = NULL,
/* grant table control hooks */
- .pre_grant_map_ref = ste_pre_grant_map_ref,
- .fail_grant_map_ref = NULL,
- .pre_grant_setup = ste_pre_grant_setup,
- .fail_grant_setup = NULL,
+ .pre_grant_map_ref = ste_pre_grant_map_ref,
+ .fail_grant_map_ref = NULL,
+ .pre_grant_setup = ste_pre_grant_setup,
+ .fail_grant_setup = NULL,
};
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/Makefile
--- a/xen/arch/x86/Makefile Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/Makefile Fri Sep 9 16:30:54 2005
@@ -17,7 +17,7 @@
OBJS := $(patsubst shadow%.o,,$(OBJS)) # drop all
ifeq ($(TARGET_SUBARCH),x86_64)
- OBJS += shadow.o shadow_public.o # x86_64: new code
+ OBJS += shadow.o shadow_public.o shadow_guest32.o # x86_64: new code
endif
ifeq ($(TARGET_SUBARCH),x86_32)
ifneq ($(pae),n)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/Rules.mk
--- a/xen/arch/x86/Rules.mk Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/Rules.mk Fri Sep 9 16:30:54 2005
@@ -13,10 +13,8 @@
CFLAGS += -I$(BASEDIR)/include/asm-x86/mach-generic
CFLAGS += -I$(BASEDIR)/include/asm-x86/mach-default
-ifeq ($(optimize),y)
+ifneq ($(debug),y)
CFLAGS += -O3 -fomit-frame-pointer
-else
-x86_32/usercopy.o: CFLAGS += -O1
endif
# Prevent floating-point variables from creeping into Xen.
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/boot/x86_32.S
--- a/xen/arch/x86/boot/x86_32.S Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/boot/x86_32.S Fri Sep 9 16:30:54 2005
@@ -9,6 +9,8 @@
.text
ENTRY(start)
+ENTRY(stext)
+ENTRY(_stext)
jmp __start
.align 4
@@ -260,6 +262,3 @@
.org 0x2000 + STACK_SIZE + PAGE_SIZE
#endif /* CONFIG_X86_PAE */
-
-ENTRY(stext)
-ENTRY(_stext)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/boot/x86_64.S
--- a/xen/arch/x86/boot/x86_64.S Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/boot/x86_64.S Fri Sep 9 16:30:54 2005
@@ -10,6 +10,8 @@
.code32
ENTRY(start)
+ENTRY(stext)
+ENTRY(_stext)
jmp __start
.org 0x004
@@ -267,5 +269,3 @@
.org 0x4000 + STACK_SIZE + PAGE_SIZE
.code64
-ENTRY(stext)
-ENTRY(_stext)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/cdb.c
--- a/xen/arch/x86/cdb.c Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/cdb.c Fri Sep 9 16:30:54 2005
@@ -21,7 +21,7 @@
debugger. so avoid it. */
#define dbg_printk(...)
-static unsigned char opt_cdb[30] = "none";
+static char opt_cdb[30] = "none";
string_param("cdb", opt_cdb);
struct xendbg_context {
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/dom0_ops.c
--- a/xen/arch/x86/dom0_ops.c Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/dom0_ops.c Fri Sep 9 16:30:54 2005
@@ -19,6 +19,7 @@
#include <xen/console.h>
#include <asm/shadow.h>
#include <asm/irq.h>
+#include <asm/processor.h>
#include <public/sched_ctl.h>
#include <asm/mtrr.h>
@@ -188,9 +189,11 @@
pi->total_pages = max_page;
pi->free_pages = avail_domheap_pages();
pi->cpu_khz = cpu_khz;
-
- copy_to_user(u_dom0_op, op, sizeof(*op));
+ 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)) )
+ ret = -EINVAL;
}
break;
@@ -389,9 +392,31 @@
}
break;
+ case DOM0_PHYSICAL_MEMORY_MAP:
+ {
+ struct dom0_memory_map_entry entry;
+ int i;
+
+ for ( i = 0; i < e820.nr_map; i++ )
+ {
+ if ( i >= op->u.physical_memory_map.max_map_entries )
+ break;
+ 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));
+ }
+
+ op->u.physical_memory_map.nr_map_entries = i;
+ (void)copy_to_user(u_dom0_op, op, sizeof(*op));
+ }
+ break;
+
default:
ret = -ENOSYS;
-
+ break;
}
return ret;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/domain.c Fri Sep 9 16:30:54 2005
@@ -255,13 +255,13 @@
v->vcpu_info = &d->shared_info->vcpu_data[v->vcpu_id];
v->cpumap = CPUMAP_RUNANYWHERE;
SHARE_PFN_WITH_DOMAIN(virt_to_page(d->shared_info), d);
- machine_to_phys_mapping[virt_to_phys(d->shared_info) >>
- PAGE_SHIFT] = INVALID_M2P_ENTRY;
+ set_pfn_from_mfn(virt_to_phys(d->shared_info) >> PAGE_SHIFT,
+ INVALID_M2P_ENTRY);
d->arch.mm_perdomain_pt = alloc_xenheap_page();
memset(d->arch.mm_perdomain_pt, 0, PAGE_SIZE);
- machine_to_phys_mapping[virt_to_phys(d->arch.mm_perdomain_pt) >>
- PAGE_SHIFT] = INVALID_M2P_ENTRY;
+ set_pfn_from_mfn(virt_to_phys(d->arch.mm_perdomain_pt) >> PAGE_SHIFT,
+ INVALID_M2P_ENTRY);
v->arch.perdomain_ptes = d->arch.mm_perdomain_pt;
v->arch.perdomain_ptes[FIRST_RESERVED_GDT_PAGE] =
l1e_from_page(virt_to_page(gdt_table), PAGE_HYPERVISOR);
@@ -381,11 +381,13 @@
out:
free_vmcs(vmcs);
if(v->arch.arch_vmx.io_bitmap_a != 0) {
- free_xenheap_pages(v->arch.arch_vmx.io_bitmap_a, get_order(0x1000));
+ free_xenheap_pages(
+ v->arch.arch_vmx.io_bitmap_a, get_order_from_bytes(0x1000));
v->arch.arch_vmx.io_bitmap_a = 0;
}
if(v->arch.arch_vmx.io_bitmap_b != 0) {
- free_xenheap_pages(v->arch.arch_vmx.io_bitmap_b, get_order(0x1000));
+ free_xenheap_pages(
+ v->arch.arch_vmx.io_bitmap_b, get_order_from_bytes(0x1000));
v->arch.arch_vmx.io_bitmap_b = 0;
}
v->arch.arch_vmx.vmcs = 0;
@@ -885,8 +887,13 @@
return switch_required;
}
-void sync_lazy_execstate_cpu(unsigned int cpu)
-{
+void sync_vcpu_execstate(struct vcpu *v)
+{
+ unsigned int cpu = v->processor;
+
+ if ( !cpu_isset(cpu, v->domain->cpumask) )
+ return;
+
if ( cpu == smp_processor_id() )
{
(void)__sync_lazy_execstate();
@@ -967,11 +974,13 @@
BUG_ON(v->arch.arch_vmx.vmcs == NULL);
free_vmcs(v->arch.arch_vmx.vmcs);
if(v->arch.arch_vmx.io_bitmap_a != 0) {
- free_xenheap_pages(v->arch.arch_vmx.io_bitmap_a, get_order(0x1000));
+ free_xenheap_pages(
+ v->arch.arch_vmx.io_bitmap_a, get_order_from_bytes(0x1000));
v->arch.arch_vmx.io_bitmap_a = 0;
}
if(v->arch.arch_vmx.io_bitmap_b != 0) {
- free_xenheap_pages(v->arch.arch_vmx.io_bitmap_b, get_order(0x1000));
+ free_xenheap_pages(
+ v->arch.arch_vmx.io_bitmap_b, get_order_from_bytes(0x1000));
v->arch.arch_vmx.io_bitmap_b = 0;
}
v->arch.arch_vmx.vmcs = 0;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/domain_build.c
--- a/xen/arch/x86/domain_build.c Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/domain_build.c Fri Sep 9 16:30:54 2005
@@ -20,6 +20,7 @@
#include <asm/processor.h>
#include <asm/desc.h>
#include <asm/i387.h>
+#include <asm/physdev.h>
#include <asm/shadow.h>
static long dom0_nrpages;
@@ -74,15 +75,12 @@
struct pfn_info *page;
unsigned int order;
/*
- * Allocate up to 2MB at a time:
- * 1. This prevents overflow of get_order() when allocating more than
- * 4GB to domain 0 on a PAE machine.
- * 2. It prevents allocating very large chunks from DMA pools before
- * the >4GB pool is fully depleted.
+ * Allocate up to 2MB at a time: It prevents allocating very large chunks
+ * from DMA pools before the >4GB pool is fully depleted.
*/
if ( max_pages > (2UL << (20 - PAGE_SHIFT)) )
max_pages = 2UL << (20 - PAGE_SHIFT);
- order = get_order(max_pages << PAGE_SHIFT);
+ order = get_order_from_pages(max_pages);
if ( (max_pages & (max_pages-1)) != 0 )
order--;
while ( (page = alloc_domheap_pages(d, order, 0)) == NULL )
@@ -217,14 +215,14 @@
vinitrd_start = round_pgup(dsi.v_end);
vinitrd_end = vinitrd_start + initrd_len;
vphysmap_start = round_pgup(vinitrd_end);
- vphysmap_end = vphysmap_start + (nr_pages * sizeof(u32));
- vpt_start = round_pgup(vphysmap_end);
+ vphysmap_end = vphysmap_start + (nr_pages * sizeof(unsigned long));
+ vstartinfo_start = round_pgup(vphysmap_end);
+ vstartinfo_end = vstartinfo_start + PAGE_SIZE;
+ vpt_start = vstartinfo_end;
for ( nr_pt_pages = 2; ; nr_pt_pages++ )
{
vpt_end = vpt_start + (nr_pt_pages * PAGE_SIZE);
- vstartinfo_start = vpt_end;
- vstartinfo_end = vstartinfo_start + PAGE_SIZE;
- vstack_start = vstartinfo_end;
+ vstack_start = vpt_end;
vstack_end = vstack_start + PAGE_SIZE;
v_end = (vstack_end + (1UL<<22)-1) & ~((1UL<<22)-1);
if ( (v_end - vstack_end) < (512UL << 10) )
@@ -251,7 +249,7 @@
#endif
}
- order = get_order(v_end - dsi.v_start);
+ order = get_order_from_bytes(v_end - dsi.v_start);
if ( (1UL << order) > nr_pages )
panic("Domain 0 allocation is too small for kernel image.\n");
@@ -271,15 +269,15 @@
" Loaded kernel: %p->%p\n"
" Init. ramdisk: %p->%p\n"
" Phys-Mach map: %p->%p\n"
+ " Start info: %p->%p\n"
" Page tables: %p->%p\n"
- " Start info: %p->%p\n"
" Boot stack: %p->%p\n"
" TOTAL: %p->%p\n",
_p(dsi.v_kernstart), _p(dsi.v_kernend),
_p(vinitrd_start), _p(vinitrd_end),
_p(vphysmap_start), _p(vphysmap_end),
+ _p(vstartinfo_start), _p(vstartinfo_end),
_p(vpt_start), _p(vpt_end),
- _p(vstartinfo_start), _p(vstartinfo_end),
_p(vstack_start), _p(vstack_end),
_p(dsi.v_start), _p(v_end));
printk(" ENTRY ADDRESS: %p\n", _p(dsi.v_kernentry));
@@ -592,8 +590,7 @@
if ( opt_dom0_translate )
{
si->shared_info = d->next_io_page << PAGE_SHIFT;
- set_machinetophys(virt_to_phys(d->shared_info) >> PAGE_SHIFT,
- d->next_io_page);
+ set_pfn_from_mfn(virt_to_phys(d->shared_info) >> PAGE_SHIFT,
d->next_io_page);
d->next_io_page++;
}
else
@@ -613,8 +610,8 @@
if ( !opt_dom0_translate && (pfn > REVERSE_START) )
mfn = alloc_epfn - (pfn - REVERSE_START);
#endif
- ((u32 *)vphysmap_start)[pfn] = mfn;
- machine_to_phys_mapping[mfn] = pfn;
+ ((unsigned long *)vphysmap_start)[pfn] = mfn;
+ set_pfn_from_mfn(mfn, pfn);
}
while ( pfn < nr_pages )
{
@@ -626,8 +623,8 @@
#ifndef NDEBUG
#define pfn (nr_pages - 1 - (pfn - (alloc_epfn - alloc_spfn)))
#endif
- ((u32 *)vphysmap_start)[pfn] = mfn;
- machine_to_phys_mapping[mfn] = pfn;
+ ((unsigned long *)vphysmap_start)[pfn] = mfn;
+ set_pfn_from_mfn(mfn, pfn);
#undef pfn
page++; pfn++;
}
@@ -708,6 +705,18 @@
printk("dom0: shadow setup done\n");
}
+ /*
+ * Modify I/O port access permissions.
+ */
+ /* Master Interrupt Controller (PIC). */
+ physdev_modify_ioport_access_range(dom0, 0, 0x20, 2);
+ /* Slave Interrupt Controller (PIC). */
+ physdev_modify_ioport_access_range(dom0, 0, 0xA0, 2);
+ /* Interval Timer (PIT). */
+ physdev_modify_ioport_access_range(dom0, 0, 0x40, 4);
+ /* PIT Channel 2 / PC Speaker Control. */
+ physdev_modify_ioport_access_range(dom0, 0, 0x61, 1);
+
return 0;
}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/mm.c Fri Sep 9 16:30:54 2005
@@ -1450,9 +1450,9 @@
((type & PGT_type_mask) != PGT_l1_page_table) )
MEM_LOG("Bad type (saw %" PRtype_info
"!= exp %" PRtype_info ") "
- "for mfn %lx (pfn %x)",
+ "for mfn %lx (pfn %lx)",
x, type, page_to_pfn(page),
- machine_to_phys_mapping[page_to_pfn(page)]);
+ get_pfn_from_mfn(page_to_pfn(page)));
return 0;
}
else if ( (x & PGT_va_mask) == PGT_va_mutable )
@@ -2206,7 +2206,7 @@
printk("privileged guest dom%d requests pfn=%lx to "
"map mfn=%lx for dom%d\n",
d->domain_id, gpfn, mfn, FOREIGNDOM->domain_id);
- set_machinetophys(mfn, gpfn);
+ set_pfn_from_mfn(mfn, gpfn);
set_p2m_entry(FOREIGNDOM, gpfn, mfn, &sh_mapcache, &mapcache);
okay = 1;
shadow_unlock(FOREIGNDOM);
@@ -2225,7 +2225,7 @@
break;
}
- set_machinetophys(mfn, gpfn);
+ set_pfn_from_mfn(mfn, gpfn);
okay = 1;
/*
@@ -3185,7 +3185,7 @@
struct pfn_info *page;
l1_pgentry_t pte;
l2_pgentry_t *pl2e, l2e;
- int which;
+ int which, flags;
unsigned long l2_idx;
if ( unlikely(shadow_mode_enabled(d)) )
@@ -3206,8 +3206,24 @@
pfn = l1e_get_pfn(pte);
page = &frame_table[pfn];
+#ifdef CONFIG_X86_64
+#define WRPT_PTE_FLAGS (_PAGE_RW | _PAGE_PRESENT | _PAGE_USER)
+#else
+#define WRPT_PTE_FLAGS (_PAGE_RW | _PAGE_PRESENT)
+#endif
+
+ /*
+ * Check the required flags for a valid wrpt mapping. If the page is
+ * already writable then we can return straight to the guest (SMP race).
+ * We decide whether or not to propagate the fault by testing for write
+ * permissions in page directories by writing back to the linear mapping.
+ */
+ if ( (flags = l1e_get_flags(pte) & WRPT_PTE_FLAGS) == WRPT_PTE_FLAGS )
+ return !__put_user(
+ pte.l1, &linear_pg_table[l1_linear_offset(addr)].l1);
+
/* We are looking only for read-only mappings of p.t. pages. */
- if ( ((l1e_get_flags(pte) & (_PAGE_RW|_PAGE_PRESENT)) != _PAGE_PRESENT) ||
+ if ( ((flags | _PAGE_RW) != WRPT_PTE_FLAGS) ||
((page->u.inuse.type_info & PGT_type_mask) != PGT_l1_page_table) ||
((page->u.inuse.type_info & PGT_count_mask) == 0) ||
(page_get_owner(page) != d) )
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/setup.c Fri Sep 9 16:30:54 2005
@@ -12,6 +12,8 @@
#include <xen/trace.h>
#include <xen/multiboot.h>
#include <xen/domain_page.h>
+#include <xen/compile.h>
+#include <public/version.h>
#include <asm/bitops.h>
#include <asm/smp.h>
#include <asm/processor.h>
@@ -90,6 +92,8 @@
unsigned long mmu_cr4_features = X86_CR4_PSE;
#endif
EXPORT_SYMBOL(mmu_cr4_features);
+
+int hvm_enabled = 0; /* can we run unmodified guests */
struct vcpu *idle_task[NR_CPUS] = { &idle0_vcpu };
@@ -529,6 +533,45 @@
startup_cpu_idle_loop();
}
+void arch_get_xen_caps(xen_capabilities_info_t *info)
+{
+ char *p=info->caps;
+
+ *p=0;
+
+#ifdef CONFIG_X86_32
+
+#ifndef CONFIG_X86_PAE
+ p+=sprintf(p,"xen_%d.%d_x86_32 ",XEN_VERSION,XEN_SUBVERSION);
+ if(hvm_enabled)
+ {
+ p+=sprintf(p,"hvm_%d.%d_x86_32 ",XEN_VERSION,XEN_SUBVERSION);
+ }
+#else
+ p+=sprintf(p,"xen_%d.%d_x86_32p ",XEN_VERSION,XEN_SUBVERSION);
+ if(hvm_enabled)
+ {
+ //p+=sprintf(p,"hvm_%d.%d_x86_32 ",XEN_VERSION,XEN_SUBVERSION);
+ //p+=sprintf(p,"hvm_%d.%d_x86_32p ",XEN_VERSION,XEN_SUBVERSION);
+ }
+
+#endif
+
+#else /* !CONFIG_X86_32 */
+ p+=sprintf(p,"xen_%d.%d_x86_64 ",XEN_VERSION,XEN_SUBVERSION);
+ if(hvm_enabled)
+ {
+ //p+=sprintf(p,"hvm_%d.%d_x86_32 ",XEN_VERSION,XEN_SUBVERSION);
+ //p+=sprintf(p,"hvm_%d.%d_x86_32p ",XEN_VERSION,XEN_SUBVERSION);
+ p+=sprintf(p,"hvm_%d.%d_x86_64 ",XEN_VERSION,XEN_SUBVERSION);
+ }
+#endif
+
+ BUG_ON((p-info->caps)>sizeof(*info));
+
+ if(p>info->caps) *(p-1) = 0;
+}
+
/*
* Local variables:
* mode: C
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/shadow.c
--- a/xen/arch/x86/shadow.c Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/shadow.c Fri Sep 9 16:30:54 2005
@@ -53,6 +53,9 @@
struct domain *d, unsigned long gpfn, unsigned long gmfn);
static void shadow_map_into_current(struct vcpu *v,
unsigned long va, unsigned int from, unsigned int to);
+static inline void validate_bl2e_change( struct domain *d,
+ guest_root_pgentry_t *new_gle_p, pgentry_64_t *shadow_l3, int index);
+
#endif
/********
@@ -217,10 +220,38 @@
}
else
{
- page = alloc_domheap_page(NULL);
- void *l1 = map_domain_page(page_to_pfn(page));
- memset(l1, 0, PAGE_SIZE);
- unmap_domain_page(l1);
+ if (d->arch.ops->guest_paging_levels == PAGING_L2)
+ {
+#if CONFIG_PAGING_LEVELS >= 4
+ /* For 32-bit VMX guest, 2 shadow L1s to simulate 1 guest L1
+ * So need allocate 2 continues shadow L1 each time.
+ */
+ page = alloc_domheap_pages(NULL, SL1_ORDER, 0);
+ if (!page)
+ domain_crash_synchronous();
+
+ void *l1_0 = map_domain_page(page_to_pfn(page));
+ memset(l1_0,0,PAGE_SIZE);
+ unmap_domain_page(l1_0);
+ void *l1_1 = map_domain_page(page_to_pfn(page+1));
+ memset(l1_1,0,PAGE_SIZE);
+ unmap_domain_page(l1_1);
+#else
+ page = alloc_domheap_page(NULL);
+ if (!page)
+ domain_crash_synchronous();
+ void *l1 = map_domain_page(page_to_pfn(page));
+ memset(l1, 0, PAGE_SIZE);
+ unmap_domain_page(l1);
+#endif
+ }
+ else
+ {
+ page = alloc_domheap_page(NULL);
+ void *l1 = map_domain_page(page_to_pfn(page));
+ memset(l1, 0, PAGE_SIZE);
+ unmap_domain_page(l1);
+ }
}
}
else {
@@ -331,7 +362,21 @@
fail:
FSH_LOG("promotion of pfn=%lx mfn=%lx failed! external gnttab refs?",
gpfn, gmfn);
- free_domheap_page(page);
+ if (psh_type == PGT_l1_shadow)
+ {
+ if (d->arch.ops->guest_paging_levels == PAGING_L2)
+ {
+#if CONFIG_PAGING_LEVELS >=4
+ free_domheap_pages(page, SL1_ORDER);
+#else
+ free_domheap_page(page);
+#endif
+ }
+ else
+ free_domheap_page(page);
+ }
+ else
+ free_domheap_page(page);
return 0;
}
@@ -478,13 +523,15 @@
{
struct vcpu *v = current;
struct domain *d = v->domain;
- l1_pgentry_t *gpl1e, *spl1e;
- l2_pgentry_t gl2e, sl2e;
+ l1_pgentry_t *spl1e;
+ l2_pgentry_t sl2e;
+ guest_l1_pgentry_t *gpl1e;
+ guest_l2_pgentry_t gl2e;
unsigned long gl1pfn, gl1mfn, sl1mfn;
int i, init_table = 0;
__guest_get_l2e(v, va, &gl2e);
- ASSERT(l2e_get_flags(gl2e) & _PAGE_PRESENT);
+ ASSERT(guest_l2e_get_flags(gl2e) & _PAGE_PRESENT);
gl1pfn = l2e_get_pfn(gl2e);
if ( !(sl1mfn = __shadow_status(d, gl1pfn, PGT_l1_shadow)) )
@@ -523,28 +570,49 @@
ASSERT( !(l2e_get_flags(old_sl2e) & _PAGE_PRESENT) );
#endif
- if ( !get_shadow_ref(sl1mfn) )
- BUG();
- l2pde_general(d, &gl2e, &sl2e, sl1mfn);
- __guest_set_l2e(v, va, &gl2e);
- __shadow_set_l2e(v, va, &sl2e);
+#if CONFIG_PAGING_LEVELS >=4
+ if (d->arch.ops->guest_paging_levels == PAGING_L2)
+ {
+ /* for 32-bit VMX guest on 64-bit host,
+ * need update two L2 entries each time
+ */
+ if ( !get_shadow_ref(sl1mfn))
+ BUG();
+ l2pde_general(d, &gl2e, &sl2e, sl1mfn);
+ __guest_set_l2e(v, va, &gl2e);
+ __shadow_set_l2e(v, va & ~((1<<L2_PAGETABLE_SHIFT_32) - 1), &sl2e);
+ if ( !get_shadow_ref(sl1mfn+1))
+ BUG();
+ sl2e = l2e_empty();
+ l2pde_general(d, &gl2e, &sl2e, sl1mfn+1);
+ __shadow_set_l2e(v,((va & ~((1<<L2_PAGETABLE_SHIFT_32) - 1)) + (1 <<
L2_PAGETABLE_SHIFT)) , &sl2e);
+ } else
+#endif
+ {
+ if ( !get_shadow_ref(sl1mfn) )
+ BUG();
+ l2pde_general(d, &gl2e, &sl2e, sl1mfn);
+ __guest_set_l2e(v, va, &gl2e);
+ __shadow_set_l2e(v, va , &sl2e);
+ }
if ( init_table )
{
l1_pgentry_t sl1e;
- int index = l1_table_offset(va);
+ int index = guest_l1_table_offset(va);
int min = 1, max = 0;
unsigned long entries, pt_va;
l1_pgentry_t tmp_sl1e;
- l1_pgentry_t tmp_gl1e;//Prepare for double compile
-
-
- entries = PAGE_SIZE / sizeof(l1_pgentry_t);
+ guest_l1_pgentry_t tmp_gl1e;//Prepare for double compile
+
+
+ entries = PAGE_SIZE / sizeof(guest_l1_pgentry_t);
pt_va = ((va >> L1_PAGETABLE_SHIFT) & ~(entries - 1)) <<
L1_PAGETABLE_SHIFT;
- gpl1e = (l1_pgentry_t *) __guest_get_l1e(v, pt_va, &tmp_gl1e);
-
- entries = PAGE_SIZE / sizeof(l1_pgentry_t);
+ gpl1e = (guest_l1_pgentry_t *) __guest_get_l1e(v, pt_va, &tmp_gl1e);
+
+ /* If the PGT_l1_shadow has two continual pages */
+ entries = PAGE_SIZE / sizeof(guest_l1_pgentry_t); //1024 entry!!!
pt_va = ((va >> L1_PAGETABLE_SHIFT) & ~(entries - 1)) <<
L1_PAGETABLE_SHIFT;
spl1e = (l1_pgentry_t *) __shadow_get_l1e(v, pt_va, &tmp_sl1e);
@@ -555,7 +623,7 @@
spl1e = &(shadow_linear_pg_table[l1_linear_offset(va) &
~(L1_PAGETABLE_ENTRIES-1)]);*/
- for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
+ for ( i = 0; i < GUEST_L1_PAGETABLE_ENTRIES; i++ )
{
l1pte_propagate_from_guest(d, gpl1e[i], &sl1e);
if ( (l1e_get_flags(sl1e) & _PAGE_PRESENT) &&
@@ -584,7 +652,7 @@
}
}
-static void
+static void
shadow_set_l1e(unsigned long va, l1_pgentry_t new_spte, int create_l1_shadow)
{
struct vcpu *v = current;
@@ -616,7 +684,7 @@
perfc_incrc(shadow_set_l1e_unlinked);
if ( !get_shadow_ref(sl1mfn) )
BUG();
- l2pde_general(d, &gpde, &sl2e, sl1mfn);
+ l2pde_general(d, (guest_l2_pgentry_t *)&gpde, &sl2e, sl1mfn);
__guest_set_l2e(v, va, &gpde);
__shadow_set_l2e(v, va, &sl2e);
}
@@ -651,6 +719,7 @@
shadow_update_min_max(l2e_get_pfn(sl2e), l1_table_offset(va));
}
+#if CONFIG_PAGING_LEVELS <= 3
static void shadow_invlpg_32(struct vcpu *v, unsigned long va)
{
struct domain *d = v->domain;
@@ -671,6 +740,7 @@
sizeof(gpte))) {*/
if (unlikely(!__guest_get_l1e(v, va, &gpte))) {
perfc_incrc(shadow_invlpg_faults);
+ shadow_unlock(d);
return;
}
l1pte_propagate_from_guest(d, gpte, &spte);
@@ -678,6 +748,7 @@
shadow_unlock(d);
}
+#endif
static struct out_of_sync_entry *
shadow_alloc_oos_entry(struct domain *d)
@@ -758,8 +829,8 @@
length = max - min + 1;
perfc_incr_histo(snapshot_copies, length, PT_UPDATES);
- min *= sizeof(l1_pgentry_t);
- length *= sizeof(l1_pgentry_t);
+ min *= sizeof(guest_l1_pgentry_t);
+ length *= sizeof(guest_l1_pgentry_t);
original = map_domain_page(gmfn);
snapshot = map_domain_page(smfn);
@@ -840,7 +911,7 @@
__shadow_get_l4e(v, va, &sl4e);
if ( !(l4e_get_flags(sl4e) & _PAGE_PRESENT)) {
- shadow_map_into_current(v, va, L3, L4);
+ shadow_map_into_current(v, va, PAGING_L3, PAGING_L4);
}
if (!__shadow_get_l3e(v, va, &sl3e)) {
@@ -848,7 +919,7 @@
}
if ( !(l3e_get_flags(sl3e) & _PAGE_PRESENT)) {
- shadow_map_into_current(v, va, L2, L3);
+ shadow_map_into_current(v, va, PAGING_L2, PAGING_L3);
}
}
#endif
@@ -886,11 +957,11 @@
* Returns 0 otherwise.
*/
static int snapshot_entry_matches(
- struct domain *d, l1_pgentry_t *guest_pt,
+ struct domain *d, guest_l1_pgentry_t *guest_pt,
unsigned long gpfn, unsigned index)
{
unsigned long smfn = __shadow_status(d, gpfn, PGT_snapshot);
- l1_pgentry_t *snapshot, gpte; // could be L1s or L2s or ...
+ guest_l1_pgentry_t *snapshot, gpte; // could be L1s or L2s or ...
int entries_match;
perfc_incrc(snapshot_entry_matches_calls);
@@ -907,7 +978,7 @@
// This could probably be smarter, but this is sufficent for
// our current needs.
//
- entries_match = !l1e_has_changed(gpte, snapshot[index],
+ entries_match = !guest_l1e_has_changed(gpte, snapshot[index],
PAGE_FLAG_MASK);
unmap_domain_page(snapshot);
@@ -935,10 +1006,10 @@
unsigned long l2mfn = pagetable_get_pfn(v->arch.guest_table);
#endif
unsigned long l2pfn = __mfn_to_gpfn(d, l2mfn);
- l2_pgentry_t l2e;
+ guest_l2_pgentry_t l2e;
unsigned long l1pfn, l1mfn;
- l1_pgentry_t *guest_pt;
- l1_pgentry_t tmp_gle;
+ guest_l1_pgentry_t *guest_pt;
+ guest_l1_pgentry_t tmp_gle;
unsigned long pt_va;
ASSERT(shadow_lock_is_acquired(d));
@@ -947,7 +1018,7 @@
perfc_incrc(shadow_out_of_sync_calls);
#if CONFIG_PAGING_LEVELS >= 4
- if (d->arch.ops->guest_paging_levels == L4) { /* Mode F */
+ if (d->arch.ops->guest_paging_levels == PAGING_L4) { /* Mode F */
pgentry_64_t le;
unsigned long gmfn;
unsigned long gpfn;
@@ -955,9 +1026,9 @@
gmfn = l2mfn;
gpfn = l2pfn;
- guest_pt = (l1_pgentry_t *)v->arch.guest_vtable;
-
- for (i = L4; i >= L3; i--) {
+ guest_pt = (guest_l1_pgentry_t *)v->arch.guest_vtable;
+
+ for (i = PAGING_L4; i >= PAGING_L3; i--) {
if ( page_out_of_sync(&frame_table[gmfn]) &&
!snapshot_entry_matches(
d, guest_pt, gpfn, table_offset_64(va, i)) )
@@ -971,7 +1042,7 @@
if ( !VALID_MFN(gmfn) )
return 0;
/* Todo: check!*/
- guest_pt = (l1_pgentry_t *)map_domain_page(gmfn);
+ guest_pt = (guest_l1_pgentry_t *)map_domain_page(gmfn);
}
@@ -985,13 +1056,13 @@
#endif
if ( page_out_of_sync(&frame_table[l2mfn]) &&
- !snapshot_entry_matches(d, (l1_pgentry_t *)v->arch.guest_vtable,
- l2pfn, l2_table_offset(va)) )
+ !snapshot_entry_matches(d, (guest_l1_pgentry_t *)v->arch.guest_vtable,
+ l2pfn, guest_l2_table_offset(va)) )
return 1;
__guest_get_l2e(v, va, &l2e);
- if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) ||
- (l2e_get_flags(l2e) & _PAGE_PSE))
+ if ( !(guest_l2e_get_flags(l2e) & _PAGE_PRESENT) ||
+ (guest_l2e_get_flags(l2e) & _PAGE_PSE))
return 0;
l1pfn = l2e_get_pfn(l2e);
@@ -1000,20 +1071,20 @@
// If the l1 pfn is invalid, it can't be out of sync...
if ( !VALID_MFN(l1mfn) )
return 0;
-
- pt_va = ((va >> L1_PAGETABLE_SHIFT) & ~(L1_PAGETABLE_ENTRIES - 1))
+
+ pt_va = ((va >> L1_PAGETABLE_SHIFT) & ~(GUEST_L1_PAGETABLE_ENTRIES - 1))
<< L1_PAGETABLE_SHIFT;
- guest_pt = (l1_pgentry_t *) __guest_get_l1e(v, pt_va, &tmp_gle);
+ guest_pt = (guest_l1_pgentry_t *) __guest_get_l1e(v, pt_va, &tmp_gle);
if ( page_out_of_sync(&frame_table[l1mfn]) &&
!snapshot_entry_matches(
- d, guest_pt, l1pfn, l1_table_offset(va)) )
+ d, guest_pt, l1pfn, guest_l1_table_offset(va)) )
return 1;
return 0;
}
-#define GPFN_TO_GPTEPAGE(_gpfn) ((_gpfn) / (PAGE_SIZE / sizeof(l1_pgentry_t)))
+#define GPFN_TO_GPTEPAGE(_gpfn) ((_gpfn) / (PAGE_SIZE /
sizeof(guest_l1_pgentry_t)))
static inline unsigned long
predict_writable_pte_page(struct domain *d, unsigned long gpfn)
{
@@ -1107,7 +1178,7 @@
return (found == max_refs_to_find);
}
- i = readonly_gpfn & (L1_PAGETABLE_ENTRIES - 1);
+ i = readonly_gpfn & (GUEST_L1_PAGETABLE_ENTRIES - 1);
if ( !l1e_has_changed(pt[i], match, flags) && fix_entry(i) )
{
perfc_incrc(remove_write_fast_exit);
@@ -1116,7 +1187,7 @@
return found;
}
- for (i = 0; i < L1_PAGETABLE_ENTRIES; i++)
+ for (i = 0; i < GUEST_L1_PAGETABLE_ENTRIES; i++)
{
if ( unlikely(!l1e_has_changed(pt[i], match, flags)) && fix_entry(i) )
break;
@@ -1281,15 +1352,15 @@
switch ( stype ) {
case PGT_l1_shadow:
{
- l1_pgentry_t *guest1 = guest;
+ guest_l1_pgentry_t *guest1 = guest;
l1_pgentry_t *shadow1 = shadow;
- l1_pgentry_t *snapshot1 = snapshot;
+ guest_l1_pgentry_t *snapshot1 = snapshot;
ASSERT(VM_ASSIST(d, VMASST_TYPE_writable_pagetables) ||
shadow_mode_write_all(d));
if ( !shadow_mode_refcounts(d) )
- revalidate_l1(d, guest1, snapshot1);
+ revalidate_l1(d, (l1_pgentry_t *)guest1, (l1_pgentry_t
*)snapshot1);
if ( !smfn )
break;
@@ -1300,7 +1371,7 @@
for ( i = min_shadow; i <= max_shadow; i++ )
{
if ( (i < min_snapshot) || (i > max_snapshot) ||
- l1e_has_changed(guest1[i], snapshot1[i], PAGE_FLAG_MASK) )
+ guest_l1e_has_changed(guest1[i], snapshot1[i],
PAGE_FLAG_MASK) )
{
need_flush |= validate_pte_change(d, guest1[i],
&shadow1[i]);
@@ -1430,32 +1501,36 @@
{
int max = -1;
- l4_pgentry_t *guest4 = guest;
+ guest_root_pgentry_t *guest_root = guest;
l4_pgentry_t *shadow4 = shadow;
- l4_pgentry_t *snapshot4 = snapshot;
+ guest_root_pgentry_t *snapshot_root = snapshot;
changed = 0;
- for ( i = 0; i < L4_PAGETABLE_ENTRIES; i++ )
+ for ( i = 0; i < GUEST_ROOT_PAGETABLE_ENTRIES; i++ )
{
if ( !is_guest_l4_slot(i) && !external )
continue;
- l4_pgentry_t new_l4e = guest4[i];
- if ( l4e_has_changed(new_l4e, snapshot4[i], PAGE_FLAG_MASK))
+ guest_root_pgentry_t new_root_e = guest_root[i];
+ if ( root_entry_has_changed(
+ new_root_e, snapshot_root[i], PAGE_FLAG_MASK))
{
- need_flush |= validate_entry_change(
- d, (pgentry_64_t *)&new_l4e,
- (pgentry_64_t *)&shadow4[i],
shadow_type_to_level(stype));
-
+ if (d->arch.ops->guest_paging_levels == PAGING_L4) {
+ need_flush |= validate_entry_change(
+ d, (pgentry_64_t *)&new_root_e,
+ (pgentry_64_t *)&shadow4[i],
shadow_type_to_level(stype));
+ } else {
+ validate_bl2e_change(d, &new_root_e, shadow, i);
+ }
changed++;
ESH_LOG("%d: shadow4 mfn: %lx, shadow root: %lx\n", i,
smfn, pagetable_get_paddr(current->arch.shadow_table));
}
- if ( l4e_get_intpte(new_l4e) != 0 ) /* FIXME: check flags? */
+ if ( guest_root_get_intpte(new_root_e) != 0 ) /* FIXME: check
flags? */
max = i;
// Need a better solution in the long term.
- if ( !(l4e_get_flags(new_l4e) & _PAGE_PRESENT) &&
- unlikely(l4e_get_intpte(new_l4e) != 0) &&
+ if ( !(guest_root_get_flags(new_root_e) & _PAGE_PRESENT) &&
+ unlikely(guest_root_get_intpte(new_root_e) != 0) &&
!unshadow &&
(frame_table[smfn].u.inuse.type_info & PGT_pinned) )
unshadow = 1;
@@ -1554,8 +1629,14 @@
if ( shadow_mode_translate(d) )
need_flush |= resync_all(d, PGT_hl2_shadow);
#endif
- need_flush |= resync_all(d, PGT_l2_shadow);
- need_flush |= resync_all(d, PGT_l3_shadow);
+
+ /*
+ * Fixme: for i386 host
+ */
+ if (d->arch.ops->guest_paging_levels == PAGING_L4) {
+ need_flush |= resync_all(d, PGT_l2_shadow);
+ need_flush |= resync_all(d, PGT_l3_shadow);
+ }
need_flush |= resync_all(d, PGT_l4_shadow);
if ( need_flush && !unlikely(shadow_mode_external(d)) )
@@ -1565,11 +1646,11 @@
}
static inline int l1pte_write_fault(
- struct vcpu *v, l1_pgentry_t *gpte_p, l1_pgentry_t *spte_p,
+ struct vcpu *v, guest_l1_pgentry_t *gpte_p, l1_pgentry_t *spte_p,
unsigned long va)
{
struct domain *d = v->domain;
- l1_pgentry_t gpte = *gpte_p;
+ guest_l1_pgentry_t gpte = *gpte_p;
l1_pgentry_t spte;
unsigned long gpfn = l1e_get_pfn(gpte);
unsigned long gmfn = __gpfn_to_mfn(d, gpfn);
@@ -1583,9 +1664,9 @@
return 0;
}
- ASSERT(l1e_get_flags(gpte) & _PAGE_RW);
- l1e_add_flags(gpte, _PAGE_DIRTY | _PAGE_ACCESSED);
- spte = l1e_from_pfn(gmfn, l1e_get_flags(gpte) & ~_PAGE_GLOBAL);
+ ASSERT(guest_l1e_get_flags(gpte) & _PAGE_RW);
+ guest_l1e_add_flags(gpte, _PAGE_DIRTY | _PAGE_ACCESSED);
+ spte = l1e_from_pfn(gmfn, guest_l1e_get_flags(gpte) & ~_PAGE_GLOBAL);
SH_VVLOG("l1pte_write_fault: updating spte=0x%" PRIpte " gpte=0x%" PRIpte,
l1e_get_intpte(spte), l1e_get_intpte(gpte));
@@ -1603,9 +1684,9 @@
}
static inline int l1pte_read_fault(
- struct domain *d, l1_pgentry_t *gpte_p, l1_pgentry_t *spte_p)
+ struct domain *d, guest_l1_pgentry_t *gpte_p, l1_pgentry_t *spte_p)
{
- l1_pgentry_t gpte = *gpte_p;
+ guest_l1_pgentry_t gpte = *gpte_p;
l1_pgentry_t spte = *spte_p;
unsigned long pfn = l1e_get_pfn(gpte);
unsigned long mfn = __gpfn_to_mfn(d, pfn);
@@ -1617,10 +1698,10 @@
return 0;
}
- l1e_add_flags(gpte, _PAGE_ACCESSED);
- spte = l1e_from_pfn(mfn, l1e_get_flags(gpte) & ~_PAGE_GLOBAL);
-
- if ( shadow_mode_log_dirty(d) || !(l1e_get_flags(gpte) & _PAGE_DIRTY) ||
+ guest_l1e_add_flags(gpte, _PAGE_ACCESSED);
+ spte = l1e_from_pfn(mfn, guest_l1e_get_flags(gpte) & ~_PAGE_GLOBAL);
+
+ if ( shadow_mode_log_dirty(d) || !(guest_l1e_get_flags(gpte) &
_PAGE_DIRTY) ||
mfn_is_page_table(mfn) )
{
l1e_remove_flags(spte, _PAGE_RW);
@@ -1633,7 +1714,7 @@
return 1;
}
-
+#if CONFIG_PAGING_LEVELS <= 3
static int shadow_fault_32(unsigned long va, struct cpu_user_regs *regs)
{
l1_pgentry_t gpte, spte, orig_gpte;
@@ -1767,6 +1848,7 @@
shadow_unlock(d);
return 0;
}
+#endif
static int do_update_va_mapping(unsigned long va,
l1_pgentry_t val,
@@ -1786,7 +1868,7 @@
//
__shadow_sync_va(v, va);
- l1pte_propagate_from_guest(d, val, &spte);
+ l1pte_propagate_from_guest(d, *(guest_l1_pgentry_t *)&val, &spte);
shadow_set_l1e(va, spte, 0);
/*
@@ -1847,7 +1929,7 @@
#if CONFIG_PAGING_LEVELS == 2
unsigned long hl2mfn;
#endif
-
+
int max_mode = ( shadow_mode_external(d) ? SHM_external
: shadow_mode_translate(d) ? SHM_translate
: shadow_mode_enabled(d) ? SHM_enable
@@ -1953,17 +2035,6 @@
#endif
}
-struct shadow_ops MODE_A_HANDLER = {
- .guest_paging_levels = 2,
- .invlpg = shadow_invlpg_32,
- .fault = shadow_fault_32,
- .update_pagetables = shadow_update_pagetables,
- .sync_all = sync_all,
- .remove_all_write_access = remove_all_write_access,
- .do_update_va_mapping = do_update_va_mapping,
- .mark_mfn_out_of_sync = mark_mfn_out_of_sync,
- .is_out_of_sync = is_out_of_sync,
-};
/************************************************************************/
/************************************************************************/
@@ -2444,12 +2515,90 @@
BUG(); /* not implemenated yet */
return 42;
}
+static unsigned long gva_to_gpa_pae(unsigned long gva)
+{
+ BUG();
+ return 43;
+}
#endif
#if CONFIG_PAGING_LEVELS >= 4
/****************************************************************************/
/* 64-bit shadow-mode code testing */
/****************************************************************************/
+/*
+ * validate_bl2e_change()
+ * The code is for 32-bit VMX gues on 64-bit host.
+ * To sync guest L2.
+ */
+
+static inline void
+validate_bl2e_change(
+ struct domain *d,
+ guest_root_pgentry_t *new_gle_p,
+ pgentry_64_t *shadow_l3,
+ int index)
+{
+ int sl3_idx, sl2_idx;
+ unsigned long sl2mfn, sl1mfn;
+ pgentry_64_t *sl2_p;
+
+ /* Using guest l2 pte index to get shadow l3&l2 index
+ * index: 0 ~ 1023, PAGETABLE_ENTRIES: 512
+ */
+ sl3_idx = index / (PAGETABLE_ENTRIES / 2);
+ sl2_idx = (index % (PAGETABLE_ENTRIES / 2)) * 2;
+
+ sl2mfn = entry_get_pfn(shadow_l3[sl3_idx]);
+ sl2_p = (pgentry_64_t *)map_domain_page(sl2mfn);
+
+ validate_pde_change(
+ d, *(guest_l2_pgentry_t *)new_gle_p, (l2_pgentry_t *)&sl2_p[sl2_idx]);
+
+ /* Mapping the second l1 shadow page */
+ if (entry_get_flags(sl2_p[sl2_idx]) & _PAGE_PRESENT) {
+ sl1mfn = entry_get_pfn(sl2_p[sl2_idx]);
+ sl2_p[sl2_idx + 1] =
+ entry_from_pfn(sl1mfn + 1, entry_get_flags(sl2_p[sl2_idx]));
+ }
+ unmap_domain_page(sl2_p);
+
+}
+
+/*
+ * init_bl2() is for 32-bit VMX guest on 64-bit host
+ * Using 1 shadow L4(l3) and 4 shadow L2s to simulate guest L2
+ */
+static inline unsigned long init_bl2(l4_pgentry_t *spl4e, unsigned long smfn)
+{
+ unsigned int count;
+ unsigned long sl2mfn;
+ struct pfn_info *page;
+
+ memset(spl4e, 0, PAGE_SIZE);
+
+ /* Map the self entry, L4&L3 share the same page */
+ spl4e[PAE_SHADOW_SELF_ENTRY] = l4e_from_pfn(smfn, __PAGE_HYPERVISOR);
+
+ /* Allocate 4 shadow L2s */
+ page = alloc_domheap_pages(NULL, SL2_ORDER, 0);
+ if (!page)
+ domain_crash_synchronous();
+
+ for (count = 0; count < PDP_ENTRIES; count++)
+ {
+ sl2mfn = page_to_pfn(page+count);
+ void *l2 = map_domain_page(sl2mfn);
+ memset(l2, 0, PAGE_SIZE);
+ unmap_domain_page(l2);
+ spl4e[count] = l4e_from_pfn(sl2mfn, _PAGE_PRESENT);
+ }
+
+ unmap_domain_page(spl4e);
+ return smfn;
+
+
+}
static unsigned long shadow_l4_table(
struct domain *d, unsigned long gpfn, unsigned long gmfn)
@@ -2463,11 +2612,16 @@
if ( unlikely(!(smfn = alloc_shadow_page(d, gpfn, gmfn, PGT_l4_shadow))) )
{
- printk("Couldn't alloc an L2 shadow for pfn=%lx mfn=%lx\n", gpfn,
gmfn);
+ printk("Couldn't alloc an L4 shadow for pfn=%lx mfn=%lx\n", gpfn,
gmfn);
BUG(); /* XXX Deal gracefully with failure. */
}
spl4e = (l4_pgentry_t *)map_domain_page(smfn);
+
+ if (d->arch.ops->guest_paging_levels == PAGING_L2) {
+ return init_bl2(spl4e, smfn);
+ }
+
/* Install hypervisor and 4x linear p.t. mapings. */
if ( (PGT_base_page_table == PGT_l4_page_table) &&
!shadow_mode_external(d) )
@@ -2575,7 +2729,7 @@
pgentry_64_t gle, sle;
unsigned long gpfn, smfn;
- if (from == L1 && to == L2) {
+ if (from == PAGING_L1 && to == PAGING_L2) {
shadow_map_l1_into_current_l2(va);
return;
}
@@ -2607,7 +2761,7 @@
if (!(l4e_get_flags(sl4e) & _PAGE_PRESENT)) {
if (create_l2_shadow) {
perfc_incrc(shadow_set_l3e_force_map);
- shadow_map_into_current(v, va, L3, L4);
+ shadow_map_into_current(v, va, PAGING_L3, PAGING_L4);
__shadow_get_l4e(v, va, &sl4e);
} else {
printk("For non VMX shadow, create_l1_shadow:%d\n",
create_l2_shadow);
@@ -2618,7 +2772,7 @@
if (!(l3e_get_flags(sl3e) & _PAGE_PRESENT)) {
if (create_l2_shadow) {
perfc_incrc(shadow_set_l2e_force_map);
- shadow_map_into_current(v, va, L2, L3);
+ shadow_map_into_current(v, va, PAGING_L2, PAGING_L3);
__shadow_get_l3e(v, va, &sl3e);
} else {
printk("For non VMX shadow, create_l1_shadow:%d\n",
create_l2_shadow);
@@ -2654,8 +2808,15 @@
l1_pgentry_t old_spte;
l1_pgentry_t sl1e = *(l1_pgentry_t *)sl1e_p;
int i;
-
- for (i = L4; i >= L2; i--) {
+ unsigned long orig_va = 0;
+
+ if (d->arch.ops->guest_paging_levels == PAGING_L2) {
+ /* This is for 32-bit VMX guest on 64-bit host */
+ orig_va = va;
+ va = va & (~((1<<L2_PAGETABLE_SHIFT_32)-1));
+ }
+
+ for (i = PAGING_L4; i >= PAGING_L2; i--) {
if (!__rw_entry(v, va, &sle, SHADOW_ENTRY | GET_ENTRY | i)) {
printk("<%s> i = %d\n", __func__, i);
BUG();
@@ -2671,9 +2832,13 @@
#endif
}
}
- if(i < L4)
+ if(i < PAGING_L4)
shadow_update_min_max(entry_get_pfn(sle_up), table_offset_64(va,
i));
sle_up = sle;
+ }
+
+ if (d->arch.ops->guest_paging_levels == PAGING_L2) {
+ va = orig_va;
}
if ( shadow_mode_refcounts(d) )
@@ -2691,9 +2856,13 @@
}
__shadow_set_l1e(v, va, &sl1e);
- shadow_update_min_max(entry_get_pfn(sle_up), table_offset_64(va, L1));
-}
-
+
+ shadow_update_min_max(entry_get_pfn(sle_up), guest_l1_table_offset(va));
+}
+
+/* As 32-bit guest don't support 4M page yet,
+ * we don't concern double compile for this function
+ */
static inline int l2e_rw_fault(
struct vcpu *v, l2_pgentry_t *gl2e_p, unsigned long va, int rw)
{
@@ -2824,12 +2993,120 @@
}
+/*
+ * Check P, R/W, U/S bits in the guest page table.
+ * If the fault belongs to guest return 1,
+ * else return 0.
+ */
+#if defined( GUEST_PGENTRY_32 )
+static inline int guest_page_fault(struct vcpu *v,
+ unsigned long va, unsigned int error_code,
+ guest_l2_pgentry_t *gpl2e, guest_l1_pgentry_t *gpl1e)
+{
+ /* The following check for 32-bit guest on 64-bit host */
+
+ __guest_get_l2e(v, va, gpl2e);
+
+ /* Check the guest L2 page-table entry first*/
+ if (unlikely(!(guest_l2e_get_flags(*gpl2e) & _PAGE_PRESENT)))
+ return 1;
+
+ if (error_code & ERROR_W) {
+ if (unlikely(!(guest_l2e_get_flags(*gpl2e) & _PAGE_RW)))
+ return 1;
+ }
+ if (error_code & ERROR_U) {
+ if (unlikely(!(guest_l2e_get_flags(*gpl2e) & _PAGE_USER)))
+ return 1;
+ }
+
+ if (guest_l2e_get_flags(*gpl2e) & _PAGE_PSE)
+ return 0;
+
+ __guest_get_l1e(v, va, gpl1e);
+
+ /* Then check the guest L1 page-table entry */
+ if (unlikely(!(guest_l1e_get_flags(*gpl1e) & _PAGE_PRESENT)))
+ return 1;
+
+ if (error_code & ERROR_W) {
+ if (unlikely(!(guest_l1e_get_flags(*gpl1e) & _PAGE_RW)))
+ return 1;
+ }
+ if (error_code & ERROR_U) {
+ if (unlikely(!(guest_l1e_get_flags(*gpl1e) & _PAGE_USER)))
+ return 1;
+ }
+
+ return 0;
+}
+#else
+static inline int guest_page_fault(struct vcpu *v,
+ unsigned long va, unsigned int error_code,
+ guest_l2_pgentry_t *gpl2e, guest_l1_pgentry_t *gpl1e)
+{
+ struct domain *d = v->domain;
+ pgentry_64_t gle, *lva;
+ unsigned long mfn;
+ int i;
+
+ __rw_entry(v, va, &gle, GUEST_ENTRY | GET_ENTRY | PAGING_L4);
+ if (unlikely(!(entry_get_flags(gle) & _PAGE_PRESENT)))
+ return 1;
+
+ if (error_code & ERROR_W) {
+ if (unlikely(!(entry_get_flags(gle) & _PAGE_RW)))
+ return 1;
+ }
+ if (error_code & ERROR_U) {
+ if (unlikely(!(entry_get_flags(gle) & _PAGE_USER)))
+ return 1;
+ }
+ for (i = PAGING_L3; i >= PAGING_L1; i--) {
+ /*
+ * If it's not external mode, then mfn should be machine physical.
+ */
+ mfn = __gpfn_to_mfn(d, (entry_get_value(gle) >> PAGE_SHIFT));
+
+ lva = (pgentry_64_t *) phys_to_virt(
+ mfn << PAGE_SHIFT);
+ gle = lva[table_offset_64(va, i)];
+
+ if (unlikely(!(entry_get_flags(gle) & _PAGE_PRESENT)))
+ return 1;
+
+ if (error_code & ERROR_W) {
+ if (unlikely(!(entry_get_flags(gle) & _PAGE_RW)))
+ return 1;
+ }
+ if (error_code & ERROR_U) {
+ if (unlikely(!(entry_get_flags(gle) & _PAGE_USER)))
+ return 1;
+ }
+
+ if (i == PAGING_L2) {
+ if (gpl2e)
+ gpl2e->l2 = gle.lo;
+
+ if (likely(entry_get_flags(gle) & _PAGE_PSE))
+ return 0;
+
+ }
+
+ if (i == PAGING_L1)
+ if (gpl1e)
+ gpl1e->l1 = gle.lo;
+ }
+ return 0;
+}
+#endif
static int shadow_fault_64(unsigned long va, struct cpu_user_regs *regs)
{
struct vcpu *v = current;
struct domain *d = v->domain;
- l2_pgentry_t gl2e;
- l1_pgentry_t sl1e, gl1e;
+ guest_l2_pgentry_t gl2e;
+ guest_l1_pgentry_t gl1e;
+ l1_pgentry_t sl1e;
perfc_incrc(shadow_fault_calls);
@@ -2852,12 +3129,11 @@
* STEP 2. Check if the fault belongs to guest
*/
if ( guest_page_fault(
- v, va, regs->error_code,
- (pgentry_64_t *)&gl2e, (pgentry_64_t *)&gl1e) ) {
+ v, va, regs->error_code, &gl2e, &gl1e) ) {
goto fail;
}
- if ( unlikely(!(l2e_get_flags(gl2e) & _PAGE_PSE)) ) {
+ if ( unlikely(!(guest_l2e_get_flags(gl2e) & _PAGE_PSE)) ) {
/*
* Handle 4K pages here
*/
@@ -2891,11 +3167,11 @@
*/
/* Write fault? */
if ( regs->error_code & 2 ) {
- if ( !l2e_rw_fault(v, &gl2e, va, WRITE_FAULT) ) {
+ if ( !l2e_rw_fault(v, (l2_pgentry_t *)&gl2e, va, WRITE_FAULT) ) {
goto fail;
}
} else {
- l2e_rw_fault(v, &gl2e, va, READ_FAULT);
+ l2e_rw_fault(v, (l2_pgentry_t *)&gl2e, va, READ_FAULT);
}
/*
@@ -2943,7 +3219,27 @@
shadow_unlock(d);
}
-#ifndef PGENTRY_32
+static unsigned long gva_to_gpa_64(unsigned long gva)
+{
+ struct vcpu *v = current;
+ guest_l1_pgentry_t gl1e = {0};
+ guest_l2_pgentry_t gl2e = {0};
+ unsigned long gpa;
+
+ if (guest_page_fault(v, gva, 0, &gl2e, &gl1e))
+ return 0;
+
+ if (guest_l2e_get_flags(gl2e) & _PAGE_PSE)
+ gpa = guest_l2e_get_paddr(gl2e) + (gva & ((1 <<
GUEST_L2_PAGETABLE_SHIFT) - 1));
+ else
+ gpa = guest_l1e_get_paddr(gl1e) + (gva & ~PAGE_MASK);
+
+ return gpa;
+
+}
+
+#ifndef GUEST_PGENTRY_32
+
struct shadow_ops MODE_F_HANDLER = {
.guest_paging_levels = 4,
.invlpg = shadow_invlpg_64,
@@ -2954,10 +3250,42 @@
.do_update_va_mapping = do_update_va_mapping,
.mark_mfn_out_of_sync = mark_mfn_out_of_sync,
.is_out_of_sync = is_out_of_sync,
+ .gva_to_gpa = gva_to_gpa_64,
};
#endif
#endif
+
+#if CONFIG_PAGING_LEVELS == 2
+struct shadow_ops MODE_A_HANDLER = {
+ .guest_paging_levels = 2,
+ .invlpg = shadow_invlpg_32,
+ .fault = shadow_fault_32,
+ .update_pagetables = shadow_update_pagetables,
+ .sync_all = sync_all,
+ .remove_all_write_access = remove_all_write_access,
+ .do_update_va_mapping = do_update_va_mapping,
+ .mark_mfn_out_of_sync = mark_mfn_out_of_sync,
+ .is_out_of_sync = is_out_of_sync,
+ .gva_to_gpa = gva_to_gpa_64,
+};
+
+#elif CONFIG_PAGING_LEVELS == 3
+struct shadow_ops MODE_B_HANDLER = {
+ .guest_paging_levels = 3,
+ .invlpg = shadow_invlpg_32,
+ .fault = shadow_fault_32,
+ .update_pagetables = shadow_update_pagetables,
+ .sync_all = sync_all,
+ .remove_all_write_access = remove_all_write_access,
+ .do_update_va_mapping = do_update_va_mapping,
+ .mark_mfn_out_of_sync = mark_mfn_out_of_sync,
+ .is_out_of_sync = is_out_of_sync,
+ .gva_to_gpa = gva_to_gpa_pae,
+};
+
+#endif
+
/*
* Local variables:
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/shadow32.c
--- a/xen/arch/x86/shadow32.c Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/shadow32.c Fri Sep 9 16:30:54 2005
@@ -827,7 +827,7 @@
{
page = list_entry(list_ent, struct pfn_info, list);
mfn = page_to_pfn(page);
- pfn = machine_to_phys_mapping[mfn];
+ pfn = get_pfn_from_mfn(mfn);
ASSERT(pfn != INVALID_M2P_ENTRY);
ASSERT(pfn < (1u<<20));
@@ -841,7 +841,7 @@
{
page = list_entry(list_ent, struct pfn_info, list);
mfn = page_to_pfn(page);
- pfn = machine_to_phys_mapping[mfn];
+ pfn = get_pfn_from_mfn(mfn);
if ( (pfn != INVALID_M2P_ENTRY) &&
(pfn < (1u<<20)) )
{
@@ -1685,6 +1685,7 @@
if (__copy_from_user(&gpte, &linear_pg_table[va >> PAGE_SHIFT],
sizeof(gpte))) {
perfc_incrc(shadow_invlpg_faults);
+ shadow_unlock(d);
return;
}
l1pte_propagate_from_guest(d, gpte, &spte);
@@ -1917,8 +1918,10 @@
snapshot = map_domain_page(smfn);
if (__copy_from_user(&gpte, &guest_pt[index],
- sizeof(gpte)))
+ sizeof(gpte))) {
+ unmap_domain_page(snapshot);
return 0;
+ }
// This could probably be smarter, but this is sufficent for
// our current needs.
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/shadow_public.c
--- a/xen/arch/x86/shadow_public.c Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/shadow_public.c Fri Sep 9 16:30:54 2005
@@ -33,11 +33,15 @@
#if CONFIG_PAGING_LEVELS >= 3
#include <asm/shadow_64.h>
+#endif
+#if CONFIG_PAGING_LEVELS == 4
extern struct shadow_ops MODE_F_HANDLER;
+extern struct shadow_ops MODE_D_HANDLER;
#endif
extern struct shadow_ops MODE_A_HANDLER;
+#define SHADOW_MAX_GUEST32(_encoded) ((L1_PAGETABLE_ENTRIES_32 - 1) -
((_encoded) >> 16))
/****************************************************************************/
/************* export interface functions ***********************************/
/****************************************************************************/
@@ -48,7 +52,7 @@
shadow_lock(d);
switch(levels) {
-#if CONFIG_PAGING_LEVELS >= 4
+#if CONFIG_PAGING_LEVELS >= 4
case 4:
if ( d->arch.ops != &MODE_F_HANDLER )
d->arch.ops = &MODE_F_HANDLER;
@@ -56,9 +60,14 @@
return 1;
#endif
case 3:
- case 2:
+ case 2:
+#if CONFIG_PAGING_LEVELS == 2
if ( d->arch.ops != &MODE_A_HANDLER )
d->arch.ops = &MODE_A_HANDLER;
+#elif CONFIG_PAGING_LEVELS == 4
+ if ( d->arch.ops != &MODE_D_HANDLER )
+ d->arch.ops = &MODE_D_HANDLER;
+#endif
shadow_unlock(d);
return 1;
default:
@@ -122,13 +131,17 @@
return d->arch.ops->is_out_of_sync(v, va);
}
+unsigned long gva_to_gpa(unsigned long gva)
+{
+ struct domain *d = current->domain;
+ return d->arch.ops->gva_to_gpa(gva);
+}
/****************************************************************************/
/****************************************************************************/
#if CONFIG_PAGING_LEVELS >= 4
/*
* Convert PAE 3-level page-table to 4-level page-table
*/
-#define PDP_ENTRIES 4
static pagetable_t page_table_convert(struct domain *d)
{
struct pfn_info *l4page, *l3page;
@@ -203,19 +216,41 @@
/*
* Free l2, l3, l4 shadow tables
*/
+
+void free_fake_shadow_l2(struct domain *d,unsigned long smfn);
+
static void inline
free_shadow_tables(struct domain *d, unsigned long smfn, u32 level)
{
pgentry_64_t *ple = map_domain_page(smfn);
int i, external = shadow_mode_external(d);
-
- for ( i = 0; i < PAGETABLE_ENTRIES; i++ )
- if ( external || is_guest_l4_slot(i) )
- if ( entry_get_flags(ple[i]) & _PAGE_PRESENT )
- put_shadow_ref(entry_get_pfn(ple[i]));
-
- unmap_domain_page(ple);
-}
+ struct pfn_info *page = &frame_table[smfn];
+
+ if (d->arch.ops->guest_paging_levels == PAGING_L2)
+ {
+#if CONFIG_PAGING_LEVELS >=4
+ for ( i = 0; i < PDP_ENTRIES; i++ )
+ {
+ if (entry_get_flags(ple[i]) & _PAGE_PRESENT )
+ free_fake_shadow_l2(d,entry_get_pfn(ple[i]));
+ }
+
+ page = &frame_table[entry_get_pfn(ple[0])];
+ free_domheap_pages(page, SL2_ORDER);
+ unmap_domain_page(ple);
+#endif
+ }
+ else
+ {
+ for ( i = 0; i < PAGETABLE_ENTRIES; i++ )
+ if ( external || is_guest_l4_slot(i) )
+ if ( entry_get_flags(ple[i]) & _PAGE_PRESENT )
+ put_shadow_ref(entry_get_pfn(ple[i]));
+
+ unmap_domain_page(ple);
+ }
+}
+
void free_monitor_pagetable(struct vcpu *v)
{
@@ -453,7 +488,12 @@
struct pfn_info *spage = pfn_to_page(smfn);
u32 min_max = spage->tlbflush_timestamp;
int min = SHADOW_MIN(min_max);
- int max = SHADOW_MAX(min_max);
+ int max;
+
+ if (d->arch.ops->guest_paging_levels == PAGING_L2)
+ max = SHADOW_MAX_GUEST32(min_max);
+ else
+ max = SHADOW_MAX(min_max);
for ( i = min; i <= max; i++ )
{
@@ -512,9 +552,24 @@
unmap_domain_page(pl2e);
}
+void free_fake_shadow_l2(struct domain *d, unsigned long smfn)
+{
+ pgentry_64_t *ple = map_domain_page(smfn);
+ int i;
+
+ for ( i = 0; i < PAGETABLE_ENTRIES; i = i + 2 )
+ {
+ if ( entry_get_flags(ple[i]) & _PAGE_PRESENT )
+ put_shadow_ref(entry_get_pfn(ple[i]));
+ }
+
+ unmap_domain_page(ple);
+}
+
void free_shadow_page(unsigned long smfn)
{
struct pfn_info *page = &frame_table[smfn];
+
unsigned long gmfn = page->u.inuse.type_info & PGT_mfn_mask;
struct domain *d = page_get_owner(pfn_to_page(gmfn));
unsigned long gpfn = __mfn_to_gpfn(d, gmfn);
@@ -531,6 +586,7 @@
gpfn |= (1UL << 63);
}
#endif
+
delete_shadow_status(d, gpfn, gmfn, type);
switch ( type )
@@ -687,7 +743,7 @@
int i;
struct shadow_status *x;
struct vcpu *v;
-
+
/*
* WARNING! The shadow page table must not currently be in use!
* e.g., You are expected to have paused the domain and synchronized CR3.
@@ -794,7 +850,16 @@
perfc_decr(free_l1_pages);
struct pfn_info *page = list_entry(list_ent, struct pfn_info, list);
- free_domheap_page(page);
+ if (d->arch.ops->guest_paging_levels == PAGING_L2)
+ {
+#if CONFIG_PAGING_LEVELS >=4
+ free_domheap_pages(page, SL1_ORDER);
+#else
+ free_domheap_page(page);
+#endif
+ }
+ else
+ free_domheap_page(page);
}
shadow_audit(d, 0);
@@ -1191,7 +1256,7 @@
{
DPRINTK("Don't try to do a shadow op on yourself!\n");
return -EINVAL;
- }
+ }
domain_pause(d);
@@ -1311,7 +1376,7 @@
{
page = list_entry(list_ent, struct pfn_info, list);
mfn = page_to_pfn(page);
- pfn = machine_to_phys_mapping[mfn];
+ pfn = get_pfn_from_mfn(mfn);
ASSERT(pfn != INVALID_M2P_ENTRY);
ASSERT(pfn < (1u<<20));
@@ -1325,7 +1390,7 @@
{
page = list_entry(list_ent, struct pfn_info, list);
mfn = page_to_pfn(page);
- pfn = machine_to_phys_mapping[mfn];
+ pfn = get_pfn_from_mfn(mfn);
if ( (pfn != INVALID_M2P_ENTRY) &&
(pfn < (1u<<20)) )
{
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/time.c
--- a/xen/arch/x86/time.c Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/time.c Fri Sep 9 16:30:54 2005
@@ -792,6 +792,13 @@
tsc_elapsed64 = curr_tsc - prev_tsc;
/*
+ * Weirdness can happen if we lose sync with the platform timer.
+ * We could be smarter here: resync platform timer with local timer?
+ */
+ if ( ((s64)stime_elapsed64 < (EPOCH / 2)) )
+ goto out;
+
+ /*
* Calculate error-correction factor. This only slows down a fast local
* clock (slow clocks are warped forwards). The scale factor is clamped
* to >= 0.5.
@@ -854,6 +861,7 @@
cpu_time[cpu].stime_local_stamp = curr_local_stime;
cpu_time[cpu].stime_master_stamp = curr_master_stime;
+ out:
set_ac_timer(&cpu_time[cpu].calibration_timer, NOW() + EPOCH);
if ( cpu == 0 )
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/traps.c Fri Sep 9 16:30:54 2005
@@ -101,6 +101,14 @@
static int debug_stack_lines = 20;
integer_param("debug_stack_lines", debug_stack_lines);
+#ifdef CONFIG_X86_32
+#define stack_words_per_line 8
+#define ESP_BEFORE_EXCEPTION(regs) ((unsigned long *)®s->esp)
+#else
+#define stack_words_per_line 4
+#define ESP_BEFORE_EXCEPTION(regs) ((unsigned long *)regs->esp)
+#endif
+
int is_kernel_text(unsigned long addr)
{
extern char _stext, _etext;
@@ -117,17 +125,16 @@
return (unsigned long) &_etext;
}
-void show_guest_stack(void)
+static void show_guest_stack(struct cpu_user_regs *regs)
{
int i;
- struct cpu_user_regs *regs = guest_cpu_user_regs();
unsigned long *stack = (unsigned long *)regs->esp, addr;
printk("Guest stack trace from "__OP"sp=%p:\n ", stack);
- for ( i = 0; i < (debug_stack_lines*8); i++ )
- {
- if ( ((long)stack & (STACK_SIZE-1)) == 0 )
+ for ( i = 0; i < (debug_stack_lines*stack_words_per_line); i++ )
+ {
+ if ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) == 0 )
break;
if ( get_user(addr, stack) )
{
@@ -137,7 +144,7 @@
i = 1;
break;
}
- if ( (i != 0) && ((i % 8) == 0) )
+ if ( (i != 0) && ((i % stack_words_per_line) == 0) )
printk("\n ");
printk("%p ", _p(addr));
stack++;
@@ -147,40 +154,100 @@
printk("\n");
}
-void show_trace(unsigned long *esp)
-{
- unsigned long *stack = esp, addr;
- int i = 0;
-
- printk("Xen call trace from "__OP"sp=%p:\n ", stack);
-
- while ( ((long) stack & (STACK_SIZE-1)) != 0 )
+#ifdef NDEBUG
+
+static void show_trace(struct cpu_user_regs *regs)
+{
+ unsigned long *stack = ESP_BEFORE_EXCEPTION(regs), addr;
+
+ printk("Xen call trace:\n ");
+
+ printk("[<%p>]", _p(regs->eip));
+ print_symbol(" %s\n ", regs->eip);
+
+ while ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) != 0 )
{
addr = *stack++;
if ( is_kernel_text(addr) )
{
printk("[<%p>]", _p(addr));
print_symbol(" %s\n ", addr);
- i++;
- }
- }
- if ( i == 0 )
- printk("Trace empty.");
+ }
+ }
+
printk("\n");
}
-void show_stack(unsigned long *esp)
-{
- unsigned long *stack = esp, addr;
+#else
+
+static void show_trace(struct cpu_user_regs *regs)
+{
+ unsigned long *frame, next, addr, low, high;
+
+ printk("Xen call trace:\n ");
+
+ printk("[<%p>]", _p(regs->eip));
+ print_symbol(" %s\n ", regs->eip);
+
+ /* Bounds for range of valid frame pointer. */
+ low = (unsigned long)(ESP_BEFORE_EXCEPTION(regs) - 2);
+ high = (low & ~(STACK_SIZE - 1)) + (STACK_SIZE - sizeof(struct cpu_info));
+
+ /* The initial frame pointer. */
+ next = regs->ebp;
+
+ for ( ; ; )
+ {
+ /* Valid frame pointer? */
+ if ( (next < low) || (next > high) )
+ {
+ /*
+ * Exception stack frames have a different layout, denoted by an
+ * inverted frame pointer.
+ */
+ next = ~next;
+ if ( (next < low) || (next > high) )
+ break;
+ frame = (unsigned long *)next;
+ next = frame[0];
+ addr = frame[(offsetof(struct cpu_user_regs, eip) -
+ offsetof(struct cpu_user_regs, ebp))
+ / BYTES_PER_LONG];
+ }
+ else
+ {
+ /* Ordinary stack frame. */
+ frame = (unsigned long *)next;
+ next = frame[0];
+ addr = frame[1];
+ }
+
+ printk("[<%p>]", _p(addr));
+ print_symbol(" %s\n ", addr);
+
+ low = (unsigned long)&frame[2];
+ }
+
+ printk("\n");
+}
+
+#endif
+
+void show_stack(struct cpu_user_regs *regs)
+{
+ unsigned long *stack = ESP_BEFORE_EXCEPTION(regs), addr;
int i;
+ if ( GUEST_MODE(regs) )
+ return show_guest_stack(regs);
+
printk("Xen stack trace from "__OP"sp=%p:\n ", stack);
- for ( i = 0; i < (debug_stack_lines*8); i++ )
- {
- if ( ((long)stack & (STACK_SIZE-1)) == 0 )
- break;
- if ( (i != 0) && ((i % 8) == 0) )
+ for ( i = 0; i < (debug_stack_lines*stack_words_per_line); i++ )
+ {
+ if ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) == 0 )
+ break;
+ if ( (i != 0) && ((i % stack_words_per_line) == 0) )
printk("\n ");
addr = *stack++;
printk("%p ", _p(addr));
@@ -189,7 +256,7 @@
printk("Stack empty.");
printk("\n");
- show_trace(esp);
+ show_trace(regs);
}
/*
@@ -403,20 +470,32 @@
return EXCRET_fault_fixed;
}
-asmlinkage int do_page_fault(struct cpu_user_regs *regs)
-{
- unsigned long addr, fixup;
- struct vcpu *v = current;
+#ifdef HYPERVISOR_VIRT_END
+#define IN_HYPERVISOR_RANGE(va) \
+ (((va) >= HYPERVISOR_VIRT_START) && ((va) < HYPERVISOR_VIRT_END))
+#else
+#define IN_HYPERVISOR_RANGE(va) \
+ (((va) >= HYPERVISOR_VIRT_START))
+#endif
+
+static int fixup_page_fault(unsigned long addr, struct cpu_user_regs *regs)
+{
+ struct vcpu *v = current;
struct domain *d = v->domain;
- __asm__ __volatile__ ("mov %%cr2,%0" : "=r" (addr) : );
-
- DEBUGGER_trap_entry(TRAP_page_fault, regs);
-
- perfc_incrc(page_faults);
-
- if ( likely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables) &&
- !shadow_mode_enabled(d)) )
+ if ( unlikely(IN_HYPERVISOR_RANGE(addr)) )
+ {
+ if ( shadow_mode_external(d) && GUEST_CONTEXT(v, regs) )
+ return shadow_fault(addr, regs);
+ if ( (addr >= PERDOMAIN_VIRT_START) && (addr < PERDOMAIN_VIRT_END) )
+ return handle_perdomain_mapping_fault(
+ addr - PERDOMAIN_VIRT_START, regs);
+ }
+ else if ( unlikely(shadow_mode_enabled(d)) )
+ {
+ return shadow_fault(addr, regs);
+ }
+ else if ( likely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables)) )
{
LOCK_BIGLOCK(d);
if ( unlikely(d->arch.ptwr[PTWR_PT_ACTIVE].l1va) &&
@@ -428,14 +507,9 @@
return EXCRET_fault_fixed;
}
- if ( ((addr < HYPERVISOR_VIRT_START)
-#if defined(__x86_64__)
- || (addr >= HYPERVISOR_VIRT_END)
-#endif
- )
- &&
- KERNEL_MODE(v, regs) &&
- ((regs->error_code & 3) == 3) && /* write-protection fault */
+ if ( KERNEL_MODE(v, regs) &&
+ /* Protection violation on write? No reserved-bit violation? */
+ ((regs->error_code & 0xb) == 0x3) &&
ptwr_do_page_fault(d, addr, regs) )
{
UNLOCK_BIGLOCK(d);
@@ -444,43 +518,51 @@
UNLOCK_BIGLOCK(d);
}
- if ( unlikely(shadow_mode_enabled(d)) &&
- ((addr < HYPERVISOR_VIRT_START) ||
-#if defined(__x86_64__)
- (addr >= HYPERVISOR_VIRT_END) ||
-#endif
- (shadow_mode_external(d) && GUEST_CONTEXT(v, regs))) &&
- shadow_fault(addr, regs) )
- return EXCRET_fault_fixed;
-
- if ( unlikely(addr >= PERDOMAIN_VIRT_START) &&
- unlikely(addr < PERDOMAIN_VIRT_END) &&
- handle_perdomain_mapping_fault(addr - PERDOMAIN_VIRT_START, regs) )
- return EXCRET_fault_fixed;
-
- if ( !GUEST_MODE(regs) )
- goto xen_fault;
+ return 0;
+}
+
+/*
+ * #PF error code:
+ * Bit 0: Protection violation (=1) ; Page not present (=0)
+ * Bit 1: Write access
+ * Bit 2: Supervisor mode
+ * Bit 3: Reserved bit violation
+ * Bit 4: Instruction fetch
+ */
+asmlinkage int do_page_fault(struct cpu_user_regs *regs)
+{
+ unsigned long addr, fixup;
+ int rc;
+
+ __asm__ __volatile__ ("mov %%cr2,%0" : "=r" (addr) : );
+
+ DEBUGGER_trap_entry(TRAP_page_fault, regs);
+
+ perfc_incrc(page_faults);
+
+ if ( unlikely((rc = fixup_page_fault(addr, regs)) != 0) )
+ return rc;
+
+ if ( unlikely(!GUEST_MODE(regs)) )
+ {
+ if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
+ {
+ perfc_incrc(copy_user_faults);
+ regs->eip = fixup;
+ return 0;
+ }
+
+ DEBUGGER_trap_fatal(TRAP_page_fault, regs);
+
+ show_registers(regs);
+ show_page_walk(addr);
+ panic("CPU%d FATAL PAGE FAULT\n"
+ "[error_code=%04x]\n"
+ "Faulting linear address: %p\n",
+ smp_processor_id(), regs->error_code, addr);
+ }
propagate_page_fault(addr, regs->error_code);
- return 0;
-
- xen_fault:
-
- if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
- {
- perfc_incrc(copy_user_faults);
- regs->eip = fixup;
- return 0;
- }
-
- DEBUGGER_trap_fatal(TRAP_page_fault, regs);
-
- show_registers(regs);
- show_page_walk(addr);
- panic("CPU%d FATAL PAGE FAULT\n"
- "[error_code=%04x]\n"
- "Faulting linear address: %p\n",
- smp_processor_id(), regs->error_code, addr);
return 0;
}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/vmx.c
--- a/xen/arch/x86/vmx.c Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/vmx.c Fri Sep 9 16:30:54 2005
@@ -49,6 +49,15 @@
int vmcs_size;
unsigned int opt_vmx_debug_level = 0;
integer_param("vmx_debug", opt_vmx_debug_level);
+
+extern int hvm_enabled;
+
+#ifdef TRACE_BUFFER
+static unsigned long trace_values[NR_CPUS][4];
+#define TRACE_VMEXIT(index,value) trace_values[current->processor][index]=value
+#else
+#define TRACE_VMEXIT(index,value) ((void)0)
+#endif
#ifdef __x86_64__
static struct msr_state percpu_msr[NR_CPUS];
@@ -338,6 +347,8 @@
vmx_save_init_msrs();
+ hvm_enabled = 1;
+
return 1;
}
@@ -351,7 +362,7 @@
* Not all cases receive valid value in the VM-exit instruction length field.
*/
#define __get_instruction_length(len) \
- __vmread(INSTRUCTION_LEN, &(len)); \
+ __vmread(VM_EXIT_INSTRUCTION_LEN, &(len)); \
if ((len) < 1 || (len) > 15) \
__vmx_bug(®s);
@@ -381,6 +392,7 @@
if (!vmx_paging_enabled(current)){
handle_mmio(va, va);
+ TRACE_VMEXIT (2,2);
return 1;
}
gpa = gva_to_gpa(va);
@@ -389,21 +401,22 @@
if ( mmio_space(gpa) ){
if (gpa >= 0xFEE00000) { /* workaround for local APIC */
u32 inst_len;
- __vmread(INSTRUCTION_LEN, &(inst_len));
+ __vmread(VM_EXIT_INSTRUCTION_LEN, &(inst_len));
__update_guest_eip(inst_len);
return 1;
}
+ TRACE_VMEXIT (2,2);
handle_mmio(va, gpa);
return 1;
}
result = shadow_fault(va, regs);
-
+ TRACE_VMEXIT (2,result);
#if 0
if ( !result )
{
__vmread(GUEST_RIP, &eip);
- printk("vmx pgfault to guest va=%p eip=%p\n", va, eip);
+ printk("vmx pgfault to guest va=%lx eip=%lx\n", va, eip);
}
#endif
@@ -447,7 +460,16 @@
clear_bit(X86_FEATURE_PSE, &edx);
clear_bit(X86_FEATURE_PAE, &edx);
clear_bit(X86_FEATURE_PSE36, &edx);
+#else
+ struct vcpu *d = current;
+ if (d->domain->arch.ops->guest_paging_levels == PAGING_L2)
+ {
+ clear_bit(X86_FEATURE_PSE, &edx);
+ clear_bit(X86_FEATURE_PAE, &edx);
+ clear_bit(X86_FEATURE_PSE36, &edx);
+ }
#endif
+
}
regs->eax = (unsigned long) eax;
@@ -542,7 +564,7 @@
int i, inst_len;
int inst_copy_from_guest(unsigned char *, unsigned long, int);
- __vmread(INSTRUCTION_LEN, &inst_len);
+ __vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len);
memset(inst, 0, MAX_INST_LEN);
if (inst_copy_from_guest(inst, eip, inst_len) != inst_len) {
printf("check_for_null_selector: get guest instruction failed\n");
@@ -584,15 +606,66 @@
return 0;
}
+void send_pio_req(struct cpu_user_regs *regs, unsigned long port,
+ unsigned long count, int size, long value, int dir, int pvalid)
+{
+ struct vcpu *v = current;
+ vcpu_iodata_t *vio;
+ ioreq_t *p;
+
+ vio = get_vio(v->domain, v->vcpu_id);
+ if (vio == NULL) {
+ printk("bad shared page: %lx\n", (unsigned long) vio);
+ domain_crash_synchronous();
+ }
+
+ if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) {
+ printf("VMX I/O has not yet completed\n");
+ domain_crash_synchronous();
+ }
+ set_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags);
+
+ p = &vio->vp_ioreq;
+ p->dir = dir;
+ p->pdata_valid = pvalid;
+
+ p->type = IOREQ_TYPE_PIO;
+ p->size = size;
+ p->addr = port;
+ p->count = count;
+ p->df = regs->eflags & EF_DF ? 1 : 0;
+
+ if (pvalid) {
+ if (vmx_paging_enabled(current))
+ p->u.pdata = (void *) gva_to_gpa(value);
+ else
+ p->u.pdata = (void *) value; /* guest VA == guest PA */
+ } else
+ p->u.data = value;
+
+ p->state = STATE_IOREQ_READY;
+
+ if (vmx_portio_intercept(p)) {
+ /* no blocking & no evtchn notification */
+ clear_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags);
+ return;
+ }
+
+ evtchn_send(iopacket_port(v->domain));
+ vmx_wait_io();
+}
+
static void vmx_io_instruction(struct cpu_user_regs *regs,
unsigned long exit_qualification, unsigned long inst_len)
{
- struct vcpu *d = current;
- vcpu_iodata_t *vio;
- ioreq_t *p;
- unsigned long addr;
+ struct mi_per_cpu_info *mpcip;
unsigned long eip, cs, eflags;
+ unsigned long port, size, dir;
int vm86;
+
+ mpcip = ¤t->domain->arch.vmx_platform.mpci;
+ mpcip->instr = INSTR_PIO;
+ mpcip->flags = 0;
__vmread(GUEST_RIP, &eip);
__vmread(GUEST_CS_SELECTOR, &cs);
@@ -605,104 +678,93 @@
vm86, cs, eip, exit_qualification);
if (test_bit(6, &exit_qualification))
- addr = (exit_qualification >> 16) & (0xffff);
+ port = (exit_qualification >> 16) & 0xFFFF;
else
- addr = regs->edx & 0xffff;
-
- vio = get_vio(d->domain, d->vcpu_id);
- if (vio == 0) {
- printk("bad shared page: %lx", (unsigned long) vio);
- domain_crash_synchronous();
- }
- p = &vio->vp_ioreq;
- p->dir = test_bit(3, &exit_qualification); /* direction */
-
- p->pdata_valid = 0;
- p->count = 1;
- p->size = (exit_qualification & 7) + 1;
+ port = regs->edx & 0xffff;
+ TRACE_VMEXIT(2, port);
+ size = (exit_qualification & 7) + 1;
+ dir = test_bit(3, &exit_qualification); /* direction */
if (test_bit(4, &exit_qualification)) { /* string instruction */
- unsigned long laddr;
-
- __vmread(GUEST_LINEAR_ADDRESS, &laddr);
+ unsigned long addr, count = 1;
+ int sign = regs->eflags & EF_DF ? -1 : 1;
+
+ __vmread(GUEST_LINEAR_ADDRESS, &addr);
+
/*
* In protected mode, guest linear address is invalid if the
* selector is null.
*/
- if (!vm86 && check_for_null_selector(eip)) {
- laddr = (p->dir == IOREQ_WRITE) ? regs->esi : regs->edi;
- }
- p->pdata_valid = 1;
-
- p->u.data = laddr;
- if (vmx_paging_enabled(d))
- p->u.pdata = (void *) gva_to_gpa(p->u.data);
- p->df = (eflags & X86_EFLAGS_DF) ? 1 : 0;
-
- if (test_bit(5, &exit_qualification)) /* "rep" prefix */
- p->count = vm86 ? regs->ecx & 0xFFFF : regs->ecx;
-
- /*
- * Split up string I/O operations that cross page boundaries. Don't
- * advance %eip so that "rep insb" will restart at the next page.
- */
- if ((p->u.data & PAGE_MASK) !=
- ((p->u.data + p->count * p->size - 1) & PAGE_MASK)) {
- VMX_DBG_LOG(DBG_LEVEL_2,
- "String I/O crosses page boundary (cs:eip=0x%lx:0x%lx)\n",
- cs, eip);
- if (p->u.data & (p->size - 1)) {
- printf("Unaligned string I/O operation (cs:eip=0x%lx:0x%lx)\n",
- cs, eip);
- domain_crash_synchronous();
- }
- p->count = (PAGE_SIZE - (p->u.data & ~PAGE_MASK)) / p->size;
- } else {
- __update_guest_eip(inst_len);
- }
- } else if (p->dir == IOREQ_WRITE) {
- p->u.data = regs->eax;
+ if (!vm86 && check_for_null_selector(eip))
+ addr = dir == IOREQ_WRITE ? regs->esi : regs->edi;
+
+ if (test_bit(5, &exit_qualification)) { /* "rep" prefix */
+ mpcip->flags |= REPZ;
+ count = vm86 ? regs->ecx & 0xFFFF : regs->ecx;
+ }
+
+ /*
+ * Handle string pio instructions that cross pages or that
+ * are unaligned. See the comments in vmx_platform.c/handle_mmio()
+ */
+ if ((addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK)) {
+ unsigned long value = 0;
+
+ mpcip->flags |= OVERLAP;
+ if (dir == IOREQ_WRITE)
+ vmx_copy(&value, addr, size, VMX_COPY_IN);
+ send_pio_req(regs, port, 1, size, value, dir, 0);
+ } else {
+ if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK)) {
+ if (sign > 0)
+ count = (PAGE_SIZE - (addr & ~PAGE_MASK)) / size;
+ else
+ count = (addr & ~PAGE_MASK) / size;
+ } else
+ __update_guest_eip(inst_len);
+
+ send_pio_req(regs, port, count, size, addr, dir, 1);
+ }
+ } else {
__update_guest_eip(inst_len);
- } else
- __update_guest_eip(inst_len);
-
- p->addr = addr;
- p->port_mm = 0;
-
- /* Check if the packet needs to be intercepted */
- if (vmx_portio_intercept(p))
- /* no blocking & no evtchn notification */
- return;
-
- set_bit(ARCH_VMX_IO_WAIT, &d->arch.arch_vmx.flags);
- p->state = STATE_IOREQ_READY;
- evtchn_send(iopacket_port(d->domain));
- vmx_wait_io();
-}
-
-enum { COPY_IN = 0, COPY_OUT };
-
-static inline int
+ send_pio_req(regs, port, 1, size, regs->eax, dir, 0);
+ }
+}
+
+int
vmx_copy(void *buf, unsigned long laddr, int size, int dir)
{
+ unsigned long gpa, mfn;
char *addr;
- unsigned long mfn;
-
- if ( (size + (laddr & (PAGE_SIZE - 1))) >= PAGE_SIZE )
- {
- printf("vmx_copy exceeds page boundary\n");
- return 0;
- }
-
- mfn = phys_to_machine_mapping(laddr >> PAGE_SHIFT);
- addr = (char *)map_domain_page(mfn) + (laddr & ~PAGE_MASK);
-
- if (dir == COPY_IN)
- memcpy(buf, addr, size);
- else
- memcpy(addr, buf, size);
-
- unmap_domain_page(addr);
+ int count;
+
+ while (size > 0) {
+ count = PAGE_SIZE - (laddr & ~PAGE_MASK);
+ if (count > size)
+ count = size;
+
+ if (vmx_paging_enabled(current)) {
+ gpa = gva_to_gpa(laddr);
+ mfn = get_mfn_from_pfn(gpa >> PAGE_SHIFT);
+ } else
+ mfn = get_mfn_from_pfn(laddr >> PAGE_SHIFT);
+ if (mfn == INVALID_MFN)
+ return 0;
+
+ addr = (char *)map_domain_page(mfn) + (laddr & ~PAGE_MASK);
+
+ if (dir == VMX_COPY_IN)
+ memcpy(buf, addr, count);
+ else
+ memcpy(addr, buf, count);
+
+ unmap_domain_page(addr);
+
+ laddr += count;
+ buf += count;
+ size -= count;
+ }
+
return 1;
}
@@ -712,7 +774,7 @@
unsigned long inst_len;
int error = 0;
- error |= __vmread(INSTRUCTION_LEN, &inst_len);
+ error |= __vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len);
error |= __vmread(GUEST_RIP, &c->eip);
c->eip += inst_len; /* skip transition instruction */
error |= __vmread(GUEST_RSP, &c->esp);
@@ -795,7 +857,7 @@
* removed some translation or changed page attributes.
* We simply invalidate the shadow.
*/
- mfn = phys_to_machine_mapping(c->cr3 >> PAGE_SHIFT);
+ mfn = get_mfn_from_pfn(c->cr3 >> PAGE_SHIFT);
if (mfn != pagetable_get_pfn(d->arch.guest_table)) {
printk("Invalid CR3 value=%x", c->cr3);
domain_crash_synchronous();
@@ -813,7 +875,7 @@
domain_crash_synchronous();
return 0;
}
- mfn = phys_to_machine_mapping(c->cr3 >> PAGE_SHIFT);
+ mfn = get_mfn_from_pfn(c->cr3 >> PAGE_SHIFT);
d->arch.guest_table = mk_pagetable(mfn << PAGE_SHIFT);
update_pagetables(d);
/*
@@ -889,7 +951,7 @@
u32 cp;
/* make sure vmxassist exists (this is not an error) */
- if (!vmx_copy(&magic, VMXASSIST_MAGIC_OFFSET, sizeof(magic), COPY_IN))
+ if (!vmx_copy(&magic, VMXASSIST_MAGIC_OFFSET, sizeof(magic), VMX_COPY_IN))
return 0;
if (magic != VMXASSIST_MAGIC)
return 0;
@@ -903,20 +965,20 @@
*/
case VMX_ASSIST_INVOKE:
/* save the old context */
- if (!vmx_copy(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp), COPY_IN))
+ if (!vmx_copy(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp), VMX_COPY_IN))
goto error;
if (cp != 0) {
if (!vmx_world_save(d, &c))
goto error;
- if (!vmx_copy(&c, cp, sizeof(c), COPY_OUT))
+ if (!vmx_copy(&c, cp, sizeof(c), VMX_COPY_OUT))
goto error;
}
/* restore the new context, this should activate vmxassist */
- if (!vmx_copy(&cp, VMXASSIST_NEW_CONTEXT, sizeof(cp), COPY_IN))
+ if (!vmx_copy(&cp, VMXASSIST_NEW_CONTEXT, sizeof(cp), VMX_COPY_IN))
goto error;
if (cp != 0) {
- if (!vmx_copy(&c, cp, sizeof(c), COPY_IN))
+ if (!vmx_copy(&c, cp, sizeof(c), VMX_COPY_IN))
goto error;
if (!vmx_world_restore(d, &c))
goto error;
@@ -930,10 +992,10 @@
*/
case VMX_ASSIST_RESTORE:
/* save the old context */
- if (!vmx_copy(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp), COPY_IN))
+ if (!vmx_copy(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp), VMX_COPY_IN))
goto error;
if (cp != 0) {
- if (!vmx_copy(&c, cp, sizeof(c), COPY_IN))
+ if (!vmx_copy(&c, cp, sizeof(c), VMX_COPY_IN))
goto error;
if (!vmx_world_restore(d, &c))
goto error;
@@ -968,7 +1030,7 @@
/*
* The guest CR3 must be pointing to the guest physical.
*/
- if ( !VALID_MFN(mfn = phys_to_machine_mapping(
+ if ( !VALID_MFN(mfn = get_mfn_from_pfn(
d->arch.arch_vmx.cpu_cr3 >> PAGE_SHIFT)) ||
!get_page(pfn_to_page(mfn), d->domain) )
{
@@ -996,6 +1058,15 @@
#if CONFIG_PAGING_LEVELS >= 4
if(!shadow_set_guest_paging_levels(d->domain, 4)) {
+ printk("Unsupported guest paging levels\n");
+ domain_crash_synchronous(); /* need to take a clean path */
+ }
+#endif
+ }
+ else
+ {
+#if CONFIG_PAGING_LEVELS >= 4
+ if(!shadow_set_guest_paging_levels(d->domain, 2)) {
printk("Unsupported guest paging levels\n");
domain_crash_synchronous(); /* need to take a clean path */
}
@@ -1164,7 +1235,7 @@
* removed some translation or changed page attributes.
* We simply invalidate the shadow.
*/
- mfn = phys_to_machine_mapping(value >> PAGE_SHIFT);
+ mfn = get_mfn_from_pfn(value >> PAGE_SHIFT);
if (mfn != pagetable_get_pfn(d->arch.guest_table))
__vmx_bug(regs);
shadow_sync_all(d->domain);
@@ -1175,7 +1246,7 @@
*/
VMX_DBG_LOG(DBG_LEVEL_VMMU, "CR3 value = %lx", value);
if ( ((value >> PAGE_SHIFT) > d->domain->max_pages ) ||
- !VALID_MFN(mfn = phys_to_machine_mapping(value >>
PAGE_SHIFT)) ||
+ !VALID_MFN(mfn = get_mfn_from_pfn(value >> PAGE_SHIFT)) ||
!get_page(pfn_to_page(mfn), d->domain) )
{
printk("Invalid CR3 value=%lx", value);
@@ -1282,13 +1353,20 @@
case TYPE_MOV_TO_CR:
gp = exit_qualification & CONTROL_REG_ACCESS_REG;
cr = exit_qualification & CONTROL_REG_ACCESS_NUM;
+ TRACE_VMEXIT(1,TYPE_MOV_TO_CR);
+ TRACE_VMEXIT(2,cr);
+ TRACE_VMEXIT(3,gp);
return mov_to_cr(gp, cr, regs);
case TYPE_MOV_FROM_CR:
gp = exit_qualification & CONTROL_REG_ACCESS_REG;
cr = exit_qualification & CONTROL_REG_ACCESS_NUM;
+ TRACE_VMEXIT(1,TYPE_MOV_FROM_CR);
+ TRACE_VMEXIT(2,cr);
+ TRACE_VMEXIT(3,gp);
mov_from_cr(cr, gp, regs);
break;
case TYPE_CLTS:
+ TRACE_VMEXIT(1,TYPE_CLTS);
clts();
setup_fpu(current);
@@ -1301,6 +1379,7 @@
__vmwrite(CR0_READ_SHADOW, value);
break;
case TYPE_LMSW:
+ TRACE_VMEXIT(1,TYPE_LMSW);
__vmread(CR0_READ_SHADOW, &value);
value = (value & ~0xF) |
(((exit_qualification & LMSW_SOURCE_DATA) >> 16) & 0xF);
@@ -1518,15 +1597,18 @@
__vmread(IDT_VECTORING_INFO_FIELD, &idtv_info_field);
if (idtv_info_field & INTR_INFO_VALID_MASK) {
- if ((idtv_info_field & 0x0700) != 0x400) { /* exclude soft ints */
- __vmwrite(VM_ENTRY_INTR_INFO_FIELD, idtv_info_field);
-
- if (idtv_info_field & 0x800) { /* valid error code */
- unsigned long error_code;
- __vmread(VM_EXIT_INTR_ERROR_CODE, &error_code);
- __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
- }
- }
+ __vmwrite(VM_ENTRY_INTR_INFO_FIELD, idtv_info_field);
+
+ __vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len);
+ if (inst_len >= 1 && inst_len <= 15)
+ __vmwrite(VM_ENTRY_INSTRUCTION_LEN, inst_len);
+
+ if (idtv_info_field & 0x800) { /* valid error code */
+ unsigned long error_code;
+ __vmread(IDT_VECTORING_ERROR_CODE, &error_code);
+ __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
+ }
+
VMX_DBG_LOG(DBG_LEVEL_1, "idtv_info_field=%x", idtv_info_field);
}
@@ -1544,6 +1626,7 @@
__vmread(GUEST_RIP, &eip);
TRACE_3D(TRC_VMX_VMEXIT, v->domain->domain_id, eip, exit_reason);
+ TRACE_VMEXIT(0,exit_reason);
switch (exit_reason) {
case EXIT_REASON_EXCEPTION_NMI:
@@ -1562,6 +1645,7 @@
__vmx_bug(®s);
vector &= 0xff;
+ TRACE_VMEXIT(1,vector);
perfc_incra(cause_vector, vector);
TRACE_3D(TRC_VMX_VECTOR, v->domain->domain_id, eip, vector);
@@ -1606,6 +1690,10 @@
{
__vmread(EXIT_QUALIFICATION, &va);
__vmread(VM_EXIT_INTR_ERROR_CODE, ®s.error_code);
+
+ TRACE_VMEXIT(3,regs.error_code);
+ TRACE_VMEXIT(4,va);
+
VMX_DBG_LOG(DBG_LEVEL_VMMU,
"eax=%lx, ebx=%lx, ecx=%lx, edx=%lx, esi=%lx, edi=%lx",
(unsigned long)regs.eax, (unsigned long)regs.ebx,
@@ -1680,6 +1768,8 @@
eip, inst_len, exit_qualification);
if (vmx_cr_access(exit_qualification, ®s))
__update_guest_eip(inst_len);
+ TRACE_VMEXIT(3,regs.error_code);
+ TRACE_VMEXIT(4,exit_qualification);
break;
}
case EXIT_REASON_DR_ACCESS:
@@ -1692,6 +1782,7 @@
__vmread(EXIT_QUALIFICATION, &exit_qualification);
__get_instruction_length(inst_len);
vmx_io_instruction(®s, exit_qualification, inst_len);
+ TRACE_VMEXIT(4,exit_qualification);
break;
case EXIT_REASON_MSR_READ:
__get_instruction_length(inst_len);
@@ -1726,6 +1817,25 @@
#endif
}
+#ifdef TRACE_BUFFER
+asmlinkage void trace_vmentry (void)
+{
+ TRACE_5D(TRC_VMENTRY,trace_values[current->processor][0],
+
trace_values[current->processor][1],trace_values[current->processor][2],
+
trace_values[current->processor][3],trace_values[current->processor][4]);
+ TRACE_VMEXIT(0,9);
+ TRACE_VMEXIT(1,9);
+ TRACE_VMEXIT(2,9);
+ TRACE_VMEXIT(3,9);
+ TRACE_VMEXIT(4,9);
+ return;
+}
+asmlinkage void trace_vmexit (void)
+{
+ TRACE_3D(TRC_VMEXIT,0,0,0);
+ return;
+}
+#endif
#endif /* CONFIG_VMX */
/*
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/vmx_intercept.c
--- a/xen/arch/x86/vmx_intercept.c Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/vmx_intercept.c Fri Sep 9 16:30:54 2005
@@ -172,7 +172,7 @@
if (p->size != 1 ||
p->pdata_valid ||
- p->port_mm)
+ p->type != IOREQ_TYPE_PIO)
return 0;
if (p->addr == PIT_MODE &&
@@ -284,7 +284,5 @@
if (!reinit)
register_portio_handler(0x40, 4, intercept_pit_io);
}
-
-}
-
+}
#endif /* CONFIG_VMX */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/vmx_io.c
--- a/xen/arch/x86/vmx_io.c Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/vmx_io.c Fri Sep 9 16:30:54 2005
@@ -33,6 +33,7 @@
#include <asm/vmx_platform.h>
#include <asm/vmx_virpit.h>
#include <asm/apic.h>
+#include <asm/shadow.h>
#include <public/io/ioreq.h>
#include <public/io/vmx_vlapic.h>
@@ -123,7 +124,6 @@
regs->esp &= 0xFFFF0000;
regs->esp |= (value & 0xFFFF);
break;
-
case 5:
regs->ebp &= 0xFFFF0000;
regs->ebp |= (value & 0xFFFF);
@@ -207,7 +207,6 @@
*reg &= ~0xFFFF;
*reg |= (value & 0xFFFF);
break;
-
case LONG:
*reg &= ~0xFFFFFFFF;
*reg |= (value & 0xFFFFFFFF);
@@ -322,13 +321,319 @@
}
#endif
+extern long get_reg_value(int size, int index, int seg, struct cpu_user_regs
*regs);
+
+static inline void set_eflags_CF(int size, unsigned long v1,
+ unsigned long v2, struct cpu_user_regs *regs)
+{
+ unsigned long mask = (1 << (8 * size)) - 1;
+
+ if ((v1 & mask) > (v2 & mask))
+ regs->eflags |= X86_EFLAGS_CF;
+ else
+ regs->eflags &= ~X86_EFLAGS_CF;
+}
+
+static inline void set_eflags_OF(int size, unsigned long v1,
+ unsigned long v2, unsigned long v3, struct cpu_user_regs *regs)
+{
+ if ((v3 ^ v2) & (v3 ^ v1) & (1 << ((8 * size) - 1)))
+ regs->eflags |= X86_EFLAGS_OF;
+}
+
+static inline void set_eflags_AF(int size, unsigned long v1,
+ unsigned long v2, unsigned long v3, struct cpu_user_regs *regs)
+{
+ if ((v1 ^ v2 ^ v3) & 0x10)
+ regs->eflags |= X86_EFLAGS_AF;
+}
+
+static inline void set_eflags_ZF(int size, unsigned long v1,
+ struct cpu_user_regs *regs)
+{
+ unsigned long mask = (1 << (8 * size)) - 1;
+
+ if ((v1 & mask) == 0)
+ regs->eflags |= X86_EFLAGS_ZF;
+}
+
+static inline void set_eflags_SF(int size, unsigned long v1,
+ struct cpu_user_regs *regs)
+{
+ if (v1 & (1 << ((8 * size) - 1)))
+ regs->eflags |= X86_EFLAGS_SF;
+}
+
+static char parity_table[256] = {
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
+};
+
+static inline void set_eflags_PF(int size, unsigned long v1,
+ struct cpu_user_regs *regs)
+{
+ if (parity_table[v1 & 0xFF])
+ regs->eflags |= X86_EFLAGS_PF;
+}
+
+static void vmx_pio_assist(struct cpu_user_regs *regs, ioreq_t *p,
+ struct mi_per_cpu_info *mpcip)
+{
+ unsigned long old_eax;
+ int sign = p->df ? -1 : 1;
+
+ if (p->dir == IOREQ_WRITE) {
+ if (p->pdata_valid) {
+ regs->esi += sign * p->count * p->size;
+ if (mpcip->flags & REPZ)
+ regs->ecx -= p->count;
+ }
+ } else {
+ if (mpcip->flags & OVERLAP) {
+ unsigned long addr;
+
+ regs->edi += sign * p->count * p->size;
+ if (mpcip->flags & REPZ)
+ regs->ecx -= p->count;
+
+ addr = regs->edi;
+ if (sign > 0)
+ addr -= p->size;
+ vmx_copy(&p->u.data, addr, p->size, VMX_COPY_OUT);
+ } else if (p->pdata_valid) {
+ regs->edi += sign * p->count * p->size;
+ if (mpcip->flags & REPZ)
+ regs->ecx -= p->count;
+ } else {
+ old_eax = regs->eax;
+ switch (p->size) {
+ case 1:
+ regs->eax = (old_eax & 0xffffff00) | (p->u.data & 0xff);
+ break;
+ case 2:
+ regs->eax = (old_eax & 0xffff0000) | (p->u.data & 0xffff);
+ break;
+ case 4:
+ regs->eax = (p->u.data & 0xffffffff);
+ break;
+ default:
+ printk("Error: %s unknown port size\n", __FUNCTION__);
+ domain_crash_synchronous();
+ }
+ }
+ }
+}
+
+static void vmx_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
+ struct mi_per_cpu_info *mpcip)
+{
+ int sign = p->df ? -1 : 1;
+ int size = -1, index = -1;
+ unsigned long value = 0, diff = 0;
+ unsigned long src, dst;
+
+ src = mpcip->operand[0];
+ dst = mpcip->operand[1];
+ size = operand_size(src);
+
+ switch (mpcip->instr) {
+ case INSTR_MOV:
+ if (dst & REGISTER) {
+ index = operand_index(dst);
+ set_reg_value(size, index, 0, regs, p->u.data);
+ }
+ break;
+
+ case INSTR_MOVZ:
+ if (dst & REGISTER) {
+ index = operand_index(dst);
+ switch (size) {
+ case BYTE: p->u.data = p->u.data & 0xFFULL; break;
+ case WORD: p->u.data = p->u.data & 0xFFFFULL; break;
+ case LONG: p->u.data = p->u.data & 0xFFFFFFFFULL; break;
+ }
+ set_reg_value(operand_size(dst), index, 0, regs, p->u.data);
+ }
+ break;
+
+ case INSTR_MOVS:
+ sign = p->df ? -1 : 1;
+ regs->esi += sign * p->count * p->size;
+ regs->edi += sign * p->count * p->size;
+
+ if ((mpcip->flags & OVERLAP) && p->dir == IOREQ_READ) {
+ unsigned long addr = regs->edi;
+
+ if (sign > 0)
+ addr -= p->size;
+ vmx_copy(&p->u.data, addr, p->size, VMX_COPY_OUT);
+ }
+
+ if (mpcip->flags & REPZ)
+ regs->ecx -= p->count;
+ break;
+
+ case INSTR_STOS:
+ sign = p->df ? -1 : 1;
+ regs->edi += sign * p->count * p->size;
+ if (mpcip->flags & REPZ)
+ regs->ecx -= p->count;
+ break;
+
+ case INSTR_AND:
+ if (src & REGISTER) {
+ index = operand_index(src);
+ value = get_reg_value(size, index, 0, regs);
+ diff = (unsigned long) p->u.data & value;
+ } else if (src & IMMEDIATE) {
+ value = mpcip->immediate;
+ diff = (unsigned long) p->u.data & value;
+ } else if (src & MEMORY) {
+ index = operand_index(dst);
+ value = get_reg_value(size, index, 0, regs);
+ diff = (unsigned long) p->u.data & value;
+ set_reg_value(size, index, 0, regs, diff);
+ }
+
+ /*
+ * The OF and CF flags are cleared; the SF, ZF, and PF
+ * flags are set according to the result. The state of
+ * the AF flag is undefined.
+ */
+ regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
+ X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
+ set_eflags_ZF(size, diff, regs);
+ set_eflags_SF(size, diff, regs);
+ set_eflags_PF(size, diff, regs);
+ break;
+
+ case INSTR_OR:
+ if (src & REGISTER) {
+ index = operand_index(src);
+ value = get_reg_value(size, index, 0, regs);
+ diff = (unsigned long) p->u.data | value;
+ } else if (src & IMMEDIATE) {
+ value = mpcip->immediate;
+ diff = (unsigned long) p->u.data | value;
+ } else if (src & MEMORY) {
+ index = operand_index(dst);
+ value = get_reg_value(size, index, 0, regs);
+ diff = (unsigned long) p->u.data | value;
+ set_reg_value(size, index, 0, regs, diff);
+ }
+
+ /*
+ * The OF and CF flags are cleared; the SF, ZF, and PF
+ * flags are set according to the result. The state of
+ * the AF flag is undefined.
+ */
+ regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
+ X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
+ set_eflags_ZF(size, diff, regs);
+ set_eflags_SF(size, diff, regs);
+ set_eflags_PF(size, diff, regs);
+ break;
+
+ case INSTR_XOR:
+ if (src & REGISTER) {
+ index = operand_index(src);
+ value = get_reg_value(size, index, 0, regs);
+ diff = (unsigned long) p->u.data ^ value;
+ } else if (src & IMMEDIATE) {
+ value = mpcip->immediate;
+ diff = (unsigned long) p->u.data ^ value;
+ } else if (src & MEMORY) {
+ index = operand_index(dst);
+ value = get_reg_value(size, index, 0, regs);
+ diff = (unsigned long) p->u.data ^ value;
+ set_reg_value(size, index, 0, regs, diff);
+ }
+
+ /*
+ * The OF and CF flags are cleared; the SF, ZF, and PF
+ * flags are set according to the result. The state of
+ * the AF flag is undefined.
+ */
+ regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
+ X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
+ set_eflags_ZF(size, diff, regs);
+ set_eflags_SF(size, diff, regs);
+ set_eflags_PF(size, diff, regs);
+ break;
+
+ case INSTR_CMP:
+ if (src & REGISTER) {
+ index = operand_index(src);
+ value = get_reg_value(size, index, 0, regs);
+ diff = (unsigned long) p->u.data - value;
+ } else if (src & IMMEDIATE) {
+ value = mpcip->immediate;
+ diff = (unsigned long) p->u.data - value;
+ } else if (src & MEMORY) {
+ index = operand_index(dst);
+ value = get_reg_value(size, index, 0, regs);
+ diff = value - (unsigned long) p->u.data;
+ }
+
+ /*
+ * The CF, OF, SF, ZF, AF, and PF flags are set according
+ * to the result
+ */
+ regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|X86_EFLAGS_AF|
+ X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
+ set_eflags_CF(size, value, (unsigned long) p->u.data, regs);
+ set_eflags_OF(size, diff, value, (unsigned long) p->u.data, regs);
+ set_eflags_AF(size, diff, value, (unsigned long) p->u.data, regs);
+ set_eflags_ZF(size, diff, regs);
+ set_eflags_SF(size, diff, regs);
+ set_eflags_PF(size, diff, regs);
+ break;
+
+ case INSTR_TEST:
+ if (src & REGISTER) {
+ index = operand_index(src);
+ value = get_reg_value(size, index, 0, regs);
+ } else if (src & IMMEDIATE) {
+ value = mpcip->immediate;
+ } else if (src & MEMORY) {
+ index = operand_index(dst);
+ value = get_reg_value(size, index, 0, regs);
+ }
+ diff = (unsigned long) p->u.data & value;
+
+ /*
+ * Sets the SF, ZF, and PF status flags. CF and OF are set to 0
+ */
+ regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
+ X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
+ set_eflags_ZF(size, diff, regs);
+ set_eflags_SF(size, diff, regs);
+ set_eflags_PF(size, diff, regs);
+ break;
+ }
+
+ load_cpu_user_regs(regs);
+}
+
void vmx_io_assist(struct vcpu *v)
{
vcpu_iodata_t *vio;
ioreq_t *p;
struct cpu_user_regs *regs = guest_cpu_user_regs();
- unsigned long old_eax;
- int sign;
struct mi_per_cpu_info *mpci_p;
struct cpu_user_regs *inst_decoder_regs;
@@ -340,80 +645,26 @@
if (vio == 0) {
VMX_DBG_LOG(DBG_LEVEL_1,
"bad shared page: %lx", (unsigned long) vio);
+ printf("bad shared page: %lx\n", (unsigned long) vio);
domain_crash_synchronous();
}
+
p = &vio->vp_ioreq;
-
- if (p->state == STATE_IORESP_HOOK){
+ if (p->state == STATE_IORESP_HOOK)
vmx_hooks_assist(v);
- }
/* clear IO wait VMX flag */
if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) {
- if (p->state != STATE_IORESP_READY) {
- /* An interrupt send event raced us */
- return;
- } else {
- p->state = STATE_INVALID;
- }
- clear_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags);
- } else {
- return;
- }
-
- sign = (p->df) ? -1 : 1;
- if (p->port_mm) {
- if (p->pdata_valid) {
- regs->esi += sign * p->count * p->size;
- regs->edi += sign * p->count * p->size;
- } else {
- if (p->dir == IOREQ_WRITE) {
- return;
- }
- int size = -1, index = -1;
-
- size = operand_size(v->domain->arch.vmx_platform.mpci.mmio_target);
- index =
operand_index(v->domain->arch.vmx_platform.mpci.mmio_target);
-
- if (v->domain->arch.vmx_platform.mpci.mmio_target & WZEROEXTEND) {
- p->u.data = p->u.data & 0xffff;
- }
- set_reg_value(size, index, 0, regs, p->u.data);
-
- }
- load_cpu_user_regs(regs);
- return;
- }
-
- if (p->dir == IOREQ_WRITE) {
- if (p->pdata_valid) {
- regs->esi += sign * p->count * p->size;
- regs->ecx -= p->count;
- }
- return;
- } else {
- if (p->pdata_valid) {
- regs->edi += sign * p->count * p->size;
- regs->ecx -= p->count;
- return;
- }
- }
-
- old_eax = regs->eax;
-
- switch(p->size) {
- case 1:
- regs->eax = (old_eax & 0xffffff00) | (p->u.data & 0xff);
- break;
- case 2:
- regs->eax = (old_eax & 0xffff0000) | (p->u.data & 0xffff);
- break;
- case 4:
- regs->eax = (p->u.data & 0xffffffff);
- break;
- default:
- printk("Error: %s unknwon port size\n", __FUNCTION__);
- domain_crash_synchronous();
+ if (p->state == STATE_IORESP_READY) {
+ p->state = STATE_INVALID;
+ clear_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags);
+
+ if (p->type == IOREQ_TYPE_PIO)
+ vmx_pio_assist(regs, p, mpci_p);
+ else
+ vmx_mmio_assist(regs, p, mpci_p);
+ }
+ /* else an interrupt send event raced us */
}
}
@@ -456,8 +707,9 @@
int port = iopacket_port(current->domain);
do {
- if(!test_bit(port, ¤t->domain->shared_info->evtchn_pending[0]))
+ if (!test_bit(port, ¤t->domain->shared_info->evtchn_pending[0]))
do_block();
+
vmx_check_events(current);
if (!test_bit(ARCH_VMX_IO_WAIT, ¤t->arch.arch_vmx.flags))
break;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/vmx_platform.c
--- a/xen/arch/x86/vmx_platform.c Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/vmx_platform.c Fri Sep 9 16:30:54 2005
@@ -64,37 +64,37 @@
case QUAD:
return (long)(reg);
default:
- printk("Error: <__get_reg_value>Invalid reg size\n");
+ printf("Error: (__get_reg_value) Invalid reg size\n");
domain_crash_synchronous();
}
}
-static long get_reg_value(int size, int index, int seg, struct cpu_user_regs
*regs)
+long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs)
{
if (size == BYTE) {
switch (index) {
- case 0: //%al
+ case 0: /* %al */
return (char)(regs->rax & 0xFF);
- case 1: //%cl
+ case 1: /* %cl */
return (char)(regs->rcx & 0xFF);
- case 2: //%dl
+ case 2: /* %dl */
return (char)(regs->rdx & 0xFF);
- case 3: //%bl
+ case 3: /* %bl */
return (char)(regs->rbx & 0xFF);
- case 4: //%ah
+ case 4: /* %ah */
return (char)((regs->rax & 0xFF00) >> 8);
- case 5: //%ch
+ case 5: /* %ch */
return (char)((regs->rcx & 0xFF00) >> 8);
- case 6: //%dh
+ case 6: /* %dh */
return (char)((regs->rdx & 0xFF00) >> 8);
- case 7: //%bh
+ case 7: /* %bh */
return (char)((regs->rbx & 0xFF00) >> 8);
default:
- printk("Error: (get_reg_value)Invalid index value\n");
+ printf("Error: (get_reg_value) Invalid index value\n");
domain_crash_synchronous();
}
-
- }
+ }
+
switch (index) {
case 0: return __get_reg_value(regs->rax, size);
case 1: return __get_reg_value(regs->rcx, size);
@@ -113,7 +113,7 @@
case 14: return __get_reg_value(regs->r14, size);
case 15: return __get_reg_value(regs->r15, size);
default:
- printk("Error: (get_reg_value)Invalid index value\n");
+ printf("Error: (get_reg_value) Invalid index value\n");
domain_crash_synchronous();
}
}
@@ -129,117 +129,91 @@
__vmread(GUEST_RIP, ®s->eip);
}
-static long get_reg_value(int size, int index, int seg, struct cpu_user_regs
*regs)
+static inline long __get_reg_value(unsigned long reg, int size)
{
- /*
- * Reference the db_reg[] table
- */
- switch (size) {
- case BYTE:
+ switch(size) {
+ case WORD:
+ return (short)(reg & 0xFFFF);
+ case LONG:
+ return (int)(reg & 0xFFFFFFFF);
+ default:
+ printf("Error: (__get_reg_value) Invalid reg size\n");
+ domain_crash_synchronous();
+ }
+}
+
+long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs)
+{
+ if (size == BYTE) {
switch (index) {
- case 0: //%al
+ case 0: /* %al */
return (char)(regs->eax & 0xFF);
- case 1: //%cl
+ case 1: /* %cl */
return (char)(regs->ecx & 0xFF);
- case 2: //%dl
+ case 2: /* %dl */
return (char)(regs->edx & 0xFF);
- case 3: //%bl
+ case 3: /* %bl */
return (char)(regs->ebx & 0xFF);
- case 4: //%ah
+ case 4: /* %ah */
return (char)((regs->eax & 0xFF00) >> 8);
- case 5: //%ch
+ case 5: /* %ch */
return (char)((regs->ecx & 0xFF00) >> 8);
- case 6: //%dh
+ case 6: /* %dh */
return (char)((regs->edx & 0xFF00) >> 8);
- case 7: //%bh
+ case 7: /* %bh */
return (char)((regs->ebx & 0xFF00) >> 8);
default:
- printk("Error: (get_reg_value)size case 0 error\n");
+ printf("Error: (get_reg_value) Invalid index value\n");
domain_crash_synchronous();
}
- case WORD:
+ }
+
switch (index) {
- case 0: //%ax
- return (short)(regs->eax & 0xFFFF);
- case 1: //%cx
- return (short)(regs->ecx & 0xFFFF);
- case 2: //%dx
- return (short)(regs->edx & 0xFFFF);
- case 3: //%bx
- return (short)(regs->ebx & 0xFFFF);
- case 4: //%sp
- return (short)(regs->esp & 0xFFFF);
- break;
- case 5: //%bp
- return (short)(regs->ebp & 0xFFFF);
- case 6: //%si
- return (short)(regs->esi & 0xFFFF);
- case 7: //%di
- return (short)(regs->edi & 0xFFFF);
- default:
- printk("Error: (get_reg_value)size case 1 error\n");
- domain_crash_synchronous();
- }
- case LONG:
- switch (index) {
- case 0: //%eax
- return regs->eax;
- case 1: //%ecx
- return regs->ecx;
- case 2: //%edx
- return regs->edx;
-
- case 3: //%ebx
- return regs->ebx;
- case 4: //%esp
- return regs->esp;
- case 5: //%ebp
- return regs->ebp;
- case 6: //%esi
- return regs->esi;
- case 7: //%edi
- return regs->edi;
- default:
- printk("Error: (get_reg_value)size case 2 error\n");
- domain_crash_synchronous();
- }
+ case 0: return __get_reg_value(regs->eax, size);
+ case 1: return __get_reg_value(regs->ecx, size);
+ case 2: return __get_reg_value(regs->edx, size);
+ case 3: return __get_reg_value(regs->ebx, size);
+ case 4: return __get_reg_value(regs->esp, size);
+ case 5: return __get_reg_value(regs->ebp, size);
+ case 6: return __get_reg_value(regs->esi, size);
+ case 7: return __get_reg_value(regs->edi, size);
default:
- printk("Error: (get_reg_value)size case error\n");
+ printf("Error: (get_reg_value) Invalid index value\n");
domain_crash_synchronous();
}
}
#endif
-static inline const unsigned char *check_prefix(const unsigned char *inst,
struct instruction *thread_inst, unsigned char *rex_p)
+static inline unsigned char *check_prefix(unsigned char *inst,
+ struct instruction *thread_inst, unsigned char *rex_p)
{
while (1) {
switch (*inst) {
- /* rex prefix for em64t instructions*/
+ /* rex prefix for em64t instructions */
case 0x40 ... 0x4e:
*rex_p = *inst;
break;
-
- case 0xf3: //REPZ
+ case 0xf3: /* REPZ */
thread_inst->flags = REPZ;
- break;
- case 0xf2: //REPNZ
+ break;
+ case 0xf2: /* REPNZ */
thread_inst->flags = REPNZ;
- break;
- case 0xf0: //LOCK
+ break;
+ case 0xf0: /* LOCK */
break;
- case 0x2e: //CS
- case 0x36: //SS
- case 0x3e: //DS
- case 0x26: //ES
- case 0x64: //FS
- case 0x65: //GS
- thread_inst->seg_sel = *inst;
+ case 0x2e: /* CS */
+ case 0x36: /* SS */
+ case 0x3e: /* DS */
+ case 0x26: /* ES */
+ case 0x64: /* FS */
+ case 0x65: /* GS */
+ thread_inst->seg_sel = *inst;
break;
- case 0x66: //32bit->16bit
+ case 0x66: /* 32bit->16bit */
thread_inst->op_size = WORD;
break;
case 0x67:
- printf("Error: Not handling 0x67 (yet)\n");
+ printf("Error: Not handling 0x67 (yet)\n");
domain_crash_synchronous();
break;
default:
@@ -249,7 +223,7 @@
}
}
-static inline unsigned long get_immediate(int op16, const unsigned char *inst,
int op_size)
+static inline unsigned long get_immediate(int op16,const unsigned char *inst,
int op_size)
{
int mod, reg, rm;
unsigned long val = 0;
@@ -317,275 +291,328 @@
static void init_instruction(struct instruction *mmio_inst)
{
- memset(mmio_inst->i_name, '0', I_NAME_LEN);
- mmio_inst->op_size = 0;
- mmio_inst->offset = 0;
+ mmio_inst->instr = 0;
+ mmio_inst->op_size = 0;
mmio_inst->immediate = 0;
mmio_inst->seg_sel = 0;
- mmio_inst->op_num = 0;
mmio_inst->operand[0] = 0;
mmio_inst->operand[1] = 0;
- mmio_inst->operand[2] = 0;
mmio_inst->flags = 0;
}
#define GET_OP_SIZE_FOR_BYTE(op_size) \
- do {if (rex) op_size = BYTE_64;else op_size = BYTE;} while(0)
+ do { \
+ if (rex) \
+ op_size = BYTE_64; \
+ else \
+ op_size = BYTE; \
+ } while(0)
#define GET_OP_SIZE_FOR_NONEBYTE(op_size) \
- do {if (rex & 0x8) op_size = QUAD; else if (op_size != WORD) op_size =
LONG;} while(0)
-
-static int vmx_decode(const unsigned char *inst, struct instruction
*thread_inst)
+ do { \
+ if (rex & 0x8) \
+ op_size = QUAD; \
+ else if (op_size != WORD) \
+ op_size = LONG; \
+ } while(0)
+
+
+/*
+ * Decode mem,accumulator operands (as in <opcode> m8/m16/m32, al,ax,eax)
+ */
+static int mem_acc(unsigned char size, struct instruction *instr)
+{
+ instr->operand[0] = mk_operand(size, 0, 0, MEMORY);
+ instr->operand[1] = mk_operand(size, 0, 0, REGISTER);
+ return DECODE_success;
+}
+
+/*
+ * Decode accumulator,mem operands (as in <opcode> al,ax,eax, m8/m16/m32)
+ */
+static int acc_mem(unsigned char size, struct instruction *instr)
+{
+ instr->operand[0] = mk_operand(size, 0, 0, REGISTER);
+ instr->operand[1] = mk_operand(size, 0, 0, MEMORY);
+ return DECODE_success;
+}
+
+/*
+ * Decode mem,reg operands (as in <opcode> r32/16, m32/16)
+ */
+static int mem_reg(unsigned char size, unsigned char *opcode,
+ struct instruction *instr, unsigned char rex)
+{
+ int index = get_index(opcode + 1, rex);
+
+ instr->operand[0] = mk_operand(size, 0, 0, MEMORY);
+ instr->operand[1] = mk_operand(size, index, 0, REGISTER);
+ return DECODE_success;
+}
+
+/*
+ * Decode reg,mem operands (as in <opcode> m32/16, r32/16)
+ */
+static int reg_mem(unsigned char size, unsigned char *opcode,
+ struct instruction *instr, unsigned char rex)
+{
+ int index = get_index(opcode + 1, rex);
+
+ instr->operand[0] = mk_operand(size, index, 0, REGISTER);
+ instr->operand[1] = mk_operand(size, 0, 0, MEMORY);
+ return DECODE_success;
+}
+
+static int vmx_decode(unsigned char *opcode, struct instruction *instr)
{
unsigned long eflags;
int index, vm86 = 0;
unsigned char rex = 0;
unsigned char tmp_size = 0;
-
- init_instruction(thread_inst);
-
- inst = check_prefix(inst, thread_inst, &rex);
+ init_instruction(instr);
+
+ opcode = check_prefix(opcode, instr, &rex);
__vmread(GUEST_RFLAGS, &eflags);
if (eflags & X86_EFLAGS_VM)
vm86 = 1;
if (vm86) { /* meaning is reversed */
- if (thread_inst->op_size == WORD)
- thread_inst->op_size = LONG;
- else if (thread_inst->op_size == LONG)
- thread_inst->op_size = WORD;
- else if (thread_inst->op_size == 0)
- thread_inst->op_size = WORD;
- }
-
- switch(*inst) {
- case 0x81:
- /* This is only a workaround for cmpl instruction*/
- strcpy((char *)thread_inst->i_name, "cmp");
+ if (instr->op_size == WORD)
+ instr->op_size = LONG;
+ else if (instr->op_size == LONG)
+ instr->op_size = WORD;
+ else if (instr->op_size == 0)
+ instr->op_size = WORD;
+ }
+
+ switch (*opcode) {
+ case 0x0B: /* or m32/16, r32/16 */
+ instr->instr = INSTR_OR;
+ GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+ return mem_reg(instr->op_size, opcode, instr, rex);
+
+ case 0x20: /* and r8, m8 */
+ instr->instr = INSTR_AND;
+ GET_OP_SIZE_FOR_BYTE(instr->op_size);
+ return reg_mem(instr->op_size, opcode, instr, rex);
+
+ case 0x21: /* and r32/16, m32/16 */
+ instr->instr = INSTR_AND;
+ GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+ return reg_mem(instr->op_size, opcode, instr, rex);
+
+ case 0x23: /* and m32/16, r32/16 */
+ instr->instr = INSTR_AND;
+ GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+ return mem_reg(instr->op_size, opcode, instr, rex);
+
+ case 0x30: /* xor r8, m8 */
+ instr->instr = INSTR_XOR;
+ GET_OP_SIZE_FOR_BYTE(instr->op_size);
+ return reg_mem(instr->op_size, opcode, instr, rex);
+
+ case 0x31: /* xor r32/16, m32/16 */
+ instr->instr = INSTR_XOR;
+ GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+ return reg_mem(instr->op_size, opcode, instr, rex);
+
+ case 0x39: /* cmp r32/16, m32/16 */
+ instr->instr = INSTR_CMP;
+ GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+ return reg_mem(instr->op_size, opcode, instr, rex);
+
+ case 0x81:
+ if (((opcode[1] >> 3) & 7) == 7) { /* cmp $imm, m32/16 */
+ instr->instr = INSTR_CMP;
+ GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+
+ instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE);
+ instr->immediate = get_immediate(vm86, opcode+1, BYTE);
+ instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
+
return DECODE_success;
-
- case 0x88:
- /* mov r8 to m8 */
- thread_inst->op_size = BYTE;
- index = get_index((inst + 1), rex);
- GET_OP_SIZE_FOR_BYTE(tmp_size);
- thread_inst->operand[0] = mk_operand(tmp_size, index, 0, REGISTER);
-
- break;
- case 0x89:
- /* mov r32/16 to m32/16 */
- index = get_index((inst + 1), rex);
- GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size);
- thread_inst->operand[0] = mk_operand(thread_inst->op_size, index,
0, REGISTER);
-
- break;
- case 0x8a:
- /* mov m8 to r8 */
- thread_inst->op_size = BYTE;
- index = get_index((inst + 1), rex);
- GET_OP_SIZE_FOR_BYTE(tmp_size);
- thread_inst->operand[1] = mk_operand(tmp_size, index, 0, REGISTER);
- break;
- case 0x8b:
- /* mov r32/16 to m32/16 */
- index = get_index((inst + 1), rex);
- GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size);
- thread_inst->operand[1] = mk_operand(thread_inst->op_size, index,
0, REGISTER);
- break;
- case 0x8c:
- case 0x8e:
- printk("%x, This opcode hasn't been handled yet!", *inst);
- return DECODE_failure;
- /* Not handle it yet. */
- case 0xa0:
- /* mov byte to al */
- thread_inst->op_size = BYTE;
- GET_OP_SIZE_FOR_BYTE(tmp_size);
- thread_inst->operand[1] = mk_operand(tmp_size, 0, 0, REGISTER);
- break;
- case 0xa1:
- /* mov word/doubleword to ax/eax */
- GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size);
- thread_inst->operand[1] = mk_operand(thread_inst->op_size, 0, 0,
REGISTER);
-
- break;
- case 0xa2:
- /* mov al to (seg:offset) */
- thread_inst->op_size = BYTE;
- GET_OP_SIZE_FOR_BYTE(tmp_size);
- thread_inst->operand[0] = mk_operand(tmp_size, 0, 0, REGISTER);
- break;
- case 0xa3:
- /* mov ax/eax to (seg:offset) */
- GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size);
- thread_inst->operand[0] = mk_operand(thread_inst->op_size, 0, 0,
REGISTER);
- break;
- case 0xa4:
- /* movsb */
- thread_inst->op_size = BYTE;
- strcpy((char *)thread_inst->i_name, "movs");
- return DECODE_success;
- case 0xa5:
- /* movsw/movsl */
- GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size);
- strcpy((char *)thread_inst->i_name, "movs");
- return DECODE_success;
- case 0xaa:
- /* stosb */
- thread_inst->op_size = BYTE;
- strcpy((char *)thread_inst->i_name, "stosb");
- return DECODE_success;
- case 0xab:
- /* stosw/stosl */
- if (thread_inst->op_size == WORD) {
- strcpy((char *)thread_inst->i_name, "stosw");
- } else {
- thread_inst->op_size = LONG;
- strcpy((char *)thread_inst->i_name, "stosl");
- }
- return DECODE_success;
- case 0xc6:
- /* mov imm8 to m8 */
- thread_inst->op_size = BYTE;
- thread_inst->operand[0] = mk_operand(BYTE, 0, 0, IMMEDIATE);
- thread_inst->immediate = get_immediate(vm86,
- (inst+1), thread_inst->op_size);
- break;
- case 0xc7:
- /* mov imm16/32 to m16/32 */
- GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size);
- thread_inst->operand[0] = mk_operand(thread_inst->op_size, 0, 0,
IMMEDIATE);
- thread_inst->immediate = get_immediate(vm86, (inst+1),
thread_inst->op_size);
+ } else
+ return DECODE_failure;
+
+ case 0x84: /* test m8, r8 */
+ instr->instr = INSTR_TEST;
+ instr->op_size = BYTE;
+ GET_OP_SIZE_FOR_BYTE(tmp_size);
+ return mem_reg(tmp_size, opcode, instr, rex);
+
+ case 0x88: /* mov r8, m8 */
+ instr->instr = INSTR_MOV;
+ instr->op_size = BYTE;
+ GET_OP_SIZE_FOR_BYTE(tmp_size);
+ return reg_mem(tmp_size, opcode, instr, rex);
+
+ case 0x89: /* mov r32/16, m32/16 */
+ instr->instr = INSTR_MOV;
+ GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+ return reg_mem(instr->op_size, opcode, instr, rex);
+
+ case 0x8A: /* mov m8, r8 */
+ instr->instr = INSTR_MOV;
+ instr->op_size = BYTE;
+ GET_OP_SIZE_FOR_BYTE(tmp_size);
+ return mem_reg(tmp_size, opcode, instr, rex);
+
+ case 0x8B: /* mov m32/16, r32/16 */
+ instr->instr = INSTR_MOV;
+ GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+ return mem_reg(instr->op_size, opcode, instr, rex);
+
+ case 0xA0: /* mov <addr>, al */
+ instr->instr = INSTR_MOV;
+ instr->op_size = BYTE;
+ GET_OP_SIZE_FOR_BYTE(tmp_size);
+ return mem_acc(tmp_size, instr);
+
+ case 0xA1: /* mov <addr>, ax/eax */
+ instr->instr = INSTR_MOV;
+ GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+ return mem_acc(instr->op_size, instr);
+
+ case 0xA2: /* mov al, <addr> */
+ instr->instr = INSTR_MOV;
+ instr->op_size = BYTE;
+ GET_OP_SIZE_FOR_BYTE(tmp_size);
+ return acc_mem(tmp_size, instr);
+
+ case 0xA3: /* mov ax/eax, <addr> */
+ instr->instr = INSTR_MOV;
+ GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+ return acc_mem(instr->op_size, instr);
+
+ case 0xA4: /* movsb */
+ instr->instr = INSTR_MOVS;
+ instr->op_size = BYTE;
+ return DECODE_success;
- break;
- case 0x0f:
- break;
- default:
- printk("%x, This opcode hasn't been handled yet!", *inst);
- return DECODE_failure;
- }
+ case 0xA5: /* movsw/movsl */
+ instr->instr = INSTR_MOVS;
+ GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+ return DECODE_success;
- strcpy((char *)thread_inst->i_name, "mov");
- if (*inst != 0x0f) {
+ case 0xAA: /* stosb */
+ instr->instr = INSTR_STOS;
+ instr->op_size = BYTE;
return DECODE_success;
- }
-
- inst++;
- switch (*inst) {
+
+ case 0xAB: /* stosw/stosl */
+ instr->instr = INSTR_STOS;
+ GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+ return DECODE_success;
- /* movz */
- case 0xb6:
- index = get_index((inst + 1), rex);
- GET_OP_SIZE_FOR_NONEBYTE(thread_inst->op_size);
- thread_inst->operand[1] = mk_operand(thread_inst->op_size, index,
0, REGISTER);
- thread_inst->op_size = BYTE;
- strcpy((char *)thread_inst->i_name, "movzb");
+ case 0xC6:
+ if (((opcode[1] >> 3) & 7) == 0) { /* mov $imm8, m8 */
+ instr->instr = INSTR_MOV;
+ instr->op_size = BYTE;
+
+ instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE);
+ instr->immediate = get_immediate(vm86, opcode+1, instr->op_size);
+ instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
return DECODE_success;
- case 0xb7:
- index = get_index((inst + 1), rex);
- if (rex & 0x8) {
- thread_inst->op_size = LONG;
- thread_inst->operand[1] = mk_operand(QUAD, index, 0,
REGISTER);
- } else {
- thread_inst->op_size = WORD;
- thread_inst->operand[1] = mk_operand(LONG, index, 0,
REGISTER);
- }
+ } else
+ return DECODE_failure;
- strcpy((char *)thread_inst->i_name, "movzw");
+ case 0xC7:
+ if (((opcode[1] >> 3) & 7) == 0) { /* mov $imm16/32, m16/32 */
+ instr->instr = INSTR_MOV;
+ GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+
+ instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE);
+ instr->immediate = get_immediate(vm86, opcode+1, instr->op_size);
+ instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
return DECODE_success;
- default:
- printk("0f %x, This opcode hasn't been handled yet!", *inst);
- return DECODE_failure;
- }
-
- /* will never reach here */
- return DECODE_failure;
+ } else
+ return DECODE_failure;
+
+ case 0xF6:
+ if (((opcode[1] >> 3) & 7) == 0) { /* testb $imm8, m8 */
+ instr->instr = INSTR_TEST;
+ instr->op_size = BYTE;
+
+ instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE);
+ instr->immediate = get_immediate(vm86, opcode+1, instr->op_size);
+ instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
+
+ return DECODE_success;
+ } else
+ return DECODE_failure;
+
+ case 0x0F:
+ break;
+
+ default:
+ printf("%x, This opcode isn't handled yet!\n", *opcode);
+ return DECODE_failure;
+ }
+
+ switch (*++opcode) {
+ case 0xB6: /* movz m8, r16/r32 */
+ instr->instr = INSTR_MOVZ;
+ GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+ index = get_index(opcode + 1, rex);
+ instr->operand[0] = mk_operand(BYTE, 0, 0, MEMORY);
+ instr->operand[1] = mk_operand(instr->op_size, index, 0, REGISTER);
+ return DECODE_success;
+
+ case 0xB7: /* movz m16, r32 */
+ instr->instr = INSTR_MOVZ;
+ index = get_index(opcode + 1, rex);
+ if (rex & 0x8) {
+ instr->op_size = LONG;
+ instr->operand[1] = mk_operand(QUAD, index, 0, REGISTER);
+ } else {
+ instr->op_size = WORD;
+ instr->operand[1] = mk_operand(LONG, index, 0, REGISTER);
+ }
+ instr->operand[0] = mk_operand(instr->op_size, 0, 0, MEMORY);
+ return DECODE_success;
+
+ default:
+ printf("0f %x, This opcode isn't handled yet\n", *opcode);
+ return DECODE_failure;
+ }
}
int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip, int
inst_len)
{
- unsigned long gpa;
- unsigned long mfn;
- unsigned char *inst_start;
- int remaining = 0;
-
- if ( (inst_len > MAX_INST_LEN) || (inst_len <= 0) )
+ if (inst_len > MAX_INST_LEN || inst_len <= 0)
return 0;
-
- if ( vmx_paging_enabled(current) )
- {
- gpa = gva_to_gpa(guest_eip);
- mfn = phys_to_machine_mapping(gpa >> PAGE_SHIFT);
-
- /* Does this cross a page boundary ? */
- if ( (guest_eip & PAGE_MASK) != ((guest_eip + inst_len) & PAGE_MASK) )
- {
- remaining = (guest_eip + inst_len) & ~PAGE_MASK;
- inst_len -= remaining;
- }
- }
- else
- {
- mfn = phys_to_machine_mapping(guest_eip >> PAGE_SHIFT);
- }
-
- inst_start = map_domain_page(mfn);
- memcpy((char *)buf, inst_start + (guest_eip & ~PAGE_MASK), inst_len);
- unmap_domain_page(inst_start);
-
- if ( remaining )
- {
- gpa = gva_to_gpa(guest_eip+inst_len+remaining);
- mfn = phys_to_machine_mapping(gpa >> PAGE_SHIFT);
-
- inst_start = map_domain_page(mfn);
- memcpy((char *)buf+inst_len, inst_start, remaining);
- unmap_domain_page(inst_start);
- }
-
- return inst_len+remaining;
-}
-
-static int read_from_mmio(struct instruction *inst_p)
-{
- // Only for mov instruction now!!!
- if (inst_p->operand[1] & REGISTER)
- return 1;
-
- return 0;
-}
-
-// dir: 1 read from mmio
-// 0 write to mmio
-static void send_mmio_req(unsigned long gpa,
- struct instruction *inst_p, long value, int dir, int pvalid)
+ if (!vmx_copy(buf, guest_eip, inst_len, VMX_COPY_IN))
+ return 0;
+ return inst_len;
+}
+
+void send_mmio_req(unsigned char type, unsigned long gpa,
+ unsigned long count, int size, long value, int dir, int pvalid)
{
struct vcpu *d = current;
vcpu_iodata_t *vio;
ioreq_t *p;
int vm86;
- struct mi_per_cpu_info *mpci_p;
- struct cpu_user_regs *inst_decoder_regs;
+ struct cpu_user_regs *regs;
extern long evtchn_send(int lport);
- mpci_p = ¤t->domain->arch.vmx_platform.mpci;
- inst_decoder_regs = mpci_p->inst_decoder_regs;
+ regs = current->domain->arch.vmx_platform.mpci.inst_decoder_regs;
vio = get_vio(d->domain, d->vcpu_id);
-
if (vio == NULL) {
- printk("bad shared page\n");
+ printf("bad shared page\n");
domain_crash_synchronous();
}
+
p = &vio->vp_ioreq;
- vm86 = inst_decoder_regs->eflags & X86_EFLAGS_VM;
+ vm86 = regs->eflags & X86_EFLAGS_VM;
if (test_bit(ARCH_VMX_IO_WAIT, &d->arch.arch_vmx.flags)) {
printf("VMX I/O has not yet completed\n");
@@ -596,24 +623,21 @@
p->dir = dir;
p->pdata_valid = pvalid;
- p->port_mm = 1;
- p->size = inst_p->op_size;
+ p->type = type;
+ p->size = size;
p->addr = gpa;
- p->u.data = value;
+ p->count = count;
+ p->df = regs->eflags & EF_DF ? 1 : 0;
+
+ if (pvalid) {
+ if (vmx_paging_enabled(current))
+ p->u.pdata = (void *) gva_to_gpa(value);
+ else
+ p->u.pdata = (void *) value; /* guest VA == guest PA */
+ } else
+ p->u.data = value;
p->state = STATE_IOREQ_READY;
-
- if (inst_p->flags & REPZ) {
- if (vm86)
- p->count = inst_decoder_regs->ecx & 0xFFFF;
- else
- p->count = inst_decoder_regs->ecx;
- p->df = (inst_decoder_regs->eflags & EF_DF) ? 1 : 0;
- } else
- p->count = 1;
-
- if ((pvalid) && vmx_paging_enabled(current))
- p->u.pdata = (void *) gva_to_gpa(p->u.data);
if (vmx_mmio_intercept(p)){
p->state = STATE_IORESP_READY;
@@ -625,21 +649,53 @@
vmx_wait_io();
}
+static void mmio_operands(int type, unsigned long gpa, struct instruction
*inst,
+ struct mi_per_cpu_info *mpcip, struct cpu_user_regs *regs)
+{
+ unsigned long value = 0;
+ int index, size;
+
+ size = operand_size(inst->operand[0]);
+
+ mpcip->flags = inst->flags;
+ mpcip->instr = inst->instr;
+ mpcip->operand[0] = inst->operand[0]; /* source */
+ mpcip->operand[1] = inst->operand[1]; /* destination */
+
+ if (inst->operand[0] & REGISTER) { /* dest is memory */
+ index = operand_index(inst->operand[0]);
+ value = get_reg_value(size, index, 0, regs);
+ send_mmio_req(type, gpa, 1, size, value, IOREQ_WRITE, 0);
+ } else if (inst->operand[0] & IMMEDIATE) { /* dest is memory */
+ value = inst->immediate;
+ send_mmio_req(type, gpa, 1, size, value, IOREQ_WRITE, 0);
+ } else if (inst->operand[0] & MEMORY) { /* dest is register */
+ /* send the request and wait for the value */
+ send_mmio_req(type, gpa, 1, size, 0, IOREQ_READ, 0);
+ } else {
+ printf("mmio_operands: invalid operand\n");
+ domain_crash_synchronous();
+ }
+}
+
+#define GET_REPEAT_COUNT() \
+ (mmio_inst.flags & REPZ ? (vm86 ? regs->ecx & 0xFFFF : regs->ecx) : 1)
+
void handle_mmio(unsigned long va, unsigned long gpa)
{
unsigned long eip, eflags, cs;
unsigned long inst_len, inst_addr;
- struct mi_per_cpu_info *mpci_p;
- struct cpu_user_regs *inst_decoder_regs;
+ struct mi_per_cpu_info *mpcip;
+ struct cpu_user_regs *regs;
struct instruction mmio_inst;
unsigned char inst[MAX_INST_LEN];
- int vm86, ret;
+ int i, vm86, ret;
- mpci_p = ¤t->domain->arch.vmx_platform.mpci;
- inst_decoder_regs = mpci_p->inst_decoder_regs;
+ mpcip = ¤t->domain->arch.vmx_platform.mpci;
+ regs = mpcip->inst_decoder_regs;
__vmread(GUEST_RIP, &eip);
- __vmread(INSTRUCTION_LEN, &inst_len);
+ __vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len);
__vmread(GUEST_RFLAGS, &eflags);
vm86 = eflags & X86_EFLAGS_VM;
@@ -647,108 +703,142 @@
__vmread(GUEST_CS_SELECTOR, &cs);
inst_addr = (cs << 4) + eip;
} else
- inst_addr = eip; /* XXX should really look at GDT[cs].base too */
-
- memset(inst, '0', MAX_INST_LEN);
+ inst_addr = eip;
+
+ memset(inst, 0, MAX_INST_LEN);
ret = inst_copy_from_guest(inst, inst_addr, inst_len);
if (ret != inst_len) {
- printk("handle_mmio - EXIT: get guest instruction fault\n");
+ printf("handle_mmio - EXIT: get guest instruction fault\n");
domain_crash_synchronous();
}
-
init_instruction(&mmio_inst);
if (vmx_decode(inst, &mmio_inst) == DECODE_failure) {
- printk("vmx decode failure: eip=%lx, va=%lx\n %x %x %x %x\n", eip, va,
- inst[0], inst[1], inst[2], inst[3]);
+ printf("mmio opcode: va 0x%lx, gpa 0x%lx, len %ld:",
+ va, gpa, inst_len);
+ for (i = 0; i < inst_len; i++)
+ printf(" %02x", inst[i] & 0xFF);
+ printf("\n");
domain_crash_synchronous();
}
- __vmwrite(GUEST_RIP, eip + inst_len);
- store_cpu_user_regs(inst_decoder_regs);
-
- // Only handle "mov" and "movs" instructions!
- if (!strncmp((char *)mmio_inst.i_name, "movz", 4)) {
- if (read_from_mmio(&mmio_inst)) {
- // Send the request and waiting for return value.
- mpci_p->mmio_target = mmio_inst.operand[1] | WZEROEXTEND;
- send_mmio_req(gpa, &mmio_inst, 0, IOREQ_READ, 0);
- return ;
- } else {
- printk("handle_mmio - EXIT: movz error!\n");
- domain_crash_synchronous();
- }
- }
-
- if (!strncmp((char *)mmio_inst.i_name, "movs", 4)) {
+ store_cpu_user_regs(regs);
+ regs->eip += inst_len; /* advance %eip */
+
+ switch (mmio_inst.instr) {
+ case INSTR_MOV:
+ mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs);
+ break;
+
+ case INSTR_MOVS:
+ {
+ unsigned long count = GET_REPEAT_COUNT();
+ unsigned long size = mmio_inst.op_size;
+ int sign = regs->eflags & EF_DF ? -1 : 1;
unsigned long addr = 0;
int dir;
+ /* determine non-MMIO address */
if (vm86) {
unsigned long seg;
__vmread(GUEST_ES_SELECTOR, &seg);
- if (((seg << 4) + (inst_decoder_regs->edi & 0xFFFF)) == va) {
+ if (((seg << 4) + (regs->edi & 0xFFFF)) == va) {
dir = IOREQ_WRITE;
__vmread(GUEST_DS_SELECTOR, &seg);
- addr = (seg << 4) + (inst_decoder_regs->esi & 0xFFFF);
+ addr = (seg << 4) + (regs->esi & 0xFFFF);
} else {
dir = IOREQ_READ;
- addr = (seg << 4) + (inst_decoder_regs->edi & 0xFFFF);
+ addr = (seg << 4) + (regs->edi & 0xFFFF);
}
- } else { /* XXX should really look at GDT[ds/es].base too */
- if (va == inst_decoder_regs->edi) {
+ } else {
+ if (va == regs->edi) {
dir = IOREQ_WRITE;
- addr = inst_decoder_regs->esi;
+ addr = regs->esi;
} else {
dir = IOREQ_READ;
- addr = inst_decoder_regs->edi;
+ addr = regs->edi;
}
}
- send_mmio_req(gpa, &mmio_inst, addr, dir, 1);
- return;
- }
-
- if (!strncmp((char *)mmio_inst.i_name, "mov", 3)) {
- long value = 0;
- int size, index;
-
- if (read_from_mmio(&mmio_inst)) {
- // Send the request and waiting for return value.
- mpci_p->mmio_target = mmio_inst.operand[1];
- send_mmio_req(gpa, &mmio_inst, value, IOREQ_READ, 0);
- return;
- } else {
- // Write to MMIO
- if (mmio_inst.operand[0] & IMMEDIATE) {
- value = mmio_inst.immediate;
- } else if (mmio_inst.operand[0] & REGISTER) {
- size = operand_size(mmio_inst.operand[0]);
- index = operand_index(mmio_inst.operand[0]);
- value = get_reg_value(size, index, 0, inst_decoder_regs);
- } else {
- domain_crash_synchronous();
- }
- send_mmio_req(gpa, &mmio_inst, value, IOREQ_WRITE, 0);
- return;
- }
- }
-
- if (!strncmp((char *)mmio_inst.i_name, "stos", 4)) {
- send_mmio_req(gpa, &mmio_inst,
- inst_decoder_regs->eax, IOREQ_WRITE, 0);
- return;
- }
- /* Workaround for cmp instruction */
- if (!strncmp((char *)mmio_inst.i_name, "cmp", 3)) {
- inst_decoder_regs->eflags &= ~X86_EFLAGS_ZF;
- __vmwrite(GUEST_RFLAGS, inst_decoder_regs->eflags);
- return;
- }
-
- domain_crash_synchronous();
+ mpcip->flags = mmio_inst.flags;
+ mpcip->instr = mmio_inst.instr;
+
+ /*
+ * In case of a movs spanning multiple pages, we break the accesses
+ * up into multiple pages (the device model works with non-continguous
+ * physical guest pages). To copy just one page, we adjust %ecx and
+ * do not advance %eip so that the next "rep movs" copies the next page.
+ * Unaligned accesses, for example movsl starting at PGSZ-2, are
+ * turned into a single copy where we handle the overlapping memory
+ * copy ourself. After this copy succeeds, "rep movs" is executed
+ * again.
+ */
+ if ((addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK)) {
+ unsigned long value = 0;
+
+ mpcip->flags |= OVERLAP;
+
+ regs->eip -= inst_len; /* do not advance %eip */
+
+ if (dir == IOREQ_WRITE)
+ vmx_copy(&value, addr, size, VMX_COPY_IN);
+ send_mmio_req(IOREQ_TYPE_COPY, gpa, 1, size, value, dir, 0);
+ } else {
+ if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK)) {
+ regs->eip -= inst_len; /* do not advance %eip */
+
+ if (sign > 0)
+ count = (PAGE_SIZE - (addr & ~PAGE_MASK)) / size;
+ else
+ count = (addr & ~PAGE_MASK) / size;
+ }
+
+ send_mmio_req(IOREQ_TYPE_COPY, gpa, count, size, addr, dir, 1);
+ }
+ break;
+ }
+
+ case INSTR_MOVZ:
+ mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs);
+ break;
+
+ case INSTR_STOS:
+ /*
+ * Since the destination is always in (contiguous) mmio space we don't
+ * need to break it up into pages.
+ */
+ mpcip->flags = mmio_inst.flags;
+ mpcip->instr = mmio_inst.instr;
+ send_mmio_req(IOREQ_TYPE_COPY, gpa,
+ GET_REPEAT_COUNT(), mmio_inst.op_size, regs->eax, IOREQ_WRITE, 0);
+ break;
+
+ case INSTR_OR:
+ mmio_operands(IOREQ_TYPE_OR, gpa, &mmio_inst, mpcip, regs);
+ break;
+
+ case INSTR_AND:
+ mmio_operands(IOREQ_TYPE_AND, gpa, &mmio_inst, mpcip, regs);
+ break;
+
+ case INSTR_XOR:
+ mmio_operands(IOREQ_TYPE_XOR, gpa, &mmio_inst, mpcip, regs);
+ break;
+
+ case INSTR_CMP:
+ mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs);
+ break;
+
+ case INSTR_TEST:
+ mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs);
+ break;
+
+ default:
+ printf("Unhandled MMIO instruction\n");
+ domain_crash_synchronous();
+ }
}
#endif /* CONFIG_VMX */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/vmx_vmcs.c
--- a/xen/arch/x86/vmx_vmcs.c Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/vmx_vmcs.c Fri Sep 9 16:30:54 2005
@@ -44,7 +44,7 @@
rdmsr(MSR_IA32_VMX_BASIC_MSR, vmx_msr_low, vmx_msr_high);
vmcs_size = vmx_msr_high & 0x1fff;
- vmcs = alloc_xenheap_pages(get_order(vmcs_size));
+ vmcs = alloc_xenheap_pages(get_order_from_bytes(vmcs_size));
memset((char *)vmcs, 0, vmcs_size); /* don't remove this */
vmcs->vmcs_revision_id = vmx_msr_low;
@@ -55,7 +55,7 @@
{
int order;
- order = get_order(vmcs_size);
+ order = get_order_from_bytes(vmcs_size);
free_xenheap_pages(vmcs, order);
}
@@ -76,8 +76,8 @@
error |= __vmwrite(VM_ENTRY_CONTROLS, MONITOR_VM_ENTRY_CONTROLS);
/* need to use 0x1000 instead of PAGE_SIZE */
- io_bitmap_a = (void*) alloc_xenheap_pages(get_order(0x1000));
- io_bitmap_b = (void*) alloc_xenheap_pages(get_order(0x1000));
+ io_bitmap_a = (void*) alloc_xenheap_pages(get_order_from_bytes(0x1000));
+ io_bitmap_b = (void*) alloc_xenheap_pages(get_order_from_bytes(0x1000));
memset(io_bitmap_a, 0xff, 0x1000);
/* don't bother debug port access */
clear_bit(PC_DEBUG_PORT, io_bitmap_a);
@@ -148,7 +148,7 @@
offset = (addr & ~PAGE_MASK);
addr = round_pgdown(addr);
- mpfn = phys_to_machine_mapping(addr >> PAGE_SHIFT);
+ mpfn = get_mfn_from_pfn(addr >> PAGE_SHIFT);
p = map_domain_page(mpfn);
e820p = (struct e820entry *) ((unsigned long) p + offset);
@@ -175,7 +175,7 @@
unmap_domain_page(p);
/* Initialise shared page */
- mpfn = phys_to_machine_mapping(gpfn);
+ mpfn = get_mfn_from_pfn(gpfn);
p = map_domain_page(mpfn);
d->domain->arch.vmx_platform.shared_page_va = (unsigned long)p;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/x86_32/asm-offsets.c
--- a/xen/arch/x86/x86_32/asm-offsets.c Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/x86_32/asm-offsets.c Fri Sep 9 16:30:54 2005
@@ -71,6 +71,9 @@
OFFSET(VCPUINFO_upcall_mask, vcpu_info_t, evtchn_upcall_mask);
BLANK();
+ DEFINE(CPUINFO_sizeof, sizeof(struct cpu_info));
+ BLANK();
+
OFFSET(TRAPBOUNCE_error_code, struct trap_bounce, error_code);
OFFSET(TRAPBOUNCE_cr2, struct trap_bounce, cr2);
OFFSET(TRAPBOUNCE_flags, struct trap_bounce, flags);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/x86_32/entry.S
--- a/xen/arch/x86/x86_32/entry.S Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/x86_32/entry.S Fri Sep 9 16:30:54 2005
@@ -61,6 +61,11 @@
#include <asm/page.h>
#include <public/xen.h>
+#define GET_GUEST_REGS(reg) \
+ movl $~(STACK_SIZE-1),reg; \
+ andl %esp,reg; \
+ orl $(STACK_SIZE-CPUINFO_sizeof),reg;
+
#define GET_CURRENT(reg) \
movl $STACK_SIZE-4, reg; \
orl %esp, reg; \
@@ -121,6 +126,9 @@
ENTRY(vmx_asm_vmexit_handler)
/* selectors are restored/saved by VMX */
VMX_SAVE_ALL_NOSEGREGS
+#ifdef TRACE_BUFFER
+ call trace_vmexit
+#endif
call vmx_vmexit_handler
jmp vmx_asm_do_resume
@@ -142,6 +150,9 @@
/* vmx_restore_all_guest */
call vmx_intr_assist
call load_cr2
+#ifdef TRACE_BUFFER
+ call trace_vmentry
+#endif
.endif
VMX_RESTORE_ALL_NOSEGREGS
/*
@@ -273,7 +284,41 @@
GET_CURRENT(%ebx)
andl $(NR_hypercalls-1),%eax
PERFC_INCR(PERFC_hypercalls, %eax)
+#ifndef NDEBUG
+ /* Deliberately corrupt parameter regs not used by this hypercall. */
+ pushl %eax
+ pushl UREGS_eip+4(%esp)
+ pushl 28(%esp) # EBP
+ pushl 28(%esp) # EDI
+ pushl 28(%esp) # ESI
+ pushl 28(%esp) # EDX
+ pushl 28(%esp) # ECX
+ pushl 28(%esp) # EBX
+ movzb hypercall_args_table(,%eax,1),%ecx
+ leal (%esp,%ecx,4),%edi
+ subl $6,%ecx
+ negl %ecx
+ movl %eax,%esi
+ movl $0xDEADBEEF,%eax
+ rep stosl
+ movl %esi,%eax
+#endif
call *hypercall_table(,%eax,4)
+#ifndef NDEBUG
+ /* Deliberately corrupt parameter regs used by this hypercall. */
+ addl $24,%esp # Shadow parameters
+ popl %ecx # Shadow EIP
+ cmpl %ecx,UREGS_eip(%esp)
+ popl %ecx # Shadow hypercall index
+ jne skip_clobber # If EIP has changed then don't clobber
+ movzb hypercall_args_table(,%ecx,1),%ecx
+ movl %esp,%edi
+ movl %eax,%esi
+ movl $0xDEADBEEF,%eax
+ rep stosl
+ movl %esi,%eax
+skip_clobber:
+#endif
movl %eax,UREGS_eax(%esp) # save the return value
test_all_events:
@@ -674,12 +719,14 @@
do_arch_sched_op:
# Ensure we return success even if we return via schedule_tail()
xorl %eax,%eax
- movl %eax,UREGS_eax+4(%esp)
+ GET_GUEST_REGS(%ecx)
+ movl %eax,UREGS_eax(%ecx)
jmp do_sched_op
do_switch_vm86:
- # Discard the return address
- addl $4,%esp
+ # Reset the stack pointer
+ GET_GUEST_REGS(%ecx)
+ movl %ecx,%esp
# GS:ESI == Ring-1 stack activation
movl UREGS_esp(%esp),%esi
@@ -749,7 +796,7 @@
.long do_get_debugreg
.long do_update_descriptor /* 10 */
.long do_ni_hypercall
- .long do_dom_mem_op
+ .long do_memory_op
.long do_multicall
.long do_update_va_mapping
.long do_set_timer_op /* 15 */
@@ -768,3 +815,36 @@
.rept NR_hypercalls-((.-hypercall_table)/4)
.long do_ni_hypercall
.endr
+
+ENTRY(hypercall_args_table)
+ .byte 1 /* do_set_trap_table */ /* 0 */
+ .byte 4 /* do_mmu_update */
+ .byte 2 /* do_set_gdt */
+ .byte 2 /* do_stack_switch */
+ .byte 4 /* do_set_callbacks */
+ .byte 1 /* do_fpu_taskswitch */ /* 5 */
+ .byte 2 /* do_arch_sched_op */
+ .byte 1 /* do_dom0_op */
+ .byte 2 /* do_set_debugreg */
+ .byte 1 /* do_get_debugreg */
+ .byte 4 /* do_update_descriptor */ /* 10 */
+ .byte 0 /* do_ni_hypercall */
+ .byte 2 /* do_memory_op */
+ .byte 2 /* do_multicall */
+ .byte 4 /* do_update_va_mapping */
+ .byte 2 /* do_set_timer_op */ /* 15 */
+ .byte 1 /* do_event_channel_op */
+ .byte 1 /* do_xen_version */
+ .byte 3 /* do_console_io */
+ .byte 1 /* do_physdev_op */
+ .byte 3 /* do_grant_table_op */ /* 20 */
+ .byte 2 /* do_vm_assist */
+ .byte 5 /* do_update_va_mapping_otherdomain */
+ .byte 0 /* do_switch_vm86 */
+ .byte 2 /* do_boot_vcpu */
+ .byte 0 /* do_ni_hypercall */ /* 25 */
+ .byte 4 /* do_mmuext_op */
+ .byte 1 /* do_acm_op */
+ .rept NR_hypercalls-(.-hypercall_args_table)
+ .byte 0 /* do_ni_hypercall */
+ .endr
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/x86_32/mm.c
--- a/xen/arch/x86/x86_32/mm.c Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/x86_32/mm.c Fri Sep 9 16:30:54 2005
@@ -95,7 +95,7 @@
* Allocate and map the machine-to-phys table and create read-only mapping
* of MPT for guest-OS use.
*/
- mpt_size = (max_page * 4) + (1UL << L2_PAGETABLE_SHIFT) - 1UL;
+ mpt_size = (max_page * BYTES_PER_LONG) + (1UL << L2_PAGETABLE_SHIFT) - 1;
mpt_size &= ~((1UL << L2_PAGETABLE_SHIFT) - 1UL);
for ( i = 0; i < (mpt_size >> L2_PAGETABLE_SHIFT); i++ )
{
@@ -118,7 +118,8 @@
}
/* Set up mapping cache for domain pages. */
- mapcache_order = get_order(MAPCACHE_MBYTES << (20 - PAGETABLE_ORDER));
+ mapcache_order = get_order_from_bytes(
+ MAPCACHE_MBYTES << (20 - PAGETABLE_ORDER));
mapcache = alloc_xenheap_pages(mapcache_order);
memset(mapcache, 0, PAGE_SIZE << mapcache_order);
for ( i = 0; i < (MAPCACHE_MBYTES >> (L2_PAGETABLE_SHIFT - 20)); i++ )
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/x86_32/traps.c
--- a/xen/arch/x86/x86_32/traps.c Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/x86_32/traps.c Fri Sep 9 16:30:54 2005
@@ -79,11 +79,8 @@
"ss: %04lx cs: %04lx\n",
ds, es, fs, gs, ss, cs);
- if ( GUEST_MODE(regs) )
- show_guest_stack();
- else
- show_stack((unsigned long *)®s->esp);
-}
+ show_stack(regs);
+}
void show_page_walk(unsigned long addr)
{
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/x86_64/asm-offsets.c
--- a/xen/arch/x86/x86_64/asm-offsets.c Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/x86_64/asm-offsets.c Fri Sep 9 16:30:54 2005
@@ -71,6 +71,9 @@
OFFSET(VCPUINFO_upcall_mask, vcpu_info_t, evtchn_upcall_mask);
BLANK();
+ DEFINE(CPUINFO_sizeof, sizeof(struct cpu_info));
+ BLANK();
+
OFFSET(TRAPBOUNCE_error_code, struct trap_bounce, error_code);
OFFSET(TRAPBOUNCE_cr2, struct trap_bounce, cr2);
OFFSET(TRAPBOUNCE_flags, struct trap_bounce, flags);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/x86_64/entry.S
--- a/xen/arch/x86/x86_64/entry.S Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/x86_64/entry.S Fri Sep 9 16:30:54 2005
@@ -11,6 +11,11 @@
#include <asm/apicdef.h>
#include <asm/page.h>
#include <public/xen.h>
+
+#define GET_GUEST_REGS(reg) \
+ movq $~(STACK_SIZE-1),reg; \
+ andq %rsp,reg; \
+ orq $(STACK_SIZE-CPUINFO_sizeof),reg;
#define GET_CURRENT(reg) \
movq $STACK_SIZE-8, reg; \
@@ -120,10 +125,42 @@
/*hypercall:*/
movq %r10,%rcx
andq $(NR_hypercalls-1),%rax
+#ifndef NDEBUG
+ /* Deliberately corrupt parameter regs not used by this hypercall. */
+ pushq %rdi; pushq %rsi; pushq %rdx; pushq %rcx; pushq %r8 ; pushq %r9
+ leaq hypercall_args_table(%rip),%r10
+ movq $6,%rcx
+ sub (%r10,%rax,1),%cl
+ movq %rsp,%rdi
+ movl $0xDEADBEEF,%eax
+ rep stosq
+ popq %r9 ; popq %r8 ; popq %rcx; popq %rdx; popq %rsi; popq %rdi
+ movq UREGS_rax(%rsp),%rax
+ andq $(NR_hypercalls-1),%rax
+ pushq %rax
+ pushq UREGS_rip+8(%rsp)
+#endif
leaq hypercall_table(%rip),%r10
PERFC_INCR(PERFC_hypercalls, %rax)
callq *(%r10,%rax,8)
- movq %rax,UREGS_rax(%rsp) # save the return value
+#ifndef NDEBUG
+ /* Deliberately corrupt parameter regs used by this hypercall. */
+ popq %r10 # Shadow RIP
+ cmpq %r10,UREGS_rip(%rsp)
+ popq %rcx # Shadow hypercall index
+ jne skip_clobber /* If RIP has changed then don't clobber. */
+ leaq hypercall_args_table(%rip),%r10
+ movb (%r10,%rcx,1),%cl
+ movl $0xDEADBEEF,%r10d
+ cmpb $1,%cl; jb skip_clobber; movq %r10,UREGS_rdi(%rsp)
+ cmpb $2,%cl; jb skip_clobber; movq %r10,UREGS_rsi(%rsp)
+ cmpb $3,%cl; jb skip_clobber; movq %r10,UREGS_rdx(%rsp)
+ cmpb $4,%cl; jb skip_clobber; movq %r10,UREGS_r10(%rsp)
+ cmpb $5,%cl; jb skip_clobber; movq %r10,UREGS_r8(%rsp)
+ cmpb $6,%cl; jb skip_clobber; movq %r10,UREGS_r9(%rsp)
+skip_clobber:
+#endif
+ movq %rax,UREGS_rax(%rsp) # save the return value
/* %rbx: struct vcpu */
test_all_events:
@@ -302,7 +339,8 @@
1: /* In kernel context already: push new frame at existing %rsp. */
movq UREGS_rsp+8(%rsp),%rsi
andb $0xfc,UREGS_cs+8(%rsp) # Indicate kernel context to guest.
-2: movq $HYPERVISOR_VIRT_START,%rax
+2: andq $~0xf,%rsi # Stack frames are 16-byte aligned.
+ movq $HYPERVISOR_VIRT_START,%rax
cmpq %rax,%rsi
jb 1f # In +ve address space? Then okay.
movq $HYPERVISOR_VIRT_END+60,%rax
@@ -538,7 +576,8 @@
do_arch_sched_op:
# Ensure we return success even if we return via schedule_tail()
xorl %eax,%eax
- movq %rax,UREGS_rax+8(%rsp)
+ GET_GUEST_REGS(%r10)
+ movq %rax,UREGS_rax(%r10)
jmp do_sched_op
.data
@@ -578,7 +617,7 @@
.quad do_get_debugreg
.quad do_update_descriptor /* 10 */
.quad do_ni_hypercall
- .quad do_dom_mem_op
+ .quad do_memory_op
.quad do_multicall
.quad do_update_va_mapping
.quad do_set_timer_op /* 15 */
@@ -597,3 +636,36 @@
.rept NR_hypercalls-((.-hypercall_table)/4)
.quad do_ni_hypercall
.endr
+
+ENTRY(hypercall_args_table)
+ .byte 1 /* do_set_trap_table */ /* 0 */
+ .byte 4 /* do_mmu_update */
+ .byte 2 /* do_set_gdt */
+ .byte 2 /* do_stack_switch */
+ .byte 3 /* do_set_callbacks */
+ .byte 1 /* do_fpu_taskswitch */ /* 5 */
+ .byte 2 /* do_arch_sched_op */
+ .byte 1 /* do_dom0_op */
+ .byte 2 /* do_set_debugreg */
+ .byte 1 /* do_get_debugreg */
+ .byte 2 /* do_update_descriptor */ /* 10 */
+ .byte 0 /* do_ni_hypercall */
+ .byte 2 /* do_memory_op */
+ .byte 2 /* do_multicall */
+ .byte 3 /* do_update_va_mapping */
+ .byte 1 /* do_set_timer_op */ /* 15 */
+ .byte 1 /* do_event_channel_op */
+ .byte 1 /* do_xen_version */
+ .byte 3 /* do_console_io */
+ .byte 1 /* do_physdev_op */
+ .byte 3 /* do_grant_table_op */ /* 20 */
+ .byte 2 /* do_vm_assist */
+ .byte 4 /* do_update_va_mapping_otherdomain */
+ .byte 0 /* do_switch_to_user */
+ .byte 2 /* do_boot_vcpu */
+ .byte 2 /* do_set_segment_base */ /* 25 */
+ .byte 4 /* do_mmuext_op */
+ .byte 1 /* do_acm_op */
+ .rept NR_hypercalls-(.-hypercall_args_table)
+ .byte 0 /* do_ni_hypercall */
+ .endr
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/x86_64/mm.c
--- a/xen/arch/x86/x86_64/mm.c Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/x86_64/mm.c Fri Sep 9 16:30:54 2005
@@ -98,7 +98,7 @@
* Allocate and map the machine-to-phys table.
* This also ensures L3 is present for fixmaps.
*/
- mpt_size = (max_page * 4) + (1UL << L2_PAGETABLE_SHIFT) - 1UL;
+ mpt_size = (max_page * BYTES_PER_LONG) + (1UL << L2_PAGETABLE_SHIFT) - 1;
mpt_size &= ~((1UL << L2_PAGETABLE_SHIFT) - 1UL);
for ( i = 0; i < (mpt_size >> L2_PAGETABLE_SHIFT); i++ )
{
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/x86_64/traps.c
--- a/xen/arch/x86/x86_64/traps.c Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/x86_64/traps.c Fri Sep 9 16:30:54 2005
@@ -15,24 +15,24 @@
void show_registers(struct cpu_user_regs *regs)
{
- printk("CPU: %d\nEIP: %04x:[<%016lx>]",
+ printk("CPU: %d\nRIP: %04x:[<%016lx>]",
smp_processor_id(), 0xffff & regs->cs, regs->rip);
if ( !GUEST_MODE(regs) )
print_symbol(" %s", regs->rip);
- printk("\nEFLAGS: %016lx\n", regs->eflags);
- printk("rax: %016lx rbx: %016lx rcx: %016lx rdx: %016lx\n",
- regs->rax, regs->rbx, regs->rcx, regs->rdx);
- printk("rsi: %016lx rdi: %016lx rbp: %016lx rsp: %016lx\n",
- regs->rsi, regs->rdi, regs->rbp, regs->rsp);
- printk("r8: %016lx r9: %016lx r10: %016lx r11: %016lx\n",
- regs->r8, regs->r9, regs->r10, regs->r11);
- printk("r12: %016lx r13: %016lx r14: %016lx r15: %016lx\n",
- regs->r12, regs->r13, regs->r14, regs->r15);
+ printk("\nRFLAGS: %016lx\n", regs->eflags);
+ printk("rax: %016lx rbx: %016lx rcx: %016lx\n",
+ regs->rax, regs->rbx, regs->rcx);
+ printk("rdx: %016lx rsi: %016lx rdi: %016lx\n",
+ regs->rdx, regs->rsi, regs->rdi);
+ printk("rbp: %016lx rsp: %016lx r8: %016lx\n",
+ regs->rbp, regs->rsp, regs->r8);
+ printk("r9: %016lx r10: %016lx r11: %016lx\n",
+ regs->r9, regs->r10, regs->r11);
+ printk("r12: %016lx r13: %016lx r14: %016lx\n",
+ regs->r12, regs->r13, regs->r14);
+ printk("r15: %016lx\n", regs->r15);
- if ( GUEST_MODE(regs) )
- show_guest_stack();
- else
- show_stack((unsigned long *)regs->rsp);
+ show_stack(regs);
}
void show_page_walk(unsigned long addr)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/common/Makefile
--- a/xen/common/Makefile Thu Sep 8 15:18:40 2005
+++ b/xen/common/Makefile Fri Sep 9 16:30:54 2005
@@ -2,7 +2,6 @@
include $(BASEDIR)/Rules.mk
ifeq ($(TARGET_ARCH),ia64)
-#OBJS := $(subst dom_mem_ops.o,,$(OBJS))
OBJS := $(subst grant_table.o,,$(OBJS))
endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/common/acm_ops.c
--- a/xen/common/acm_ops.c Thu Sep 8 15:18:40 2005
+++ b/xen/common/acm_ops.c Fri Sep 9 16:30:54 2005
@@ -19,6 +19,7 @@
#include <xen/types.h>
#include <xen/lib.h>
#include <xen/mm.h>
+#include <public/acm.h>
#include <public/acm_ops.h>
#include <xen/sched.h>
#include <xen/event.h>
@@ -41,7 +42,8 @@
POLICY, /* access to policy interface (early drop) */
GETPOLICY, /* dump policy cache */
SETPOLICY, /* set policy cache (controls security) */
- DUMPSTATS /* dump policy statistics */
+ DUMPSTATS, /* dump policy statistics */
+ GETSSID /* retrieve ssidref for domain id */
} acm_operation_t;
int acm_authorize_acm_ops(struct domain *d, acm_operation_t pops)
@@ -117,6 +119,35 @@
}
break;
+ case ACM_GETSSID:
+ {
+ ssidref_t ssidref;
+
+ if (acm_authorize_acm_ops(current->domain, GETSSID))
+ return -EACCES;
+
+ if (op->u.getssid.get_ssid_by == SSIDREF)
+ ssidref = op->u.getssid.id.ssidref;
+ else if (op->u.getssid.get_ssid_by == DOMAINID) {
+ struct domain *subj =
find_domain_by_id(op->u.getssid.id.domainid);
+ if (!subj)
+ return -ESRCH; /* domain not found */
+
+ ssidref = ((struct acm_ssid_domain
*)(subj->ssid))->ssidref;
+ put_domain(subj);
+ } else
+ return -ESRCH;
+
+ ret = acm_get_ssid(ssidref,
+ op->u.getssid.ssidbuf,
+ op->u.getssid.ssidbuf_size);
+ if (ret == ACM_OK)
+ ret = 0;
+ else
+ ret = -ESRCH;
+ }
+ break;
+
default:
ret = -ESRCH;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/common/domain.c
--- a/xen/common/domain.c Thu Sep 8 15:18:40 2005
+++ b/xen/common/domain.c Fri Sep 9 16:30:54 2005
@@ -114,6 +114,8 @@
sched_rem_domain(v);
domain_relinquish_resources(d);
put_domain(d);
+
+ send_guest_virq(dom0->vcpu[0], VIRQ_DOM_EXC);
}
}
@@ -174,7 +176,7 @@
void domain_shutdown(u8 reason)
{
struct domain *d = current->domain;
- struct vcpu *v;
+ struct vcpu *v;
if ( d->domain_id == 0 )
{
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/common/event_channel.c
--- a/xen/common/event_channel.c Thu Sep 8 15:18:40 2005
+++ b/xen/common/event_channel.c Fri Sep 9 16:30:54 2005
@@ -250,6 +250,9 @@
if ( virq >= ARRAY_SIZE(v->virq_to_evtchn) )
return -EINVAL;
+
+ if ( d->domain_id == 0 && virq >= VIRQ_CONSOLE )
+ v = d->vcpu[0];
spin_lock(&d->evtchn_lock);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/common/grant_table.c
--- a/xen/common/grant_table.c Thu Sep 8 15:18:40 2005
+++ b/xen/common/grant_table.c Fri Sep 9 16:30:54 2005
@@ -399,7 +399,7 @@
{
int i;
grant_mapping_t *new_mt;
- grant_table_t *lgt = ld->grant_table;
+ grant_table_t *lgt = ld->grant_table;
if ( (lgt->maptrack_limit << 1) > MAPTRACK_MAX_ENTRIES )
{
@@ -437,9 +437,8 @@
ref, dom, dev_hst_ro_flags);
#endif
- if ( 0 <= ( rc = __gnttab_activate_grant_ref( ld, led, rd, ref,
- dev_hst_ro_flags,
- addr, &frame)))
+ if ( (rc = __gnttab_activate_grant_ref(ld, led, rd, ref, dev_hst_ro_flags,
+ addr, &frame)) >= 0 )
{
/*
* Only make the maptrack live _after_ writing the pte, in case we
@@ -807,7 +806,8 @@
int i;
int result = GNTST_okay;
- for (i = 0; i < count; i++) {
+ for ( i = 0; i < count; i++ )
+ {
gnttab_donate_t *gop = &uop[i];
#if GRANT_DEBUG
printk("gnttab_donate: i=%d mfn=%lx domid=%d gref=%08x\n",
@@ -815,19 +815,24 @@
#endif
page = &frame_table[gop->mfn];
- if (unlikely(IS_XEN_HEAP_FRAME(page))) {
+ if ( unlikely(IS_XEN_HEAP_FRAME(page)))
+ {
printk("gnttab_donate: xen heap frame mfn=%lx\n",
(unsigned long) gop->mfn);
gop->status = GNTST_bad_virt_addr;
continue;
}
- if (unlikely(!pfn_valid(page_to_pfn(page)))) {
+
+ if ( unlikely(!pfn_valid(page_to_pfn(page))) )
+ {
printk("gnttab_donate: invalid pfn for mfn=%lx\n",
(unsigned long) gop->mfn);
gop->status = GNTST_bad_virt_addr;
continue;
}
- if (unlikely((e = find_domain_by_id(gop->domid)) == NULL)) {
+
+ if ( unlikely((e = find_domain_by_id(gop->domid)) == NULL) )
+ {
printk("gnttab_donate: can't find domain %d\n", gop->domid);
gop->status = GNTST_bad_domain;
continue;
@@ -881,47 +886,23 @@
* headroom. Also, a domain mustn't have PGC_allocated
* pages when it is dying.
*/
-#ifdef GRANT_DEBUG
- if (unlikely(e->tot_pages >= e->max_pages)) {
- printk("gnttab_dontate: no headroom tot_pages=%d max_pages=%d\n",
- e->tot_pages, e->max_pages);
+ if ( unlikely(test_bit(DOMFLAGS_DYING, &e->domain_flags)) ||
+ unlikely(e->tot_pages >= e->max_pages) ||
+ unlikely(!gnttab_prepare_for_transfer(e, d, gop->handle)) )
+ {
+ DPRINTK("gnttab_donate: Transferee has no reservation headroom "
+ "(%d,%d) or provided a bad grant ref (%08x) or "
+ "is dying (%lx)\n",
+ e->tot_pages, e->max_pages, gop->handle, e->domain_flags);
spin_unlock(&e->page_alloc_lock);
put_domain(e);
- result = GNTST_general_error;
+ gop->status = result = GNTST_general_error;
break;
}
- if (unlikely(test_bit(DOMFLAGS_DYING, &e->domain_flags))) {
- printk("gnttab_donate: target domain is dying\n");
- spin_unlock(&e->page_alloc_lock);
- put_domain(e);
- result = GNTST_general_error;
- break;
- }
- if (unlikely(!gnttab_prepare_for_transfer(e, d, gop->handle))) {
- printk("gnttab_donate: gnttab_prepare_for_transfer fails\n");
- spin_unlock(&e->page_alloc_lock);
- put_domain(e);
- result = GNTST_general_error;
- break;
- }
-#else
- ASSERT(e->tot_pages <= e->max_pages);
- if (unlikely(test_bit(DOMFLAGS_DYING, &e->domain_flags)) ||
- unlikely(e->tot_pages == e->max_pages) ||
- unlikely(!gnttab_prepare_for_transfer(e, d, gop->handle))) {
- printk("gnttab_donate: Transferee has no reservation headroom (%d,"
- "%d) or provided a bad grant ref (%08x) or is dying (%p)\n",
- e->tot_pages, e->max_pages, gop->handle, e->d_flags);
- spin_unlock(&e->page_alloc_lock);
- put_domain(e);
- result = GNTST_general_error;
- break;
- }
-#endif
+
/* Okay, add the page to 'e'. */
- if (unlikely(e->tot_pages++ == 0)) {
+ if ( unlikely(e->tot_pages++ == 0) )
get_knownalive_domain(e);
- }
list_add_tail(&page->list, &e->page_list);
page_set_owner(page, e);
@@ -937,6 +918,7 @@
gop->status = GNTST_okay;
}
+
return result;
}
@@ -956,38 +938,38 @@
rc = -EFAULT;
switch ( cmd )
- {
- case GNTTABOP_map_grant_ref:
- if ( unlikely(!array_access_ok(
- uop, count, sizeof(gnttab_map_grant_ref_t))) )
- goto out;
- rc = gnttab_map_grant_ref((gnttab_map_grant_ref_t *)uop, count);
- break;
- case GNTTABOP_unmap_grant_ref:
- if ( unlikely(!array_access_ok(
- uop, count, sizeof(gnttab_unmap_grant_ref_t))) )
- goto out;
- rc = gnttab_unmap_grant_ref((gnttab_unmap_grant_ref_t *)uop,
- count);
- break;
- case GNTTABOP_setup_table:
- rc = gnttab_setup_table((gnttab_setup_table_t *)uop, count);
- break;
+ {
+ case GNTTABOP_map_grant_ref:
+ if ( unlikely(!array_access_ok(
+ uop, count, sizeof(gnttab_map_grant_ref_t))) )
+ goto out;
+ rc = gnttab_map_grant_ref((gnttab_map_grant_ref_t *)uop, count);
+ break;
+ case GNTTABOP_unmap_grant_ref:
+ if ( unlikely(!array_access_ok(
+ uop, count, sizeof(gnttab_unmap_grant_ref_t))) )
+ goto out;
+ rc = gnttab_unmap_grant_ref(
+ (gnttab_unmap_grant_ref_t *)uop, count);
+ break;
+ case GNTTABOP_setup_table:
+ rc = gnttab_setup_table((gnttab_setup_table_t *)uop, count);
+ break;
#if GRANT_DEBUG
- case GNTTABOP_dump_table:
- rc = gnttab_dump_table((gnttab_dump_table_t *)uop);
- break;
+ case GNTTABOP_dump_table:
+ rc = gnttab_dump_table((gnttab_dump_table_t *)uop);
+ break;
#endif
- case GNTTABOP_donate:
- if (unlikely(!array_access_ok(uop, count,
- sizeof(gnttab_donate_t))))
- goto out;
- rc = gnttab_donate(uop, count);
- break;
- default:
- rc = -ENOSYS;
- break;
- }
+ case GNTTABOP_donate:
+ if (unlikely(!array_access_ok(
+ uop, count, sizeof(gnttab_donate_t))))
+ goto out;
+ rc = gnttab_donate(uop, count);
+ break;
+ default:
+ rc = -ENOSYS;
+ break;
+ }
out:
UNLOCK_BIGLOCK(d);
@@ -1020,17 +1002,17 @@
lgt = ld->grant_table;
#if GRANT_DEBUG_VERBOSE
- if ( ld->domain_ id != 0 ) {
- DPRINTK("Foreign unref rd(%d) ld(%d) frm(%lx) flgs(%x).\n",
- rd->domain_id, ld->domain_id, frame, readonly);
- }
+ if ( ld->domain_id != 0 )
+ DPRINTK("Foreign unref rd(%d) ld(%d) frm(%lx) flgs(%x).\n",
+ rd->domain_id, ld->domain_id, frame, readonly);
#endif
/* Fast exit if we're not mapping anything using grant tables */
if ( lgt->map_count == 0 )
return 0;
- if ( get_domain(rd) == 0 ) {
+ if ( get_domain(rd) == 0 )
+ {
DPRINTK("gnttab_check_unmap: couldn't get_domain rd(%d)\n",
rd->domain_id);
return 0;
@@ -1211,13 +1193,13 @@
DPRINTK("Bad pfn (%lx)\n", pfn);
else
{
- machine_to_phys_mapping[frame] = pfn;
+ set_pfn_from_mfn(frame, pfn);
if ( unlikely(shadow_mode_log_dirty(ld)))
mark_dirty(ld, frame);
if (shadow_mode_translate(ld))
- __phys_to_machine_mapping[pfn] = frame;
+ set_mfn_from_pfn(pfn, frame);
}
sha->frame = __mfn_to_gpfn(rd, frame);
sha->domid = rd->domain_id;
@@ -1267,9 +1249,11 @@
for ( i = 0; i < NR_GRANT_FRAMES; i++ )
{
SHARE_PFN_WITH_DOMAIN(
- virt_to_page((char *)(t->shared)+(i*PAGE_SIZE)), d);
- machine_to_phys_mapping[(virt_to_phys(t->shared) >> PAGE_SHIFT) + i] =
- INVALID_M2P_ENTRY;
+ virt_to_page((char *)t->shared + (i * PAGE_SIZE)),
+ d);
+ set_pfn_from_mfn(
+ (virt_to_phys(t->shared) >> PAGE_SHIFT) + i,
+ INVALID_M2P_ENTRY);
}
/* Okay, install the structure. */
@@ -1306,57 +1290,53 @@
{
map = >->maptrack[handle];
- if ( map->ref_and_flags & GNTMAP_device_map )
- {
- dom = map->domid;
- ref = map->ref_and_flags >> MAPTRACK_REF_SHIFT;
-
- DPRINTK("Grant release (%hu) ref:(%hu) flags:(%x) dom:(%hu)\n",
- handle, ref,
- map->ref_and_flags & MAPTRACK_GNTMAP_MASK, dom);
-
- if ( unlikely((rd = find_domain_by_id(dom)) == NULL) ||
- unlikely(ld == rd) )
+ if ( !(map->ref_and_flags & GNTMAP_device_map) )
+ continue;
+
+ dom = map->domid;
+ ref = map->ref_and_flags >> MAPTRACK_REF_SHIFT;
+
+ DPRINTK("Grant release (%hu) ref:(%hu) flags:(%x) dom:(%hu)\n",
+ handle, ref, map->ref_and_flags & MAPTRACK_GNTMAP_MASK, dom);
+
+ if ( unlikely((rd = find_domain_by_id(dom)) == NULL) ||
+ unlikely(ld == rd) )
+ {
+ if ( rd != NULL )
+ put_domain(rd);
+ printk(KERN_WARNING "Grant release: No dom%d\n", dom);
+ continue;
+ }
+
+ act = &rd->grant_table->active[ref];
+ sha = &rd->grant_table->shared[ref];
+
+ spin_lock(&rd->grant_table->lock);
+
+ if ( act->pin & (GNTPIN_devw_mask | GNTPIN_devr_mask) )
+ {
+ frame = act->frame;
+
+ if ( ( (act->pin & GNTPIN_hstw_mask) == 0 ) &&
+ ( (act->pin & GNTPIN_devw_mask) > 0 ) )
{
- if ( rd != NULL )
- put_domain(rd);
-
- printk(KERN_WARNING "Grant release: No dom%d\n", dom);
- continue;
+ clear_bit(_GTF_writing, &sha->flags);
+ put_page_type(&frame_table[frame]);
}
- act = &rd->grant_table->active[ref];
- sha = &rd->grant_table->shared[ref];
-
- spin_lock(&rd->grant_table->lock);
-
- if ( act->pin & (GNTPIN_devw_mask | GNTPIN_devr_mask) )
+ map->ref_and_flags &= ~GNTMAP_device_map;
+ act->pin &= ~(GNTPIN_devw_mask | GNTPIN_devr_mask);
+ if ( act->pin == 0 )
{
- frame = act->frame;
-
- if ( ( (act->pin & GNTPIN_hstw_mask) == 0 ) &&
- ( (act->pin & GNTPIN_devw_mask) > 0 ) )
- {
- clear_bit(_GTF_writing, &sha->flags);
- put_page_type(&frame_table[frame]);
- }
-
- act->pin &= ~(GNTPIN_devw_mask | GNTPIN_devr_mask);
-
- if ( act->pin == 0 )
- {
- clear_bit(_GTF_reading, &sha->flags);
- map->ref_and_flags = 0;
- put_page(&frame_table[frame]);
- }
- else
- map->ref_and_flags &= ~GNTMAP_device_map;
+ clear_bit(_GTF_reading, &sha->flags);
+ map->ref_and_flags = 0;
+ put_page(&frame_table[frame]);
}
-
- spin_unlock(&rd->grant_table->lock);
-
- put_domain(rd);
- }
+ }
+
+ spin_unlock(&rd->grant_table->lock);
+
+ put_domain(rd);
}
}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/common/kernel.c
--- a/xen/common/kernel.c Thu Sep 8 15:18:40 2005
+++ b/xen/common/kernel.c Fri Sep 9 16:30:54 2005
@@ -46,7 +46,7 @@
if ( optval != NULL )
*optval++ = '\0';
- for ( param = &__setup_start; param != &__setup_end; param++ )
+ for ( param = &__setup_start; param <= &__setup_end; param++ )
{
if ( strcmp(param->name, opt ) != 0 )
continue;
@@ -110,6 +110,38 @@
return -EFAULT;
return 0;
}
+
+ case XENVER_capabilities:
+ {
+ xen_capabilities_info_t info;
+ extern void arch_get_xen_caps(xen_capabilities_info_t * info);
+
+ memset(&info, 0, sizeof(info));
+ arch_get_xen_caps(&info);
+
+ if ( copy_to_user(arg, &info, sizeof(info)) )
+ return -EFAULT;
+ return 0;
+ }
+
+ case XENVER_parameters:
+ {
+ xen_parameters_info_t info = { .virt_start = HYPERVISOR_VIRT_START };
+
+ if ( copy_to_user(arg, &info, sizeof(info)) )
+ return -EFAULT;
+ return 0;
+
+ }
+
+ case XENVER_changeset:
+ {
+ xen_changeset_info_t chgset;
+ safe_strcpy(chgset, XEN_CHANGESET);
+ if ( copy_to_user(arg, chgset, sizeof(chgset)) )
+ return -EFAULT;
+ return 0;
+ }
}
return -ENOSYS;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/common/multicall.c
--- a/xen/common/multicall.c Thu Sep 8 15:18:40 2005
+++ b/xen/common/multicall.c Fri Sep 9 16:30:54 2005
@@ -45,6 +45,18 @@
do_multicall_call(&mcs->call);
+#ifndef NDEBUG
+ {
+ /*
+ * Deliberately corrupt the contents of the multicall structure.
+ * The caller must depend only on the 'result' field on return.
+ */
+ multicall_entry_t corrupt;
+ memset(&corrupt, 0xAA, sizeof(corrupt));
+ (void)__copy_to_user(&call_list[i], &corrupt, sizeof(corrupt));
+ }
+#endif
+
if ( unlikely(__put_user(mcs->call.result, &call_list[i].result)) )
{
DPRINTK("Error writing result back to multicall block.\n");
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/common/page_alloc.c
--- a/xen/common/page_alloc.c Thu Sep 8 15:18:40 2005
+++ b/xen/common/page_alloc.c Fri Sep 9 16:30:54 2005
@@ -216,7 +216,7 @@
#define NR_ZONES 3
-#define MAX_DMADOM_PFN 0xFFFFF
+#define MAX_DMADOM_PFN 0x7FFFFUL /* 31 addressable bits */
#define pfn_dom_zone_type(_pfn) \
(((_pfn) <= MAX_DMADOM_PFN) ? MEMZONE_DMADOM : MEMZONE_DOM)
@@ -485,43 +485,40 @@
void init_domheap_pages(physaddr_t ps, physaddr_t pe)
{
+ unsigned long s_tot, e_tot, s_dma, e_dma, s_nrm, e_nrm;
+
ASSERT(!in_irq());
- ps = round_pgup(ps) >> PAGE_SHIFT;
- pe = round_pgdown(pe) >> PAGE_SHIFT;
- if ( pe <= ps )
- return;
-
- if ( (ps < MAX_DMADOM_PFN) && (pe > MAX_DMADOM_PFN) )
- {
- init_heap_pages(
- MEMZONE_DMADOM, pfn_to_page(ps), MAX_DMADOM_PFN - ps);
- init_heap_pages(
- MEMZONE_DOM, pfn_to_page(MAX_DMADOM_PFN), pe - MAX_DMADOM_PFN);
- }
- else
- {
- init_heap_pages(pfn_dom_zone_type(ps), pfn_to_page(ps), pe - ps);
- }
+ s_tot = round_pgup(ps) >> PAGE_SHIFT;
+ e_tot = round_pgdown(pe) >> PAGE_SHIFT;
+
+ s_dma = min(s_tot, MAX_DMADOM_PFN + 1);
+ e_dma = min(e_tot, MAX_DMADOM_PFN + 1);
+ if ( s_dma < e_dma )
+ init_heap_pages(MEMZONE_DMADOM, pfn_to_page(s_dma), e_dma - s_dma);
+
+ s_nrm = max(s_tot, MAX_DMADOM_PFN + 1);
+ e_nrm = max(e_tot, MAX_DMADOM_PFN + 1);
+ if ( s_nrm < e_nrm )
+ init_heap_pages(MEMZONE_DOM, pfn_to_page(s_nrm), e_nrm - s_nrm);
}
struct pfn_info *alloc_domheap_pages(
struct domain *d, unsigned int order, unsigned int flags)
{
- struct pfn_info *pg;
+ struct pfn_info *pg = NULL;
cpumask_t mask;
int i;
ASSERT(!in_irq());
- pg = NULL;
- if (! (flags & ALLOC_DOM_DMA))
+ if ( !(flags & ALLOC_DOM_DMA) )
pg = alloc_heap_pages(MEMZONE_DOM, order);
- if (pg == NULL) {
- if ( unlikely((pg = alloc_heap_pages(MEMZONE_DMADOM, order)) == NULL) )
+
+ if ( pg == NULL )
+ if ( (pg = alloc_heap_pages(MEMZONE_DMADOM, order)) == NULL )
return NULL;
- }
mask = pg->u.free.cpumask;
tlbflush_filter(mask, pg->tlbflush_timestamp);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/common/schedule.c
--- a/xen/common/schedule.c Thu Sep 8 15:18:40 2005
+++ b/xen/common/schedule.c Fri Sep 9 16:30:54 2005
@@ -218,9 +218,7 @@
&& spin_is_locked(&schedule_data[v->processor].schedule_lock) )
cpu_relax();
- /* Counteract lazy context switching. */
- if ( cpu_isset(v->processor, v->domain->cpumask) )
- sync_lazy_execstate_cpu(v->processor);
+ sync_vcpu_execstate(v);
}
void vcpu_wake(struct vcpu *v)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/common/trace.c
--- a/xen/common/trace.c Thu Sep 8 15:18:40 2005
+++ b/xen/common/trace.c Fri Sep 9 16:30:54 2005
@@ -66,7 +66,7 @@
}
nr_pages = num_online_cpus() * opt_tbuf_size;
- order = get_order(nr_pages * PAGE_SIZE);
+ order = get_order_from_pages(nr_pages);
if ( (rawbuf = alloc_xenheap_pages(order)) == NULL )
{
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/common/xmalloc.c
--- a/xen/common/xmalloc.c Thu Sep 8 15:18:40 2005
+++ b/xen/common/xmalloc.c Fri Sep 9 16:30:54 2005
@@ -86,7 +86,7 @@
static void *xmalloc_whole_pages(size_t size)
{
struct xmalloc_hdr *hdr;
- unsigned int pageorder = get_order(size);
+ unsigned int pageorder = get_order_from_bytes(size);
hdr = alloc_xenheap_pages(pageorder);
if ( hdr == NULL )
@@ -159,7 +159,7 @@
/* Big allocs free directly. */
if ( hdr->size >= PAGE_SIZE )
{
- free_xenheap_pages(hdr, get_order(hdr->size));
+ free_xenheap_pages(hdr, get_order_from_bytes(hdr->size));
return;
}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/drivers/char/console.c
--- a/xen/drivers/char/console.c Thu Sep 8 15:18:40 2005
+++ b/xen/drivers/char/console.c Fri Sep 9 16:30:54 2005
@@ -627,7 +627,7 @@
if ( bytes == 0 )
return 0;
- order = get_order(bytes);
+ order = get_order_from_bytes(bytes);
debugtrace_buf = alloc_xenheap_pages(order);
ASSERT(debugtrace_buf != NULL);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/drivers/char/serial.c
--- a/xen/drivers/char/serial.c Thu Sep 8 15:18:40 2005
+++ b/xen/drivers/char/serial.c Fri Sep 9 16:30:54 2005
@@ -366,8 +366,9 @@
void serial_async_transmit(struct serial_port *port)
{
BUG_ON(!port->driver->tx_empty);
- if ( !port->txbuf )
- port->txbuf = alloc_xenheap_pages(get_order(SERIAL_TXBUFSZ));
+ if ( port->txbuf == NULL )
+ port->txbuf = alloc_xenheap_pages(
+ get_order_from_bytes(SERIAL_TXBUFSZ));
}
/*
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/acm/acm_core.h
--- a/xen/include/acm/acm_core.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/acm/acm_core.h Fri Sep 9 16:30:54 2005
@@ -101,9 +101,15 @@
* primary ssidref = lower 16 bit
* secondary ssidref = higher 16 bit
*/
+#define ACM_PRIMARY(ssidref) \
+ ((ssidref) & 0xffff)
+
+#define ACM_SECONDARY(ssidref) \
+ ((ssidref) >> 16)
+
#define GET_SSIDREF(POLICY, ssidref) \
((POLICY) == acm_bin_pol.primary_policy_code) ? \
- ((ssidref) & 0xffff) : ((ssidref) >> 16)
+ ACM_PRIMARY(ssidref) : ACM_SECONDARY(ssidref)
/* macros to access ssid pointer for primary / secondary policy */
#define GET_SSIDP(POLICY, ssid) \
@@ -116,6 +122,7 @@
int acm_set_policy(void *buf, u16 buf_size, int isuserbuffer);
int acm_get_policy(void *buf, u16 buf_size);
int acm_dump_statistics(void *buf, u16 buf_size);
+int acm_get_ssid(ssidref_t ssidref, u8 *buf, u16 buf_size);
#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/acm/acm_hooks.h
--- a/xen/include/acm/acm_hooks.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/acm/acm_hooks.h Fri Sep 9 16:30:54 2005
@@ -92,6 +92,7 @@
int (*dump_binary_policy) (u8 *buffer, u16 buf_size);
int (*set_binary_policy) (u8 *buffer, u16 buf_size);
int (*dump_statistics) (u8 *buffer, u16 buf_size);
+ int (*dump_ssid_types) (ssidref_t ssidref, u8 *buffer, u16
buf_size);
/* domain management control hooks (can be NULL) */
int (*pre_domain_create) (void *subject_ssid, ssidref_t ssidref);
void (*post_domain_create) (domid_t domid, ssidref_t ssidref);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/asm_defns.h
--- a/xen/include/asm-x86/asm_defns.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/asm-x86/asm_defns.h Fri Sep 9 16:30:54 2005
@@ -6,11 +6,6 @@
#include <asm/asm-offsets.h>
#include <asm/processor.h>
-#ifndef STR
-#define __STR(x) #x
-#define STR(x) __STR(x)
-#endif
-
#ifdef __x86_64__
#include <asm/x86_64/asm_defns.h>
#else
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/bitops.h
--- a/xen/include/asm-x86/bitops.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/asm-x86/bitops.h Fri Sep 9 16:30:54 2005
@@ -6,11 +6,6 @@
*/
#include <xen/config.h>
-
-#ifndef STR
-#define __STR(x) #x
-#define STR(x) __STR(x)
-#endif
/*
* These have to be done with inline assembly: that way the bit-setting
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/mm.h
--- a/xen/include/asm-x86/mm.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/asm-x86/mm.h Fri Sep 9 16:30:54 2005
@@ -255,10 +255,13 @@
* contiguous (or near contiguous) physical memory.
*/
#undef machine_to_phys_mapping
-#define machine_to_phys_mapping ((u32 *)RDWR_MPT_VIRT_START)
-#define INVALID_M2P_ENTRY (~0U)
-#define VALID_M2P(_e) (!((_e) & (1U<<31)))
+#define machine_to_phys_mapping ((unsigned long *)RDWR_MPT_VIRT_START)
+#define INVALID_M2P_ENTRY (~0UL)
+#define VALID_M2P(_e) (!((_e) & (1UL<<(BITS_PER_LONG-1))))
#define IS_INVALID_M2P_ENTRY(_e) (!VALID_M2P(_e))
+
+#define set_pfn_from_mfn(mfn, pfn) (machine_to_phys_mapping[(mfn)] = (pfn))
+#define get_pfn_from_mfn(mfn) (machine_to_phys_mapping[(mfn)])
/*
* The phys_to_machine_mapping is the reversed mapping of MPT for full
@@ -266,17 +269,17 @@
* guests, so we steal the address space that would have normally
* been used by the read-only MPT map.
*/
-#define __phys_to_machine_mapping ((unsigned long *)RO_MPT_VIRT_START)
-#define INVALID_MFN (~0UL)
-#define VALID_MFN(_mfn) (!((_mfn) & (1U<<31)))
-
-/* Returns the machine physical */
-static inline unsigned long phys_to_machine_mapping(unsigned long pfn)
+#define phys_to_machine_mapping ((unsigned long *)RO_MPT_VIRT_START)
+#define INVALID_MFN (~0UL)
+#define VALID_MFN(_mfn) (!((_mfn) & (1U<<31)))
+
+#define set_mfn_from_pfn(pfn, mfn) (phys_to_machine_mapping[(pfn)] = (mfn))
+static inline unsigned long get_mfn_from_pfn(unsigned long pfn)
{
unsigned long mfn;
l1_pgentry_t pte;
- if ( (__copy_from_user(&pte, &__phys_to_machine_mapping[pfn],
+ if ( (__copy_from_user(&pte, &phys_to_machine_mapping[pfn],
sizeof(pte)) == 0) &&
(l1e_get_flags(pte) & _PAGE_PRESENT) )
mfn = l1e_get_pfn(pte);
@@ -285,7 +288,6 @@
return mfn;
}
-#define set_machinetophys(_mfn, _pfn) machine_to_phys_mapping[(_mfn)] = (_pfn)
#ifdef MEMORY_GUARD
void memguard_init(void);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/page-guest32.h
--- a/xen/include/asm-x86/page-guest32.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/asm-x86/page-guest32.h Fri Sep 9 16:30:54 2005
@@ -32,6 +32,11 @@
/* Get pte access flags (unsigned int). */
#define l1e_get_flags_32(x) (get_pte_flags_32((x).l1))
#define l2e_get_flags_32(x) (get_pte_flags_32((x).l2))
+
+#define l1e_get_paddr_32(x) \
+ ((physaddr_t)(((x).l1 & (PADDR_MASK&PAGE_MASK))))
+#define l2e_get_paddr_32(x) \
+ ((physaddr_t)(((x).l2 & (PADDR_MASK&PAGE_MASK))))
/* Construct an empty pte. */
#define l1e_empty_32() ((l1_pgentry_32_t) { 0 })
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/page.h
--- a/xen/include/asm-x86/page.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/asm-x86/page.h Fri Sep 9 16:30:54 2005
@@ -280,12 +280,21 @@
#ifndef __ASSEMBLY__
-static __inline__ int get_order(unsigned long size)
+static inline int get_order_from_bytes(physaddr_t size)
{
int order;
size = (size-1) >> PAGE_SHIFT;
for ( order = 0; size; order++ )
size >>= 1;
+ return order;
+}
+
+static inline int get_order_from_pages(unsigned long nr_pages)
+{
+ int order;
+ nr_pages--;
+ for ( order = 0; nr_pages; order++ )
+ nr_pages >>= 1;
return order;
}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/processor.h
--- a/xen/include/asm-x86/processor.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/asm-x86/processor.h Fri Sep 9 16:30:54 2005
@@ -496,9 +496,7 @@
#endif
-void show_guest_stack();
-void show_trace(unsigned long *esp);
-void show_stack(unsigned long *esp);
+void show_stack(struct cpu_user_regs *regs);
void show_registers(struct cpu_user_regs *regs);
void show_page_walk(unsigned long addr);
asmlinkage void fatal_trap(int trapnr, struct cpu_user_regs *regs);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/shadow.h
--- a/xen/include/asm-x86/shadow.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/asm-x86/shadow.h Fri Sep 9 16:30:54 2005
@@ -34,6 +34,8 @@
#include <asm/vmx.h>
#include <public/dom0_ops.h>
#include <asm/shadow_public.h>
+#include <asm/page-guest32.h>
+#include <asm/shadow_ops.h>
/* Shadow PT operation mode : shadow-mode variable in arch_domain. */
@@ -104,9 +106,9 @@
} while (0)
#endif
-#define SHADOW_ENCODE_MIN_MAX(_min, _max) ((((L1_PAGETABLE_ENTRIES - 1) -
(_max)) << 16) | (_min))
+#define SHADOW_ENCODE_MIN_MAX(_min, _max) ((((GUEST_L1_PAGETABLE_ENTRIES - 1)
- (_max)) << 16) | (_min))
#define SHADOW_MIN(_encoded) ((_encoded) & ((1u<<16) - 1))
-#define SHADOW_MAX(_encoded) ((L1_PAGETABLE_ENTRIES - 1) - ((_encoded) >> 16))
+#define SHADOW_MAX(_encoded) ((GUEST_L1_PAGETABLE_ENTRIES - 1) - ((_encoded)
>> 16))
extern void shadow_mode_init(void);
extern int shadow_mode_control(struct domain *p, dom0_shadow_control_t *sc);
@@ -132,6 +134,7 @@
struct domain_mmap_cache *cache);
#if CONFIG_PAGING_LEVELS >= 3
#include <asm/page-guest32.h>
+extern unsigned long gva_to_gpa(unsigned long gva);
extern void shadow_l3_normal_pt_update(struct domain *d,
unsigned long pa, l3_pgentry_t l3e,
struct domain_mmap_cache *cache);
@@ -269,14 +272,14 @@
#define __mfn_to_gpfn(_d, mfn) \
( (shadow_mode_translate(_d)) \
- ? machine_to_phys_mapping[(mfn)] \
+ ? get_pfn_from_mfn(mfn) \
: (mfn) )
#define __gpfn_to_mfn(_d, gpfn) \
({ \
ASSERT(current->domain == (_d)); \
(shadow_mode_translate(_d)) \
- ? phys_to_machine_mapping(gpfn) \
+ ? get_mfn_from_pfn(gpfn) \
: (gpfn); \
})
@@ -461,7 +464,7 @@
// This wants the nice compact set of PFNs from 0..domain's max,
// which __mfn_to_gpfn() only returns for translated domains.
//
- pfn = machine_to_phys_mapping[mfn];
+ pfn = get_pfn_from_mfn(mfn);
/*
* Values with the MSB set denote MFNs that aren't really part of the
@@ -562,7 +565,7 @@
old_hl2e = v->arch.hl2_vtable[index];
if ( (l2e_get_flags(gl2e) & _PAGE_PRESENT) &&
- VALID_MFN(mfn = phys_to_machine_mapping(l2e_get_pfn(gl2e))) )
+ VALID_MFN(mfn = get_mfn_from_pfn(l2e_get_pfn(gl2e))) )
new_hl2e = l1e_from_pfn(mfn, __PAGE_HYPERVISOR);
else
new_hl2e = l1e_empty();
@@ -794,22 +797,22 @@
#endif
static inline void l1pte_propagate_from_guest(
- struct domain *d, l1_pgentry_t gpte, l1_pgentry_t *spte_p)
+ struct domain *d, guest_l1_pgentry_t gpte, l1_pgentry_t *spte_p)
{
unsigned long mfn;
l1_pgentry_t spte;
spte = l1e_empty();
- if ( ((l1e_get_flags(gpte) & (_PAGE_PRESENT|_PAGE_ACCESSED) ) ==
+ if ( ((guest_l1e_get_flags(gpte) & (_PAGE_PRESENT|_PAGE_ACCESSED) ) ==
(_PAGE_PRESENT|_PAGE_ACCESSED)) &&
VALID_MFN(mfn = __gpfn_to_mfn(d, l1e_get_pfn(gpte))) )
{
spte = l1e_from_pfn(
- mfn, l1e_get_flags(gpte) & ~(_PAGE_GLOBAL | _PAGE_AVAIL));
+ mfn, guest_l1e_get_flags(gpte) & ~(_PAGE_GLOBAL | _PAGE_AVAIL));
if ( shadow_mode_log_dirty(d) ||
- !(l1e_get_flags(gpte) & _PAGE_DIRTY) ||
+ !(guest_l1e_get_flags(gpte) & _PAGE_DIRTY) ||
mfn_is_page_table(mfn) )
{
l1e_remove_flags(spte, _PAGE_RW);
@@ -859,22 +862,22 @@
static inline void l2pde_general(
struct domain *d,
- l2_pgentry_t *gpde_p,
+ guest_l2_pgentry_t *gpde_p,
l2_pgentry_t *spde_p,
unsigned long sl1mfn)
{
- l2_pgentry_t gpde = *gpde_p;
+ guest_l2_pgentry_t gpde = *gpde_p;
l2_pgentry_t spde;
spde = l2e_empty();
- if ( (l2e_get_flags(gpde) & _PAGE_PRESENT) && (sl1mfn != 0) )
+ if ( (guest_l2e_get_flags(gpde) & _PAGE_PRESENT) && (sl1mfn != 0) )
{
spde = l2e_from_pfn(
- sl1mfn,
- (l2e_get_flags(gpde) | _PAGE_RW | _PAGE_ACCESSED) & ~_PAGE_AVAIL);
+ sl1mfn,
+ (guest_l2e_get_flags(gpde) | _PAGE_RW | _PAGE_ACCESSED) &
~_PAGE_AVAIL);
/* N.B. PDEs do not have a dirty bit. */
- l2e_add_flags(gpde, _PAGE_ACCESSED);
+ guest_l2e_add_flags(gpde, _PAGE_ACCESSED);
*gpde_p = gpde;
}
@@ -887,12 +890,12 @@
}
static inline void l2pde_propagate_from_guest(
- struct domain *d, l2_pgentry_t *gpde_p, l2_pgentry_t *spde_p)
-{
- l2_pgentry_t gpde = *gpde_p;
+ struct domain *d, guest_l2_pgentry_t *gpde_p, l2_pgentry_t *spde_p)
+{
+ guest_l2_pgentry_t gpde = *gpde_p;
unsigned long sl1mfn = 0;
- if ( l2e_get_flags(gpde) & _PAGE_PRESENT )
+ if ( guest_l2e_get_flags(gpde) & _PAGE_PRESENT )
sl1mfn = __shadow_status(d, l2e_get_pfn(gpde), PGT_l1_shadow);
l2pde_general(d, gpde_p, spde_p, sl1mfn);
}
@@ -904,7 +907,7 @@
static int inline
validate_pte_change(
struct domain *d,
- l1_pgentry_t new_pte,
+ guest_l1_pgentry_t new_pte,
l1_pgentry_t *shadow_pte_p)
{
l1_pgentry_t old_spte, new_spte;
@@ -1004,7 +1007,7 @@
static int inline
validate_pde_change(
struct domain *d,
- l2_pgentry_t new_gpde,
+ guest_l2_pgentry_t new_gpde,
l2_pgentry_t *shadow_pde_p)
{
l2_pgentry_t old_spde, new_spde;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/shadow_64.h
--- a/xen/include/asm-x86/shadow_64.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/asm-x86/shadow_64.h Fri Sep 9 16:30:54 2005
@@ -27,6 +27,7 @@
#ifndef _XEN_SHADOW_64_H
#define _XEN_SHADOW_64_H
#include <asm/shadow.h>
+#include <asm/shadow_ops.h>
#define READ_FAULT 0
#define WRITE_FAULT 1
@@ -42,14 +43,14 @@
#define ESH_LOG(_f, _a...) ((void)0)
#endif
-#define L4 4UL
-#define L3 3UL
-#define L2 2UL
-#define L1 1UL
+#define PAGING_L4 4UL
+#define PAGING_L3 3UL
+#define PAGING_L2 2UL
+#define PAGING_L1 1UL
#define L_MASK 0xff
-#define ROOT_LEVEL_64 L4
-#define ROOT_LEVEL_32 L2
+#define ROOT_LEVEL_64 PAGING_L4
+#define ROOT_LEVEL_32 PAGING_L2
#define SHADOW_ENTRY (2UL << 16)
#define GUEST_ENTRY (1UL << 16)
@@ -58,6 +59,10 @@
#define SET_ENTRY (1UL << 8)
#define PAGETABLE_ENTRIES (1<<PAGETABLE_ORDER)
+
+/* For 32-bit VMX guest to allocate shadow L1 & L2*/
+#define SL1_ORDER 1
+#define SL2_ORDER 2
typedef struct { intpte_t lo; } pgentry_64_t;
#define shadow_level_to_type(l) (l << 29)
@@ -76,6 +81,10 @@
#define entry_remove_flags(x, flags) ((x).lo &= ~put_pte_flags(flags))
#define entry_has_changed(x,y,flags) \
( !!(((x).lo ^ (y).lo) &
((PADDR_MASK&PAGE_MASK)|put_pte_flags(flags))) )
+
+#define PAE_SHADOW_SELF_ENTRY 259
+#define PDP_ENTRIES 4
+
static inline int table_offset_64(unsigned long va, int level)
{
switch(level) {
@@ -86,8 +95,13 @@
case 3:
return (((va) >> L3_PAGETABLE_SHIFT) & (L3_PAGETABLE_ENTRIES -
1));
#if CONFIG_PAGING_LEVELS >= 4
+#ifndef GUEST_PGENTRY_32
case 4:
return (((va) >> L4_PAGETABLE_SHIFT) & (L4_PAGETABLE_ENTRIES -
1));
+#else
+ case 4:
+ return PAE_SHADOW_SELF_ENTRY;
+#endif
#endif
default:
//printk("<table_offset_64> level %d is too big\n", level);
@@ -138,7 +152,7 @@
return NULL;
mfn = entry_get_value(*le_e) >> PAGE_SHIFT;
if ((flag & GUEST_ENTRY) && shadow_mode_translate(d))
- mfn = phys_to_machine_mapping(mfn);
+ mfn = get_mfn_from_pfn(mfn);
le_p = (pgentry_64_t *)phys_to_virt(mfn << PAGE_SHIFT);
index = table_offset_64(va, (level + i - 1));
le_e = &le_p[index];
@@ -165,30 +179,30 @@
return le_e;
}
#define __shadow_set_l4e(v, va, value) \
- __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | L4)
+ __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | PAGING_L4)
#define __shadow_get_l4e(v, va, sl4e) \
- __rw_entry(v, va, sl4e, SHADOW_ENTRY | GET_ENTRY | L4)
+ __rw_entry(v, va, sl4e, SHADOW_ENTRY | GET_ENTRY | PAGING_L4)
#define __shadow_set_l3e(v, va, value) \
- __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | L3)
+ __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | PAGING_L3)
#define __shadow_get_l3e(v, va, sl3e) \
- __rw_entry(v, va, sl3e, SHADOW_ENTRY | GET_ENTRY | L3)
+ __rw_entry(v, va, sl3e, SHADOW_ENTRY | GET_ENTRY | PAGING_L3)
#define __shadow_set_l2e(v, va, value) \
- __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | L2)
+ __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | PAGING_L2)
#define __shadow_get_l2e(v, va, sl2e) \
- __rw_entry(v, va, sl2e, SHADOW_ENTRY | GET_ENTRY | L2)
+ __rw_entry(v, va, sl2e, SHADOW_ENTRY | GET_ENTRY | PAGING_L2)
#define __shadow_set_l1e(v, va, value) \
- __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | L1)
+ __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | PAGING_L1)
#define __shadow_get_l1e(v, va, sl1e) \
- __rw_entry(v, va, sl1e, SHADOW_ENTRY | GET_ENTRY | L1)
+ __rw_entry(v, va, sl1e, SHADOW_ENTRY | GET_ENTRY | PAGING_L1)
#define __guest_set_l4e(v, va, value) \
- __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | L4)
+ __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | PAGING_L4)
#define __guest_get_l4e(v, va, gl4e) \
- __rw_entry(v, va, gl4e, GUEST_ENTRY | GET_ENTRY | L4)
+ __rw_entry(v, va, gl4e, GUEST_ENTRY | GET_ENTRY | PAGING_L4)
#define __guest_set_l3e(v, va, value) \
- __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | L3)
+ __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | PAGING_L3)
#define __guest_get_l3e(v, va, sl3e) \
- __rw_entry(v, va, gl3e, GUEST_ENTRY | GET_ENTRY | L3)
+ __rw_entry(v, va, gl3e, GUEST_ENTRY | GET_ENTRY | PAGING_L3)
static inline void * __guest_set_l2e(
struct vcpu *v, u64 va, void *value, int size)
@@ -205,7 +219,7 @@
return &l2va[l2_table_offset_32(va)];
}
case 8:
- return __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | L2);
+ return __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY |
PAGING_L2);
default:
BUG();
return NULL;
@@ -230,7 +244,7 @@
return &l2va[l2_table_offset_32(va)];
}
case 8:
- return __rw_entry(v, va, gl2e, GUEST_ENTRY | GET_ENTRY | L2);
+ return __rw_entry(v, va, gl2e, GUEST_ENTRY | GET_ENTRY |
PAGING_L2);
default:
BUG();
return NULL;
@@ -257,7 +271,7 @@
if (unlikely(!(l2e_get_flags_32(gl2e) & _PAGE_PRESENT)))
return NULL;
- l1mfn = phys_to_machine_mapping(
+ l1mfn = get_mfn_from_pfn(
l2e_get_pfn(gl2e));
l1va = (l1_pgentry_32_t *)
@@ -269,7 +283,7 @@
}
case 8:
- return __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | L1);
+ return __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY |
PAGING_L1);
default:
BUG();
return NULL;
@@ -299,7 +313,7 @@
return NULL;
- l1mfn = phys_to_machine_mapping(
+ l1mfn = get_mfn_from_pfn(
l2e_get_pfn(gl2e));
l1va = (l1_pgentry_32_t *) phys_to_virt(
l1mfn << L1_PAGETABLE_SHIFT);
@@ -310,7 +324,7 @@
}
case 8:
// 64-bit guest
- return __rw_entry(v, va, gl1e, GUEST_ENTRY | GET_ENTRY | L1);
+ return __rw_entry(v, va, gl1e, GUEST_ENTRY | GET_ENTRY |
PAGING_L1);
default:
BUG();
return NULL;
@@ -334,7 +348,7 @@
sle = entry_empty();
if ( (entry_get_flags(gle) & _PAGE_PRESENT) && (smfn != 0) )
{
- if ((entry_get_flags(gle) & _PAGE_PSE) && level == L2) {
+ if ((entry_get_flags(gle) & _PAGE_PSE) && level == PAGING_L2) {
sle = entry_from_pfn(smfn, entry_get_flags(gle));
entry_remove_flags(sle, _PAGE_PSE);
@@ -376,7 +390,7 @@
unsigned long smfn = 0;
if ( entry_get_flags(gle) & _PAGE_PRESENT ) {
- if ((entry_get_flags(gle) & _PAGE_PSE) && level == L2) {
+ if ((entry_get_flags(gle) & _PAGE_PSE) && level == PAGING_L2) {
smfn = __shadow_status(d, entry_get_value(gle) >> PAGE_SHIFT,
PGT_fl1_shadow);
} else {
smfn = __shadow_status(d, entry_get_pfn(gle),
@@ -421,86 +435,6 @@
return 1;
}
-/*
- * Check P, R/W, U/S bits in the guest page table.
- * If the fault belongs to guest return 1,
- * else return 0.
- */
-static inline int guest_page_fault(struct vcpu *v,
- unsigned long va, unsigned int error_code, pgentry_64_t *gpl2e, pgentry_64_t
*gpl1e)
-{
- struct domain *d = v->domain;
- pgentry_64_t gle, *lva;
- unsigned long mfn;
- int i;
-
- __rw_entry(v, va, &gle, GUEST_ENTRY | GET_ENTRY | L4);
- if (unlikely(!(entry_get_flags(gle) & _PAGE_PRESENT)))
- return 1;
-
- if (error_code & ERROR_W) {
- if (unlikely(!(entry_get_flags(gle) & _PAGE_RW)))
- return 1;
- }
- if (error_code & ERROR_U) {
- if (unlikely(!(entry_get_flags(gle) & _PAGE_USER)))
- return 1;
- }
- for (i = L3; i >= L1; i--) {
- /*
- * If it's not external mode, then mfn should be machine physical.
- */
- mfn = __gpfn_to_mfn(d, (entry_get_value(gle) >> PAGE_SHIFT));
-
- lva = (pgentry_64_t *) phys_to_virt(
- mfn << PAGE_SHIFT);
- gle = lva[table_offset_64(va, i)];
-
- if (unlikely(!(entry_get_flags(gle) & _PAGE_PRESENT)))
- return 1;
-
- if (error_code & ERROR_W) {
- if (unlikely(!(entry_get_flags(gle) & _PAGE_RW)))
- return 1;
- }
- if (error_code & ERROR_U) {
- if (unlikely(!(entry_get_flags(gle) & _PAGE_USER)))
- return 1;
- }
-
- if (i == L2) {
- if (gpl2e)
- *gpl2e = gle;
-
- if (likely(entry_get_flags(gle) & _PAGE_PSE))
- return 0;
-
- }
-
- if (i == L1)
- if (gpl1e)
- *gpl1e = gle;
- }
- return 0;
-}
-
-static inline unsigned long gva_to_gpa(unsigned long gva)
-{
- struct vcpu *v = current;
- pgentry_64_t gl1e = {0};
- pgentry_64_t gl2e = {0};
- unsigned long gpa;
-
- if (guest_page_fault(v, gva, 0, &gl2e, &gl1e))
- return 0;
- if (entry_get_flags(gl2e) & _PAGE_PSE)
- gpa = entry_get_paddr(gl2e) + (gva & ((1 << L2_PAGETABLE_SHIFT) - 1));
- else
- gpa = entry_get_paddr(gl1e) + (gva & ~PAGE_MASK);
-
- return gpa;
-
-}
#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/shadow_public.h
--- a/xen/include/asm-x86/shadow_public.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/asm-x86/shadow_public.h Fri Sep 9 16:30:54 2005
@@ -49,6 +49,7 @@
(*mark_mfn_out_of_sync)(struct vcpu *v, unsigned long gpfn,
unsigned long mfn);
int (*is_out_of_sync)(struct vcpu *v, unsigned long va);
+ unsigned long (*gva_to_gpa)(unsigned long gva);
};
#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/vmx.h
--- a/xen/include/asm-x86/vmx.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/asm-x86/vmx.h Fri Sep 9 16:30:54 2005
@@ -275,7 +275,9 @@
return 0;
}
-static inline int __vmread (unsigned long field, void *value)
+#define __vmread(x, ptr) ___vmread((x), (ptr), sizeof(*(ptr)))
+
+static always_inline int ___vmread (const unsigned long field, void *ptr,
const int size)
{
unsigned long eflags;
unsigned long ecx = 0;
@@ -286,7 +288,23 @@
: "a" (field)
: "memory");
- *((long *) value) = ecx;
+ switch (size) {
+ case 1:
+ *((u8 *) (ptr)) = ecx;
+ break;
+ case 2:
+ *((u16 *) (ptr)) = ecx;
+ break;
+ case 4:
+ *((u32 *) (ptr)) = ecx;
+ break;
+ case 8:
+ *((u64 *) (ptr)) = ecx;
+ break;
+ default:
+ domain_crash_synchronous();
+ break;
+ }
__save_flags(eflags);
if (eflags & X86_EFLAGS_ZF || eflags & X86_EFLAGS_CF)
@@ -453,4 +471,7 @@
void load_cpu_user_regs(struct cpu_user_regs *regs);
void store_cpu_user_regs(struct cpu_user_regs *regs);
+enum { VMX_COPY_IN = 0, VMX_COPY_OUT };
+int vmx_copy(void *buf, unsigned long laddr, int size, int dir);
+
#endif /* __ASM_X86_VMX_H__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/vmx_platform.h
--- a/xen/include/asm-x86/vmx_platform.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/asm-x86/vmx_platform.h Fri Sep 9 16:30:54 2005
@@ -24,8 +24,7 @@
#include <asm/vmx_virpit.h>
#include <asm/vmx_intercept.h>
-#define MAX_OPERAND_NUM 3
-#define I_NAME_LEN 16
+#define MAX_OPERAND_NUM 2
#define mk_operand(size, index, seg, flag) \
(((size) << 24) | ((index) << 16) | ((seg) << 8) | (flag))
@@ -35,54 +34,60 @@
#define operand_index(operand) \
((operand >> 16) & 0xFF)
- //For instruction.operand[].size
+
+/* for instruction.operand[].size */
#define BYTE 1
#define WORD 2
#define LONG 4
#define QUAD 8
#define BYTE_64 16
- //For instruction.operand[].flag
+/* for instruction.operand[].flag */
#define REGISTER 0x1
#define MEMORY 0x2
#define IMMEDIATE 0x4
-#define WZEROEXTEND 0x8
- //For instruction.flags
+/* for instruction.flags */
#define REPZ 0x1
#define REPNZ 0x2
+#define OVERLAP 0x4
+
+#define INSTR_PIO 1
+#define INSTR_OR 2
+#define INSTR_AND 3
+#define INSTR_XOR 4
+#define INSTR_CMP 5
+#define INSTR_MOV 6
+#define INSTR_MOVS 7
+#define INSTR_MOVZ 8
+#define INSTR_STOS 9
+#define INSTR_TEST 10
struct instruction {
- __s8 i_name[I_NAME_LEN]; //Instruction's name
- __s16 op_size; //The operand's bit size, e.g. 16-bit or 32-bit.
-
- __u64 offset; //The effective address
- //offset = Base + (Index * Scale) + Displacement
-
+ __s8 instr; /* instruction type */
+ __s16 op_size; /* the operand's bit size, e.g. 16-bit or 32-bit */
__u64 immediate;
-
- __u16 seg_sel; //Segmentation selector
-
- __u32 operand[MAX_OPERAND_NUM]; //The order of operand is from AT&T
Assembly
- __s16 op_num; //The operand numbers
-
- __u32 flags; //
+ __u16 seg_sel; /* segmentation selector */
+ __u32 operand[MAX_OPERAND_NUM]; /* order is AT&T assembly */
+ __u32 flags;
};
#define MAX_INST_LEN 32
-struct mi_per_cpu_info
-{
- unsigned long mmio_target;
- struct cpu_user_regs *inst_decoder_regs;
+struct mi_per_cpu_info {
+ int flags;
+ int instr; /* instruction */
+ unsigned long operand[2]; /* operands */
+ unsigned long immediate; /* immediate portion */
+ struct cpu_user_regs *inst_decoder_regs; /* current context */
};
struct virtual_platform_def {
- unsigned long *real_mode_data; /* E820, etc. */
+ unsigned long *real_mode_data; /* E820, etc. */
unsigned long shared_page_va;
struct vmx_virpit_t vmx_pit;
struct vmx_handler_t vmx_handler;
- struct mi_per_cpu_info mpci; /* MMIO */
+ struct mi_per_cpu_info mpci; /* MMIO */
};
extern void handle_mmio(unsigned long, unsigned long);
@@ -91,6 +96,6 @@
extern void vmx_io_assist(struct vcpu *v);
// XXX - think about this -- maybe use bit 30 of the mfn to signify an MMIO
frame.
-#define mmio_space(gpa) (!VALID_MFN(phys_to_machine_mapping((gpa) >>
PAGE_SHIFT)))
+#define mmio_space(gpa) (!VALID_MFN(get_mfn_from_pfn((gpa) >> PAGE_SHIFT)))
#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/vmx_vmcs.h
--- a/xen/include/asm-x86/vmx_vmcs.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/asm-x86/vmx_vmcs.h Fri Sep 9 16:30:54 2005
@@ -183,7 +183,7 @@
VM_ENTRY_MSR_LOAD_COUNT = 0x00004014,
VM_ENTRY_INTR_INFO_FIELD = 0x00004016,
VM_ENTRY_EXCEPTION_ERROR_CODE = 0x00004018,
- VM_ENTRY_INSTRUCTION_LENGTH = 0x0000401a,
+ VM_ENTRY_INSTRUCTION_LEN = 0x0000401a,
TPR_THRESHOLD = 0x0000401c,
SECONDARY_VM_EXEC_CONTROL = 0x0000401e,
VM_INSTRUCTION_ERROR = 0x00004400,
@@ -192,7 +192,7 @@
VM_EXIT_INTR_ERROR_CODE = 0x00004406,
IDT_VECTORING_INFO_FIELD = 0x00004408,
IDT_VECTORING_ERROR_CODE = 0x0000440a,
- INSTRUCTION_LEN = 0x0000440c,
+ VM_EXIT_INSTRUCTION_LEN = 0x0000440c,
VMX_INSTRUCTION_INFO = 0x0000440e,
GUEST_ES_LIMIT = 0x00004800,
GUEST_CS_LIMIT = 0x00004802,
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/x86_32/asm_defns.h
--- a/xen/include/asm-x86/x86_32/asm_defns.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/asm-x86/x86_32/asm_defns.h Fri Sep 9 16:30:54 2005
@@ -1,56 +1,26 @@
#ifndef __X86_32_ASM_DEFNS_H__
#define __X86_32_ASM_DEFNS_H__
-/* Maybe auto-generate the following two cases (quoted vs. unquoted). */
-#ifndef __ASSEMBLY__
-
-#define __SAVE_ALL_PRE \
- "cld;" \
- "pushl %eax;" \
- "pushl %ebp;" \
- "pushl %edi;" \
- "pushl %esi;" \
- "pushl %edx;" \
- "pushl %ecx;" \
- "pushl %ebx;" \
- "testl $"STR(X86_EFLAGS_VM)","STR(UREGS_eflags)"(%esp);" \
- "jz 2f;" \
- "call setup_vm86_frame;" \
- "jmp 3f;" \
- "2:testb $3,"STR(UREGS_cs)"(%esp);" \
- "jz 1f;" \
- "mov %ds,"STR(UREGS_ds)"(%esp);" \
- "mov %es,"STR(UREGS_es)"(%esp);" \
- "mov %fs,"STR(UREGS_fs)"(%esp);" \
- "mov %gs,"STR(UREGS_gs)"(%esp);" \
- "3:"
-
-#define SAVE_ALL_NOSEGREGS(_reg) \
- __SAVE_ALL_PRE \
- "1:"
-
-#define SET_XEN_SEGMENTS(_reg) \
- "movl $("STR(__HYPERVISOR_DS)"),%e"STR(_reg)"x;" \
- "mov %e"STR(_reg)"x,%ds;" \
- "mov %e"STR(_reg)"x,%es;"
-
-#define SAVE_ALL(_reg) \
- __SAVE_ALL_PRE \
- SET_XEN_SEGMENTS(_reg) \
- "1:"
-
+#ifndef NDEBUG
+/* Indicate special exception stack frame by inverting the frame pointer. */
+#define SETUP_EXCEPTION_FRAME_POINTER \
+ movl %esp,%ebp; \
+ notl %ebp
#else
+#define SETUP_EXCEPTION_FRAME_POINTER
+#endif
#define __SAVE_ALL_PRE \
cld; \
pushl %eax; \
pushl %ebp; \
+ SETUP_EXCEPTION_FRAME_POINTER; \
pushl %edi; \
pushl %esi; \
pushl %edx; \
pushl %ecx; \
pushl %ebx; \
- testl $X86_EFLAGS_VM,UREGS_eflags(%esp); \
+ testl $(X86_EFLAGS_VM),UREGS_eflags(%esp); \
jz 2f; \
call setup_vm86_frame; \
jmp 3f; \
@@ -83,8 +53,6 @@
#define PERFC_INCR(_name,_idx)
#endif
-#endif
-
#define BUILD_SMP_INTERRUPT(x,v) XBUILD_SMP_INTERRUPT(x,v)
#define XBUILD_SMP_INTERRUPT(x,v) \
asmlinkage void x(void); \
@@ -92,7 +60,7 @@
"\n"__ALIGN_STR"\n" \
STR(x) ":\n\t" \
"pushl $"#v"<<16\n\t" \
- SAVE_ALL(a) \
+ STR(SAVE_ALL(a)) \
"call "STR(smp_##x)"\n\t" \
"jmp ret_from_intr\n");
@@ -103,7 +71,7 @@
"\n"__ALIGN_STR"\n" \
STR(x) ":\n\t" \
"pushl $"#v"<<16\n\t" \
- SAVE_ALL(a) \
+ STR(SAVE_ALL(a)) \
"movl %esp,%eax\n\t" \
"pushl %eax\n\t" \
"call "STR(smp_##x)"\n\t" \
@@ -114,7 +82,7 @@
__asm__( \
"\n" __ALIGN_STR"\n" \
"common_interrupt:\n\t" \
- SAVE_ALL(a) \
+ STR(SAVE_ALL(a)) \
"movl %esp,%eax\n\t" \
"pushl %eax\n\t" \
"call " STR(do_IRQ) "\n\t" \
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/x86_64/asm_defns.h
--- a/xen/include/asm-x86/x86_64/asm_defns.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/asm-x86/x86_64/asm_defns.h Fri Sep 9 16:30:54 2005
@@ -1,49 +1,14 @@
#ifndef __X86_64_ASM_DEFNS_H__
#define __X86_64_ASM_DEFNS_H__
-/* Maybe auto-generate the following two cases (quoted vs. unquoted). */
-#ifndef __ASSEMBLY__
-
-#define SAVE_ALL \
- "cld;" \
- "pushq %rdi;" \
- "pushq %rsi;" \
- "pushq %rdx;" \
- "pushq %rcx;" \
- "pushq %rax;" \
- "pushq %r8;" \
- "pushq %r9;" \
- "pushq %r10;" \
- "pushq %r11;" \
- "pushq %rbx;" \
- "pushq %rbp;" \
- "pushq %r12;" \
- "pushq %r13;" \
- "pushq %r14;" \
- "pushq %r15;"
-
-#define RESTORE_ALL \
- "popq %r15;" \
- "popq %r14;" \
- "popq %r13;" \
- "popq %r12;" \
- "popq %rbp;" \
- "popq %rbx;" \
- "popq %r11;" \
- "popq %r10;" \
- "popq %r9;" \
- "popq %r8;" \
- "popq %rax;" \
- "popq %rcx;" \
- "popq %rdx;" \
- "popq %rsi;" \
- "popq %rdi;"
-
-/* Work around AMD erratum #88 */
-#define safe_swapgs \
- "mfence; swapgs;"
-
+#ifndef NDEBUG
+/* Indicate special exception stack frame by inverting the frame pointer. */
+#define SETUP_EXCEPTION_FRAME_POINTER \
+ movq %rsp,%rbp; \
+ notq %rbp
#else
+#define SETUP_EXCEPTION_FRAME_POINTER
+#endif
#define SAVE_ALL \
cld; \
@@ -58,6 +23,7 @@
pushq %r11; \
pushq %rbx; \
pushq %rbp; \
+ SETUP_EXCEPTION_FRAME_POINTER; \
pushq %r12; \
pushq %r13; \
pushq %r14; \
@@ -90,7 +56,9 @@
#define PERFC_INCR(_name,_idx)
#endif
-#endif
+/* Work around AMD erratum #88 */
+#define safe_swapgs \
+ "mfence; swapgs;"
#define BUILD_SMP_INTERRUPT(x,v) XBUILD_SMP_INTERRUPT(x,v)
#define XBUILD_SMP_INTERRUPT(x,v) \
@@ -100,7 +68,7 @@
STR(x) ":\n\t" \
"pushq $0\n\t" \
"movl $"#v",4(%rsp)\n\t" \
- SAVE_ALL \
+ STR(SAVE_ALL) \
"callq "STR(smp_##x)"\n\t" \
"jmp ret_from_intr\n");
@@ -112,7 +80,7 @@
STR(x) ":\n\t" \
"pushq $0\n\t" \
"movl $"#v",4(%rsp)\n\t" \
- SAVE_ALL \
+ STR(SAVE_ALL) \
"movq %rsp,%rdi\n\t" \
"callq "STR(smp_##x)"\n\t" \
"jmp ret_from_intr\n");
@@ -121,7 +89,7 @@
__asm__( \
"\n" __ALIGN_STR"\n" \
"common_interrupt:\n\t" \
- SAVE_ALL \
+ STR(SAVE_ALL) \
"movq %rsp,%rdi\n\t" \
"callq " STR(do_IRQ) "\n\t" \
"jmp ret_from_intr\n");
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/public/acm.h
--- a/xen/include/public/acm.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/public/acm.h Fri Sep 9 16:30:54 2005
@@ -56,20 +56,22 @@
#define ACM_ACCESS_DENIED -111
#define ACM_NULL_POINTER_ERROR -200
-#define ACM_MAX_POLICY 3
-
+/* primary policy in lower 4 bits */
#define ACM_NULL_POLICY 0
#define ACM_CHINESE_WALL_POLICY 1
#define ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY 2
-#define ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY 3
+
+/* combinations have secondary policy component in higher 4bit */
+#define ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY \
+ ((ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY << 4) | ACM_CHINESE_WALL_POLICY)
/* policy: */
#define ACM_POLICY_NAME(X) \
- (X == ACM_NULL_POLICY) ? "NULL policy" : \
- (X == ACM_CHINESE_WALL_POLICY) ? "CHINESE WALL policy" : \
- (X == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) ? "SIMPLE TYPE ENFORCEMENT
policy" : \
- (X == ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY) ? "CHINESE
WALL AND SIMPLE TYPE ENFORCEMENT policy" : \
- "UNDEFINED policy"
+ ((X) == (ACM_NULL_POLICY)) ? "NULL policy" : \
+ ((X) == (ACM_CHINESE_WALL_POLICY)) ? "CHINESE WALL policy" : \
+ ((X) == (ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)) ? "SIMPLE TYPE ENFORCEMENT
policy" : \
+ ((X) == (ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY)) ? "CHINESE
WALL AND SIMPLE TYPE ENFORCEMENT policy" : \
+ "UNDEFINED policy"
/* the following policy versions must be increased
* whenever the interpretation of the related
@@ -122,7 +124,7 @@
*/
struct acm_policy_buffer {
u32 policy_version; /* ACM_POLICY_VERSION */
- u32 magic;
+ u32 magic;
u32 len;
u32 primary_policy_code;
u32 primary_buffer_offset;
@@ -151,7 +153,7 @@
};
struct acm_stats_buffer {
- u32 magic;
+ u32 magic;
u32 len;
u32 primary_policy_code;
u32 primary_stats_offset;
@@ -168,5 +170,15 @@
u32 gt_cachehit_count;
};
+struct acm_ssid_buffer {
+ u32 len;
+ ssidref_t ssidref;
+ u32 primary_policy_code;
+ u32 primary_max_types;
+ u32 primary_types_offset;
+ u32 secondary_policy_code;
+ u32 secondary_max_types;
+ u32 secondary_types_offset;
+};
#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/public/acm_ops.h
--- a/xen/include/public/acm_ops.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/public/acm_ops.h Fri Sep 9 16:30:54 2005
@@ -1,3 +1,4 @@
+
/******************************************************************************
* acm_ops.h
*
@@ -27,7 +28,7 @@
* This makes sure that old versions of acm tools will stop working in a
* well-defined way (rather than crashing the machine, for instance).
*/
-#define ACM_INTERFACE_VERSION 0xAAAA0003
+#define ACM_INTERFACE_VERSION 0xAAAA0004
/************************************************************************/
@@ -46,12 +47,25 @@
u16 pullcache_size;
} acm_getpolicy_t;
+
#define ACM_DUMPSTATS 6
typedef struct acm_dumpstats {
void *pullcache;
u16 pullcache_size;
} acm_dumpstats_t;
+
+#define ACM_GETSSID 7
+enum get_type {UNSET, SSIDREF, DOMAINID};
+typedef struct acm_getssid {
+ enum get_type get_ssid_by;
+ union {
+ domaintype_t domainid;
+ ssidref_t ssidref;
+ } id;
+ void *ssidbuf;
+ u16 ssidbuf_size;
+} acm_getssid_t;
typedef struct acm_op {
u32 cmd;
@@ -60,6 +74,7 @@
acm_setpolicy_t setpolicy;
acm_getpolicy_t getpolicy;
acm_dumpstats_t dumpstats;
+ acm_getssid_t getssid;
} u;
} acm_op_t;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/public/arch-x86_32.h
--- a/xen/include/public/arch-x86_32.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/public/arch-x86_32.h Fri Sep 9 16:30:54 2005
@@ -55,7 +55,7 @@
# define HYPERVISOR_VIRT_START (0xFC000000UL)
#endif
#ifndef machine_to_phys_mapping
-#define machine_to_phys_mapping ((u32 *)HYPERVISOR_VIRT_START)
+#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
#endif
/* Maximum number of virtual CPUs in multi-processor guests. */
@@ -128,8 +128,11 @@
} vcpu_guest_context_t;
typedef struct arch_shared_info {
- /* MFN of a table of MFNs that make up p2m table */
- u64 pfn_to_mfn_frame_list;
+ unsigned long max_pfn; /* max pfn that appears in table */
+ unsigned long pfn_to_mfn_frame_list_list;
+ /* frame containing list of mfns
+ containing list of mfns
+ containing the p2m table. */
} arch_shared_info_t;
#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/public/arch-x86_64.h
--- a/xen/include/public/arch-x86_64.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/public/arch-x86_64.h Fri Sep 9 16:30:54 2005
@@ -71,7 +71,7 @@
/* The machine->physical mapping table starts at this address, read-only. */
#ifndef machine_to_phys_mapping
-#define machine_to_phys_mapping ((u32 *)HYPERVISOR_VIRT_START)
+#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
#endif
/*
@@ -186,8 +186,11 @@
} vcpu_guest_context_t;
typedef struct arch_shared_info {
- /* MFN of a table of MFNs that make up p2m table */
- u64 pfn_to_mfn_frame_list;
+ unsigned long max_pfn; /* max pfn that appears in table */
+ unsigned long pfn_to_mfn_frame_list_list;
+ /* frame containing list of mfns
+ containing list of mfns
+ containing the p2m table. */
} arch_shared_info_t;
#endif /* !__ASSEMBLY__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/public/dom0_ops.h
--- a/xen/include/public/dom0_ops.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/public/dom0_ops.h Fri Sep 9 16:30:54 2005
@@ -213,6 +213,7 @@
u32 cpu_khz;
unsigned long total_pages;
unsigned long free_pages;
+ u32 hw_cap[8];
} dom0_physinfo_t;
/*
@@ -373,6 +374,18 @@
/* IN variables. */
int quirk_id;
} dom0_platform_quirk_t;
+
+#define DOM0_PHYSICAL_MEMORY_MAP 40
+typedef struct {
+ /* IN variables. */
+ int max_map_entries;
+ /* OUT variables. */
+ int nr_map_entries;
+ struct dom0_memory_map_entry {
+ u64 start, end;
+ int is_ram;
+ } *memory_map;
+} dom0_physical_memory_map_t;
typedef struct {
u32 cmd;
@@ -408,6 +421,7 @@
dom0_getvcpucontext_t getvcpucontext;
dom0_getdomaininfolist_t getdomaininfolist;
dom0_platform_quirk_t platform_quirk;
+ dom0_physical_memory_map_t physical_memory_map;
} u;
} dom0_op_t;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/public/io/ioreq.h
--- a/xen/include/public/io/ioreq.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/public/io/ioreq.h Fri Sep 9 16:30:54 2005
@@ -29,9 +29,17 @@
#define STATE_IORESP_READY 3
#define STATE_IORESP_HOOK 4
-/* VMExit dispatcher should cooperate with instruction decoder to
- prepare this structure and notify service OS and DM by sending
- virq */
+#define IOREQ_TYPE_PIO 0 /* pio */
+#define IOREQ_TYPE_COPY 1 /* mmio ops */
+#define IOREQ_TYPE_AND 2
+#define IOREQ_TYPE_OR 3
+#define IOREQ_TYPE_XOR 4
+
+/*
+ * VMExit dispatcher should cooperate with instruction decoder to
+ * prepare this structure and notify service OS and DM by sending
+ * virq
+ */
typedef struct {
u64 addr; /* physical address */
u64 size; /* size in bytes */
@@ -43,8 +51,8 @@
u8 state:4;
u8 pdata_valid:1; /* if 1, use pdata above */
u8 dir:1; /* 1=read, 0=write */
- u8 port_mm:1; /* 0=portio, 1=mmio */
u8 df:1;
+ u8 type; /* I/O type */
} ioreq_t;
#define MAX_VECTOR 256
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/public/io/netif.h
--- a/xen/include/public/io/netif.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/public/io/netif.h Fri Sep 9 16:30:54 2005
@@ -23,13 +23,13 @@
typedef struct {
u16 id; /* Echoed in response message. */
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+#ifdef CONFIG_XEN_NETDEV_GRANT
grant_ref_t gref; /* 2: Reference to incoming granted frame */
#endif
} netif_rx_request_t;
typedef struct {
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+#ifdef CONFIG_XEN_NETDEV_GRANT
u32 addr; /* 0: Offset in page of start of received packet */
#else
unsigned long addr; /* Machine address of packet. */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/public/trace.h
--- a/xen/include/public/trace.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/public/trace.h Fri Sep 9 16:30:54 2005
@@ -23,7 +23,7 @@
#define TRC_VMXTIMER 0x00082000 /* VMX timer trace */
#define TRC_VMXINT 0x00084000 /* VMX interrupt trace */
#define TRC_VMXIO 0x00088000 /* VMX io emulation trace */
-
+#define TRC_VMEXIT_HANDLER 0x00090000 /* VMX handler trace */
/* Trace events per class */
@@ -49,6 +49,10 @@
#define TRC_VMX_INT (TRC_VMXINT + 1)
+#define TRC_VMEXIT (TRC_VMEXIT_HANDLER + 1)
+#define TRC_VMENTRY (TRC_VMEXIT_HANDLER + 2)
+
+
/* This structure represents a single trace buffer record. */
struct t_rec {
u64 cycles; /* cycle counter timestamp */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/public/version.h
--- a/xen/include/public/version.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/public/version.h Fri Sep 9 16:30:54 2005
@@ -28,4 +28,17 @@
char compile_date[32];
} xen_compile_info_t;
+#define XENVER_capabilities 3
+typedef struct xen_capabilities_info {
+ char caps[1024];
+} xen_capabilities_info_t;
+
+#define XENVER_changeset 4
+typedef char xen_changeset_info_t[64];
+
+#define XENVER_parameters 5
+typedef struct xen_paramaters_info {
+unsigned long virt_start;
+} xen_parameters_info_t;
+
#endif /* __XEN_PUBLIC_VERSION_H__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/public/xen.h
--- a/xen/include/public/xen.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/public/xen.h Fri Sep 9 16:30:54 2005
@@ -42,7 +42,7 @@
#define __HYPERVISOR_set_debugreg 8
#define __HYPERVISOR_get_debugreg 9
#define __HYPERVISOR_update_descriptor 10
-#define __HYPERVISOR_dom_mem_op 12
+#define __HYPERVISOR_memory_op 12
#define __HYPERVISOR_multicall 13
#define __HYPERVISOR_update_va_mapping 14
#define __HYPERVISOR_set_timer_op 15
@@ -223,12 +223,6 @@
*/
#define CONSOLEIO_write 0
#define CONSOLEIO_read 1
-
-/*
- * Commands to HYPERVISOR_dom_mem_op().
- */
-#define MEMOP_increase_reservation 0
-#define MEMOP_decrease_reservation 1
/*
* Commands to HYPERVISOR_vm_assist().
@@ -438,19 +432,20 @@
#define MAX_GUEST_CMDLINE 1024
typedef struct start_info {
/* THE FOLLOWING ARE FILLED IN BOTH ON INITIAL BOOT AND ON RESUME. */
- unsigned long nr_pages; /* Total pages allocated to this domain. */
- unsigned long shared_info;/* MACHINE address of shared info struct. */
- u32 flags; /* SIF_xxx flags. */
- u16 domain_controller_evtchn;
+ unsigned long nr_pages; /* Total pages allocated to this domain. */
+ unsigned long shared_info; /* MACHINE address of shared info struct. */
+ u32 flags; /* SIF_xxx flags. */
+ unsigned long store_mfn; /* MACHINE page number of shared page. */
+ u16 store_evtchn; /* Event channel for store communication. */
+ unsigned long console_mfn; /* MACHINE address of console page. */
+ u16 console_evtchn; /* Event channel for console messages. */
/* THE FOLLOWING ARE ONLY FILLED IN ON INITIAL BOOT (NOT RESUME). */
- unsigned long pt_base; /* VIRTUAL address of page directory. */
- unsigned long nr_pt_frames;/* Number of bootstrap p.t. frames. */
- unsigned long mfn_list; /* VIRTUAL address of page-frame list. */
- unsigned long mod_start; /* VIRTUAL address of pre-loaded module. */
- unsigned long mod_len; /* Size (bytes) of pre-loaded module. */
+ unsigned long pt_base; /* VIRTUAL address of page directory. */
+ unsigned long nr_pt_frames; /* Number of bootstrap p.t. frames. */
+ unsigned long mfn_list; /* VIRTUAL address of page-frame list. */
+ unsigned long mod_start; /* VIRTUAL address of pre-loaded module. */
+ unsigned long mod_len; /* Size (bytes) of pre-loaded module. */
s8 cmd_line[MAX_GUEST_CMDLINE];
- unsigned long store_mfn; /* MACHINE page number of shared page. */
- u16 store_evtchn; /* Event channel for store communication. */
} start_info_t;
/* These flags are passed in the 'flags' field of start_info_t. */
@@ -459,6 +454,7 @@
#define SIF_BLK_BE_DOMAIN (1<<4) /* Is this a block backend domain? */
#define SIF_NET_BE_DOMAIN (1<<5) /* Is this a net backend domain? */
#define SIF_USB_BE_DOMAIN (1<<6) /* Is this a usb backend domain? */
+#define SIF_TPM_BE_DOMAIN (1<<7) /* Is this a TPM backend domain? */
/* For use in guest OSes. */
extern shared_info_t *HYPERVISOR_shared_info;
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/xen/config.h
--- a/xen/include/xen/config.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/xen/config.h Fri Sep 9 16:30:54 2005
@@ -40,4 +40,7 @@
#include <xen/compiler.h>
#endif
+#define __STR(...) #__VA_ARGS__
+#define STR(...) __STR(__VA_ARGS__)
+
#endif /* __XEN_CONFIG_H__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/xen/perfc.h
--- a/xen/include/xen/perfc.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/xen/perfc.h Fri Sep 9 16:30:54 2005
@@ -4,6 +4,7 @@
#ifdef PERF_COUNTERS
+#include <xen/lib.h>
#include <asm/atomic.h>
/*
@@ -87,7 +88,7 @@
* Histogram: special treatment for 0 and 1 count. After that equally spaced
* with last bucket taking the rest.
*/
-#ifdef PERFC_ARRAYS
+#ifdef PERF_ARRAYS
#define perfc_incr_histo(_x,_v,_n) \
do { \
if ( (_v) == 0 ) \
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/xen/sched.h
--- a/xen/include/xen/sched.h Thu Sep 8 15:18:40 2005
+++ b/xen/include/xen/sched.h Fri Sep 9 16:30:54 2005
@@ -250,10 +250,11 @@
void vcpu_sleep_sync(struct vcpu *d);
/*
- * Force loading of currently-executing domain state on the specified CPU.
- * This is used to counteract lazy state switching where required.
- */
-extern void sync_lazy_execstate_cpu(unsigned int cpu);
+ * Force synchronisation of given VCPU's state. If it is currently descheduled,
+ * this call will ensure that all its state is committed to memory and that
+ * no CPU is using critical state (e.g., page tables) belonging to the VCPU.
+ */
+extern void sync_vcpu_execstate(struct vcpu *v);
/*
* Called by the scheduler to switch to another VCPU. On entry, although
@@ -265,7 +266,7 @@
* The callee must ensure that the local CPU is no longer running in @prev's
* context, and that the context is saved to memory, before returning.
* Alternatively, if implementing lazy context switching, it suffices to ensure
- * that invoking sync_lazy_execstate() will switch and commit @prev's state.
+ * that invoking sync_vcpu_execstate() will switch and commit @prev's state.
*/
extern void context_switch(
struct vcpu *prev,
diff -r 10b1d30d3f66 -r b2f4823b6ff0 docs/misc/vtpm.txt
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/docs/misc/vtpm.txt Fri Sep 9 16:30:54 2005
@@ -0,0 +1,122 @@
+Copyright: IBM Corporation (C), Intel Corporation
+17 August 2005
+Authors: Stefan Berger <stefanb@xxxxxxxxxx> (IBM),
+ Employees of Intel Corp
+
+This document gives a short introduction to the virtual TPM support
+in XEN and goes as far as connecting a user domain to a virtual TPM
+instance and doing a short test to verify success. It is assumed
+that the user is fairly familiar with compiling and installing XEN
+and Linux on a machine.
+
+Production Prerequisites: An x86-based machine machine with an ATMEL or
+National Semiconductor (NSC) TPM on the motherboard.
+Development Prerequisites: An emulator for TESTING ONLY is provided
+
+
+Compiling XEN tree:
+-------------------
+
+Compile the XEN tree as usual.
+
+make uninstall; make mrproper; make install
+
+After compiling the tree, verify that in the linux-2.6.XX-xen0/.config
+file at least the following entries are set as below (they should be set
+by default):
+
+CONFIG_XEN_TPMDEV_BACKEND=y
+CONFIG_XEN_TPMDEV_GRANT=y
+
+CONFIG_TCG_TPM=m
+CONFIG_TCG_NSC=m
+CONFIG_TCG_ATMEL=m
+
+
+Verify that in the linux-2.6.XX-xenU/.config file at least the
+Following entries are set as below (they should be set by default):
+
+CONFIG_XEN_TPMDEV_FRONTEND=y
+CONFIG_XEN_TPMDEV_GRANT=y
+
+CONFIG_TCG_TPM=y
+CONFIG_TCG_XEN=y
+
+
+Reboot the machine with the created XEN-0 kernel.
+
+Note: If you do not want any TPM-related code compiled into your
+kernel or built as module then comment all the above lines like
+this example:
+# CONFIG_TCG_TPM is not set
+
+
+Modifying VM Configuration files:
+---------------------------------
+
+VM configuration files need to be adapted to make a TPM instance
+available to a user domain. The following VM configuration file is
+an example of how a user domain can be configured to have a TPM
+available. It works similar to making a network interface
+available to a domain.
+
+kernel = "/boot/vmlinuz-2.6.12-xenU"
+ramdisk = "/xen/initrd_domU/U1_ramdisk.img"
+memory = 32
+name = "TPMUserDomain0"
+vtpm = ['instance=1,backend=0']
+root = "/dev/ram0 cosole=tty ro"
+vif = ['backend=0']
+
+In the above configuration file the line 'vtpm = ...' provides
+information about the domain where the virtual TPM is running and
+where the TPM backend has been compiled into - this has to be
+domain 0 at the moment - and which TPM instance the user domain
+is supposed to talk to. Note that each running VM must use a
+different instance and that using instance 0 is NOT allowed.
+
+Note: If you do not want TPM functionality for your user domain simply
+leave out the 'vtpm' line in the configuration file.
+
+
+Running the TPM:
+----------------
+
+To run the vTPM, dev device /dev/vtpm must be available.
+Verify that 'ls -l /dev/vtpm' shows the following output:
+
+crw------- 1 root root 10, 225 Aug 11 06:58 /dev/vtpm
+
+If it is not available, run the following command as 'root'.
+mknod /dev/vtpm c 10 225
+
+Make sure that the vTPM is running in domain 0. To do this run the
+following
+
+/usr/bin/vtpm_managerd
+
+Start a user domain using the 'xm create' command. Once you are in the
+shell of the user domain, you should be able to do the following:
+
+> cd /sys/devices/vtpm
+> ls
+cancel caps pcrs pubek
+> cat pcrs
+PCR-00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PCR-01: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PCR-02: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PCR-03: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PCR-04: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PCR-05: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PCR-06: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PCR-07: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PCR-08: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+[...]
+
+At this point the user domain has been sucessfully connected to its
+virtual TPM instance.
+
+For further information please read the documentation in
+tools/vtpm_manager/README and tools/vtpm/README
+
+Stefan Berger and Employees of the Intel Corp
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/domain_config
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/domain_config Fri Sep 9 16:30:54 2005
@@ -0,0 +1,17 @@
+# -*- mode: python; -*-
+#============================================================================
+# Python configuration setup for 'xm create'.
+# This script sets the parameters used when a domain is created using 'xm
create'.
+# You use a separate script for each domain you want to create, or
+# you can set the parameters for the domain on the xm command line.
+#============================================================================
+
+#----------------------------------------------------------------------------
+# Kernel image file.
+kernel = "mini-os.elf"
+
+# Initial memory allocation (in megabytes) for the new domain.
+memory = 32
+
+# A name for your domain. All domains must have different names.
+name = "Mini-OS"
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/ctype.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/include/ctype.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,79 @@
+#ifndef _CTYPE_H
+#define _CTYPE_H
+
+/*
+ * NOTE! This ctype does not handle EOF like the standard C
+ * library is required to.
+ */
+
+#define _U 0x01 /* upper */
+#define _L 0x02 /* lower */
+#define _D 0x04 /* digit */
+#define _C 0x08 /* cntrl */
+#define _P 0x10 /* punct */
+#define _S 0x20 /* white space (space/lf/tab) */
+#define _X 0x40 /* hex digit */
+#define _SP 0x80 /* hard space (0x20) */
+
+
+unsigned char _ctype[] = {
+_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
+_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
+_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
+_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
+_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
+_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
+_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
+_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
+_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
+_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
+_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
+_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
+_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
+_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
+_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
+_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
+_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
+_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
+_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
+_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
+
+#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
+
+#define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0)
+#define isalpha(c) ((__ismask(c)&(_U|_L)) != 0)
+#define iscntrl(c) ((__ismask(c)&(_C)) != 0)
+#define isdigit(c) ((__ismask(c)&(_D)) != 0)
+#define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0)
+#define islower(c) ((__ismask(c)&(_L)) != 0)
+#define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
+#define ispunct(c) ((__ismask(c)&(_P)) != 0)
+#define isspace(c) ((__ismask(c)&(_S)) != 0)
+#define isupper(c) ((__ismask(c)&(_U)) != 0)
+#define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0)
+
+#define isascii(c) (((unsigned char)(c))<=0x7f)
+#define toascii(c) (((unsigned char)(c))&0x7f)
+
+static inline unsigned char __tolower(unsigned char c)
+{
+ if (isupper(c))
+ c -= 'A'-'a';
+ return c;
+}
+
+static inline unsigned char __toupper(unsigned char c)
+{
+ if (islower(c))
+ c -= 'a'-'A';
+ return c;
+}
+
+#define tolower(c) __tolower(c)
+#define toupper(c) __toupper(c)
+
+#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/err.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/include/err.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,31 @@
+#ifndef _ERR_H
+#define _ERR_H
+
+#include <errno.h>
+
+/*
+ * Kernel pointers have redundant information, so we can use a
+ * scheme where we can return either an error code or a dentry
+ * pointer with the same return value.
+ *
+ * This should be a per-architecture thing, to allow different
+ * error and pointer decisions.
+ */
+#define IS_ERR_VALUE(x) ((x) > (unsigned long)-1000L)
+
+static inline void *ERR_PTR(long error)
+{
+ return (void *) error;
+}
+
+static inline long PTR_ERR(const void *ptr)
+{
+ return (long) ptr;
+}
+
+static inline long IS_ERR(const void *ptr)
+{
+ return IS_ERR_VALUE((unsigned long)ptr);
+}
+
+#endif /* _LINUX_ERR_H */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/errno-base.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/include/errno-base.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,39 @@
+#ifndef _ERRNO_BASE_H
+#define _ERRNO_BASE_H
+
+#define EPERM 1 /* Operation not permitted */
+#define ENOENT 2 /* No such file or directory */
+#define ESRCH 3 /* No such process */
+#define EINTR 4 /* Interrupted system call */
+#define EIO 5 /* I/O error */
+#define ENXIO 6 /* No such device or address */
+#define E2BIG 7 /* Argument list too long */
+#define ENOEXEC 8 /* Exec format error */
+#define EBADF 9 /* Bad file number */
+#define ECHILD 10 /* No child processes */
+#define EAGAIN 11 /* Try again */
+#define ENOMEM 12 /* Out of memory */
+#define EACCES 13 /* Permission denied */
+#define EFAULT 14 /* Bad address */
+#define ENOTBLK 15 /* Block device required */
+#define EBUSY 16 /* Device or resource busy */
+#define EEXIST 17 /* File exists */
+#define EXDEV 18 /* Cross-device link */
+#define ENODEV 19 /* No such device */
+#define ENOTDIR 20 /* Not a directory */
+#define EISDIR 21 /* Is a directory */
+#define EINVAL 22 /* Invalid argument */
+#define ENFILE 23 /* File table overflow */
+#define EMFILE 24 /* Too many open files */
+#define ENOTTY 25 /* Not a typewriter */
+#define ETXTBSY 26 /* Text file busy */
+#define EFBIG 27 /* File too large */
+#define ENOSPC 28 /* No space left on device */
+#define ESPIPE 29 /* Illegal seek */
+#define EROFS 30 /* Read-only file system */
+#define EMLINK 31 /* Too many links */
+#define EPIPE 32 /* Broken pipe */
+#define EDOM 33 /* Math argument out of domain of func
*/
+#define ERANGE 34 /* Math result not representable */
+
+#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/errno.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/include/errno.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,109 @@
+#ifndef _ERRNO_H
+#define _ERRNO_H
+
+#include <errno-base.h>
+
+#define EDEADLK 35 /* Resource deadlock would occur */
+#define ENAMETOOLONG 36 /* File name too long */
+#define ENOLCK 37 /* No record locks available */
+#define ENOSYS 38 /* Function not implemented */
+#define ENOTEMPTY 39 /* Directory not empty */
+#define ELOOP 40 /* Too many symbolic links encountered
*/
+#define EWOULDBLOCK EAGAIN /* Operation would block */
+#define ENOMSG 42 /* No message of desired type */
+#define EIDRM 43 /* Identifier removed */
+#define ECHRNG 44 /* Channel number out of range */
+#define EL2NSYNC 45 /* Level 2 not synchronized */
+#define EL3HLT 46 /* Level 3 halted */
+#define EL3RST 47 /* Level 3 reset */
+#define ELNRNG 48 /* Link number out of range */
+#define EUNATCH 49 /* Protocol driver not attached */
+#define ENOCSI 50 /* No CSI structure available */
+#define EL2HLT 51 /* Level 2 halted */
+#define EBADE 52 /* Invalid exchange */
+#define EBADR 53 /* Invalid request descriptor */
+#define EXFULL 54 /* Exchange full */
+#define ENOANO 55 /* No anode */
+#define EBADRQC 56 /* Invalid request code */
+#define EBADSLT 57 /* Invalid slot */
+
+#define EDEADLOCK EDEADLK
+
+#define EBFONT 59 /* Bad font file format */
+#define ENOSTR 60 /* Device not a stream */
+#define ENODATA 61 /* No data available */
+#define ETIME 62 /* Timer expired */
+#define ENOSR 63 /* Out of streams resources */
+#define ENONET 64 /* Machine is not on the network */
+#define ENOPKG 65 /* Package not installed */
+#define EREMOTE 66 /* Object is remote */
+#define ENOLINK 67 /* Link has been severed */
+#define EADV 68 /* Advertise error */
+#define ESRMNT 69 /* Srmount error */
+#define ECOMM 70 /* Communication error on send */
+#define EPROTO 71 /* Protocol error */
+#define EMULTIHOP 72 /* Multihop attempted */
+#define EDOTDOT 73 /* RFS specific error */
+#define EBADMSG 74 /* Not a data message */
+#define EOVERFLOW 75 /* Value too large for defined data
type */
+#define ENOTUNIQ 76 /* Name not unique on network */
+#define EBADFD 77 /* File descriptor in bad state */
+#define EREMCHG 78 /* Remote address changed */
+#define ELIBACC 79 /* Can not access a needed shared
library */
+#define ELIBBAD 80 /* Accessing a corrupted shared library
*/
+#define ELIBSCN 81 /* .lib section in a.out corrupted */
+#define ELIBMAX 82 /* Attempting to link in too many
shared libraries */
+#define ELIBEXEC 83 /* Cannot exec a shared library
directly */
+#define EILSEQ 84 /* Illegal byte sequence */
+#define ERESTART 85 /* Interrupted system call should be
restarted */
+#define ESTRPIPE 86 /* Streams pipe error */
+#define EUSERS 87 /* Too many users */
+#define ENOTSOCK 88 /* Socket operation on non-socket */
+#define EDESTADDRREQ 89 /* Destination address required */
+#define EMSGSIZE 90 /* Message too long */
+#define EPROTOTYPE 91 /* Protocol wrong type for socket */
+#define ENOPROTOOPT 92 /* Protocol not available */
+#define EPROTONOSUPPORT 93 /* Protocol not supported */
+#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
+#define EOPNOTSUPP 95 /* Operation not supported on transport
endpoint */
+#define EPFNOSUPPORT 96 /* Protocol family not supported */
+#define EAFNOSUPPORT 97 /* Address family not supported by
protocol */
+#define EADDRINUSE 98 /* Address already in use */
+#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
+#define ENETDOWN 100 /* Network is down */
+#define ENETUNREACH 101 /* Network is unreachable */
+#define ENETRESET 102 /* Network dropped connection because
of reset */
+#define ECONNABORTED 103 /* Software caused connection abort */
+#define ECONNRESET 104 /* Connection reset by peer */
+#define ENOBUFS 105 /* No buffer space available */
+#define EISCONN 106 /* Transport endpoint is already
connected */
+#define ENOTCONN 107 /* Transport endpoint is not connected
*/
+#define ESHUTDOWN 108 /* Cannot send after transport endpoint
shutdown */
+#define ETOOMANYREFS 109 /* Too many references: cannot splice */
+#define ETIMEDOUT 110 /* Connection timed out */
+#define ECONNREFUSED 111 /* Connection refused */
+#define EHOSTDOWN 112 /* Host is down */
+#define EHOSTUNREACH 113 /* No route to host */
+#define EALREADY 114 /* Operation already in progress */
+#define EINPROGRESS 115 /* Operation now in progress */
+#define ESTALE 116 /* Stale NFS file handle */
+#define EUCLEAN 117 /* Structure needs cleaning */
+#define ENOTNAM 118 /* Not a XENIX named type file */
+#define ENAVAIL 119 /* No XENIX semaphores available */
+#define EISNAM 120 /* Is a named type file */
+#define EREMOTEIO 121 /* Remote I/O error */
+#define EDQUOT 122 /* Quota exceeded */
+
+#define ENOMEDIUM 123 /* No medium found */
+#define EMEDIUMTYPE 124 /* Wrong medium type */
+#define ECANCELED 125 /* Operation Canceled */
+#define ENOKEY 126 /* Required key not available */
+#define EKEYEXPIRED 127 /* Key has expired */
+#define EKEYREVOKED 128 /* Key has been revoked */
+#define EKEYREJECTED 129 /* Key was rejected by service */
+
+/* for robust mutexes */
+#define EOWNERDEAD 130 /* Owner died */
+#define ENOTRECOVERABLE 131 /* State not recoverable */
+
+#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/fcntl.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/include/fcntl.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,89 @@
+#ifndef _I386_FCNTL_H
+#define _I386_FCNTL_H
+
+/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
+ located on an ext2 file system */
+#define O_ACCMODE 0003
+#define O_RDONLY 00
+#define O_WRONLY 01
+#define O_RDWR 02
+#define O_CREAT 0100 /* not fcntl */
+#define O_EXCL 0200 /* not fcntl */
+#define O_NOCTTY 0400 /* not fcntl */
+#define O_TRUNC 01000 /* not fcntl */
+#define O_APPEND 02000
+#define O_NONBLOCK 04000
+#define O_NDELAY O_NONBLOCK
+#define O_SYNC 010000
+#define FASYNC 020000 /* fcntl, for BSD compatibility */
+#define O_DIRECT 040000 /* direct disk access hint */
+#define O_LARGEFILE 0100000
+#define O_DIRECTORY 0200000 /* must be a directory */
+#define O_NOFOLLOW 0400000 /* don't follow links */
+#define O_NOATIME 01000000
+
+#define F_DUPFD 0 /* dup */
+#define F_GETFD 1 /* get close_on_exec */
+#define F_SETFD 2 /* set/clear close_on_exec */
+#define F_GETFL 3 /* get file->f_flags */
+#define F_SETFL 4 /* set file->f_flags */
+#define F_GETLK 5
+#define F_SETLK 6
+#define F_SETLKW 7
+
+#define F_SETOWN 8 /* for sockets. */
+#define F_GETOWN 9 /* for sockets. */
+#define F_SETSIG 10 /* for sockets. */
+#define F_GETSIG 11 /* for sockets. */
+
+#define F_GETLK64 12 /* using 'struct flock64' */
+#define F_SETLK64 13
+#define F_SETLKW64 14
+
+/* for F_[GET|SET]FL */
+#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
+
+/* for posix fcntl() and lockf() */
+#define F_RDLCK 0
+#define F_WRLCK 1
+#define F_UNLCK 2
+
+/* for old implementation of bsd flock () */
+#define F_EXLCK 4 /* or 3 */
+#define F_SHLCK 8 /* or 4 */
+
+/* for leases */
+#define F_INPROGRESS 16
+
+/* operations for bsd flock(), also used by the kernel implementation */
+#define LOCK_SH 1 /* shared lock */
+#define LOCK_EX 2 /* exclusive lock */
+#define LOCK_NB 4 /* or'd with one of the above to prevent
+ blocking */
+#define LOCK_UN 8 /* remove lock */
+
+#define LOCK_MAND 32 /* This is a mandatory flock */
+#define LOCK_READ 64 /* ... Which allows concurrent read operations
*/
+#define LOCK_WRITE 128 /* ... Which allows concurrent write operations
*/
+#define LOCK_RW 192 /* ... Which allows concurrent read &
write ops */
+
+/*
+struct flock {
+ short l_type;
+ short l_whence;
+ off_t l_start;
+ off_t l_len;
+ pid_t l_pid;
+};
+
+struct flock64 {
+ short l_type;
+ short l_whence;
+ loff_t l_start;
+ loff_t l_len;
+ pid_t l_pid;
+};
+
+#define F_LINUX_SPECIFIC_BASE 1024
+*/
+#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/list.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/include/list.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,184 @@
+#ifndef _LINUX_LIST_H
+#define _LINUX_LIST_H
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+ struct list_head name = LIST_HEAD_INIT(name)
+
+#define INIT_LIST_HEAD(ptr) do { \
+ (ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static __inline__ void __list_add(struct list_head * new,
+ struct list_head * prev,
+ struct list_head * next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static __inline__ void list_add(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head, head->next);
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static __inline__ void list_add_tail(struct list_head *new, struct list_head
*head)
+{
+ __list_add(new, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static __inline__ void __list_del(struct list_head * prev,
+ struct list_head * next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty on entry does not return true after this, the entry is in
an undefined state.
+ */
+static __inline__ void list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static __inline__ void list_del_init(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ INIT_LIST_HEAD(entry);
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static __inline__ int list_empty(struct list_head *head)
+{
+ return head->next == head;
+}
+
+/**
+ * list_splice - join two lists
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static __inline__ void list_splice(struct list_head *list, struct list_head
*head)
+{
+ struct list_head *first = list->next;
+
+ if (first != list) {
+ struct list_head *last = list->prev;
+ struct list_head *at = head->next;
+
+ first->prev = head;
+ head->next = first;
+
+ last->next = at;
+ at->prev = last;
+ }
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr: the &struct list_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+
+/**
+ * list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop counter.
+ * @head: the head for your list.
+ */
+#define list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * list_for_each_safe - iterate over a list safe against removal of
list entry
+ * @pos: the &struct list_head to use as a loop counter.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
+ */
+#define list_for_each_safe(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
+
+/**
+ * list_for_each_entry - iterate over list of given type
+ * @pos: the type * to use as a loop counter.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against
removal of list entry
+ * @pos: the type * to use as a loop counter.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe(pos, n, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member), \
+ n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+#endif /* _LINUX_LIST_H */
+
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/sched.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/include/sched.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,38 @@
+#ifndef __SCHED_H__
+#define __SCHED_H__
+
+#include <list.h>
+
+struct thread
+{
+ char *name;
+ char *stack;
+ unsigned long eps;
+ unsigned long eip;
+ struct list_head thread_list;
+ u32 flags;
+};
+
+
+
+void init_sched(void);
+void run_idle_thread(void);
+struct thread* create_thread(char *name, void (*function)(void *), void *data);
+void schedule(void);
+
+static inline struct thread* get_current(void)
+{
+ struct thread **current;
+#ifdef __i386__
+ __asm__("andl %%esp,%0; ":"=r" (current) : "r" (~8191UL));
+#endif
+ return *current;
+}
+
+#define current get_current()
+
+
+void wake(struct thread *thread);
+void block(struct thread *thread);
+
+#endif /* __SCHED_H__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/semaphore.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/include/semaphore.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,46 @@
+#ifndef _SEMAPHORE_H_
+#define _SEMAPHORE_H_
+
+#include <wait.h>
+
+/*
+ * Implementation of semaphore in Mini-os is simple, because
+ * there are no preemptive threads, the atomicity is guaranteed.
+ */
+
+struct semaphore
+{
+ int count;
+ struct wait_queue_head wait;
+};
+
+
+#define __SEMAPHORE_INITIALIZER(name, n) \
+{ \
+ .count = n, \
+ .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+}
+
+#define __MUTEX_INITIALIZER(name) \
+ __SEMAPHORE_INITIALIZER(name,1)
+
+#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+
+#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+
+#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
+
+static void inline down(struct semaphore *sem)
+{
+ wait_event(sem->wait, sem->count > 0);
+ sem->count--;
+}
+
+static void inline up(struct semaphore *sem)
+{
+ sem->count++;
+ wake_up(&sem->wait);
+}
+
+#endif /* _SEMAPHORE_H */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/wait.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/include/wait.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,91 @@
+#ifndef __WAIT_H__
+#define __WAIT_H__
+
+#include <sched.h>
+#include <list.h>
+#include <lib.h>
+#include <os.h>
+
+struct wait_queue
+{
+ struct thread *thread;
+ struct list_head thread_list;
+};
+
+struct wait_queue_head
+{
+ /* TODO - lock required? */
+ struct list_head thread_list;
+};
+
+#define DECLARE_WAIT_QUEUE_HEAD(name) \
+ struct wait_queue_head name = \
+ { .thread_list = { &(name).thread_list, &(name).thread_list} }
+
+#define __WAIT_QUEUE_HEAD_INITIALIZER(name) { \
+ .thread_list = { &(name).thread_list, &(name).thread_list } }
+
+
+#define DEFINE_WAIT(name) \
+struct wait_queue name = { \
+ .thread = current, \
+ .thread_list = LIST_HEAD_INIT((name).thread_list), \
+}
+
+
+
+static inline void init_waitqueue_entry(struct wait_queue *q, struct thread
*thread)
+{
+ q->thread = thread;
+}
+
+
+static inline void add_wait_queue(struct wait_queue_head *h, struct wait_queue
*q)
+{
+ if (list_empty(&q->thread_list))
+ list_add(&q->thread_list, &h->thread_list);
+}
+
+static inline void remove_wait_queue(struct wait_queue *q)
+{
+ list_del(&q->thread_list);
+}
+
+static inline void wake_up(struct wait_queue_head *head)
+{
+ struct list_head *tmp, *next;
+ list_for_each_safe(tmp, next, &head->thread_list)
+ {
+ struct wait_queue *curr;
+ curr = list_entry(tmp, struct wait_queue, thread_list);
+ wake(curr->thread);
+ }
+}
+
+#define wait_event(wq, condition) do{ \
+ unsigned long flags; \
+ if(condition) \
+ break; \
+ DEFINE_WAIT(__wait); \
+ for(;;) \
+ { \
+ /* protect the list */ \
+ local_irq_save(flags); \
+ add_wait_queue(&wq, &__wait); \
+ block(current); \
+ local_irq_restore(flags); \
+ if(condition) \
+ break; \
+ schedule(); \
+ } \
+ local_irq_save(flags); \
+ /* need to wake up */ \
+ wake(current); \
+ remove_wait_queue(&__wait); \
+ local_irq_restore(flags); \
+} while(0)
+
+
+
+
+#endif /* __WAIT_H__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/include/xenbus.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/include/xenbus.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,89 @@
+/******************************************************************************
+ * xenbus.h
+ *
+ * Talks to Xen Store to figure out what devices we have.
+ *
+ * Copyright (C) 2005 Rusty Russell, IBM Corporation
+ *
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef _ASM_XEN_XENBUS_H
+#define _ASM_XEN_XENBUS_H
+
+
+/* Caller must hold this lock to call these functions: it's also held
+ * across watch callbacks. */
+// TODO
+//extern struct semaphore xenbus_lock;
+
+char **xenbus_directory(const char *dir, const char *node, unsigned int *num);
+void *xenbus_read(const char *dir, const char *node, unsigned int *len);
+int xenbus_write(const char *dir, const char *node,
+ const char *string, int createflags);
+int xenbus_mkdir(const char *dir, const char *node);
+int xenbus_exists(const char *dir, const char *node);
+int xenbus_rm(const char *dir, const char *node);
+int xenbus_transaction_start(const char *subtree);
+int xenbus_transaction_end(int abort);
+
+/* Single read and scanf: returns -errno or num scanned if > 0. */
+int xenbus_scanf(const char *dir, const char *node, const char *fmt, ...)
+ __attribute__((format(scanf, 3, 4)));
+
+/* Single printf and write: returns -errno or 0. */
+int xenbus_printf(const char *dir, const char *node, const char *fmt, ...)
+ __attribute__((format(printf, 3, 4)));
+
+/* Generic read function: NULL-terminated triples of name,
+ * sprintf-style type string, and pointer. Returns 0 or errno.*/
+int xenbus_gather(const char *dir, ...);
+
+/* Register callback to watch this node. */
+struct xenbus_watch
+{
+ struct list_head list;
+ char *node;
+ void (*callback)(struct xenbus_watch *, const char *node);
+};
+
+int register_xenbus_watch(struct xenbus_watch *watch);
+void unregister_xenbus_watch(struct xenbus_watch *watch);
+void reregister_xenbus_watches(void);
+
+/* Called from xen core code. */
+void xenbus_suspend(void);
+void xenbus_resume(void);
+
+#define XENBUS_IS_ERR_READ(str) ({ \
+ if (!IS_ERR(str) && strlen(str) == 0) { \
+ kfree(str); \
+ str = ERR_PTR(-ERANGE); \
+ } \
+ IS_ERR(str); \
+})
+
+#define XENBUS_EXIST_ERR(err) ((err) == -ENOENT || (err) == -ERANGE)
+
+int xs_init(void);
+
+#endif /* _ASM_XEN_XENBUS_H */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/sched.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/sched.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,300 @@
+/*
+ ****************************************************************************
+ * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
+ ****************************************************************************
+ *
+ * File: sched.c
+ * Author: Grzegorz Milos
+ * Changes:
+ *
+ * Date: Aug 2005
+ *
+ * Environment: Xen Minimal OS
+ * Description: simple scheduler for Mini-Os
+ *
+ * The scheduler is non-preemptive (cooperative), and schedules according
+ * to Round Robin algorithm.
+ *
+ ****************************************************************************
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <os.h>
+#include <hypervisor.h>
+#include <time.h>
+#include <mm.h>
+#include <types.h>
+#include <lib.h>
+#include <xmalloc.h>
+#include <list.h>
+#include <sched.h>
+#include <semaphore.h>
+
+#ifdef SCHED_DEBUG
+#define DEBUG(_f, _a...) \
+ printk("MINI_OS(file=sched.c, line=%d) " _f "\n", __LINE__, ## _a)
+#else
+#define DEBUG(_f, _a...) ((void)0)
+#endif
+
+
+#define RUNNABLE_FLAG 0x00000001
+
+#define is_runnable(_thread) (_thread->flags & RUNNABLE_FLAG)
+#define set_runnable(_thread) (_thread->flags |= RUNNABLE_FLAG)
+#define clear_runnable(_thread) (_thread->flags &= ~RUNNABLE_FLAG)
+
+
+struct thread *idle_thread;
+LIST_HEAD(exited_threads);
+
+void dump_stack(struct thread *thread)
+{
+ unsigned long *bottom = (unsigned long *)thread->stack + 2048;
+ unsigned long *pointer = (unsigned long *)thread->eps;
+ int count;
+ printk("The stack for \"%s\"\n", thread->name);
+ for(count = 0; count < 15 && pointer < bottom; count ++)
+ {
+ printk("[0x%lx] 0x%lx\n", pointer, *pointer);
+ pointer++;
+ }
+
+ if(pointer < bottom) printk("Not the whole stack printed\n");
+}
+
+#ifdef __i386__
+#define switch_threads(prev, next) do { \
+ unsigned long esi,edi; \
+ __asm__ __volatile__("pushfl\n\t" \
+ "pushl %%ebp\n\t" \
+ "movl %%esp,%0\n\t" /* save ESP */ \
+ "movl %4,%%esp\n\t" /* restore ESP */ \
+ "movl $1f,%1\n\t" /* save EIP */ \
+ "pushl %5\n\t" /* restore EIP */ \
+ "ret\n\t" \
+ "1:\t" \
+ "popl %%ebp\n\t" \
+ "popfl" \
+ :"=m" (prev->eps),"=m" (prev->eip), \
+ "=S" (esi),"=D" (edi) \
+ :"m" (next->eps),"m" (next->eip), \
+ "2" (prev), "d" (next)); \
+} while (0)
+#elif __x86_64__
+/* FIXME */
+#endif
+
+void inline print_runqueue(void)
+{
+ struct list_head *it;
+ struct thread *th;
+ list_for_each(it, &idle_thread->thread_list)
+ {
+ th = list_entry(it, struct thread, thread_list);
+ printk(" Thread \"%s\", runnable=%d\n", th->name, is_runnable(th));
+ }
+ printk("\n");
+}
+
+
+void schedule(void)
+{
+ struct thread *prev, *next, *thread;
+ struct list_head *iterator;
+ unsigned long flags;
+ prev = current;
+ local_irq_save(flags);
+ list_for_each(iterator, &exited_threads)
+ {
+ thread = list_entry(iterator, struct thread, thread_list);
+ if(thread != prev)
+ {
+ list_del(&thread->thread_list);
+ free_pages(thread->stack, 1);
+ xfree(thread);
+ }
+ }
+ next = idle_thread;
+ /* Thread list needs to be protected */
+ list_for_each(iterator, &idle_thread->thread_list)
+ {
+ thread = list_entry(iterator, struct thread, thread_list);
+ if(is_runnable(thread))
+ {
+ next = thread;
+ /* Put this thread on the end of the list */
+ list_del(&thread->thread_list);
+ list_add_tail(&thread->thread_list, &idle_thread->thread_list);
+ break;
+ }
+ }
+ local_irq_restore(flags);
+ /* Interrupting the switch is equivalent to having the next thread
+ inturrupted at the return instruction. And therefore at safe point. */
+/* The thread switching only works for i386 at the moment */
+#ifdef __i386__
+ if(prev != next) switch_threads(prev, next);
+#endif
+}
+
+
+
+void exit_thread(struct thread *thread)
+{
+ unsigned long flags;
+ printk("Thread \"%s\" exited.\n", thread->name);
+ local_irq_save(flags);
+ /* Remove from the thread list */
+ list_del(&thread->thread_list);
+ clear_runnable(thread);
+ /* Put onto exited list */
+ list_add(&thread->thread_list, &exited_threads);
+ local_irq_restore(flags);
+ /* Schedule will free the resources */
+ schedule();
+}
+
+
+struct thread* create_thread(char *name, void (*function)(void *), void *data)
+{
+ struct thread *thread;
+ unsigned long flags;
+
+ thread = xmalloc(struct thread);
+ /* Allocate 2 pages for stack, stack will be 2pages aligned */
+ thread->stack = (char *)alloc_pages(1);
+ thread->name = name;
+ printk("Thread \"%s\": pointer: 0x%lx, stack: 0x%lx\n", name, thread,
+ thread->stack);
+
+ thread->eps = (unsigned long)thread->stack + 4096 * 2 - 4;
+ /* Save pointer to the thread on the stack, used by current macro */
+ *((unsigned long *)thread->stack) = (unsigned long)thread;
+ *((unsigned long *)thread->eps) = (unsigned long)thread;
+ thread->eps -= 4;
+ *((unsigned long *)thread->eps) = (unsigned long)data;
+
+ /* No return address */
+ thread->eps -= 4;
+ *((unsigned long *)thread->eps) = (unsigned long)exit_thread;
+
+ thread->eip = (unsigned long)function;
+
+ /* Not runable, not exited */
+ thread->flags = 0;
+ set_runnable(thread);
+
+ local_irq_save(flags);
+ if(idle_thread != NULL)
+ list_add_tail(&thread->thread_list, &idle_thread->thread_list);
+ local_irq_restore(flags);
+
+ return thread;
+}
+
+
+void block(struct thread *thread)
+{
+ clear_runnable(thread);
+}
+
+void wake(struct thread *thread)
+{
+ set_runnable(thread);
+}
+
+void idle_thread_fn(void *unused)
+{
+ for(;;)
+ {
+ schedule();
+ printk("Blocking the domain\n");
+ block_domain(10000);
+ }
+}
+
+void run_idle_thread(void)
+{
+ /* Switch stacks and run the thread */
+ __asm__ __volatile__("mov %0,%%esp\n\t"
+ "push %1\n\t"
+ "ret"
+ :"=m" (idle_thread->eps)
+ :"m" (idle_thread->eip));
+}
+
+
+
+DECLARE_MUTEX(mutex);
+
+void th_f1(void *data)
+{
+ struct timeval tv1, tv2;
+
+ for(;;)
+ {
+ down(&mutex);
+ printk("Thread \"%s\" got semaphore, runnable %d\n", current->name,
is_runnable(current));
+ schedule();
+ printk("Thread \"%s\" releases the semaphore\n", current->name);
+ up(&mutex);
+
+
+ gettimeofday(&tv1);
+ for(;;)
+ {
+ gettimeofday(&tv2);
+ if(tv2.tv_sec - tv1.tv_sec > 2) break;
+ }
+
+
+ schedule();
+ }
+}
+
+void th_f2(void *data)
+{
+ for(;;)
+ {
+ printk("Thread OTHER executing, data 0x%lx\n", data);
+ schedule();
+ }
+}
+
+
+
+void init_sched(void)
+{
+ printk("Initialising scheduler\n");
+
+ idle_thread = create_thread("Idle", idle_thread_fn, NULL);
+ INIT_LIST_HEAD(&idle_thread->thread_list);
+
+
+/* create_thread("1", th_f1, (void *)0x1234);
+ create_thread("2", th_f1, (void *)0x1234);
+ create_thread("3", th_f1, (void *)0x1234);
+ create_thread("4", th_f1, (void *)0x1234);
+ create_thread("5", th_f1, (void *)0x1234);
+ create_thread("6", th_f1, (void *)0x1234);
+ create_thread("second", th_f2, NULL);
+*/
+}
+
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/xenbus/Makefile
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/xenbus/Makefile Fri Sep 9 16:30:54 2005
@@ -0,0 +1,9 @@
+all: xenstore.h xenbus_comms.o xenbus_xs.o xenbus_probe.o
+
+xenstore.h:
+ [ -e xenstored.h ] || ln -sf ../../../tools/xenstore/xenstored.h
xenstored.h
+
+clean:
+ #Taken care of by main Makefile
+ #rm xenstored.h
+ #rm *.o
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/xenbus/xenbus_comms.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/xenbus/xenbus_comms.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,231 @@
+/******************************************************************************
+ * xenbus_comms.c
+ *
+ * Low level code to talks to Xen Store: ringbuffer and event channel.
+ *
+ * Copyright (C) 2005 Rusty Russell, IBM Corporation
+ *
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <types.h>
+#include <wait.h>
+#include <mm.h>
+#include <hypervisor.h>
+#include <events.h>
+#include <os.h>
+#include <lib.h>
+
+
+#ifdef XENBUS_COMMS_DEBUG
+#define DEBUG(_f, _a...) \
+ printk("MINI_OS(file=xenbus_comms.c, line=%d) " _f "\n", __LINE__, ## _a)
+#else
+#define DEBUG(_f, _a...) ((void)0)
+#endif
+
+
+#define RINGBUF_DATASIZE ((PAGE_SIZE / 2) - sizeof(struct ringbuf_head))
+struct ringbuf_head
+{
+ u32 write; /* Next place to write to */
+ u32 read; /* Next place to read from */
+ u8 flags;
+ char buf[0];
+} __attribute__((packed));
+
+DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
+
+static inline struct ringbuf_head *outbuf(void)
+{
+ return mfn_to_virt(start_info.store_mfn);
+}
+
+static inline struct ringbuf_head *inbuf(void)
+{
+ return (struct ringbuf_head *)((char
*)mfn_to_virt(start_info.store_mfn) + PAGE_SIZE/2);
+}
+
+static void wake_waiting(int port, struct pt_regs *regs)
+{
+ wake_up(&xb_waitq);
+}
+
+static int check_buffer(const struct ringbuf_head *h)
+{
+ return (h->write < RINGBUF_DATASIZE && h->read < RINGBUF_DATASIZE);
+}
+
+/* We can't fill last byte: would look like empty buffer. */
+static void *get_output_chunk(const struct ringbuf_head *h,
+ void *buf, u32 *len)
+{
+ u32 read_mark;
+
+ if (h->read == 0)
+ read_mark = RINGBUF_DATASIZE - 1;
+ else
+ read_mark = h->read - 1;
+
+ /* Here to the end of buffer, unless they haven't read some out. */
+ *len = RINGBUF_DATASIZE - h->write;
+ if (read_mark >= h->write)
+ *len = read_mark - h->write;
+ return (void *)((char *)buf + h->write);
+}
+
+static const void *get_input_chunk(const struct ringbuf_head *h,
+ const void *buf, u32 *len)
+{
+ /* Here to the end of buffer, unless they haven't written some. */
+ *len = RINGBUF_DATASIZE - h->read;
+ if (h->write >= h->read)
+ *len = h->write - h->read;
+ return (void *)((char *)buf + h->read);
+}
+
+static void update_output_chunk(struct ringbuf_head *h, u32 len)
+{
+ h->write += len;
+ if (h->write == RINGBUF_DATASIZE)
+ h->write = 0;
+}
+
+static void update_input_chunk(struct ringbuf_head *h, u32 len)
+{
+ h->read += len;
+ if (h->read == RINGBUF_DATASIZE)
+ h->read = 0;
+}
+
+static int output_avail(struct ringbuf_head *out)
+{
+ unsigned int avail;
+
+ get_output_chunk(out, out->buf, &avail);
+ return avail != 0;
+}
+
+int xb_write(const void *data, unsigned len)
+{
+ struct ringbuf_head h;
+ struct ringbuf_head *out = outbuf();
+
+ do {
+ void *dst;
+ unsigned int avail;
+
+ wait_event(xb_waitq, output_avail(out));
+
+ /* Read, then check: not that we don't trust store.
+ * Hell, some of my best friends are daemons. But,
+ * in this post-911 world... */
+ h = *out;
+ mb();
+ if (!check_buffer(&h)) {
+ return -1; /* ETERRORIST! */
+ }
+
+ dst = get_output_chunk(&h, out->buf, &avail);
+ if (avail > len)
+ avail = len;
+ memcpy(dst, data, avail);
+ data = (void *)((char *)data + avail);
+ len -= avail;
+ update_output_chunk(out, avail);
+ notify_via_evtchn(start_info.store_evtchn);
+ } while (len != 0);
+
+ return 0;
+}
+
+int xs_input_avail(void)
+{
+ unsigned int avail;
+ struct ringbuf_head *in = inbuf();
+
+ get_input_chunk(in, in->buf, &avail);
+ return avail != 0;
+}
+
+int xb_read(void *data, unsigned len)
+{
+ struct ringbuf_head h;
+ struct ringbuf_head *in = inbuf();
+ int was_full;
+
+ while (len != 0) {
+ unsigned int avail;
+ const char *src;
+
+ wait_event(xb_waitq, xs_input_avail());
+ h = *in;
+ mb();
+ if (!check_buffer(&h)) {
+ return -1;
+ }
+
+ src = get_input_chunk(&h, in->buf, &avail);
+ if (avail > len)
+ avail = len;
+ was_full = !output_avail(&h);
+
+ memcpy(data, src, avail);
+ data = (void *)((char *)data + avail);
+ len -= avail;
+ update_input_chunk(in, avail);
+ DEBUG("Finished read of %i bytes (%i to go)\n", avail, len);
+ /* If it was full, tell them we've taken some. */
+ if (was_full)
+ notify_via_evtchn(start_info.store_evtchn);
+ }
+
+ /* If we left something, wake watch thread to deal with it. */
+ if (xs_input_avail())
+ wake_up(&xb_waitq);
+
+ return 0;
+}
+
+/* Set up interrupt handler off store event channel. */
+int xb_init_comms(void)
+{
+ printk("Init xenbus comms, store event channel %d\n",
start_info.store_evtchn);
+ if (!start_info.store_evtchn)
+ return 0;
+ printk("Binding virq\n");
+ bind_evtchn(start_info.store_evtchn, &wake_waiting);
+
+ /* FIXME zero out page -- domain builder should probably do this*/
+ memset(mfn_to_virt(start_info.store_mfn), 0, PAGE_SIZE);
+ notify_via_evtchn(start_info.store_evtchn);
+ return 0;
+}
+
+void xb_suspend_comms(void)
+{
+
+ if (!start_info.store_evtchn)
+ return;
+
+ // TODO
+ //unbind_evtchn_from_irqhandler(xen_start_info.store_evtchn, &xb_waitq);
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/xenbus/xenbus_comms.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/xenbus/xenbus_comms.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,40 @@
+/*
+ * Private include for xenbus communications.
+ *
+ * Copyright (C) 2005 Rusty Russell, IBM Corporation
+ *
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef _XENBUS_COMMS_H
+#define _XENBUS_COMMS_H
+
+int xb_init_comms(void);
+void xb_suspend_comms(void);
+
+/* Low level routines. */
+int xb_write(const void *data, unsigned len);
+int xb_read(void *data, unsigned len);
+int xs_input_avail(void);
+extern struct wait_queue_head xb_waitq;
+
+#endif /* _XENBUS_COMMS_H */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 extras/mini-os/xenbus/xenbus_xs.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/extras/mini-os/xenbus/xenbus_xs.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,554 @@
+/******************************************************************************
+ * xenbus_xs.c
+ *
+ * This is the kernel equivalent of the "xs" library. We don't need everything
+ * and we use xenbus_comms for communication.
+ *
+ * Copyright (C) 2005 Rusty Russell, IBM Corporation
+ *
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <errno.h>
+#include <types.h>
+#include <list.h>
+#include <lib.h>
+#include <err.h>
+#include <os.h>
+#include <xmalloc.h>
+#include <fcntl.h>
+#include <xenbus.h>
+#include <wait.h>
+#include <sched.h>
+#include <semaphore.h>
+#include "xenstored.h"
+#include "xenbus_comms.h"
+
+#define streq(a, b) (strcmp((a), (b)) == 0)
+
+static char printf_buffer[4096];
+static LIST_HEAD(watches);
+//TODO
+DECLARE_MUTEX(xenbus_lock);
+
+static int get_error(const char *errorstring)
+{
+ unsigned int i;
+
+ for (i = 0; !streq(errorstring, xsd_errors[i].errstring); i++) {
+ if (i == ARRAY_SIZE(xsd_errors) - 1) {
+ printk("XENBUS xen store gave: unknown error %s",
+ errorstring);
+ return EINVAL;
+ }
+ }
+ return xsd_errors[i].errnum;
+}
+
+static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len)
+{
+ struct xsd_sockmsg msg;
+ void *ret;
+ int err;
+
+ err = xb_read(&msg, sizeof(msg));
+ if (err)
+ return ERR_PTR(err);
+
+ ret = xmalloc_array(char, msg.len + 1);
+ if (!ret)
+ return ERR_PTR(-ENOMEM);
+
+ err = xb_read(ret, msg.len);
+ if (err) {
+ xfree(ret);
+ return ERR_PTR(err);
+ }
+ ((char*)ret)[msg.len] = '\0';
+
+ *type = msg.type;
+ if (len)
+ *len = msg.len;
+ return ret;
+}
+
+/* Emergency write. */
+void xenbus_debug_write(const char *str, unsigned int count)
+{
+ struct xsd_sockmsg msg;
+
+ msg.type = XS_DEBUG;
+ msg.len = sizeof("print") + count + 1;
+
+ xb_write(&msg, sizeof(msg));
+ xb_write("print", sizeof("print"));
+ xb_write(str, count);
+ xb_write("", 1);
+}
+
+/* Send message to xs, get kmalloc'ed reply. ERR_PTR() on error. */
+static void *xs_talkv(enum xsd_sockmsg_type type,
+ const struct kvec *iovec,
+ unsigned int num_vecs,
+ unsigned int *len)
+{
+ struct xsd_sockmsg msg;
+ void *ret = NULL;
+ unsigned int i;
+ int err;
+
+ //WARN_ON(down_trylock(&xenbus_lock) == 0);
+
+ msg.type = type;
+ msg.len = 0;
+ for (i = 0; i < num_vecs; i++)
+ msg.len += iovec[i].iov_len;
+
+ err = xb_write(&msg, sizeof(msg));
+ if (err)
+ return ERR_PTR(err);
+
+ for (i = 0; i < num_vecs; i++) {
+ err = xb_write(iovec[i].iov_base, iovec[i].iov_len);;
+ if (err)
+ return ERR_PTR(err);
+ }
+
+ /* Watches can have fired before reply comes: daemon detects
+ * and re-transmits, so we can ignore this. */
+ do {
+ xfree(ret);
+ ret = read_reply(&msg.type, len);
+ if (IS_ERR(ret))
+ return ret;
+ } while (msg.type == XS_WATCH_EVENT);
+
+ if (msg.type == XS_ERROR) {
+ err = get_error(ret);
+ xfree(ret);
+ return ERR_PTR(-err);
+ }
+
+ //BUG_ON(msg.type != type);
+ return ret;
+}
+
+/* Simplified version of xs_talkv: single message. */
+static void *xs_single(enum xsd_sockmsg_type type,
+ const char *string, unsigned int *len)
+{
+ struct kvec iovec;
+
+ iovec.iov_base = (void *)string;
+ iovec.iov_len = strlen(string) + 1;
+ return xs_talkv(type, &iovec, 1, len);
+}
+
+/* Many commands only need an ack, don't care what it says. */
+static int xs_error(char *reply)
+{
+ if (IS_ERR(reply))
+ return PTR_ERR(reply);
+ xfree(reply);
+ return 0;
+}
+
+static unsigned int count_strings(const char *strings, unsigned int len)
+{
+ unsigned int num;
+ const char *p;
+
+ for (p = strings, num = 0; p < strings + len; p += strlen(p) + 1)
+ num++;
+
+ return num;
+}
+
+/* Return the path to dir with /name appended. */
+static char *join(const char *dir, const char *name)
+{
+ static char buffer[4096];
+
+ //BUG_ON(down_trylock(&xenbus_lock) == 0);
+ /* XXX FIXME: might not be correct if name == "" */
+ //BUG_ON(strlen(dir) + strlen("/") + strlen(name) + 1 > sizeof(buffer));
+
+ strcpy(buffer, dir);
+ if (!streq(name, "")) {
+ strcat(buffer, "/");
+ strcat(buffer, name);
+ }
+ return buffer;
+}
+
+char **xenbus_directory(const char *dir, const char *node, unsigned int *num)
+{
+ char *strings, *p, **ret;
+ unsigned int len;
+
+ strings = xs_single(XS_DIRECTORY, join(dir, node), &len);
+ if (IS_ERR(strings))
+ return (char **)strings;
+
+ /* Count the strings. */
+ *num = count_strings(strings, len);
+
+ /* Transfer to one big alloc for easy freeing. */
+ ret = (char **)xmalloc_array(char, *num * sizeof(char *) + len);
+ if (!ret) {
+ xfree(strings);
+ return ERR_PTR(-ENOMEM);
+ }
+ memcpy(&ret[*num], strings, len);
+ xfree(strings);
+
+ strings = (char *)&ret[*num];
+ for (p = strings, *num = 0; p < strings + len; p += strlen(p) + 1)
+ ret[(*num)++] = p;
+ return ret;
+}
+
+/* Check if a path exists. Return 1 if it does. */
+int xenbus_exists(const char *dir, const char *node)
+{
+ char **d;
+ int dir_n;
+
+ d = xenbus_directory(dir, node, &dir_n);
+ if (IS_ERR(d))
+ return 0;
+ xfree(d);
+ return 1;
+}
+
+/* Get the value of a single file.
+ * Returns a kmalloced value: call free() on it after use.
+ * len indicates length in bytes.
+ */
+void *xenbus_read(const char *dir, const char *node, unsigned int *len)
+{
+ return xs_single(XS_READ, join(dir, node), len);
+}
+
+/* Write the value of a single file.
+ * Returns -err on failure. createflags can be 0, O_CREAT, or O_CREAT|O_EXCL.
+ */
+int xenbus_write(const char *dir, const char *node,
+ const char *string, int createflags)
+{
+ const char *flags, *path;
+ struct kvec iovec[3];
+
+ path = join(dir, node);
+ /* Format: Flags (as string), path, data. */
+ if (createflags == 0)
+ flags = XS_WRITE_NONE;
+ else if (createflags == O_CREAT)
+ flags = XS_WRITE_CREATE;
+ else if (createflags == (O_CREAT|O_EXCL))
+ flags = XS_WRITE_CREATE_EXCL;
+ else
+ return -EINVAL;
+
+ iovec[0].iov_base = (void *)path;
+ iovec[0].iov_len = strlen(path) + 1;
+ iovec[1].iov_base = (void *)flags;
+ iovec[1].iov_len = strlen(flags) + 1;
+ iovec[2].iov_base = (void *)string;
+ iovec[2].iov_len = strlen(string);
+
+ return xs_error(xs_talkv(XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL));
+}
+
+/* Create a new directory. */
+int xenbus_mkdir(const char *dir, const char *node)
+{
+ return xs_error(xs_single(XS_MKDIR, join(dir, node), NULL));
+}
+
+/* Destroy a file or directory (directories must be empty). */
+int xenbus_rm(const char *dir, const char *node)
+{
+ return xs_error(xs_single(XS_RM, join(dir, node), NULL));
+}
+
+/* Start a transaction: changes by others will not be seen during this
+ * transaction, and changes will not be visible to others until end.
+ * Transaction only applies to the given subtree.
+ * You can only have one transaction at any time.
+ */
+int xenbus_transaction_start(const char *subtree)
+{
+ return xs_error(xs_single(XS_TRANSACTION_START, subtree, NULL));
+}
+
+/* End a transaction.
+ * If abandon is true, transaction is discarded instead of committed.
+ */
+int xenbus_transaction_end(int abort)
+{
+ char abortstr[2];
+
+ if (abort)
+ strcpy(abortstr, "F");
+ else
+ strcpy(abortstr, "T");
+ return xs_error(xs_single(XS_TRANSACTION_END, abortstr, NULL));
+}
+
+/* Single read and scanf: returns -errno or num scanned. */
+int xenbus_scanf(const char *dir, const char *node, const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+ char *val;
+
+ val = xenbus_read(dir, node, NULL);
+ if (IS_ERR(val))
+ return PTR_ERR(val);
+
+ va_start(ap, fmt);
+ ret = vsscanf(val, fmt, ap);
+ va_end(ap);
+ xfree(val);
+ /* Distinctive errno. */
+ if (ret == 0)
+ return -ERANGE;
+ return ret;
+}
+
+/* Single printf and write: returns -errno or 0. */
+int xenbus_printf(const char *dir, const char *node, const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ //BUG_ON(down_trylock(&xenbus_lock) == 0);
+ va_start(ap, fmt);
+ ret = vsnprintf(printf_buffer, sizeof(printf_buffer), fmt, ap);
+ va_end(ap);
+
+ //BUG_ON(ret > sizeof(printf_buffer)-1);
+ return xenbus_write(dir, node, printf_buffer, O_CREAT);
+}
+
+
+/* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
+int xenbus_gather(const char *dir, ...)
+{
+ va_list ap;
+ const char *name;
+ int ret = 0;
+
+ va_start(ap, dir);
+ while (ret == 0 && (name = va_arg(ap, char *)) != NULL) {
+ const char *fmt = va_arg(ap, char *);
+ void *result = va_arg(ap, void *);
+ char *p;
+
+ p = xenbus_read(dir, name, NULL);
+ if (IS_ERR(p)) {
+ ret = PTR_ERR(p);
+ break;
+ }
+ if (fmt) {
+ if (sscanf(p, fmt, result) == 0)
+ ret = -EINVAL;
+ xfree(p);
+ } else
+ *(char **)result = p;
+ }
+ va_end(ap);
+ return ret;
+}
+
+static int xs_watch(const char *path, const char *token)
+{
+ struct kvec iov[2];
+
+ iov[0].iov_base = (void *)path;
+ iov[0].iov_len = strlen(path) + 1;
+ iov[1].iov_base = (void *)token;
+ iov[1].iov_len = strlen(token) + 1;
+
+ return xs_error(xs_talkv(XS_WATCH, iov, ARRAY_SIZE(iov), NULL));
+}
+
+static char *xs_read_watch(char **token)
+{
+ enum xsd_sockmsg_type type;
+ char *ret;
+
+ ret = read_reply(&type, NULL);
+ if (IS_ERR(ret))
+ return ret;
+
+ //BUG_ON(type != XS_WATCH_EVENT);
+ *token = ret + strlen(ret) + 1;
+ return ret;
+}
+
+static int xs_acknowledge_watch(const char *token)
+{
+ return xs_error(xs_single(XS_WATCH_ACK, token, NULL));
+}
+
+static int xs_unwatch(const char *path, const char *token)
+{
+ struct kvec iov[2];
+
+ iov[0].iov_base = (char *)path;
+ iov[0].iov_len = strlen(path) + 1;
+ iov[1].iov_base = (char *)token;
+ iov[1].iov_len = strlen(token) + 1;
+
+ return xs_error(xs_talkv(XS_UNWATCH, iov, ARRAY_SIZE(iov), NULL));
+}
+
+/* A little paranoia: we don't just trust token. */
+static struct xenbus_watch *find_watch(const char *token)
+{
+ struct xenbus_watch *i, *cmp;
+
+ cmp = (void *)simple_strtoul(token, NULL, 16);
+
+ list_for_each_entry(i, &watches, list)
+ if (i == cmp)
+ return i;
+ return NULL;
+}
+
+/* Register callback to watch this node. */
+int register_xenbus_watch(struct xenbus_watch *watch)
+{
+ /* Pointer in ascii is the token. */
+ char token[sizeof(watch) * 2 + 1];
+ int err;
+
+ sprintf(token, "%lX", (long)watch);
+ //BUG_ON(find_watch(token));
+printk("Registered watch for: %s\n", token);
+ err = xs_watch(watch->node, token);
+ if (!err)
+ list_add(&watch->list, &watches);
+ return err;
+}
+
+void unregister_xenbus_watch(struct xenbus_watch *watch)
+{
+ char token[sizeof(watch) * 2 + 1];
+ int err;
+
+ sprintf(token, "%lX", (long)watch);
+ //BUG_ON(!find_watch(token));
+
+ err = xs_unwatch(watch->node, token);
+ list_del(&watch->list);
+
+ if (err)
+ printk("XENBUS Failed to release watch %s: %i\n",
+ watch->node, err);
+}
+
+/* Re-register callbacks to all watches. */
+void reregister_xenbus_watches(void)
+{
+ struct xenbus_watch *watch;
+ char token[sizeof(watch) * 2 + 1];
+
+ list_for_each_entry(watch, &watches, list) {
+ sprintf(token, "%lX", (long)watch);
+ xs_watch(watch->node, token);
+ }
+}
+
+void watch_thread(void *unused)
+{
+ for (;;) {
+ char *token;
+ char *node = NULL;
+
+ wait_event(xb_waitq, xs_input_avail());
+
+ /* If this is a spurious wakeup caused by someone
+ * doing an op, they'll hold the lock and the buffer
+ * will be empty by the time we get there.
+ */
+ down(&xenbus_lock);
+ if (xs_input_avail())
+ node = xs_read_watch(&token);
+
+ if (node && !IS_ERR(node)) {
+ struct xenbus_watch *w;
+ int err;
+
+ err = xs_acknowledge_watch(token);
+ if (err)
+ printk("XENBUS ack %s fail %i\n", node, err);
+ w = find_watch(token);
+ //BUG_ON(!w);
+ w->callback(w, node);
+ xfree(node);
+ } else
+ printk("XENBUS xs_read_watch: %li\n", PTR_ERR(node));
+ up(&xenbus_lock);
+ }
+}
+
+
+static void ballon_changed(struct xenbus_watch *watch, const char *node)
+{
+ unsigned long new_target;
+ int err;
+ err = xenbus_scanf("memory", "target", "%lu", &new_target);
+
+ if(err != 1)
+ {
+ printk("Unable to read memory/target\n");
+ return;
+ }
+
+ printk("Memory target changed to: %ld bytes, ignoring.\n", new_target);
+}
+
+
+static struct xenbus_watch ballon_watch = {
+ .node = "memory/target",
+ .callback = ballon_changed,
+};
+
+
+
+int xs_init(void)
+{
+ int err;
+ struct thread *watcher;
+ printk("xb_init_comms\n");
+ err = xb_init_comms();
+ if (err)
+ return err;
+
+ watcher = create_thread("kxwatch", watch_thread, NULL);
+ down(&xenbus_lock);
+ register_xenbus_watch(&ballon_watch);
+ up(&xenbus_lock);
+ return 0;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/char/tpm/Kconfig.domU
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/Kconfig.domU Fri Sep 9
16:30:54 2005
@@ -0,0 +1,30 @@
+#
+# TPM device configuration
+#
+
+menu "TPM devices"
+
+config TCG_TPM
+ tristate "TPM Support for XEN"
+ depends on ARCH_XEN && !XEN_PHYSDEV_ACCESS
+ ---help---
+ If you want to make TPM security available in your system,
+ say Yes and it will be accessible from within a user domain. For
+ more information see <http://www.trustedcomputinggroup.org>.
+ An implementation of the Trusted Software Stack (TSS), the
+ userspace enablement piece of the specification, can be
+ obtained at: <http://sourceforge.net/projects/trousers>. To
+ compile this driver as a module, choose M here; the module
+ will be called tpm. If unsure, say N.
+
+config TCG_XEN
+ tristate "XEN TPM Interface"
+ depends on TCG_TPM && ARCH_XEN && XEN_TPMDEV_FRONTEND
+ ---help---
+ If you want to make TPM support available to a Xen
+ user domain, say Yes and it will
+ be accessible from within Linux. To compile this driver
+ as a module, choose M here; the module will be called
+ tpm_xen.
+
+endmenu
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/char/tpm/Makefile
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/Makefile Fri Sep 9 16:30:54 2005
@@ -0,0 +1,12 @@
+#
+# Makefile for the kernel tpm device drivers.
+#
+ifeq ($(CONFIG_XEN_PHYSDEV_ACCESS),y)
+obj-$(CONFIG_TCG_TPM) += tpm.o
+obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
+obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
+obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
+else
+obj-$(CONFIG_TCG_TPM) += tpm_nopci.o
+obj-$(CONFIG_TCG_XEN) += tpm_xen.o
+endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 linux-2.6-xen-sparse/drivers/char/tpm/tpm.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,627 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@xxxxxxxxxxxxxx>
+ * Dave Safford <safford@xxxxxxxxxxxxxx>
+ * Reiner Sailer <sailer@xxxxxxxxxxxxxx>
+ * Kylene Hall <kjhall@xxxxxxxxxx>
+ *
+ * Maintained by: <tpmdd_devel@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ * Note, the TPM chip is not interrupt driven (only polling)
+ * and can have very long timeouts (minutes!). Hence the unusual
+ * calls to schedule_timeout.
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/poll.h>
+#include <linux/spinlock.h>
+#include "tpm.h"
+
+#define TPM_MINOR 224 /* officially assigned
*/
+
+#define TPM_BUFSIZE 2048
+
+static LIST_HEAD(tpm_chip_list);
+static DEFINE_SPINLOCK(driver_lock);
+static int dev_mask[32];
+
+static void user_reader_timeout(unsigned long ptr)
+{
+ struct tpm_chip *chip = (struct tpm_chip *) ptr;
+
+ down(&chip->buffer_mutex);
+ atomic_set(&chip->data_pending, 0);
+ memset(chip->data_buffer, 0, TPM_BUFSIZE);
+ up(&chip->buffer_mutex);
+}
+
+void tpm_time_expired(unsigned long ptr)
+{
+ int *exp = (int *) ptr;
+ *exp = 1;
+}
+
+EXPORT_SYMBOL_GPL(tpm_time_expired);
+
+/*
+ * Internal kernel interface to transmit TPM commands
+ */
+static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
+ size_t bufsiz)
+{
+ ssize_t len;
+ u32 count;
+ __be32 *native_size;
+
+ native_size = (__force __be32 *) (buf + 2);
+ count = be32_to_cpu(*native_size);
+
+ if (count == 0)
+ return -ENODATA;
+ if (count > bufsiz) {
+ dev_err(&chip->pci_dev->dev,
+ "invalid count value %x %zx \n", count, bufsiz);
+ return -E2BIG;
+ }
+
+ down(&chip->tpm_mutex);
+
+ if ((len = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
+ dev_err(&chip->pci_dev->dev,
+ "tpm_transmit: tpm_send: error %zd\n", len);
+ return len;
+ }
+
+ down(&chip->timer_manipulation_mutex);
+ chip->time_expired = 0;
+ init_timer(&chip->device_timer);
+ chip->device_timer.function = tpm_time_expired;
+ chip->device_timer.expires = jiffies + 2 * 60 * HZ;
+ chip->device_timer.data = (unsigned long) &chip->time_expired;
+ add_timer(&chip->device_timer);
+ up(&chip->timer_manipulation_mutex);
+
+ do {
+ u8 status = inb(chip->vendor->base + 1);
+ if ((status & chip->vendor->req_complete_mask) ==
+ chip->vendor->req_complete_val) {
+ down(&chip->timer_manipulation_mutex);
+ del_singleshot_timer_sync(&chip->device_timer);
+ up(&chip->timer_manipulation_mutex);
+ goto out_recv;
+ }
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(TPM_TIMEOUT);
+ rmb();
+ } while (!chip->time_expired);
+
+
+ chip->vendor->cancel(chip);
+ dev_err(&chip->pci_dev->dev, "Time expired\n");
+ up(&chip->tpm_mutex);
+ return -EIO;
+
+out_recv:
+ len = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
+ if (len < 0)
+ dev_err(&chip->pci_dev->dev,
+ "tpm_transmit: tpm_recv: error %zd\n", len);
+ up(&chip->tpm_mutex);
+ return len;
+}
+
+#define TPM_DIGEST_SIZE 20
+#define CAP_PCR_RESULT_SIZE 18
+static u8 cap_pcr[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 22, /* length */
+ 0, 0, 0, 101, /* TPM_ORD_GetCapability */
+ 0, 0, 0, 5,
+ 0, 0, 0, 4,
+ 0, 0, 1, 1
+};
+
+#define READ_PCR_RESULT_SIZE 30
+static u8 pcrread[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 14, /* length */
+ 0, 0, 0, 21, /* TPM_ORD_PcrRead */
+ 0, 0, 0, 0 /* PCR index */
+};
+
+static ssize_t show_pcrs(struct device *dev, char *buf)
+{
+ u8 data[READ_PCR_RESULT_SIZE];
+ ssize_t len;
+ int i, j, index, num_pcrs;
+ char *str = buf;
+
+ struct tpm_chip *chip =
+ pci_get_drvdata(container_of(dev, struct pci_dev, dev));
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, cap_pcr, sizeof(cap_pcr));
+ if ((len = tpm_transmit(chip, data, sizeof(data)))
+ < CAP_PCR_RESULT_SIZE)
+ return len;
+
+ num_pcrs = be32_to_cpu(*((__force __be32 *) (data + 14)));
+
+ for (i = 0; i < num_pcrs; i++) {
+ memcpy(data, pcrread, sizeof(pcrread));
+ index = cpu_to_be32(i);
+ memcpy(data + 10, &index, 4);
+ if ((len = tpm_transmit(chip, data, sizeof(data)))
+ < READ_PCR_RESULT_SIZE)
+ return len;
+ str += sprintf(str, "PCR-%02d: ", i);
+ for (j = 0; j < TPM_DIGEST_SIZE; j++)
+ str += sprintf(str, "%02X ", *(data + 10 + j));
+ str += sprintf(str, "\n");
+ }
+ return str - buf;
+}
+
+static DEVICE_ATTR(pcrs, S_IRUGO, show_pcrs, NULL);
+
+#define READ_PUBEK_RESULT_SIZE 314
+static u8 readpubek[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 30, /* length */
+ 0, 0, 0, 124, /* TPM_ORD_ReadPubek */
+};
+
+static ssize_t show_pubek(struct device *dev, char *buf)
+{
+ u8 data[READ_PUBEK_RESULT_SIZE];
+ ssize_t len;
+ __be32 *native_val;
+ int i;
+ char *str = buf;
+
+ struct tpm_chip *chip =
+ pci_get_drvdata(container_of(dev, struct pci_dev, dev));
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, readpubek, sizeof(readpubek));
+ memset(data + sizeof(readpubek), 0, 20); /* zero nonce */
+
+ if ((len = tpm_transmit(chip, data, sizeof(data))) <
+ READ_PUBEK_RESULT_SIZE)
+ return len;
+
+ /*
+ ignore header 10 bytes
+ algorithm 32 bits (1 == RSA )
+ encscheme 16 bits
+ sigscheme 16 bits
+ parameters (RSA 12->bytes: keybit, #primes, expbit)
+ keylenbytes 32 bits
+ 256 byte modulus
+ ignore checksum 20 bytes
+ */
+
+ native_val = (__force __be32 *) (data + 34);
+
+ str +=
+ sprintf(str,
+ "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n"
+ "Sigscheme: %02X %02X\nParameters: %02X %02X %02X %02X"
+ " %02X %02X %02X %02X %02X %02X %02X %02X\n"
+ "Modulus length: %d\nModulus: \n",
+ data[10], data[11], data[12], data[13], data[14],
+ data[15], data[16], data[17], data[22], data[23],
+ data[24], data[25], data[26], data[27], data[28],
+ data[29], data[30], data[31], data[32], data[33],
+ be32_to_cpu(*native_val)
+ );
+
+ for (i = 0; i < 256; i++) {
+ str += sprintf(str, "%02X ", data[i + 39]);
+ if ((i + 1) % 16 == 0)
+ str += sprintf(str, "\n");
+ }
+ return str - buf;
+}
+
+static DEVICE_ATTR(pubek, S_IRUGO, show_pubek, NULL);
+
+#define CAP_VER_RESULT_SIZE 18
+static u8 cap_version[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 18, /* length */
+ 0, 0, 0, 101, /* TPM_ORD_GetCapability */
+ 0, 0, 0, 6,
+ 0, 0, 0, 0
+};
+
+#define CAP_MANUFACTURER_RESULT_SIZE 18
+static u8 cap_manufacturer[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 22, /* length */
+ 0, 0, 0, 101, /* TPM_ORD_GetCapability */
+ 0, 0, 0, 5,
+ 0, 0, 0, 4,
+ 0, 0, 1, 3
+};
+
+static ssize_t show_caps(struct device *dev, char *buf)
+{
+ u8 data[READ_PUBEK_RESULT_SIZE];
+ ssize_t len;
+ char *str = buf;
+
+ struct tpm_chip *chip =
+ pci_get_drvdata(container_of(dev, struct pci_dev, dev));
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, cap_manufacturer, sizeof(cap_manufacturer));
+
+ if ((len = tpm_transmit(chip, data, sizeof(data))) <
+ CAP_MANUFACTURER_RESULT_SIZE)
+ return len;
+
+ str += sprintf(str, "Manufacturer: 0x%x\n",
+ be32_to_cpu(*(data + 14)));
+
+ memcpy(data, cap_version, sizeof(cap_version));
+
+ if ((len = tpm_transmit(chip, data, sizeof(data))) <
+ CAP_VER_RESULT_SIZE)
+ return len;
+
+ str +=
+ sprintf(str, "TCG version: %d.%d\nFirmware version: %d.%d\n",
+ (int) data[14], (int) data[15], (int) data[16],
+ (int) data[17]);
+
+ return str - buf;
+}
+
+static DEVICE_ATTR(caps, S_IRUGO, show_caps, NULL);
+
+/*
+ * Device file system interface to the TPM
+ */
+int tpm_open(struct inode *inode, struct file *file)
+{
+ int rc = 0, minor = iminor(inode);
+ struct tpm_chip *chip = NULL, *pos;
+
+ spin_lock(&driver_lock);
+
+ list_for_each_entry(pos, &tpm_chip_list, list) {
+ if (pos->vendor->miscdev.minor == minor) {
+ chip = pos;
+ break;
+ }
+ }
+
+ if (chip == NULL) {
+ rc = -ENODEV;
+ goto err_out;
+ }
+
+ if (chip->num_opens) {
+ dev_dbg(&chip->pci_dev->dev,
+ "Another process owns this TPM\n");
+ rc = -EBUSY;
+ goto err_out;
+ }
+
+ chip->num_opens++;
+ pci_dev_get(chip->pci_dev);
+
+ spin_unlock(&driver_lock);
+
+ chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
+ if (chip->data_buffer == NULL) {
+ chip->num_opens--;
+ pci_dev_put(chip->pci_dev);
+ return -ENOMEM;
+ }
+
+ atomic_set(&chip->data_pending, 0);
+
+ file->private_data = chip;
+ return 0;
+
+err_out:
+ spin_unlock(&driver_lock);
+ return rc;
+}
+
+EXPORT_SYMBOL_GPL(tpm_open);
+
+int tpm_release(struct inode *inode, struct file *file)
+{
+ struct tpm_chip *chip = file->private_data;
+
+ file->private_data = NULL;
+
+ spin_lock(&driver_lock);
+ chip->num_opens--;
+ spin_unlock(&driver_lock);
+
+ down(&chip->timer_manipulation_mutex);
+ if (timer_pending(&chip->user_read_timer))
+ del_singleshot_timer_sync(&chip->user_read_timer);
+ else if (timer_pending(&chip->device_timer))
+ del_singleshot_timer_sync(&chip->device_timer);
+ up(&chip->timer_manipulation_mutex);
+
+ kfree(chip->data_buffer);
+ atomic_set(&chip->data_pending, 0);
+
+ pci_dev_put(chip->pci_dev);
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_release);
+
+ssize_t tpm_write(struct file * file, const char __user * buf,
+ size_t size, loff_t * off)
+{
+ struct tpm_chip *chip = file->private_data;
+ int in_size = size, out_size;
+
+ /* cannot perform a write until the read has cleared
+ either via tpm_read or a user_read_timer timeout */
+ while (atomic_read(&chip->data_pending) != 0) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(TPM_TIMEOUT);
+ }
+
+ down(&chip->buffer_mutex);
+
+ if (in_size > TPM_BUFSIZE)
+ in_size = TPM_BUFSIZE;
+
+ if (copy_from_user
+ (chip->data_buffer, (void __user *) buf, in_size)) {
+ up(&chip->buffer_mutex);
+ return -EFAULT;
+ }
+
+ /* atomic tpm command send and result receive */
+ out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE);
+
+ atomic_set(&chip->data_pending, out_size);
+ atomic_set(&chip->data_position, 0);
+ up(&chip->buffer_mutex);
+
+ /* Set a timeout by which the reader must come claim the result */
+ down(&chip->timer_manipulation_mutex);
+ init_timer(&chip->user_read_timer);
+ chip->user_read_timer.function = user_reader_timeout;
+ chip->user_read_timer.data = (unsigned long) chip;
+ chip->user_read_timer.expires = jiffies + (60 * HZ);
+ add_timer(&chip->user_read_timer);
+ up(&chip->timer_manipulation_mutex);
+
+ return in_size;
+}
+
+EXPORT_SYMBOL_GPL(tpm_write);
+
+ssize_t tpm_read(struct file * file, char __user * buf,
+ size_t size, loff_t * off)
+{
+ struct tpm_chip *chip = file->private_data;
+ int ret_size = -ENODATA;
+ int pos, pending = 0;
+
+ down(&chip->buffer_mutex);
+ ret_size = atomic_read(&chip->data_pending);
+ if ( ret_size > 0 ) { /* Result available */
+ if (size < ret_size)
+ ret_size = size;
+
+ pos = atomic_read(&chip->data_position);
+
+ if (copy_to_user((void __user *) buf,
+ &chip->data_buffer[pos], ret_size)) {
+ ret_size = -EFAULT;
+ } else {
+ pending = atomic_read(&chip->data_pending) - ret_size;
+ if ( pending ) {
+ atomic_set( &chip->data_pending, pending );
+ atomic_set( &chip->data_position, pos+ret_size
);
+ }
+ }
+ }
+ up(&chip->buffer_mutex);
+
+ if ( ret_size <= 0 || pending == 0 ) {
+ atomic_set( &chip->data_pending, 0 );
+ down(&chip->timer_manipulation_mutex);
+ del_singleshot_timer_sync(&chip->user_read_timer);
+ up(&chip->timer_manipulation_mutex);
+ }
+
+ return ret_size;
+}
+
+EXPORT_SYMBOL_GPL(tpm_read);
+
+void __devexit tpm_remove(struct pci_dev *pci_dev)
+{
+ struct tpm_chip *chip = pci_get_drvdata(pci_dev);
+
+ if (chip == NULL) {
+ dev_err(&pci_dev->dev, "No device data found\n");
+ return;
+ }
+
+ spin_lock(&driver_lock);
+
+ list_del(&chip->list);
+
+ spin_unlock(&driver_lock);
+
+ pci_set_drvdata(pci_dev, NULL);
+ misc_deregister(&chip->vendor->miscdev);
+
+ device_remove_file(&pci_dev->dev, &dev_attr_pubek);
+ device_remove_file(&pci_dev->dev, &dev_attr_pcrs);
+ device_remove_file(&pci_dev->dev, &dev_attr_caps);
+
+ pci_disable_device(pci_dev);
+
+ dev_mask[chip->dev_num / 32] &= !(1 << (chip->dev_num % 32));
+
+ kfree(chip);
+
+ pci_dev_put(pci_dev);
+}
+
+EXPORT_SYMBOL_GPL(tpm_remove);
+
+static u8 savestate[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 10, /* blob length (in bytes) */
+ 0, 0, 0, 152 /* TPM_ORD_SaveState */
+};
+
+/*
+ * We are about to suspend. Save the TPM state
+ * so that it can be restored.
+ */
+int tpm_pm_suspend(struct pci_dev *pci_dev, pm_message_t pm_state)
+{
+ struct tpm_chip *chip = pci_get_drvdata(pci_dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ tpm_transmit(chip, savestate, sizeof(savestate));
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_pm_suspend);
+
+/*
+ * Resume from a power safe. The BIOS already restored
+ * the TPM state.
+ */
+int tpm_pm_resume(struct pci_dev *pci_dev)
+{
+ struct tpm_chip *chip = pci_get_drvdata(pci_dev);
+
+ if (chip == NULL)
+ return -ENODEV;
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_pm_resume);
+
+/*
+ * Called from tpm_<specific>.c probe function only for devices
+ * the driver has determined it should claim. Prior to calling
+ * this function the specific probe function has called pci_enable_device
+ * upon errant exit from this function specific probe function should call
+ * pci_disable_device
+ */
+int tpm_register_hardware(struct pci_dev *pci_dev,
+ struct tpm_vendor_specific *entry)
+{
+ char devname[7];
+ struct tpm_chip *chip;
+ int i, j;
+
+ /* Driver specific per-device data */
+ chip = kmalloc(sizeof(*chip), GFP_KERNEL);
+ if (chip == NULL)
+ return -ENOMEM;
+
+ memset(chip, 0, sizeof(struct tpm_chip));
+
+ init_MUTEX(&chip->buffer_mutex);
+ init_MUTEX(&chip->tpm_mutex);
+ init_MUTEX(&chip->timer_manipulation_mutex);
+ INIT_LIST_HEAD(&chip->list);
+
+ chip->vendor = entry;
+
+ chip->dev_num = -1;
+
+ for (i = 0; i < 32; i++)
+ for (j = 0; j < 8; j++)
+ if ((dev_mask[i] & (1 << j)) == 0) {
+ chip->dev_num = i * 32 + j;
+ dev_mask[i] |= 1 << j;
+ goto dev_num_search_complete;
+ }
+
+dev_num_search_complete:
+ if (chip->dev_num < 0) {
+ dev_err(&pci_dev->dev,
+ "No available tpm device numbers\n");
+ kfree(chip);
+ return -ENODEV;
+ } else if (chip->dev_num == 0)
+ chip->vendor->miscdev.minor = TPM_MINOR;
+ else
+ chip->vendor->miscdev.minor = MISC_DYNAMIC_MINOR;
+
+ snprintf(devname, sizeof(devname), "%s%d", "tpm", chip->dev_num);
+ chip->vendor->miscdev.name = devname;
+
+ chip->vendor->miscdev.dev = &(pci_dev->dev);
+ chip->pci_dev = pci_dev_get(pci_dev);
+
+ if (misc_register(&chip->vendor->miscdev)) {
+ dev_err(&chip->pci_dev->dev,
+ "unable to misc_register %s, minor %d\n",
+ chip->vendor->miscdev.name,
+ chip->vendor->miscdev.minor);
+ pci_dev_put(pci_dev);
+ kfree(chip);
+ dev_mask[i] &= !(1 << j);
+ return -ENODEV;
+ }
+
+ pci_set_drvdata(pci_dev, chip);
+
+ list_add(&chip->list, &tpm_chip_list);
+
+ device_create_file(&pci_dev->dev, &dev_attr_pubek);
+ device_create_file(&pci_dev->dev, &dev_attr_pcrs);
+ device_create_file(&pci_dev->dev, &dev_attr_caps);
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_register_hardware);
+
+static int __init init_tpm(void)
+{
+ return 0;
+}
+
+static void __exit cleanup_tpm(void)
+{
+
+}
+
+module_init(init_tpm);
+module_exit(cleanup_tpm);
+
+MODULE_AUTHOR("Leendert van Doorn (leendert@xxxxxxxxxxxxxx)");
+MODULE_DESCRIPTION("TPM Driver");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff -r 10b1d30d3f66 -r b2f4823b6ff0 linux-2.6-xen-sparse/drivers/char/tpm/tpm.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@xxxxxxxxxxxxxx>
+ * Dave Safford <safford@xxxxxxxxxxxxxx>
+ * Reiner Sailer <sailer@xxxxxxxxxxxxxx>
+ * Kylene Hall <kjhall@xxxxxxxxxx>
+ *
+ * Maintained by: <tpmdd_devel@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+
+#define TPM_TIMEOUT msecs_to_jiffies(5)
+
+/* TPM addresses */
+#define TPM_ADDR 0x4E
+#define TPM_DATA 0x4F
+
+struct tpm_chip;
+
+struct tpm_vendor_specific {
+ u8 req_complete_mask;
+ u8 req_complete_val;
+ u16 base; /* TPM base address */
+
+ int (*recv) (struct tpm_chip *, u8 *, size_t);
+ int (*send) (struct tpm_chip *, u8 *, size_t);
+ void (*cancel) (struct tpm_chip *);
+ struct miscdevice miscdev;
+};
+
+struct tpm_chip {
+ struct pci_dev *pci_dev; /* PCI device stuff */
+
+ int dev_num; /* /dev/tpm# */
+ int num_opens; /* only one allowed */
+ int time_expired;
+
+ /* Data passed to and from the tpm via the read/write calls */
+ u8 *data_buffer;
+ atomic_t data_pending;
+ atomic_t data_position;
+ struct semaphore buffer_mutex;
+
+ struct timer_list user_read_timer; /* user needs to claim result */
+ struct semaphore tpm_mutex; /* tpm is processing */
+ struct timer_list device_timer; /* tpm is processing */
+ struct semaphore timer_manipulation_mutex;
+
+ struct tpm_vendor_specific *vendor;
+
+ struct list_head list;
+};
+
+static inline int tpm_read_index(int index)
+{
+ outb(index, TPM_ADDR);
+ return inb(TPM_DATA) & 0xFF;
+}
+
+static inline void tpm_write_index(int index, int value)
+{
+ outb(index, TPM_ADDR);
+ outb(value & 0xFF, TPM_DATA);
+}
+
+extern void tpm_time_expired(unsigned long);
+extern int tpm_register_hardware(struct pci_dev *,
+ struct tpm_vendor_specific *);
+extern int tpm_open(struct inode *, struct file *);
+extern int tpm_release(struct inode *, struct file *);
+extern ssize_t tpm_write(struct file *, const char __user *, size_t,
+ loff_t *);
+extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *);
+extern void __devexit tpm_remove(struct pci_dev *);
+extern int tpm_pm_suspend(struct pci_dev *, pm_message_t);
+extern int tpm_pm_resume(struct pci_dev *);
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/char/tpm/tpm_atmel.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_atmel.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@xxxxxxxxxxxxxx>
+ * Dave Safford <safford@xxxxxxxxxxxxxx>
+ * Reiner Sailer <sailer@xxxxxxxxxxxxxx>
+ * Kylene Hall <kjhall@xxxxxxxxxx>
+ *
+ * Maintained by: <tpmdd_devel@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+
+#include "tpm.h"
+
+/* Atmel definitions */
+enum tpm_atmel_addr {
+ TPM_ATMEL_BASE_ADDR_LO = 0x08,
+ TPM_ATMEL_BASE_ADDR_HI = 0x09
+};
+
+/* write status bits */
+#define ATML_STATUS_ABORT 0x01
+#define ATML_STATUS_LASTBYTE 0x04
+
+/* read status bits */
+#define ATML_STATUS_BUSY 0x01
+#define ATML_STATUS_DATA_AVAIL 0x02
+#define ATML_STATUS_REWRITE 0x04
+
+
+static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+ u8 status, *hdr = buf;
+ u32 size;
+ int i;
+ __be32 *native_size;
+
+ /* start reading header */
+ if (count < 6)
+ return -EIO;
+
+ for (i = 0; i < 6; i++) {
+ status = inb(chip->vendor->base + 1);
+ if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
+ dev_err(&chip->pci_dev->dev,
+ "error reading header\n");
+ return -EIO;
+ }
+ *buf++ = inb(chip->vendor->base);
+ }
+
+ /* size of the data received */
+ native_size = (__force __be32 *) (hdr + 2);
+ size = be32_to_cpu(*native_size);
+
+ if (count < size) {
+ dev_err(&chip->pci_dev->dev,
+ "Recv size(%d) less than available space\n", size);
+ for (; i < size; i++) { /* clear the waiting data anyway */
+ status = inb(chip->vendor->base + 1);
+ if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
+ dev_err(&chip->pci_dev->dev,
+ "error reading data\n");
+ return -EIO;
+ }
+ }
+ return -EIO;
+ }
+
+ /* read all the data available */
+ for (; i < size; i++) {
+ status = inb(chip->vendor->base + 1);
+ if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
+ dev_err(&chip->pci_dev->dev,
+ "error reading data\n");
+ return -EIO;
+ }
+ *buf++ = inb(chip->vendor->base);
+ }
+
+ /* make sure data available is gone */
+ status = inb(chip->vendor->base + 1);
+ if (status & ATML_STATUS_DATA_AVAIL) {
+ dev_err(&chip->pci_dev->dev, "data available is stuck\n");
+ return -EIO;
+ }
+
+ return size;
+}
+
+static int tpm_atml_send(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+ int i;
+
+ dev_dbg(&chip->pci_dev->dev, "tpm_atml_send: ");
+ for (i = 0; i < count; i++) {
+ dev_dbg(&chip->pci_dev->dev, "0x%x(%d) ", buf[i], buf[i]);
+ outb(buf[i], chip->vendor->base);
+ }
+
+ return count;
+}
+
+static void tpm_atml_cancel(struct tpm_chip *chip)
+{
+ outb(ATML_STATUS_ABORT, chip->vendor->base + 1);
+}
+
+static struct file_operations atmel_ops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .open = tpm_open,
+ .read = tpm_read,
+ .write = tpm_write,
+ .release = tpm_release,
+};
+
+static struct tpm_vendor_specific tpm_atmel = {
+ .recv = tpm_atml_recv,
+ .send = tpm_atml_send,
+ .cancel = tpm_atml_cancel,
+ .req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL,
+ .req_complete_val = ATML_STATUS_DATA_AVAIL,
+ .miscdev = { .fops = &atmel_ops, },
+};
+
+static int __devinit tpm_atml_init(struct pci_dev *pci_dev,
+ const struct pci_device_id *pci_id)
+{
+ u8 version[4];
+ int rc = 0;
+ int lo, hi;
+
+ if (pci_enable_device(pci_dev))
+ return -EIO;
+
+ lo = tpm_read_index( TPM_ATMEL_BASE_ADDR_LO );
+ hi = tpm_read_index( TPM_ATMEL_BASE_ADDR_HI );
+
+ tpm_atmel.base = (hi<<8)|lo;
+ dev_dbg( &pci_dev->dev, "Operating with base: 0x%x\n", tpm_atmel.base);
+
+ /* verify that it is an Atmel part */
+ if (tpm_read_index(4) != 'A' || tpm_read_index(5) != 'T'
+ || tpm_read_index(6) != 'M' || tpm_read_index(7) != 'L') {
+ rc = -ENODEV;
+ goto out_err;
+ }
+
+ /* query chip for its version number */
+ if ((version[0] = tpm_read_index(0x00)) != 0xFF) {
+ version[1] = tpm_read_index(0x01);
+ version[2] = tpm_read_index(0x02);
+ version[3] = tpm_read_index(0x03);
+ } else {
+ dev_info(&pci_dev->dev, "version query failed\n");
+ rc = -ENODEV;
+ goto out_err;
+ }
+
+ if ((rc = tpm_register_hardware(pci_dev, &tpm_atmel)) < 0)
+ goto out_err;
+
+ dev_info(&pci_dev->dev,
+ "Atmel TPM version %d.%d.%d.%d\n", version[0], version[1],
+ version[2], version[3]);
+
+ return 0;
+out_err:
+ pci_disable_device(pci_dev);
+ return rc;
+}
+
+static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
+ {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
+ {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, tpm_pci_tbl);
+
+static struct pci_driver atmel_pci_driver = {
+ .name = "tpm_atmel",
+ .id_table = tpm_pci_tbl,
+ .probe = tpm_atml_init,
+ .remove = __devexit_p(tpm_remove),
+ .suspend = tpm_pm_suspend,
+ .resume = tpm_pm_resume,
+};
+
+static int __init init_atmel(void)
+{
+ return pci_register_driver(&atmel_pci_driver);
+}
+
+static void __exit cleanup_atmel(void)
+{
+ pci_unregister_driver(&atmel_pci_driver);
+}
+
+module_init(init_atmel);
+module_exit(cleanup_atmel);
+
+MODULE_AUTHOR("Leendert van Doorn (leendert@xxxxxxxxxxxxxx)");
+MODULE_DESCRIPTION("TPM Driver");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/char/tpm/tpm_nopci.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_nopci.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,741 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@xxxxxxxxxxxxxx>
+ * Dave Safford <safford@xxxxxxxxxxxxxx>
+ * Reiner Sailer <sailer@xxxxxxxxxxxxxx>
+ * Kylene Hall <kjhall@xxxxxxxxxx>
+ *
+ * Maintained by: <tpmdd_devel@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ * Note, the TPM chip is not interrupt driven (only polling)
+ * and can have very long timeouts (minutes!). Hence the unusual
+ * calls to schedule_timeout.
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/poll.h>
+#include <linux/spinlock.h>
+#include "tpm_nopci.h"
+
+enum {
+ TPM_MINOR = 224, /* officially assigned */
+ TPM_BUFSIZE = 2048,
+ TPM_NUM_DEVICES = 256,
+ TPM_NUM_MASK_ENTRIES = TPM_NUM_DEVICES / (8 * sizeof(int))
+};
+
+ /* PCI configuration addresses */
+enum {
+ PCI_GEN_PMCON_1 = 0xA0,
+ PCI_GEN1_DEC = 0xE4,
+ PCI_LPC_EN = 0xE6,
+ PCI_GEN2_DEC = 0xEC
+};
+
+enum {
+ TPM_LOCK_REG = 0x0D,
+ TPM_INTERUPT_REG = 0x0A,
+ TPM_BASE_ADDR_LO = 0x08,
+ TPM_BASE_ADDR_HI = 0x09,
+ TPM_UNLOCK_VALUE = 0x55,
+ TPM_LOCK_VALUE = 0xAA,
+ TPM_DISABLE_INTERUPT_VALUE = 0x00
+};
+
+static LIST_HEAD(tpm_chip_list);
+static spinlock_t driver_lock = SPIN_LOCK_UNLOCKED;
+static int dev_mask[32];
+
+static void user_reader_timeout(unsigned long ptr)
+{
+ struct tpm_chip *chip = (struct tpm_chip *) ptr;
+
+ down(&chip->buffer_mutex);
+ atomic_set(&chip->data_pending, 0);
+ memset(chip->data_buffer, 0, TPM_BUFSIZE);
+ up(&chip->buffer_mutex);
+}
+
+void tpm_time_expired(unsigned long ptr)
+{
+ int *exp = (int *) ptr;
+ *exp = 1;
+}
+
+EXPORT_SYMBOL_GPL(tpm_time_expired);
+
+
+/*
+ * This function should be used by other kernel subsystems attempting to use
the tpm through the tpm_transmit interface.
+ * A call to this function will return the chip structure corresponding to the
TPM you are looking for that can then be sent with your command to tpm_transmit.
+ * Passing 0 as the argument corresponds to /dev/tpm0 and thus the first and
probably primary TPM on the system. Passing 1 corresponds to /dev/tpm1 and the
next TPM discovered. If a TPM with the given chip_num does not exist NULL will
be returned.
+ */
+struct tpm_chip* tpm_chip_lookup(int chip_num)
+{
+
+ struct tpm_chip *pos;
+ list_for_each_entry(pos, &tpm_chip_list, list)
+ if (pos->dev_num == chip_num ||
+ chip_num == TPM_ANY_NUM)
+ return pos;
+
+ return NULL;
+
+}
+
+/*
+ * Internal kernel interface to transmit TPM commands
+ */
+ssize_t tpm_transmit(struct tpm_chip * chip, const char *buf,
+ size_t bufsiz)
+{
+ ssize_t rc;
+ u32 count;
+ unsigned long stop;
+
+ count = be32_to_cpu(*((__be32 *) (buf + 2)));
+
+ if (count == 0)
+ return -ENODATA;
+ if (count > bufsiz) {
+ dev_err(chip->dev,
+ "invalid count value %x %x \n", count, bufsiz);
+ return -E2BIG;
+ }
+
+ dev_dbg(chip->dev, "TPM Ordinal: %d\n",
+ be32_to_cpu(*((__be32 *) (buf + 6))));
+ dev_dbg(chip->dev, "Chip Status: %x\n",
+ inb(chip->vendor->base + 1));
+
+ down(&chip->tpm_mutex);
+
+ if ((rc = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
+ dev_err(chip->dev,
+ "tpm_transmit: tpm_send: error %d\n", rc);
+ goto out;
+ }
+
+ stop = jiffies + 2 * 60 * HZ;
+ do {
+ u8 status = chip->vendor->status(chip);
+ if ((status & chip->vendor->req_complete_mask) ==
+ chip->vendor->req_complete_val) {
+ goto out_recv;
+ }
+
+ if ((status == chip->vendor->req_canceled)) {
+ dev_err(chip->dev, "Operation Canceled\n");
+ rc = -ECANCELED;
+ goto out;
+ }
+
+ msleep(TPM_TIMEOUT); /* CHECK */
+ rmb();
+ }
+ while (time_before(jiffies, stop));
+
+
+ chip->vendor->cancel(chip);
+ dev_err(chip->dev, "Operation Timed out\n");
+ rc = -ETIME;
+ goto out;
+
+out_recv:
+ rc = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
+ if (rc < 0)
+ dev_err(chip->dev,
+ "tpm_transmit: tpm_recv: error %d\n", rc);
+ atomic_set(&chip->data_position, 0);
+
+out:
+ up(&chip->tpm_mutex);
+ return rc;
+}
+
+EXPORT_SYMBOL_GPL(tpm_transmit);
+
+#define TPM_DIGEST_SIZE 20
+#define CAP_PCR_RESULT_SIZE 18
+static const u8 cap_pcr[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 22, /* length */
+ 0, 0, 0, 101, /* TPM_ORD_GetCapability */
+ 0, 0, 0, 5,
+ 0, 0, 0, 4,
+ 0, 0, 1, 1
+};
+
+#define READ_PCR_RESULT_SIZE 30
+static const u8 pcrread[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 14, /* length */
+ 0, 0, 0, 21, /* TPM_ORD_PcrRead */
+ 0, 0, 0, 0 /* PCR index */
+};
+
+ssize_t tpm_show_pcrs(struct device *dev, char *buf)
+{
+ u8 data[READ_PCR_RESULT_SIZE];
+ ssize_t len;
+ int i, j, num_pcrs;
+ __be32 index;
+ char *str = buf;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, cap_pcr, sizeof(cap_pcr));
+ if ((len = tpm_transmit(chip, data, sizeof(data)))
+ < CAP_PCR_RESULT_SIZE)
+ return len;
+
+ num_pcrs = be32_to_cpu(*((__be32 *) (data + 14)));
+
+ for (i = 0; i < num_pcrs; i++) {
+ memcpy(data, pcrread, sizeof(pcrread));
+ index = cpu_to_be32(i);
+ memcpy(data + 10, &index, 4);
+ if ((len = tpm_transmit(chip, data, sizeof(data)))
+ < READ_PCR_RESULT_SIZE)
+ return len;
+ str += sprintf(str, "PCR-%02d: ", i);
+ for (j = 0; j < TPM_DIGEST_SIZE; j++)
+ str += sprintf(str, "%02X ", *(data + 10 + j));
+ str += sprintf(str, "\n");
+ }
+ return str - buf;
+}
+
+EXPORT_SYMBOL_GPL(tpm_show_pcrs);
+
+/*
+ * Return 0 on success. On error pass along error code.
+ * chip_id Upper 2 bytes equal ANY, HW_ONLY or SW_ONLY
+ * Lower 2 bytes equal tpm idx # or AN&
+ * res_buf must fit a TPM_PCR (20 bytes) or NULL if you don't care
+ */
+int tpm_pcr_read( u32 chip_id, int pcr_idx, u8* res_buf, int res_buf_size )
+{
+ u8 data[READ_PCR_RESULT_SIZE];
+ int rc;
+ __be32 index;
+ int chip_num = chip_id & TPM_CHIP_NUM_MASK;
+ struct tpm_chip* chip;
+
+ if ( res_buf && res_buf_size < TPM_DIGEST_SIZE )
+ return -ENOSPC;
+ if ( (chip = tpm_chip_lookup( chip_num /*,
+ chip_id >> TPM_CHIP_TYPE_SHIFT*/ ) ) ==
NULL ) {
+ printk("chip %d not found.\n",chip_num);
+ return -ENODEV;
+ }
+ memcpy(data, pcrread, sizeof(pcrread));
+ index = cpu_to_be32(pcr_idx);
+ memcpy(data + 10, &index, 4);
+ if ((rc = tpm_transmit(chip, data, sizeof(data))) > 0 )
+ rc = be32_to_cpu(*((u32*)(data+6)));
+
+ if ( rc == 0 && res_buf )
+ memcpy(res_buf, data+10, TPM_DIGEST_SIZE);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(tpm_pcr_read);
+
+#define EXTEND_PCR_SIZE 34
+static const u8 pcrextend[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND
*/
+ 0, 0, 0, 34, /* length */
+ 0, 0, 0, 20, /* TPM_ORD_Extend */
+ 0, 0, 0, 0 /* PCR index */
+};
+
+/*
+ * Return 0 on success. On error pass along error code.
+ * chip_id Upper 2 bytes equal ANY, HW_ONLY or SW_ONLY
+ * Lower 2 bytes equal tpm idx # or ANY
+ */
+int tpm_pcr_extend(u32 chip_id, int pcr_idx, const u8* hash)
+{
+ u8 data[EXTEND_PCR_SIZE];
+ int rc;
+ __be32 index;
+ int chip_num = chip_id & TPM_CHIP_NUM_MASK;
+ struct tpm_chip* chip;
+
+ if ( (chip = tpm_chip_lookup( chip_num /*,
+ chip_id >> TPM_CHIP_TYPE_SHIFT */)) ==
NULL )
+ return -ENODEV;
+
+ memcpy(data, pcrextend, sizeof(pcrextend));
+ index = cpu_to_be32(pcr_idx);
+ memcpy(data + 10, &index, 4);
+ memcpy( data + 14, hash, TPM_DIGEST_SIZE );
+ if ((rc = tpm_transmit(chip, data, sizeof(data))) > 0 )
+ rc = be32_to_cpu(*((u32*)(data+6)));
+ return rc;
+}
+EXPORT_SYMBOL_GPL(tpm_pcr_extend);
+
+
+
+#define READ_PUBEK_RESULT_SIZE 314
+static const u8 readpubek[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 30, /* length */
+ 0, 0, 0, 124, /* TPM_ORD_ReadPubek */
+};
+
+ssize_t tpm_show_pubek(struct device *dev, char *buf)
+{
+ u8 *data;
+ ssize_t len;
+ int i, rc;
+ char *str = buf;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ data = kmalloc(READ_PUBEK_RESULT_SIZE, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ memcpy(data, readpubek, sizeof(readpubek));
+ memset(data + sizeof(readpubek), 0, 20); /* zero nonce */
+
+ if ((len = tpm_transmit(chip, data, READ_PUBEK_RESULT_SIZE)) <
+ READ_PUBEK_RESULT_SIZE) {
+ rc = len;
+ goto out;
+ }
+
+ /*
+ ignore header 10 bytes
+ algorithm 32 bits (1 == RSA )
+ encscheme 16 bits
+ sigscheme 16 bits
+ parameters (RSA 12->bytes: keybit, #primes, expbit)
+ keylenbytes 32 bits
+ 256 byte modulus
+ ignore checksum 20 bytes
+ */
+
+ str +=
+ sprintf(str,
+ "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n"
+ "Sigscheme: %02X %02X\nParameters: %02X %02X %02X %02X"
+ " %02X %02X %02X %02X %02X %02X %02X %02X\n"
+ "Modulus length: %d\nModulus: \n",
+ data[10], data[11], data[12], data[13], data[14],
+ data[15], data[16], data[17], data[22], data[23],
+ data[24], data[25], data[26], data[27], data[28],
+ data[29], data[30], data[31], data[32], data[33],
+ be32_to_cpu(*((__be32 *) (data + 32))));
+
+ for (i = 0; i < 256; i++) {
+ str += sprintf(str, "%02X ", data[i + 39]);
+ if ((i + 1) % 16 == 0)
+ str += sprintf(str, "\n");
+ }
+ rc = str - buf;
+out:
+ kfree(data);
+ return rc;
+}
+
+EXPORT_SYMBOL_GPL(tpm_show_pubek);
+
+#define CAP_VER_RESULT_SIZE 18
+static const u8 cap_version[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 18, /* length */
+ 0, 0, 0, 101, /* TPM_ORD_GetCapability */
+ 0, 0, 0, 6,
+ 0, 0, 0, 0
+};
+
+#define CAP_MANUFACTURER_RESULT_SIZE 18
+static const u8 cap_manufacturer[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 22, /* length */
+ 0, 0, 0, 101, /* TPM_ORD_GetCapability */
+ 0, 0, 0, 5,
+ 0, 0, 0, 4,
+ 0, 0, 1, 3
+};
+
+ssize_t tpm_show_caps(struct device *dev, char *buf)
+{
+ u8 data[sizeof(cap_manufacturer)];
+ ssize_t len;
+ char *str = buf;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, cap_manufacturer, sizeof(cap_manufacturer));
+
+ if ((len = tpm_transmit(chip, data, sizeof(data))) <
+ CAP_MANUFACTURER_RESULT_SIZE)
+ return len;
+
+ str += sprintf(str, "Manufacturer: 0x%x\n",
+ be32_to_cpu(*((__be32 *)(data + 14))));
+
+ memcpy(data, cap_version, sizeof(cap_version));
+
+ if ((len = tpm_transmit(chip, data, sizeof(data))) <
+ CAP_VER_RESULT_SIZE)
+ return len;
+
+ str +=
+ sprintf(str, "TCG version: %d.%d\nFirmware version: %d.%d\n",
+ (int) data[14], (int) data[15], (int) data[16],
+ (int) data[17]);
+
+ return str - buf;
+}
+
+EXPORT_SYMBOL_GPL(tpm_show_caps);
+
+ssize_t tpm_store_cancel(struct device * dev, const char *buf,
+ size_t count)
+{
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return 0;
+
+ chip->vendor->cancel(chip);
+ return count;
+}
+
+EXPORT_SYMBOL_GPL(tpm_store_cancel);
+
+/*
+ * Device file system interface to the TPM
+ */
+int tpm_open(struct inode *inode, struct file *file)
+{
+ int rc = 0, minor = iminor(inode);
+ struct tpm_chip *chip = NULL, *pos;
+
+ spin_lock(&driver_lock);
+
+ list_for_each_entry(pos, &tpm_chip_list, list) {
+ if (pos->vendor->miscdev.minor == minor) {
+ chip = pos;
+ break;
+ }
+ }
+
+ if (chip == NULL) {
+ rc = -ENODEV;
+ goto err_out;
+ }
+
+ if (chip->num_opens) {
+ dev_dbg(chip->dev, "Another process owns this TPM\n");
+ rc = -EBUSY;
+ goto err_out;
+ }
+
+ chip->num_opens++;
+ get_device(chip->dev);
+
+ spin_unlock(&driver_lock);
+
+ chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
+ if (chip->data_buffer == NULL) {
+ chip->num_opens--;
+ put_device(chip->dev);
+ return -ENOMEM;
+ }
+
+ atomic_set(&chip->data_pending, 0);
+
+ file->private_data = chip;
+ return 0;
+
+err_out:
+ spin_unlock(&driver_lock);
+ return rc;
+}
+
+EXPORT_SYMBOL_GPL(tpm_open);
+
+int tpm_release(struct inode *inode, struct file *file)
+{
+ struct tpm_chip *chip = file->private_data;
+
+ spin_lock(&driver_lock);
+ file->private_data = NULL;
+ chip->num_opens--;
+ del_singleshot_timer_sync(&chip->user_read_timer);
+ atomic_set(&chip->data_pending, 0);
+ put_device(chip->dev);
+ kfree(chip->data_buffer);
+ spin_unlock(&driver_lock);
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_release);
+
+ssize_t tpm_write(struct file * file, const char __user * buf,
+ size_t size, loff_t * off)
+{
+ struct tpm_chip *chip = file->private_data;
+ int in_size = size, out_size;
+
+ /* cannot perform a write until the read has cleared
+ either via tpm_read or a user_read_timer timeout */
+ while (atomic_read(&chip->data_pending) != 0)
+ msleep(TPM_TIMEOUT);
+
+ down(&chip->buffer_mutex);
+
+ if (in_size > TPM_BUFSIZE)
+ in_size = TPM_BUFSIZE;
+
+ if (copy_from_user
+ (chip->data_buffer, (void __user *) buf, in_size)) {
+ up(&chip->buffer_mutex);
+ return -EFAULT;
+ }
+
+ /* atomic tpm command send and result receive */
+ out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE);
+
+ atomic_set(&chip->data_pending, out_size);
+ up(&chip->buffer_mutex);
+
+ /* Set a timeout by which the reader must come claim the result */
+ mod_timer(&chip->user_read_timer, jiffies + (60 * HZ));
+
+ return in_size;
+}
+
+EXPORT_SYMBOL_GPL(tpm_write);
+
+ssize_t tpm_read(struct file * file, char __user * buf,
+ size_t size, loff_t * off)
+{
+ struct tpm_chip *chip = file->private_data;
+ int ret_size;
+
+ del_singleshot_timer_sync(&chip->user_read_timer);
+ ret_size = atomic_read(&chip->data_pending);
+
+ if (ret_size > 0) { /* relay data */
+ int position = atomic_read(&chip->data_position);
+
+ if (size < ret_size)
+ ret_size = size;
+
+ down(&chip->buffer_mutex);
+
+ if (copy_to_user((void __user *) buf,
+ &chip->data_buffer[position],
+ ret_size)) {
+ ret_size = -EFAULT;
+ } else {
+ int pending = atomic_read(&chip->data_pending) -
ret_size;
+ atomic_set(&chip->data_pending,
+ pending);
+ atomic_set(&chip->data_position,
+ position + ret_size);
+ }
+ up(&chip->buffer_mutex);
+ }
+
+ return ret_size;
+}
+
+EXPORT_SYMBOL_GPL(tpm_read);
+
+void tpm_remove_hardware(struct device *dev)
+{
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ int i;
+
+ if (chip == NULL) {
+ dev_err(dev, "No device data found\n");
+ return;
+ }
+
+ spin_lock(&driver_lock);
+
+ list_del(&chip->list);
+
+ spin_unlock(&driver_lock);
+
+ dev_set_drvdata(dev, NULL);
+ misc_deregister(&chip->vendor->miscdev);
+
+ for (i = 0; i < TPM_NUM_ATTR; i++)
+ device_remove_file(dev, &chip->vendor->attr[i]);
+
+ dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES] &=
+ !(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES));
+
+ kfree(chip);
+
+ put_device(dev);
+}
+
+EXPORT_SYMBOL_GPL(tpm_remove_hardware);
+
+static const u8 savestate[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 10, /* blob length (in bytes) */
+ 0, 0, 0, 152 /* TPM_ORD_SaveState */
+};
+
+/*
+ * We are about to suspend. Save the TPM state
+ * so that it can be restored.
+ */
+int tpm_pm_suspend(struct pci_dev *pci_dev, u32 pm_state)
+{
+ struct tpm_chip *chip = pci_get_drvdata(pci_dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ tpm_transmit(chip, savestate, sizeof(savestate));
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_pm_suspend);
+
+/*
+ * Resume from a power safe. The BIOS already restored
+ * the TPM state.
+ */
+int tpm_pm_resume(struct pci_dev *pci_dev)
+{
+ struct tpm_chip *chip = pci_get_drvdata(pci_dev);
+
+ if (chip == NULL)
+ return -ENODEV;
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_pm_resume);
+
+/*
+ * Called from tpm_<specific>.c probe function only for devices
+ * the driver has determined it should claim. Prior to calling
+ * this function the specific probe function has called pci_enable_device
+ * upon errant exit from this function specific probe function should call
+ * pci_disable_device
+ */
+int tpm_register_hardware_nopci(struct device *dev,
+ struct tpm_vendor_specific *entry)
+{
+ char devname[7];
+ struct tpm_chip *chip;
+ int i, j;
+
+ /* Driver specific per-device data */
+ chip = kmalloc(sizeof(*chip), GFP_KERNEL);
+ if (chip == NULL)
+ return -ENOMEM;
+
+ memset(chip, 0, sizeof(struct tpm_chip));
+
+ init_MUTEX(&chip->buffer_mutex);
+ init_MUTEX(&chip->tpm_mutex);
+ INIT_LIST_HEAD(&chip->list);
+
+ init_timer(&chip->user_read_timer);
+ chip->user_read_timer.function = user_reader_timeout;
+ chip->user_read_timer.data = (unsigned long) chip;
+
+ chip->vendor = entry;
+
+ chip->dev_num = -1;
+
+ for (i = 0; i < TPM_NUM_MASK_ENTRIES; i++)
+ for (j = 0; j < 8 * sizeof(int); j++)
+ if ((dev_mask[i] & (1 << j)) == 0) {
+ chip->dev_num =
+ i * TPM_NUM_MASK_ENTRIES + j;
+ dev_mask[i] |= 1 << j;
+ goto dev_num_search_complete;
+ }
+
+dev_num_search_complete:
+ if (chip->dev_num < 0) {
+ dev_err(dev, "No available tpm device numbers\n");
+ kfree(chip);
+ return -ENODEV;
+ } else if (chip->dev_num == 0)
+ chip->vendor->miscdev.minor = TPM_MINOR;
+ else
+ chip->vendor->miscdev.minor = MISC_DYNAMIC_MINOR;
+
+ snprintf(devname, sizeof(devname), "%s%d", "tpm", chip->dev_num);
+ chip->vendor->miscdev.name = devname;
+
+ chip->vendor->miscdev.dev = dev;
+ chip->dev = get_device(dev);
+
+
+ if (misc_register(&chip->vendor->miscdev)) {
+ dev_err(chip->dev,
+ "unable to misc_register %s, minor %d\n",
+ chip->vendor->miscdev.name,
+ chip->vendor->miscdev.minor);
+ put_device(dev);
+ kfree(chip);
+ dev_mask[i] &= !(1 << j);
+ return -ENODEV;
+ }
+
+ spin_lock(&driver_lock);
+
+ dev_set_drvdata(dev, chip);
+
+ list_add(&chip->list, &tpm_chip_list);
+
+ spin_unlock(&driver_lock);
+
+ for (i = 0; i < TPM_NUM_ATTR; i++)
+ device_create_file(dev, &chip->vendor->attr[i]);
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_register_hardware_nopci);
+
+static int __init init_tpm(void)
+{
+ return 0;
+}
+
+static void __exit cleanup_tpm(void)
+{
+
+}
+
+module_init(init_tpm);
+module_exit(cleanup_tpm);
+
+MODULE_AUTHOR("Leendert van Doorn (leendert@xxxxxxxxxxxxxx)");
+MODULE_DESCRIPTION("TPM Driver");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/char/tpm/tpm_nopci.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_nopci.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@xxxxxxxxxxxxxx>
+ * Dave Safford <safford@xxxxxxxxxxxxxx>
+ * Reiner Sailer <sailer@xxxxxxxxxxxxxx>
+ * Kylene Hall <kjhall@xxxxxxxxxx>
+ *
+ * Maintained by: <tpmdd_devel@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/miscdevice.h>
+
+enum {
+ TPM_TIMEOUT = 5, /* msecs */
+ TPM_NUM_ATTR = 4
+};
+
+/* TPM addresses */
+enum {
+ TPM_ADDR = 0x4E,
+ TPM_DATA = 0x4F
+};
+
+/*
+ * Chip num is this value or a valid tpm idx in lower two bytes of chip_id
+ */
+enum tpm_chip_num {
+ TPM_ANY_NUM = 0xFFFF,
+};
+
+#define TPM_CHIP_NUM_MASK 0x0000ffff
+
+extern ssize_t tpm_show_pubek(struct device *, char *);
+extern ssize_t tpm_show_pcrs(struct device *, char *);
+extern ssize_t tpm_show_caps(struct device *, char *);
+extern ssize_t tpm_store_cancel(struct device *, const char *, size_t);
+
+#define TPM_DEVICE_ATTRS { \
+ __ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL), \
+ __ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL), \
+ __ATTR(caps, S_IRUGO, tpm_show_caps, NULL), \
+ __ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel) }
+
+struct tpm_chip;
+
+struct tpm_vendor_specific {
+ u8 req_complete_mask;
+ u8 req_complete_val;
+ u8 req_canceled;
+ u16 base; /* TPM base address */
+
+ int (*recv) (struct tpm_chip *, u8 *, size_t);
+ int (*send) (struct tpm_chip *, u8 *, size_t);
+ void (*cancel) (struct tpm_chip *);
+ u8(*status) (struct tpm_chip *);
+ struct miscdevice miscdev;
+ struct device_attribute attr[TPM_NUM_ATTR];
+};
+
+struct tpm_chip {
+ struct device *dev; /* PCI device stuff */
+
+ int dev_num; /* /dev/tpm# */
+ int num_opens; /* only one allowed */
+ int time_expired;
+
+ /* Data passed to and from the tpm via the read/write calls */
+ u8 *data_buffer;
+ atomic_t data_pending;
+ atomic_t data_position;
+ struct semaphore buffer_mutex;
+
+ struct timer_list user_read_timer; /* user needs to claim result */
+ struct semaphore tpm_mutex; /* tpm is processing */
+
+ struct tpm_vendor_specific *vendor;
+
+ struct list_head list;
+};
+
+static inline int tpm_read_index(int index)
+{
+ outb(index, TPM_ADDR);
+ return inb(TPM_DATA) & 0xFF;
+}
+
+static inline void tpm_write_index(int index, int value)
+{
+ outb(index, TPM_ADDR);
+ outb(value & 0xFF, TPM_DATA);
+}
+
+extern void tpm_time_expired(unsigned long);
+extern int tpm_lpc_bus_init(struct pci_dev *, u16);
+
+extern int tpm_register_hardware_nopci(struct device *,
+ struct tpm_vendor_specific *);
+extern void tpm_remove_hardware(struct device *);
+extern int tpm_open(struct inode *, struct file *);
+extern int tpm_release(struct inode *, struct file *);
+extern ssize_t tpm_write(struct file *, const char __user *, size_t,
+ loff_t *);
+extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *);
+extern int tpm_pcr_extend(u32 chip_id, int pcr_idx, const u8* hash);
+extern int tpm_pcr_read( u32 chip_id, int pcr_idx, u8* res_buf, int
res_buf_size );
+
+extern int tpm_pm_suspend(struct pci_dev *, u32);
+extern int tpm_pm_resume(struct pci_dev *);
+
+/* internal kernel interface */
+extern ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
+ size_t bufsiz);
+extern struct tpm_chip *tpm_chip_lookup(int chip_num);
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/char/tpm/tpm_nsc.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_nsc.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,377 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@xxxxxxxxxxxxxx>
+ * Dave Safford <safford@xxxxxxxxxxxxxx>
+ * Reiner Sailer <sailer@xxxxxxxxxxxxxx>
+ * Kylene Hall <kjhall@xxxxxxxxxx>
+ *
+ * Maintained by: <tpmdd_devel@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+
+#include "tpm.h"
+
+/* National definitions */
+#define TPM_NSC_BASE 0x360
+#define TPM_NSC_IRQ 0x07
+#define TPM_NSC_BASE0_HI 0x60
+#define TPM_NSC_BASE0_LO 0x61
+#define TPM_NSC_BASE1_HI 0x62
+#define TPM_NSC_BASE1_LO 0x63
+
+#define NSC_LDN_INDEX 0x07
+#define NSC_SID_INDEX 0x20
+#define NSC_LDC_INDEX 0x30
+#define NSC_DIO_INDEX 0x60
+#define NSC_CIO_INDEX 0x62
+#define NSC_IRQ_INDEX 0x70
+#define NSC_ITS_INDEX 0x71
+
+#define NSC_STATUS 0x01
+#define NSC_COMMAND 0x01
+#define NSC_DATA 0x00
+
+/* status bits */
+#define NSC_STATUS_OBF 0x01 /* output buffer full */
+#define NSC_STATUS_IBF 0x02 /* input buffer full */
+#define NSC_STATUS_F0 0x04 /* F0 */
+#define NSC_STATUS_A2 0x08 /* A2 */
+#define NSC_STATUS_RDY 0x10 /* ready to receive
command */
+#define NSC_STATUS_IBR 0x20 /* ready to receive
data */
+
+/* command bits */
+#define NSC_COMMAND_NORMAL 0x01 /* normal mode */
+#define NSC_COMMAND_EOC 0x03
+#define NSC_COMMAND_CANCEL 0x22
+
+/*
+ * Wait for a certain status to appear
+ */
+static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data)
+{
+ int expired = 0;
+ struct timer_list status_timer =
+ TIMER_INITIALIZER(tpm_time_expired, jiffies + 10 * HZ,
+ (unsigned long) &expired);
+
+ /* status immediately available check */
+ *data = inb(chip->vendor->base + NSC_STATUS);
+ if ((*data & mask) == val)
+ return 0;
+
+ /* wait for status */
+ add_timer(&status_timer);
+ do {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(TPM_TIMEOUT);
+ *data = inb(chip->vendor->base + 1);
+ if ((*data & mask) == val) {
+ del_singleshot_timer_sync(&status_timer);
+ return 0;
+ }
+ }
+ while (!expired);
+
+ return -EBUSY;
+}
+
+static int nsc_wait_for_ready(struct tpm_chip *chip)
+{
+ int status;
+ int expired = 0;
+ struct timer_list status_timer =
+ TIMER_INITIALIZER(tpm_time_expired, jiffies + 100,
+ (unsigned long) &expired);
+
+ /* status immediately available check */
+ status = inb(chip->vendor->base + NSC_STATUS);
+ if (status & NSC_STATUS_OBF)
+ status = inb(chip->vendor->base + NSC_DATA);
+ if (status & NSC_STATUS_RDY)
+ return 0;
+
+ /* wait for status */
+ add_timer(&status_timer);
+ do {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(TPM_TIMEOUT);
+ status = inb(chip->vendor->base + NSC_STATUS);
+ if (status & NSC_STATUS_OBF)
+ status = inb(chip->vendor->base + NSC_DATA);
+ if (status & NSC_STATUS_RDY) {
+ del_singleshot_timer_sync(&status_timer);
+ return 0;
+ }
+ }
+ while (!expired);
+
+ dev_info(&chip->pci_dev->dev, "wait for ready failed\n");
+ return -EBUSY;
+}
+
+
+static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+ u8 *buffer = buf;
+ u8 data, *p;
+ u32 size;
+ __be32 *native_size;
+
+ if (count < 6)
+ return -EIO;
+
+ if (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0) {
+ dev_err(&chip->pci_dev->dev, "F0 timeout\n");
+ return -EIO;
+ }
+ if ((data =
+ inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
+ dev_err(&chip->pci_dev->dev, "not in normal mode (0x%x)\n",
+ data);
+ return -EIO;
+ }
+
+ /* read the whole packet */
+ for (p = buffer; p < &buffer[count]; p++) {
+ if (wait_for_stat
+ (chip, NSC_STATUS_OBF, NSC_STATUS_OBF, &data) < 0) {
+ dev_err(&chip->pci_dev->dev,
+ "OBF timeout (while reading data)\n");
+ return -EIO;
+ }
+ if (data & NSC_STATUS_F0)
+ break;
+ *p = inb(chip->vendor->base + NSC_DATA);
+ }
+
+ if ((data & NSC_STATUS_F0) == 0) {
+ dev_err(&chip->pci_dev->dev, "F0 not set\n");
+ return -EIO;
+ }
+ if ((data = inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_EOC) {
+ dev_err(&chip->pci_dev->dev,
+ "expected end of command(0x%x)\n", data);
+ return -EIO;
+ }
+
+ native_size = (__force __be32 *) (buf + 2);
+ size = be32_to_cpu(*native_size);
+
+ if (count < size)
+ return -EIO;
+
+ return size;
+}
+
+static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+ u8 data;
+ int i;
+
+ /*
+ * If we hit the chip with back to back commands it locks up
+ * and never set IBF. Hitting it with this "hammer" seems to
+ * fix it. Not sure why this is needed, we followed the flow
+ * chart in the manual to the letter.
+ */
+ outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
+
+ if (nsc_wait_for_ready(chip) != 0)
+ return -EIO;
+
+ if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
+ dev_err(&chip->pci_dev->dev, "IBF timeout\n");
+ return -EIO;
+ }
+
+ outb(NSC_COMMAND_NORMAL, chip->vendor->base + NSC_COMMAND);
+ if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) {
+ dev_err(&chip->pci_dev->dev, "IBR timeout\n");
+ return -EIO;
+ }
+
+ for (i = 0; i < count; i++) {
+ if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
+ dev_err(&chip->pci_dev->dev,
+ "IBF timeout (while writing data)\n");
+ return -EIO;
+ }
+ outb(buf[i], chip->vendor->base + NSC_DATA);
+ }
+
+ if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
+ dev_err(&chip->pci_dev->dev, "IBF timeout\n");
+ return -EIO;
+ }
+ outb(NSC_COMMAND_EOC, chip->vendor->base + NSC_COMMAND);
+
+ return count;
+}
+
+static void tpm_nsc_cancel(struct tpm_chip *chip)
+{
+ outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
+}
+
+static struct file_operations nsc_ops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .open = tpm_open,
+ .read = tpm_read,
+ .write = tpm_write,
+ .release = tpm_release,
+};
+
+static struct tpm_vendor_specific tpm_nsc = {
+ .recv = tpm_nsc_recv,
+ .send = tpm_nsc_send,
+ .cancel = tpm_nsc_cancel,
+ .req_complete_mask = NSC_STATUS_OBF,
+ .req_complete_val = NSC_STATUS_OBF,
+ .miscdev = { .fops = &nsc_ops, },
+
+};
+
+static int __devinit tpm_nsc_init(struct pci_dev *pci_dev,
+ const struct pci_device_id *pci_id)
+{
+ int rc = 0;
+ int lo, hi;
+
+ hi = tpm_read_index(TPM_NSC_BASE0_HI);
+ lo = tpm_read_index(TPM_NSC_BASE0_LO);
+
+ tpm_nsc.base = (hi<<8) | lo;
+
+ if (pci_enable_device(pci_dev))
+ return -EIO;
+
+ /* verify that it is a National part (SID) */
+ if (tpm_read_index(NSC_SID_INDEX) != 0xEF) {
+ rc = -ENODEV;
+ goto out_err;
+ }
+
+ dev_dbg(&pci_dev->dev, "NSC TPM detected\n");
+ dev_dbg(&pci_dev->dev,
+ "NSC LDN 0x%x, SID 0x%x, SRID 0x%x\n",
+ tpm_read_index(0x07), tpm_read_index(0x20),
+ tpm_read_index(0x27));
+ dev_dbg(&pci_dev->dev,
+ "NSC SIOCF1 0x%x SIOCF5 0x%x SIOCF6 0x%x SIOCF8 0x%x\n",
+ tpm_read_index(0x21), tpm_read_index(0x25),
+ tpm_read_index(0x26), tpm_read_index(0x28));
+ dev_dbg(&pci_dev->dev, "NSC IO Base0 0x%x\n",
+ (tpm_read_index(0x60) << 8) | tpm_read_index(0x61));
+ dev_dbg(&pci_dev->dev, "NSC IO Base1 0x%x\n",
+ (tpm_read_index(0x62) << 8) | tpm_read_index(0x63));
+ dev_dbg(&pci_dev->dev, "NSC Interrupt number and wakeup 0x%x\n",
+ tpm_read_index(0x70));
+ dev_dbg(&pci_dev->dev, "NSC IRQ type select 0x%x\n",
+ tpm_read_index(0x71));
+ dev_dbg(&pci_dev->dev,
+ "NSC DMA channel select0 0x%x, select1 0x%x\n",
+ tpm_read_index(0x74), tpm_read_index(0x75));
+ dev_dbg(&pci_dev->dev,
+ "NSC Config "
+ "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ tpm_read_index(0xF0), tpm_read_index(0xF1),
+ tpm_read_index(0xF2), tpm_read_index(0xF3),
+ tpm_read_index(0xF4), tpm_read_index(0xF5),
+ tpm_read_index(0xF6), tpm_read_index(0xF7),
+ tpm_read_index(0xF8), tpm_read_index(0xF9));
+
+ dev_info(&pci_dev->dev,
+ "NSC PC21100 TPM revision %d\n",
+ tpm_read_index(0x27) & 0x1F);
+
+ if (tpm_read_index(NSC_LDC_INDEX) == 0)
+ dev_info(&pci_dev->dev, ": NSC TPM not active\n");
+
+ /* select PM channel 1 */
+ tpm_write_index(NSC_LDN_INDEX, 0x12);
+ tpm_read_index(NSC_LDN_INDEX);
+
+ /* disable the DPM module */
+ tpm_write_index(NSC_LDC_INDEX, 0);
+ tpm_read_index(NSC_LDC_INDEX);
+
+ /* set the data register base addresses */
+ tpm_write_index(NSC_DIO_INDEX, TPM_NSC_BASE >> 8);
+ tpm_write_index(NSC_DIO_INDEX + 1, TPM_NSC_BASE);
+ tpm_read_index(NSC_DIO_INDEX);
+ tpm_read_index(NSC_DIO_INDEX + 1);
+
+ /* set the command register base addresses */
+ tpm_write_index(NSC_CIO_INDEX, (TPM_NSC_BASE + 1) >> 8);
+ tpm_write_index(NSC_CIO_INDEX + 1, (TPM_NSC_BASE + 1));
+ tpm_read_index(NSC_DIO_INDEX);
+ tpm_read_index(NSC_DIO_INDEX + 1);
+
+ /* set the interrupt number to be used for the host interface */
+ tpm_write_index(NSC_IRQ_INDEX, TPM_NSC_IRQ);
+ tpm_write_index(NSC_ITS_INDEX, 0x00);
+ tpm_read_index(NSC_IRQ_INDEX);
+
+ /* enable the DPM module */
+ tpm_write_index(NSC_LDC_INDEX, 0x01);
+ tpm_read_index(NSC_LDC_INDEX);
+
+ if ((rc = tpm_register_hardware(pci_dev, &tpm_nsc)) < 0)
+ goto out_err;
+
+ return 0;
+
+out_err:
+ pci_disable_device(pci_dev);
+ return rc;
+}
+
+static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
+ {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
+ {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, tpm_pci_tbl);
+
+static struct pci_driver nsc_pci_driver = {
+ .name = "tpm_nsc",
+ .id_table = tpm_pci_tbl,
+ .probe = tpm_nsc_init,
+ .remove = __devexit_p(tpm_remove),
+ .suspend = tpm_pm_suspend,
+ .resume = tpm_pm_resume,
+};
+
+static int __init init_nsc(void)
+{
+ return pci_register_driver(&nsc_pci_driver);
+}
+
+static void __exit cleanup_nsc(void)
+{
+ pci_unregister_driver(&nsc_pci_driver);
+}
+
+module_init(init_nsc);
+module_exit(cleanup_nsc);
+
+MODULE_AUTHOR("Leendert van Doorn (leendert@xxxxxxxxxxxxxx)");
+MODULE_DESCRIPTION("TPM Driver");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,513 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@xxxxxxxxxxxxxx>
+ * Dave Safford <safford@xxxxxxxxxxxxxx>
+ * Reiner Sailer <sailer@xxxxxxxxxxxxxx>
+ * Kylene Hall <kjhall@xxxxxxxxxx>
+ * Stefan Berger <stefanb@xxxxxxxxxx>
+ *
+ * Maintained by: <tpmdd_devel@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module) for XEN.
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+
+#include <asm/uaccess.h>
+#include <linux/list.h>
+#include <linux/tpmfe.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include "tpm_nopci.h"
+
+/* read status bits */
+enum {
+ STATUS_BUSY = 0x01,
+ STATUS_DATA_AVAIL = 0x02,
+ STATUS_READY = 0x04
+};
+
+#define MIN(x,y) ((x) < (y)) ? (x) : (y)
+
+struct transmission {
+ struct list_head next;
+ unsigned char *request;
+ unsigned int request_len;
+ unsigned char *rcv_buffer;
+ unsigned int buffersize;
+ struct tpm_chip *chip;
+ unsigned int flags;
+};
+
+enum {
+ TRANSMISSION_FLAG_WAS_QUEUED = 0x1
+};
+
+struct data_exchange {
+ struct transmission *current_request;
+ spinlock_t req_list_lock;
+ wait_queue_head_t req_wait_queue;
+
+ struct list_head queued_requests;
+
+ struct transmission *current_response;
+ spinlock_t resp_list_lock;
+ wait_queue_head_t resp_wait_queue; // processes waiting for
responses
+
+ struct transmission *req_cancelled; // if a cancellation was
encounterd
+
+ unsigned int fe_status;
+ unsigned int flags;
+};
+
+enum {
+ DATAEX_FLAG_QUEUED_ONLY = 0x1
+};
+
+static struct data_exchange dataex;
+
+static unsigned long disconnect_time;
+
+/* local function prototypes */
+static void __exit cleanup_xen(void);
+
+
+/* =============================================================
+ * Some utility functions
+ * =============================================================
+ */
+static inline struct transmission *
+transmission_alloc(void)
+{
+ struct transmission *t = kmalloc(sizeof(*t), GFP_KERNEL);
+ if (t) {
+ memset(t, 0x0, sizeof(*t));
+ }
+ return t;
+}
+
+static inline unsigned char *
+transmission_set_buffer(struct transmission *t,
+ unsigned char *buffer, unsigned int len)
+{
+ if (NULL != t->request) {
+ kfree(t->request);
+ }
+ t->request = kmalloc(len, GFP_KERNEL);
+ if (t->request) {
+ memcpy(t->request,
+ buffer,
+ len);
+ t->request_len = len;
+ }
+ return t->request;
+}
+
+static inline void
+transmission_free(struct transmission *t)
+{
+ if (t->request) {
+ kfree(t->request);
+ }
+ if (t->rcv_buffer) {
+ kfree(t->rcv_buffer);
+ }
+ kfree(t);
+}
+
+/* =============================================================
+ * Interface with the TPM shared memory driver for XEN
+ * =============================================================
+ */
+static int tpm_recv(const u8 *buffer, size_t count, const void *ptr)
+{
+ int ret_size = 0;
+ struct transmission *t, *temp;
+
+ /*
+ * The list with requests must contain one request
+ * only and the element there must be the one that
+ * was passed to me from the front-end.
+ */
+ if (dataex.current_request != ptr) {
+ printk("WARNING: The request pointer is different than the
pointer "
+ "the shared memory driver returned to me. %p != %p\n",
+ dataex.current_request, ptr);
+ }
+
+ /*
+ * If the request has been cancelled, just quit here
+ */
+ if (dataex.req_cancelled == (struct transmission *)ptr) {
+ if (dataex.current_request == dataex.req_cancelled) {
+ dataex.current_request = NULL;
+ }
+ transmission_free(dataex.req_cancelled);
+ dataex.req_cancelled = NULL;
+ return 0;
+ }
+
+ if (NULL != (temp = dataex.current_request)) {
+ transmission_free(temp);
+ dataex.current_request = NULL;
+ }
+
+ t = transmission_alloc();
+ if (NULL != t) {
+ unsigned long flags;
+ t->rcv_buffer = kmalloc(count, GFP_KERNEL);
+ if (NULL == t->rcv_buffer) {
+ transmission_free(t);
+ return -ENOMEM;
+ }
+ t->buffersize = count;
+ memcpy(t->rcv_buffer, buffer, count);
+ ret_size = count;
+
+ spin_lock_irqsave(&dataex.resp_list_lock ,flags);
+ dataex.current_response = t;
+ spin_unlock_irqrestore(&dataex.resp_list_lock, flags);
+ wake_up_interruptible(&dataex.resp_wait_queue);
+ }
+ return ret_size;
+}
+
+
+static void tpm_fe_status(unsigned int flags)
+{
+ dataex.fe_status = flags;
+ if ((dataex.fe_status & TPMFE_STATUS_CONNECTED) == 0) {
+ disconnect_time = jiffies;
+ }
+}
+
+/* =============================================================
+ * Interface with the generic TPM driver
+ * =============================================================
+ */
+static int tpm_xen_recv(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+ unsigned long flags;
+ int rc = 0;
+
+ spin_lock_irqsave(&dataex.resp_list_lock, flags);
+ /*
+ * Check if the previous operation only queued the command
+ * In this case there won't be a response, so I just
+ * return from here and reset that flag. In any other
+ * case I should receive a response from the back-end.
+ */
+ if ((dataex.flags & DATAEX_FLAG_QUEUED_ONLY) != 0) {
+ dataex.flags &= ~DATAEX_FLAG_QUEUED_ONLY;
+ spin_unlock_irqrestore(&dataex.resp_list_lock, flags);
+ /*
+ * a little hack here. The first few measurements
+ * are queued since there's no way to talk to the
+ * TPM yet (due to slowness of the control channel)
+ * So we just make IMA happy by giving it 30 NULL
+ * bytes back where the most important part is
+ * that the result code is '0'.
+ */
+
+ count = MIN(count, 30);
+ memset(buf, 0x0, count);
+ return count;
+ }
+ /*
+ * Check whether something is in the responselist and if
+ * there's nothing in the list wait for something to appear.
+ */
+
+ if (NULL == dataex.current_response) {
+ spin_unlock_irqrestore(&dataex.resp_list_lock, flags);
+ interruptible_sleep_on_timeout(&dataex.resp_wait_queue,
+ 1000);
+ spin_lock_irqsave(&dataex.resp_list_lock ,flags);
+ }
+
+ if (NULL != dataex.current_response) {
+ struct transmission *t = dataex.current_response;
+ dataex.current_response = NULL;
+ rc = MIN(count, t->buffersize);
+ memcpy(buf, t->rcv_buffer, rc);
+ transmission_free(t);
+ }
+
+ spin_unlock_irqrestore(&dataex.resp_list_lock, flags);
+ return rc;
+}
+
+static int tpm_xen_send(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+ /*
+ * We simply pass the packet onto the XEN shared
+ * memory driver.
+ */
+ unsigned long flags;
+ int rc;
+ struct transmission *t = transmission_alloc();
+
+ spin_lock_irqsave(&dataex.req_list_lock, flags);
+ /*
+ * If there's a current request, it must be the
+ * previous request that has timed out.
+ */
+ if (dataex.current_request != NULL) {
+ printk("WARNING: Sending although there is a request
outstanding.\n"
+ " Previous request must have timed out.\n");
+ transmission_free(dataex.current_request);
+ dataex.current_request = NULL;
+ }
+
+ if (t != NULL) {
+ unsigned int error = 0;
+ t->rcv_buffer = NULL;
+ t->buffersize = 0;
+ t->chip = chip;
+
+ /*
+ * Queue the packet if the driver below is not
+ * ready, yet, or there is any packet already
+ * in the queue.
+ * If the driver below is ready, unqueue all
+ * packets first before sending our current
+ * packet.
+ * For each unqueued packet, except for the
+ * last (=current) packet, call the function
+ * tpm_xen_recv to wait for the response to come
+ * back.
+ */
+ if ((dataex.fe_status & TPMFE_STATUS_CONNECTED) == 0) {
+ if (time_after(jiffies, disconnect_time + HZ * 10)) {
+ rc = -ENOENT;
+ } else {
+ /*
+ * copy the request into the buffer
+ */
+ if (transmission_set_buffer(t, buf, count)
+ == NULL) {
+ transmission_free(t);
+ rc = -ENOMEM;
+ goto exit;
+ }
+ dataex.flags |= DATAEX_FLAG_QUEUED_ONLY;
+ list_add_tail(&t->next,
&dataex.queued_requests);
+ rc = 0;
+ }
+ } else {
+ /*
+ * Check whether there are any packets in the queue
+ */
+ while (!list_empty(&dataex.queued_requests)) {
+ /*
+ * Need to dequeue them.
+ * Read the result into a dummy buffer.
+ */
+ unsigned char buffer[1];
+ struct transmission *qt = (struct transmission
*) dataex.queued_requests.next;
+ list_del(&qt->next);
+ dataex.current_request = qt;
+ spin_unlock_irqrestore(&dataex.req_list_lock,
flags);
+
+ rc = tpm_fe_send(qt->request,
+ qt->request_len,
+ qt);
+
+ if (rc < 0) {
+
spin_lock_irqsave(&dataex.req_list_lock, flags);
+ if ((qt = dataex.current_request) !=
NULL) {
+ /*
+ * requeue it at the beginning
+ * of the list
+ */
+ list_add(&qt->next,
+
&dataex.queued_requests);
+ }
+ dataex.current_request = NULL;
+ error = 1;
+ break;
+ }
+ /*
+ * After this point qt is not valid anymore!
+ * It is freed when the front-end is delivering
the data
+ * by calling tpm_recv
+ */
+
+ /*
+ * Try to receive the response now into the
provided dummy
+ * buffer (I don't really care about this
response since
+ * there is no receiver anymore for this
response)
+ */
+ rc = tpm_xen_recv(chip, buffer, sizeof(buffer));
+
+ spin_lock_irqsave(&dataex.req_list_lock, flags);
+ }
+
+ if (error == 0) {
+ /*
+ * Finally, send the current request.
+ */
+ dataex.current_request = t;
+ /*
+ * Call the shared memory driver
+ * Pass to it the buffer with the request, the
+ * amount of bytes in the request and
+ * a void * pointer (here: transmission
structure)
+ */
+ rc = tpm_fe_send(buf, count, t);
+ /*
+ * The generic TPM driver will call
+ * the function to receive the response.
+ */
+ if (rc < 0) {
+ dataex.current_request = NULL;
+ goto queue_it;
+ }
+ } else {
+queue_it:
+ if (transmission_set_buffer(t, buf, count) ==
NULL) {
+ transmission_free(t);
+ rc = -ENOMEM;
+ goto exit;
+ }
+ /*
+ * An error occurred. Don't event try
+ * to send the current request. Just
+ * queue it.
+ */
+ dataex.flags |= DATAEX_FLAG_QUEUED_ONLY;
+ list_add_tail(&t->next,
&dataex.queued_requests);
+ rc = 0;
+ }
+ }
+ } else {
+ rc = -ENOMEM;
+ }
+
+exit:
+ spin_unlock_irqrestore(&dataex.req_list_lock, flags);
+ return rc;
+}
+
+static void tpm_xen_cancel(struct tpm_chip *chip)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&dataex.resp_list_lock,flags);
+
+ dataex.req_cancelled = dataex.current_request;
+
+ spin_unlock_irqrestore(&dataex.resp_list_lock,flags);
+}
+
+static u8 tpm_xen_status(struct tpm_chip *chip)
+{
+ unsigned long flags;
+ u8 rc = 0;
+ spin_lock_irqsave(&dataex.resp_list_lock, flags);
+ /*
+ * Data are available if:
+ * - there's a current response
+ * - the last packet was queued only (this is fake, but necessary to
+ * get the generic TPM layer to call the receive function.)
+ */
+ if (NULL != dataex.current_response ||
+ 0 != (dataex.flags & DATAEX_FLAG_QUEUED_ONLY)) {
+ rc = STATUS_DATA_AVAIL;
+ }
+ spin_unlock_irqrestore(&dataex.resp_list_lock, flags);
+ return rc;
+}
+
+static struct file_operations tpm_xen_ops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .open = tpm_open,
+ .read = tpm_read,
+ .write = tpm_write,
+ .release = tpm_release,
+};
+
+static struct tpm_vendor_specific tpm_xen = {
+ .recv = tpm_xen_recv,
+ .send = tpm_xen_send,
+ .cancel = tpm_xen_cancel,
+ .status = tpm_xen_status,
+ .req_complete_mask = STATUS_BUSY | STATUS_DATA_AVAIL,
+ .req_complete_val = STATUS_DATA_AVAIL,
+ .req_canceled = STATUS_READY,
+ .base = 0,
+ .attr = TPM_DEVICE_ATTRS,
+ .miscdev.fops = &tpm_xen_ops,
+};
+
+static struct device tpm_device = {
+ .bus_id = "vtpm",
+};
+
+static struct tpmfe_device tpmfe = {
+ .receive = tpm_recv,
+ .status = tpm_fe_status,
+};
+
+
+static int __init init_xen(void)
+{
+ int rc;
+
+ /*
+ * Register device with the low lever front-end
+ * driver
+ */
+ if ((rc = tpm_fe_register_receiver(&tpmfe)) < 0) {
+ return rc;
+ }
+
+ /*
+ * Register our device with the system.
+ */
+ if ((rc = device_register(&tpm_device)) < 0) {
+ tpm_fe_unregister_receiver();
+ return rc;
+ }
+
+ if ((rc = tpm_register_hardware_nopci(&tpm_device, &tpm_xen)) < 0) {
+ device_unregister(&tpm_device);
+ tpm_fe_unregister_receiver();
+ return rc;
+ }
+
+ dataex.current_request = NULL;
+ spin_lock_init(&dataex.req_list_lock);
+ init_waitqueue_head(&dataex.req_wait_queue);
+ INIT_LIST_HEAD(&dataex.queued_requests);
+
+ dataex.current_response = NULL;
+ spin_lock_init(&dataex.resp_list_lock);
+ init_waitqueue_head(&dataex.resp_wait_queue);
+
+ disconnect_time = jiffies;
+
+ return 0;
+}
+
+static void __exit cleanup_xen(void)
+{
+ tpm_remove_hardware(&tpm_device);
+ device_unregister(&tpm_device);
+ tpm_fe_unregister_receiver();
+}
+
+fs_initcall(init_xen);
+module_exit(cleanup_xen);
+
+MODULE_AUTHOR("Stefan Berger (stefanb@xxxxxxxxxx)");
+MODULE_DESCRIPTION("TPM Driver for XEN (shared memory)");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/blktap/common.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/common.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,112 @@
+
+#ifndef __BLKIF__BACKEND__COMMON_H__
+#define __BLKIF__BACKEND__COMMON_H__
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+#include <asm/pgalloc.h>
+#include <asm-xen/evtchn.h>
+#include <asm-xen/hypervisor.h>
+#include <asm-xen/xen-public/io/blkif.h>
+#include <asm-xen/xen-public/io/ring.h>
+#include <asm-xen/gnttab.h>
+
+#if 0
+#define ASSERT(_p) \
+ if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \
+ __LINE__, __FILE__); *(int*)0=0; }
+#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \
+ __FILE__ , __LINE__ , ## _a )
+#else
+#define ASSERT(_p) ((void)0)
+#define DPRINTK(_f, _a...) ((void)0)
+#endif
+
+#define WPRINTK(fmt, args...) printk(KERN_WARNING "blk_tap: " fmt, ##args)
+
+struct vbd {
+ blkif_vdev_t handle; /* what the domain refers to this vbd as */
+ unsigned char readonly; /* Non-zero -> read-only */
+ unsigned char type; /* VDISK_xxx */
+ blkif_pdev_t pdevice; /* phys device that this vbd maps to */
+ struct block_device *bdev;
+};
+
+typedef struct blkif_st {
+ /* Unique identifier for this interface. */
+ domid_t domid;
+ unsigned int handle;
+ /* Physical parameters of the comms window. */
+ unsigned long shmem_frame;
+ unsigned int evtchn;
+ unsigned int remote_evtchn;
+ /* Comms information. */
+ blkif_back_ring_t blk_ring;
+ /* VBDs attached to this interface. */
+ struct vbd vbd;
+ /* Private fields. */
+ enum { DISCONNECTED, CONNECTED } status;
+#ifdef CONFIG_XEN_BLKDEV_TAP_BE
+ /* Is this a blktap frontend */
+ unsigned int is_blktap;
+#endif
+ struct list_head blkdev_list;
+ spinlock_t blk_ring_lock;
+ atomic_t refcnt;
+
+ struct work_struct free_work;
+ u16 shmem_handle;
+ unsigned long shmem_vaddr;
+ grant_ref_t shmem_ref;
+} blkif_t;
+
+void blkif_create(blkif_be_create_t *create);
+void blkif_destroy(blkif_be_destroy_t *destroy);
+void blkif_connect(blkif_be_connect_t *connect);
+int blkif_disconnect(blkif_be_disconnect_t *disconnect, u8 rsp_id);
+void blkif_disconnect_complete(blkif_t *blkif);
+blkif_t *alloc_blkif(domid_t domid);
+void free_blkif_callback(blkif_t *blkif);
+int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn);
+
+#define blkif_get(_b) (atomic_inc(&(_b)->refcnt))
+#define blkif_put(_b) \
+ do { \
+ if ( atomic_dec_and_test(&(_b)->refcnt) ) \
+ free_blkif_callback(_b); \
+ } while (0)
+
+/* Create a vbd. */
+int vbd_create(blkif_t *blkif, blkif_vdev_t vdevice, blkif_pdev_t pdevice,
+ int readonly);
+void vbd_free(struct vbd *vbd);
+
+unsigned long vbd_size(struct vbd *vbd);
+unsigned int vbd_info(struct vbd *vbd);
+unsigned long vbd_secsize(struct vbd *vbd);
+
+struct phys_req {
+ unsigned short dev;
+ unsigned short nr_sects;
+ struct block_device *bdev;
+ blkif_sector_t sector_number;
+};
+
+int vbd_translate(struct phys_req *req, blkif_t *blkif, int operation);
+
+void blkif_interface_init(void);
+
+void blkif_deschedule(blkif_t *blkif);
+
+void blkif_xenbus_init(void);
+
+irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs);
+
+#endif /* __BLKIF__BACKEND__COMMON_H__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/blktap/interface.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c Fri Sep 9
16:30:54 2005
@@ -0,0 +1,141 @@
+/******************************************************************************
+ * arch/xen/drivers/blkif/backend/interface.c
+ *
+ * Block-device interface management.
+ *
+ * Copyright (c) 2004, Keir Fraser
+ */
+
+#include "common.h"
+#include <asm-xen/evtchn.h>
+
+static kmem_cache_t *blkif_cachep;
+
+blkif_t *alloc_blkif(domid_t domid)
+{
+ blkif_t *blkif;
+
+ blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL);
+ if (!blkif)
+ return ERR_PTR(-ENOMEM);
+
+ memset(blkif, 0, sizeof(*blkif));
+ blkif->domid = domid;
+ blkif->status = DISCONNECTED;
+ spin_lock_init(&blkif->blk_ring_lock);
+ atomic_set(&blkif->refcnt, 1);
+
+ return blkif;
+}
+
+static int map_frontend_page(blkif_t *blkif, unsigned long localaddr,
+ unsigned long shared_page)
+{
+ struct gnttab_map_grant_ref op;
+ op.host_addr = localaddr;
+ op.flags = GNTMAP_host_map;
+ op.ref = shared_page;
+ op.dom = blkif->domid;
+
+ BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) );
+
+ if (op.handle < 0) {
+ DPRINTK(" Grant table operation failure !\n");
+ return op.handle;
+ }
+
+ blkif->shmem_ref = shared_page;
+ blkif->shmem_handle = op.handle;
+ blkif->shmem_vaddr = localaddr;
+ return 0;
+}
+
+static void unmap_frontend_page(blkif_t *blkif)
+{
+ struct gnttab_unmap_grant_ref op;
+
+ op.host_addr = blkif->shmem_vaddr;
+ op.handle = blkif->shmem_handle;
+ op.dev_bus_addr = 0;
+ BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
+}
+
+int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn)
+{
+ struct vm_struct *vma;
+ blkif_sring_t *sring;
+ evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain };
+ int err;
+
+ BUG_ON(blkif->remote_evtchn);
+
+ if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL )
+ return -ENOMEM;
+
+ err = map_frontend_page(blkif, (unsigned long)vma->addr, shared_page);
+ if (err) {
+ vfree(vma->addr);
+ return err;
+ }
+
+ op.u.bind_interdomain.dom1 = DOMID_SELF;
+ op.u.bind_interdomain.dom2 = blkif->domid;
+ op.u.bind_interdomain.port1 = 0;
+ op.u.bind_interdomain.port2 = evtchn;
+ err = HYPERVISOR_event_channel_op(&op);
+ if (err) {
+ unmap_frontend_page(blkif);
+ vfree(vma->addr);
+ return err;
+ }
+
+ blkif->evtchn = op.u.bind_interdomain.port1;
+ blkif->remote_evtchn = evtchn;
+
+ sring = (blkif_sring_t *)vma->addr;
+ SHARED_RING_INIT(sring);
+ BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE);
+
+ bind_evtchn_to_irqhandler(blkif->evtchn, blkif_be_int, 0, "blkif-backend",
+ blkif);
+ blkif->status = CONNECTED;
+ blkif->shmem_frame = shared_page;
+
+ return 0;
+}
+
+static void free_blkif(void *arg)
+{
+ evtchn_op_t op = { .cmd = EVTCHNOP_close };
+ blkif_t *blkif = (blkif_t *)arg;
+
+ op.u.close.port = blkif->evtchn;
+ op.u.close.dom = DOMID_SELF;
+ HYPERVISOR_event_channel_op(&op);
+ op.u.close.port = blkif->remote_evtchn;
+ op.u.close.dom = blkif->domid;
+ HYPERVISOR_event_channel_op(&op);
+
+ if (blkif->evtchn)
+ unbind_evtchn_from_irqhandler(blkif->evtchn, blkif);
+
+ if (blkif->blk_ring.sring) {
+ unmap_frontend_page(blkif);
+ vfree(blkif->blk_ring.sring);
+ blkif->blk_ring.sring = NULL;
+ }
+
+ kmem_cache_free(blkif_cachep, blkif);
+}
+
+void free_blkif_callback(blkif_t *blkif)
+{
+ INIT_WORK(&blkif->free_work, free_blkif, (void *)blkif);
+ schedule_work(&blkif->free_work);
+}
+
+void __init blkif_interface_init(void)
+{
+ blkif_cachep = kmem_cache_create("blkif_cache", sizeof(blkif_t),
+ 0, 0, NULL, NULL);
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,225 @@
+/* Xenbus code for blkif tap
+
+ A Warfield.
+
+ Hastily modified from the oroginal backend code:
+
+ Copyright (C) 2005 Rusty Russell <rusty@xxxxxxxxxxxxxxx>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <stdarg.h>
+#include <linux/module.h>
+#include <asm-xen/xenbus.h>
+#include "common.h"
+
+struct backend_info
+{
+ struct xenbus_device *dev;
+
+ /* our communications channel */
+ blkif_t *blkif;
+
+ long int frontend_id;
+
+ /* watch back end for changes */
+ struct xenbus_watch backend_watch;
+
+ /* watch front end for changes */
+ struct xenbus_watch watch;
+ char *frontpath;
+};
+
+static int blkback_remove(struct xenbus_device *dev)
+{
+ struct backend_info *be = dev->data;
+
+ if (be->watch.node)
+ unregister_xenbus_watch(&be->watch);
+ unregister_xenbus_watch(&be->backend_watch);
+ if (be->blkif)
+ blkif_put(be->blkif);
+ if (be->frontpath)
+ kfree(be->frontpath);
+ kfree(be);
+ return 0;
+}
+
+/* Front end tells us frame. */
+static void frontend_changed(struct xenbus_watch *watch, const char *node)
+{
+ unsigned long ring_ref;
+ unsigned int evtchn;
+ int err;
+ struct backend_info *be
+ = container_of(watch, struct backend_info, watch);
+
+ /* If other end is gone, delete ourself. */
+ if (node && !xenbus_exists(be->frontpath, "")) {
+ xenbus_rm(be->dev->nodename, "");
+ device_unregister(&be->dev->dev);
+ return;
+ }
+ if (be->blkif == NULL || be->blkif->status == CONNECTED)
+ return;
+
+ err = xenbus_gather(be->frontpath, "ring-ref", "%lu", &ring_ref,
+ "event-channel", "%u", &evtchn, NULL);
+ if (err) {
+ xenbus_dev_error(be->dev, err,
+ "reading %s/ring-ref and event-channel",
+ be->frontpath);
+ return;
+ }
+
+ /* Map the shared frame, irq etc. */
+ err = blkif_map(be->blkif, ring_ref, evtchn);
+ if (err) {
+ xenbus_dev_error(be->dev, err, "mapping ring-ref %lu port %u",
+ ring_ref, evtchn);
+ goto abort;
+ }
+
+ xenbus_dev_ok(be->dev);
+
+ return;
+
+abort:
+ xenbus_transaction_end(1);
+}
+
+/*
+ Setup supplies physical device.
+ We provide event channel and device details to front end.
+ Frontend supplies shared frame and event channel.
+ */
+static void backend_changed(struct xenbus_watch *watch, const char *node)
+{
+ int err;
+ char *p;
+ long int handle;
+ struct backend_info *be
+ = container_of(watch, struct backend_info, backend_watch);
+ struct xenbus_device *dev = be->dev;
+
+ if (be->blkif == NULL) {
+ /* Front end dir is a number, which is used as the handle. */
+ p = strrchr(be->frontpath, '/') + 1;
+ handle = simple_strtoul(p, NULL, 0);
+
+ be->blkif = alloc_blkif(be->frontend_id);
+ if (IS_ERR(be->blkif)) {
+ err = PTR_ERR(be->blkif);
+ be->blkif = NULL;
+ xenbus_dev_error(dev, err, "creating block interface");
+ return;
+ }
+
+ /* Pass in NULL node to skip exist test. */
+ frontend_changed(&be->watch, NULL);
+ }
+}
+
+static int blkback_probe(struct xenbus_device *dev,
+ const struct xenbus_device_id *id)
+{
+ struct backend_info *be;
+ char *frontend;
+ int err;
+
+ be = kmalloc(sizeof(*be), GFP_KERNEL);
+ if (!be) {
+ xenbus_dev_error(dev, -ENOMEM, "allocating backend structure");
+ return -ENOMEM;
+ }
+ memset(be, 0, sizeof(*be));
+
+ frontend = NULL;
+ err = xenbus_gather(dev->nodename,
+ "frontend-id", "%li", &be->frontend_id,
+ "frontend", NULL, &frontend,
+ NULL);
+ if (XENBUS_EXIST_ERR(err))
+ goto free_be;
+ if (err < 0) {
+ xenbus_dev_error(dev, err,
+ "reading %s/frontend or frontend-id",
+ dev->nodename);
+ goto free_be;
+ }
+ if (strlen(frontend) == 0 || !xenbus_exists(frontend, "")) {
+ /* If we can't get a frontend path and a frontend-id,
+ * then our bus-id is no longer valid and we need to
+ * destroy the backend device.
+ */
+ err = -ENOENT;
+ goto free_be;
+ }
+
+ be->dev = dev;
+ be->backend_watch.node = dev->nodename;
+ be->backend_watch.callback = backend_changed;
+ err = register_xenbus_watch(&be->backend_watch);
+ if (err) {
+ be->backend_watch.node = NULL;
+ xenbus_dev_error(dev, err, "adding backend watch on %s",
+ dev->nodename);
+ goto free_be;
+ }
+
+ be->frontpath = frontend;
+ be->watch.node = be->frontpath;
+ be->watch.callback = frontend_changed;
+ err = register_xenbus_watch(&be->watch);
+ if (err) {
+ be->watch.node = NULL;
+ xenbus_dev_error(dev, err,
+ "adding frontend watch on %s",
+ be->frontpath);
+ goto free_be;
+ }
+
+ dev->data = be;
+
+ backend_changed(&be->backend_watch, dev->nodename);
+ return 0;
+
+ free_be:
+ if (be->backend_watch.node)
+ unregister_xenbus_watch(&be->backend_watch);
+ if (frontend)
+ kfree(frontend);
+ kfree(be);
+ return err;
+}
+
+static struct xenbus_device_id blkback_ids[] = {
+ { "vbd" },
+ { "" }
+};
+
+static struct xenbus_driver blkback = {
+ .name = "vbd",
+ .owner = THIS_MODULE,
+ .ids = blkback_ids,
+ .probe = blkback_probe,
+ .remove = blkback_remove,
+};
+
+void blkif_xenbus_init(void)
+{
+ xenbus_register_backend(&blkback);
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c Fri Sep 9
16:30:54 2005
@@ -0,0 +1,128 @@
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/major.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+#include <asm-xen/hypervisor.h>
+#include <asm-xen/evtchn.h>
+#include <linux/wait.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include "xencons_ring.h"
+
+
+struct ring_head
+{
+ u32 cons;
+ u32 prod;
+ char buf[0];
+} __attribute__((packed));
+
+
+#define XENCONS_RING_SIZE (PAGE_SIZE/2 - sizeof (struct ring_head))
+#define XENCONS_IDX(cnt) ((cnt) % XENCONS_RING_SIZE)
+#define XENCONS_FULL(ring) (((ring)->prod - (ring)->cons) == XENCONS_RING_SIZE)
+
+static inline struct ring_head *outring(void)
+{
+ return machine_to_virt(xen_start_info->console_mfn << PAGE_SHIFT);
+}
+
+static inline struct ring_head *inring(void)
+{
+ return machine_to_virt(xen_start_info->console_mfn << PAGE_SHIFT)
+ + PAGE_SIZE/2;
+}
+
+
+/* don't block - write as much as possible and return */
+static int __xencons_ring_send(struct ring_head *ring, const char *data,
unsigned len)
+{
+ int copied = 0;
+
+ mb();
+ while (copied < len && !XENCONS_FULL(ring)) {
+ ring->buf[XENCONS_IDX(ring->prod)] = data[copied];
+ ring->prod++;
+ copied++;
+ }
+ mb();
+
+ return copied;
+}
+
+int xencons_ring_send(const char *data, unsigned len)
+{
+ struct ring_head *out = outring();
+ int sent = 0;
+
+ sent = __xencons_ring_send(out, data, len);
+ notify_via_evtchn(xen_start_info->console_evtchn);
+ return sent;
+
+}
+
+
+static xencons_receiver_func *xencons_receiver;
+
+static irqreturn_t handle_input(int irq, void *unused, struct pt_regs *regs)
+{
+ struct ring_head *ring = inring();
+ while (ring->cons < ring->prod) {
+ if (xencons_receiver != NULL) {
+ xencons_receiver(ring->buf + XENCONS_IDX(ring->cons),
+ 1, regs);
+ }
+ ring->cons++;
+ }
+ return IRQ_HANDLED;
+}
+
+void xencons_ring_register_receiver(xencons_receiver_func *f)
+{
+ xencons_receiver = f;
+}
+
+int xencons_ring_init(void)
+{
+ int err;
+
+ if (!xen_start_info->console_evtchn)
+ return 0;
+
+ err = bind_evtchn_to_irqhandler(xen_start_info->console_evtchn,
+ handle_input, 0, "xencons", inring());
+ if (err) {
+ xprintk("XEN console request irq failed %i\n", err);
+ return err;
+ }
+
+ return 0;
+}
+
+void xencons_suspend(void)
+{
+
+ if (!xen_start_info->console_evtchn)
+ return;
+
+ unbind_evtchn_from_irqhandler(xen_start_info->console_evtchn,
+ inring());
+}
+
+void xencons_resume(void)
+{
+
+ (void)xencons_ring_init();
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.h Fri Sep 9
16:30:54 2005
@@ -0,0 +1,14 @@
+#ifndef _XENCONS_RING_H
+#define _XENCONS_RING_H
+
+asmlinkage int xprintk(const char *fmt, ...);
+
+
+int xencons_ring_init(void);
+int xencons_ring_send(const char *data, unsigned len);
+
+typedef void (xencons_receiver_func)(char *buf, unsigned len,
+ struct pt_regs *regs);
+void xencons_ring_register_receiver(xencons_receiver_func *f);
+
+#endif /* _XENCONS_RING_H */
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/tpmback/Makefile
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/Makefile Fri Sep 9 16:30:54 2005
@@ -0,0 +1,4 @@
+
+obj-$(CONFIG_XEN_TPMDEV_BACKEND) += tpmbk.o
+
+tpmbk-y += tpmback.o interface.o xenbus.o
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/tpmback/common.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,88 @@
+/******************************************************************************
+ * drivers/xen/tpmback/common.h
+ */
+
+#ifndef __NETIF__BACKEND__COMMON_H__
+#define __NETIF__BACKEND__COMMON_H__
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <asm-xen/evtchn.h>
+#include <asm-xen/xen-public/io/tpmif.h>
+#include <asm/io.h>
+#include <asm/pgalloc.h>
+#include <asm-xen/xen-public/io/domain_controller.h>
+
+#if 0
+#define ASSERT(_p) \
+ if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \
+ __LINE__, __FILE__); *(int*)0=0; }
+#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \
+ __FILE__ , __LINE__ , ## _a )
+#else
+#define ASSERT(_p) ((void)0)
+#define DPRINTK(_f, _a...) ((void)0)
+#endif
+
+typedef struct tpmif_st {
+ struct list_head tpmif_list;
+ /* Unique identifier for this interface. */
+ domid_t domid;
+ unsigned int handle;
+
+ /* Physical parameters of the comms window. */
+ unsigned long tx_shmem_frame;
+ unsigned int evtchn;
+ unsigned int remote_evtchn;
+
+ /* The shared rings and indexes. */
+ tpmif_tx_interface_t *tx;
+
+ /* Miscellaneous private stuff. */
+ enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
+ int active;
+
+ struct tpmif_st *hash_next;
+ struct list_head list; /* scheduling list */
+ atomic_t refcnt;
+
+ long int tpm_instance;
+ unsigned long mmap_vstart;
+
+ struct work_struct work;
+
+ u16 shmem_handle;
+ unsigned long shmem_vaddr;
+ grant_ref_t shmem_ref;
+
+} tpmif_t;
+
+void tpmif_disconnect_complete(tpmif_t * tpmif);
+tpmif_t *tpmif_find(domid_t domid, long int instance);
+void tpmif_interface_init(void);
+void tpmif_schedule_work(tpmif_t * tpmif);
+void tpmif_deschedule_work(tpmif_t * tpmif);
+void tpmif_xenbus_init(void);
+int tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn);
+irqreturn_t tpmif_be_int(int irq, void *dev_id, struct pt_regs *regs);
+int tpmif_vtpm_open(tpmif_t *tpmif, domid_t domain, u32 instance);
+int tpmif_vtpm_close(u32 instance);
+
+int vtpm_release_packets(tpmif_t * tpmif, int send_msgs);
+
+#define tpmif_get(_b) (atomic_inc(&(_b)->refcnt))
+#define tpmif_put(_b) \
+ do { \
+ if ( atomic_dec_and_test(&(_b)->refcnt) ) \
+ tpmif_disconnect_complete(_b); \
+ } while (0)
+
+
+extern int num_frontends;
+
+#define MMAP_VADDR(t,_req) ((t)->mmap_vstart + ((_req) * PAGE_SIZE))
+
+#endif /* __TPMIF__BACKEND__COMMON_H__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c Fri Sep 9
16:30:54 2005
@@ -0,0 +1,200 @@
+/******************************************************************************
+ * drivers/xen/tpmback/interface.c
+ *
+ * Vritual TPM interface management.
+ *
+ * Copyright (c) 2005, IBM Corporation
+ *
+ * Author: Stefan Berger, stefanb@xxxxxxxxxx
+ *
+ * This code has been derived from drivers/xen/netback/interface.c
+ * Copyright (c) 2004, Keir Fraser
+ */
+
+#include "common.h"
+#include <asm-xen/balloon.h>
+
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+
+#define TPMIF_HASHSZ (2 << 5)
+#define TPMIF_HASH(_d,_h) (((int)(_d)^(int)(_h))&(TPMIF_HASHSZ-1))
+
+static kmem_cache_t *tpmif_cachep;
+int num_frontends = 0;
+LIST_HEAD(tpmif_list);
+
+
+tpmif_t *alloc_tpmif(domid_t domid, long int instance)
+{
+ struct page *page;
+ tpmif_t *tpmif;
+
+ tpmif = kmem_cache_alloc(tpmif_cachep, GFP_KERNEL);
+ if (!tpmif)
+ return ERR_PTR(-ENOMEM);
+
+ memset(tpmif, 0, sizeof(*tpmif));
+ tpmif->domid = domid;
+ tpmif->status = DISCONNECTED;
+ tpmif->tpm_instance = instance;
+ atomic_set(&tpmif->refcnt, 1);
+
+ page = balloon_alloc_empty_page_range(TPMIF_TX_RING_SIZE);
+ BUG_ON(page == NULL);
+ tpmif->mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
+
+ list_add(&tpmif->tpmif_list, &tpmif_list);
+ num_frontends++;
+
+ return tpmif;
+}
+
+
+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;
+
+ list_for_each_entry(tpmif, &tpmif_list, tpmif_list) {
+ if (tpmif->tpm_instance == instance) {
+ if (tpmif->domid == domid) {
+ tpmif_get(tpmif);
+ return tpmif;
+ } else {
+ return NULL;
+ }
+ }
+ }
+
+ return alloc_tpmif(domid, instance);
+}
+
+
+static int map_frontend_page(tpmif_t *tpmif, unsigned long localaddr,
+ unsigned long shared_page)
+{
+ struct gnttab_map_grant_ref op = {
+ .host_addr = localaddr,
+ .flags = GNTMAP_host_map,
+ .ref = shared_page,
+ .dom = tpmif->domid,
+ };
+
+ BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) );
+
+ if (op.handle < 0) {
+ DPRINTK(" Grant table operation failure !\n");
+ return op.handle;
+ }
+
+ tpmif->shmem_ref = shared_page;
+ tpmif->shmem_handle = op.handle;
+ tpmif->shmem_vaddr = localaddr;
+ return 0;
+}
+
+
+static void unmap_frontend_page(tpmif_t *tpmif)
+{
+ struct gnttab_unmap_grant_ref op;
+
+ op.host_addr = tpmif->shmem_vaddr;
+ op.handle = tpmif->shmem_handle;
+ op.dev_bus_addr = 0;
+
+ BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
+}
+
+
+int tpmif_map(tpmif_t *tpmif,
+ unsigned long shared_page, unsigned int evtchn)
+{
+ struct vm_struct *vma;
+ evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain };
+ int err;
+
+ BUG_ON(tpmif->remote_evtchn);
+
+ if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL )
+ return -ENOMEM;
+
+ err = map_frontend_page(tpmif,
+ VMALLOC_VMADDR(vma->addr),
+ shared_page);
+ if (err) {
+ vfree(vma->addr);
+ return err;
+ }
+
+ op.u.bind_interdomain.dom1 = DOMID_SELF;
+ op.u.bind_interdomain.dom2 = tpmif->domid;
+ op.u.bind_interdomain.port1 = 0;
+ op.u.bind_interdomain.port2 = evtchn;
+ err = HYPERVISOR_event_channel_op(&op);
+ if (err) {
+ unmap_frontend_page(tpmif);
+ vfree(vma->addr);
+ return err;
+ }
+
+ tpmif->evtchn = op.u.bind_interdomain.port1;
+ tpmif->remote_evtchn = evtchn;
+
+ tpmif->tx = (tpmif_tx_interface_t *) vma->addr;
+
+ bind_evtchn_to_irqhandler(tpmif->evtchn,
+ tpmif_be_int,
+ 0,
+ "tpmif-backend",
+ tpmif);
+ tpmif->status = CONNECTED;
+ tpmif->shmem_ref = shared_page;
+ tpmif->active = 1;
+
+ return 0;
+}
+
+
+static void __tpmif_disconnect_complete(void *arg)
+{
+ evtchn_op_t op = { .cmd = EVTCHNOP_close };
+ tpmif_t *tpmif = (tpmif_t *) arg;
+
+ op.u.close.port = tpmif->evtchn;
+ op.u.close.dom = DOMID_SELF;
+ HYPERVISOR_event_channel_op(&op);
+ op.u.close.port = tpmif->remote_evtchn;
+ op.u.close.dom = tpmif->domid;
+ HYPERVISOR_event_channel_op(&op);
+
+ if (tpmif->evtchn)
+ unbind_evtchn_from_irqhandler(tpmif->evtchn, tpmif);
+
+ if (tpmif->tx) {
+ unmap_frontend_page(tpmif);
+ vfree(tpmif->tx);
+ }
+
+ free_tpmif(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)
+{
+ tpmif_cachep = kmem_cache_create("tpmif_cache", sizeof(tpmif_t),
+ 0, 0, NULL, NULL);
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c Fri Sep 9
16:30:54 2005
@@ -0,0 +1,1077 @@
+/******************************************************************************
+ * drivers/xen/tpmback/tpmback.c
+ *
+ * Copyright (c) 2005, IBM Corporation
+ *
+ * Author: Stefan Berger, stefanb@xxxxxxxxxx
+ * Grant table support: Mahadevan Gomathisankaran
+ *
+ * This code has been derived from drivers/xen/netback/netback.c
+ * Copyright (c) 2002-2004, K A Fraser
+ *
+ */
+
+#include "common.h"
+#include <asm-xen/evtchn.h>
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/miscdevice.h>
+#include <asm/uaccess.h>
+#include <asm-xen/xenbus.h>
+#include <asm-xen/xen-public/grant_table.h>
+
+
+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
+ wait_queue_head_t wait_queue;
+};
+
+struct packet {
+ struct list_head next;
+ unsigned int data_len;
+ u8 *data_buffer;
+ tpmif_t *tpmif;
+ u32 tpm_instance;
+ u8 req_tag;
+ u32 last_read;
+ u8 flags;
+ struct timer_list processing_timer;
+};
+
+enum {
+ PACKET_FLAG_DISCARD_RESPONSE = 1,
+ PACKET_FLAG_SEND_CONTROLMESSAGE = 2,
+};
+
+static struct data_exchange dataex;
+
+/* local function prototypes */
+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 MAX_PENDING_REQS TPMIF_TX_RING_SIZE
+
+static multicall_entry_t tx_mcl[MAX_PENDING_REQS];
+
+#define MIN(x,y) (x) < (y) ? (x) : (y)
+
+/***************************************************************
+ Packet-related functions
+***************************************************************/
+
+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;
+ }
+ }
+ return NULL;
+}
+
+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;
+ }
+ }
+ return NULL;
+}
+
+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);
+ 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->last_read = 0;
+ pak->flags = flags;
+
+ /*
+ * cannot do tpmif_get(tpmif); bad things happen
+ * on the last tpmif_put()
+ */
+ init_timer(&pak->processing_timer);
+ pak->processing_timer.function = processing_timeout;
+ pak->processing_timer.data = (unsigned long)pak;
+ }
+ return 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);
+ if (pak->data_buffer) {
+ kfree(pak->data_buffer);
+ }
+ /*
+ * cannot do tpmif_put(pak->tpmif); bad things happen
+ * on the last tpmif_put()
+ */
+ kfree(pak);
+}
+
+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) {
+ pak->data_buffer = buf;
+ memcpy(buf, buffer, size);
+ pak->data_len = size;
+ } else {
+ rc = -ENOMEM;
+ }
+ 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)
+{
+ int rc = 0;
+
+ DPRINTK("Supposed to send %d bytes to front-end!\n",
+ size);
+
+ if (0 != (pak->flags & PACKET_FLAG_SEND_CONTROLMESSAGE)) {
+#ifdef CONFIG_XEN_TPMDEV_CLOSE_IF_VTPM_FAILS
+ u32 res;
+ memcpy(&res, &data[2+4], sizeof(res));
+ if (res != 0) {
+ /*
+ * Will close down this device and have the
+ * FE notified about closure.
+ */
+ }
+#endif
+ }
+
+ if (0 != (pak->flags & PACKET_FLAG_DISCARD_RESPONSE)) {
+ /* Don't send a respone to this packet. Just acknowledge it. */
+ rc = size;
+ } else {
+ rc = _packet_write(pak, data, size, userbuffer);
+ }
+
+ return rc;
+}
+
+
+static int
+_packet_write(struct packet *pak,
+ const char *data, size_t size,
+ int userbuffer)
+{
+ /*
+ * Write into the shared memory pages directly
+ * and send it to the front end.
+ */
+ tpmif_t *tpmif = pak->tpmif;
+ u16 handle;
+ int rc = 0;
+ unsigned int i = 0;
+ unsigned int offset = 0;
+ multicall_entry_t *mcl;
+
+ if (tpmif == NULL)
+ return -EFAULT;
+
+ if (tpmif->status != CONNECTED) {
+ return size;
+ }
+
+ mcl = tx_mcl;
+ while (offset < size && i < TPMIF_TX_RING_SIZE) {
+ unsigned int tocopy;
+ struct gnttab_map_grant_ref map_op;
+ struct gnttab_unmap_grant_ref unmap_op;
+ tpmif_tx_request_t *tx;
+
+ tx = &tpmif->tx->ring[i].req;
+
+ if (0 == tx->addr) {
+ DPRINTK("ERROR: Buffer for outgoing packet NULL?!
i=%d\n", i);
+ 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))) {
+ BUG();
+ }
+
+ handle = map_op.handle;
+
+ if (map_op.handle < 0) {
+ DPRINTK(" Grant table operation failure !\n");
+ return 0;
+ }
+ phys_to_machine_mapping[__pa(MMAP_VADDR(tpmif,i)) >>
+ PAGE_SHIFT] =
+ FOREIGN_FRAME(map_op.dev_bus_addr >> PAGE_SHIFT);
+
+ tocopy = size - offset;
+ if (tocopy > PAGE_SIZE) {
+ tocopy = PAGE_SIZE;
+ }
+ if (userbuffer) {
+ if (copy_from_user((void *)(MMAP_VADDR(tpmif,i) |
+ (tx->addr & ~PAGE_MASK)),
+ (void __user *)&data[offset],
+ tocopy)) {
+ tpmif_put(tpmif);
+ return -EFAULT;
+ }
+ } else {
+ memcpy((void *)(MMAP_VADDR(tpmif,i) |
+ (tx->addr & ~PAGE_MASK)),
+ &data[offset], tocopy);
+ }
+ tx->size = tocopy;
+
+ 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))) {
+ BUG();
+ }
+
+ offset += tocopy;
+ i++;
+ }
+
+ rc = offset;
+ DPRINTK("Notifying frontend via event channel %d\n",
+ tpmif->evtchn);
+ notify_via_evtchn(tpmif->evtchn);
+
+ return rc;
+}
+
+/*
+ * Read data from the shared memory and copy it directly into the
+ * 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)
+{
+ 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.
+ */
+ 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) {
+ /*
+ * copy the instance number into the buffer
+ */
+ 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);
+ }
+
+ pak->last_read += to_copy;
+ offset += to_copy;
+ room_left -= to_copy;
+ }
+
+ /*
+ * If the packet has a data buffer appended, read from it...
+ */
+
+ if (room_left > 0) {
+ 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);
+ }
+ pak->last_read += to_copy;
+ offset += to_copy;
+ } else {
+ offset = packet_read_shmem(pak,
+ tpmif,
+ offset,
+ buffer,
+ userbuffer,
+ room_left);
+ }
+ }
+ return offset;
+}
+
+
+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);
+ u32 to_copy;
+ u16 handle;
+
+ tpmif_tx_request_t *tx;
+ tx = &tpmif->tx->ring[0].req;
+ /*
+ * Start copying data at the page with index 'index'
+ * and within that page at offset 'offset'.
+ * Copy a maximum of 'room_left' bytes.
+ */
+ to_copy = MIN(PAGE_SIZE - pg_offset, room_left);
+ while (to_copy > 0) {
+ void *src;
+ struct gnttab_map_grant_ref map_op;
+ struct gnttab_unmap_grant_ref unmap_op;
+
+ 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))) {
+ BUG();
+ }
+
+ if (map_op.handle < 0) {
+ DPRINTK(" Grant table operation failure !\n");
+ return -EFAULT;
+ }
+
+ handle = map_op.handle;
+
+ 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.
+ */
+ 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);
+ }
+
+
+ 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;
+ unmap_op.dev_bus_addr = 0;
+
+ if(unlikely(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
+ &unmap_op,
+ 1))) {
+ BUG();
+ }
+
+ offset += to_copy;
+ pg_offset = 0;
+ last_read += to_copy;
+ room_left -= to_copy;
+
+ to_copy = MIN(PAGE_SIZE, room_left);
+ i++;
+ } /* 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)
+{
+ int rc = 0;
+ unsigned long flags;
+
+ write_lock_irqsave(&dataex.pak_lock, flags);
+ if (dataex.has_opener == 0) {
+ dataex.has_opener = 1;
+ } else {
+ rc = -EPERM;
+ }
+ write_unlock_irqrestore(&dataex.pak_lock, flags);
+ return rc;
+}
+
+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;
+ unsigned long flags;
+
+ write_lock_irqsave(&dataex.pak_lock, flags);
+
+ if (list_empty(&dataex.pending_pak)) {
+ write_unlock_irqrestore(&dataex.pak_lock, flags);
+ wait_event_interruptible(dataex.wait_queue,
+ !list_empty(&dataex.pending_pak));
+ write_lock_irqsave(&dataex.pak_lock, flags);
+ }
+
+ if (!list_empty(&dataex.pending_pak)) {
+ unsigned int left;
+ pak = list_entry(dataex.pending_pak.next, struct packet, next);
+
+ left = pak->data_len - dataex.copied_so_far;
+
+ DPRINTK("size given by app: %d, available: %d\n", size, left);
+
+ ret_size = MIN(size,left);
+
+ ret_size = packet_read(pak, ret_size, data, size, 1);
+ if (ret_size < 0) {
+ ret_size = -EFAULT;
+ } else {
+ DPRINTK("Copied %d bytes to user buffer\n", ret_size);
+
+ dataex.copied_so_far += ret_size;
+ if (dataex.copied_so_far >= pak->data_len + 4) {
+ DPRINTK("All data from this packet given to
app.\n");
+ /* All data given to app */
+
+
del_singleshot_timer_sync(&pak->processing_timer);
+ list_del(&pak->next);
+ list_add_tail(&pak->next, &dataex.current_pak);
+ /*
+ * The more fontends that are handled at the
same time,
+ * the more time we give the TPM to process the
request.
+ */
+ mod_timer(&pak->processing_timer,
+ jiffies + (num_frontends * 10 * HZ));
+ dataex.copied_so_far = 0;
+ }
+ }
+ }
+ write_unlock_irqrestore(&dataex.pak_lock, flags);
+
+ DPRINTK("Returning result from read to app: %d\n", ret_size);
+
+ return ret_size;
+}
+
+/*
+ * 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)
+{
+ struct packet *pak;
+ int rc = 0;
+ unsigned int off = 4;
+ unsigned long flags;
+ u32 instance_no = 0;
+ u32 len_no = 0;
+
+ /*
+ * Minimum required packet size is:
+ * 4 bytes for instance number
+ * 2 bytes for tag
+ * 4 bytes for paramSize
+ * 4 bytes for the ordinal
+ * sum: 14 bytes
+ */
+ if ( size < off + 10 ) {
+ return -EFAULT;
+ }
+
+ if (copy_from_user(&instance_no,
+ (void __user *)&data[0],
+ 4)) {
+ return -EFAULT;
+ }
+
+ if (copy_from_user(&len_no,
+ (void __user *)&data[off+2],
+ 4) ||
+ (off + ntohl(len_no) != size)) {
+ return -EFAULT;
+ }
+
+ write_lock_irqsave(&dataex.pak_lock, flags);
+ pak = packet_find_instance(&dataex.current_pak, ntohl(instance_no));
+
+ if (pak == NULL) {
+ write_unlock_irqrestore(&dataex.pak_lock, flags);
+ printk(KERN_ALERT "No associated packet!\n");
+ return -EFAULT;
+ } else {
+ 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.
+ */
+ size -= off;
+ data = &data[off];
+
+ rc = packet_write(pak, data, size, 1);
+
+ if (rc > 0) {
+ /* I neglected the first 4 bytes */
+ rc += off;
+ }
+ packet_free(pak);
+ return rc;
+}
+
+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;
+ write_unlock_irqrestore(&dataex.pak_lock, flags);
+ return 0;
+}
+
+static unsigned int
+vtpm_op_poll(struct file *file, struct poll_table_struct *pst)
+{
+ return 0;
+}
+
+static struct file_operations vtpm_ops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .open = vtpm_op_open,
+ .read = vtpm_op_read,
+ .write = vtpm_op_write,
+ .release = vtpm_op_release,
+ .poll = vtpm_op_poll,
+};
+
+static struct miscdevice ibmvtpms_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 */
+};
+
+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 rc = 0;
+ struct packet *pak = packet_alloc(tpmif, sizeof(create_cmd),
create_cmd[0],
+ PACKET_FLAG_DISCARD_RESPONSE|
+ PACKET_FLAG_SEND_CONTROLMESSAGE);
+ if (pak) {
+ 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));
+
+ /* copy the buffer into the packet */
+ rc = packet_set(pak, buf, sizeof(buf));
+
+ if (rc == 0) {
+ pak->tpm_instance = 0;
+ rc = vtpm_queue_packet(pak);
+ }
+ if (rc < 0) {
+ /* could not be queued or built */
+ packet_free(pak);
+ }
+ } else {
+ rc = -ENOMEM;
+ }
+ return rc;
+}
+
+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|
+ PACKET_FLAG_SEND_CONTROLMESSAGE);
+ if (pak) {
+ u8 buf[sizeof(destroy_cmd)];
+ u32 instid_no = htonl(instid);
+ 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));
+
+ if (rc == 0) {
+ pak->tpm_instance = 0;
+ rc = vtpm_queue_packet(pak);
+ }
+ if (rc < 0) {
+ /* could not be queued or built */
+ packet_free(pak);
+ }
+ } else {
+ rc = -ENOMEM;
+ }
+ return rc;
+}
+
+
+/***************************************************************
+ Utility functions
+***************************************************************/
+
+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 */
+ };
+ 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.
+ */
+ buffer[1] = req_tag + 3;
+
+ /*
+ * Write the data to shared memory and notify the front-end
+ */
+ 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)
+{
+ struct packet *pak;
+ 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);
+
+ if (pak->tpmif && pak->tpmif->status == CONNECTED) {
+ can_send = 1;
+ }
+
+ if (send_msgs && can_send) {
+ tpm_send_fail_message(pak, pak->req_tag);
+ }
+ packet_free(pak);
+ }
+ }
+}
+
+
+int
+vtpm_release_packets(tpmif_t *tpmif, int send_msgs)
+{
+ unsigned long flags;
+
+ write_lock_irqsave(&dataex.pak_lock, flags);
+
+ _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);
+ 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 + (10 * HZ));
+ write_unlock_irqrestore(&dataex.pak_lock,
+ flags);
+
+ wake_up_interruptible(&dataex.wait_queue);
+ } else {
+ rc = -EFAULT;
+ }
+ return rc;
+}
+
+
+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) {
+ 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)) {
+ goto failexit;
+ }
+ /*
+ * Reset the packet read pointer so we can read all its
+ * contents again.
+ */
+ packet_reset(pak);
+
+ 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.
+ * The minimum size of the packet is '10' for tag, size indicator
+ * and ordinal.
+ */
+ if (size < 10 ||
+ be32_to_cpu(*native_size) != size ||
+ 0 == dataex.has_opener) {
+ rc = -EINVAL;
+ goto failexit;
+ } else {
+ if ((rc = vtpm_queue_packet(pak)) < 0) {
+ goto failexit;
+ }
+ }
+ return 0;
+
+failexit:
+ if (pak) {
+ 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
+ * during the timeout period.
+ * The packet must be on a list when this function is invoked. This
+ * also means that once its taken off a list, the timer must be
+ * destroyed as well.
+ */
+static void processing_timeout(unsigned long ptr)
+{
+ 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) ) {
+ list_del(&pak->next);
+ 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);
+
+#define MAX_PENDING_REQS TPMIF_TX_RING_SIZE
+
+static struct list_head tpm_schedule_list;
+static spinlock_t tpm_schedule_list_lock;
+
+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)
+{
+ return tpmif->list.next != NULL;
+}
+
+static void
+remove_from_tpm_schedule_list(tpmif_t * tpmif)
+{
+ spin_lock_irq(&tpm_schedule_list_lock);
+ if (likely(__on_tpm_schedule_list(tpmif))) {
+ list_del(&tpmif->list);
+ tpmif->list.next = NULL;
+ tpmif_put(tpmif);
+ }
+ spin_unlock_irq(&tpm_schedule_list_lock);
+}
+
+static void
+add_to_tpm_schedule_list_tail(tpmif_t * tpmif)
+{
+ if (__on_tpm_schedule_list(tpmif))
+ return;
+
+ spin_lock_irq(&tpm_schedule_list_lock);
+ if (!__on_tpm_schedule_list(tpmif) && tpmif->active) {
+ list_add_tail(&tpmif->list, &tpm_schedule_list);
+ tpmif_get(tpmif);
+ }
+ spin_unlock_irq(&tpm_schedule_list_lock);
+}
+
+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)
+{
+ remove_from_tpm_schedule_list(tpmif);
+}
+
+
+static void
+tpm_tx_action(unsigned long unused)
+{
+ struct list_head *ent;
+ tpmif_t *tpmif;
+ tpmif_tx_request_t *tx;
+
+ DPRINTK("%s: Getting data from front-end(s)!\n", __FUNCTION__);
+
+ while (!list_empty(&tpm_schedule_list)) {
+ /* Get a tpmif from the list with work to do. */
+ ent = tpm_schedule_list.next;
+ 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;
+
+ /* pass it up */
+ vtpm_receive(tpmif, tx->size);
+
+ tpmif_put(tpmif);
+ }
+}
+
+irqreturn_t
+tpmif_be_int(int irq, void *dev_id, struct pt_regs *regs)
+{
+ tpmif_t *tpmif = dev_id;
+ add_to_tpm_schedule_list_tail(tpmif);
+ maybe_schedule_tx_action();
+ return IRQ_HANDLED;
+}
+
+static int __init
+tpmback_init(void)
+{
+ int rc;
+ if (!(xen_start_info->flags & SIF_TPM_BE_DOMAIN) &&
+ !(xen_start_info->flags & SIF_INITDOMAIN)) {
+ printk(KERN_ALERT "Neither TPM-BE Domain nor INIT domain!\n");
+ return 0;
+ }
+
+ if ((rc = misc_register(&ibmvtpms_miscdevice)) != 0) {
+ printk(KERN_ALERT "Could not register misc device for TPM
BE.\n");
+ return rc;
+ }
+
+ INIT_LIST_HEAD(&dataex.pending_pak);
+ INIT_LIST_HEAD(&dataex.current_pak);
+ dataex.has_opener = 0;
+ rwlock_init(&dataex.pak_lock);
+ init_waitqueue_head(&dataex.wait_queue);
+
+ spin_lock_init(&tpm_schedule_list_lock);
+ INIT_LIST_HEAD(&tpm_schedule_list);
+
+ tpmif_interface_init();
+ tpmif_xenbus_init();
+
+ printk(KERN_ALERT "Successfully initialized TPM backend driver.\n");
+
+ return 0;
+}
+
+__initcall(tpmback_init);
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,271 @@
+/* Xenbus code for tpmif backend
+ Copyright (C) 2005 Rusty Russell <rusty@xxxxxxxxxxxxxxx>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+#include <stdarg.h>
+#include <linux/module.h>
+#include <asm-xen/xenbus.h>
+#include "common.h"
+
+struct backend_info
+{
+ struct xenbus_device *dev;
+
+ /* our communications channel */
+ tpmif_t *tpmif;
+
+ long int frontend_id;
+ long int instance; // instance of TPM
+
+ /* watch front end for changes */
+ struct xenbus_watch backend_watch;
+
+ struct xenbus_watch watch;
+ char * frontpath;
+};
+
+static int tpmback_remove(struct xenbus_device *dev)
+{
+ struct backend_info *be = dev->data;
+
+ if (be->watch.node) {
+ unregister_xenbus_watch(&be->watch);
+ }
+ unregister_xenbus_watch(&be->backend_watch);
+
+ tpmif_vtpm_close(be->instance);
+
+ if (be->tpmif) {
+ tpmif_put(be->tpmif);
+ }
+
+ if (be->frontpath)
+ kfree(be->frontpath);
+ kfree(be);
+ return 0;
+}
+
+
+static void frontend_changed(struct xenbus_watch *watch, const char *node)
+{
+ unsigned long ringref;
+ unsigned int evtchn;
+ unsigned long ready = 1;
+ int err;
+ struct backend_info *be
+ = container_of(watch, struct backend_info, watch);
+
+ /* If other end is gone, delete ourself. */
+ if (node && !xenbus_exists(be->frontpath, "")) {
+ xenbus_rm(be->dev->nodename, "");
+ device_unregister(&be->dev->dev);
+ return;
+ }
+
+ if (be->tpmif == NULL || be->tpmif->status == CONNECTED)
+ return;
+
+ err = xenbus_gather(be->frontpath,
+ "ring-ref", "%lu", &ringref,
+ "event-channel", "%u", &evtchn, NULL);
+ if (err) {
+ xenbus_dev_error(be->dev, err,
+ "reading %s/ring-ref and event-channel",
+ be->frontpath);
+ return;
+ }
+
+
+ /*
+ * Tell the front-end that we are ready to go -
+ * unless something bad happens
+ */
+ err = xenbus_transaction_start(be->dev->nodename);
+ if (err) {
+ xenbus_dev_error(be->dev, err, "starting transaction");
+ return;
+ }
+
+ err = xenbus_printf(be->dev->nodename,
+ "ready", "%lu", ready);
+ if (err) {
+ xenbus_dev_error(be->dev, err, "writing 'ready'");
+ goto abort;
+ }
+
+ err = tpmif_map(be->tpmif, ringref, evtchn);
+ if (err) {
+ xenbus_dev_error(be->dev, err,
+ "mapping shared-frame %lu port %u",
+ ringref, evtchn);
+ goto abort;
+ }
+
+ err = tpmif_vtpm_open(be->tpmif,
+ be->frontend_id,
+ be->instance);
+ if (err) {
+ xenbus_dev_error(be->dev, err,
+ "queueing vtpm open packet");
+ /*
+ * Should close down this device and notify FE
+ * about closure.
+ */
+ goto abort;
+ }
+
+ xenbus_transaction_end(0);
+ xenbus_dev_ok(be->dev);
+ return;
+abort:
+ xenbus_transaction_end(1);
+}
+
+
+static void backend_changed(struct xenbus_watch *watch, const char *node)
+{
+ int err;
+ long int instance;
+ struct backend_info *be
+ = container_of(watch, struct backend_info, backend_watch);
+ struct xenbus_device *dev = be->dev;
+
+ err = xenbus_scanf(dev->nodename, "instance", "%li", &instance);
+ if (XENBUS_EXIST_ERR(err))
+ return;
+ if (err < 0) {
+ xenbus_dev_error(dev, err, "reading 'instance' variable");
+ return;
+ }
+
+ if (be->instance != -1 && be->instance != instance) {
+ printk(KERN_WARNING
+ "cannot change the instance\n");
+ return;
+ }
+ be->instance = instance;
+
+ if (be->tpmif == NULL) {
+ be->tpmif = tpmif_find(be->frontend_id,
+ instance);
+ if (IS_ERR(be->tpmif)) {
+ err = PTR_ERR(be->tpmif);
+ be->tpmif = NULL;
+ xenbus_dev_error(dev, err, "creating interface");
+ return;
+ }
+
+ /* Pass in NULL node to skip exist test. */
+ frontend_changed(&be->watch, be->frontpath);
+ }
+}
+
+
+static int tpmback_probe(struct xenbus_device *dev,
+ const struct xenbus_device_id *id)
+{
+ struct backend_info *be;
+ char *frontend;
+ int err;
+
+ be = kmalloc(sizeof(*be), GFP_KERNEL);
+ if (!be) {
+ xenbus_dev_error(dev, -ENOMEM, "allocating backend structure");
+ err = -ENOMEM;
+ }
+
+ memset(be, 0, sizeof(*be));
+
+ frontend = NULL;
+ err = xenbus_gather(dev->nodename,
+ "frontend-id", "%li", &be->frontend_id,
+ "frontend", NULL, &frontend,
+ NULL);
+ if (XENBUS_EXIST_ERR(err))
+ goto free_be;
+ if (err < 0) {
+ xenbus_dev_error(dev, err,
+ "reading %s/frontend or frontend-id",
+ dev->nodename);
+ goto free_be;
+ }
+ if (strlen(frontend) == 0 || !xenbus_exists(frontend, "")) {
+ /* If we can't get a frontend path and a frontend-id,
+ * then our bus-id is no longer valid and we need to
+ * destroy the backend device.
+ */
+ err = -ENOENT;
+ goto free_be;
+ }
+
+ be->dev = dev;
+ be->backend_watch.node = dev->nodename;
+ be->backend_watch.callback = backend_changed;
+ be->instance = -1;
+ err = register_xenbus_watch(&be->backend_watch);
+ if (err) {
+ be->backend_watch.node = NULL;
+ xenbus_dev_error(dev, err, "adding backend watch on %s",
+ dev->nodename);
+ goto free_be;
+ }
+
+ be->frontpath = frontend;
+ be->watch.node = be->frontpath;
+ be->watch.callback = frontend_changed;
+ err = register_xenbus_watch(&be->watch);
+ if (err) {
+ be->watch.node = NULL;
+ xenbus_dev_error(dev, err,
+ "adding frontend watch on %s",
+ be->frontpath);
+ goto free_be;
+ }
+
+ dev->data = be;
+
+ backend_changed(&be->backend_watch, dev->nodename);
+ return err;
+
+free_be:
+ if (be->backend_watch.node)
+ unregister_xenbus_watch(&be->backend_watch);
+ if (frontend)
+ kfree(frontend);
+ kfree(be);
+ return err;
+}
+
+
+static struct xenbus_device_id tpmback_ids[] = {
+ { "vtpm" },
+ { "" }
+};
+
+
+static struct xenbus_driver tpmback = {
+ .name = "vtpm",
+ .owner = THIS_MODULE,
+ .ids = tpmback_ids,
+ .probe = tpmback_probe,
+ .remove = tpmback_remove,
+};
+
+
+void tpmif_xenbus_init(void)
+{
+ xenbus_register_backend(&tpmback);
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/tpmfront/Makefile
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/Makefile Fri Sep 9
16:30:54 2005
@@ -0,0 +1,2 @@
+
+obj-$(CONFIG_XEN_TPMDEV_FRONTEND) += tpmfront.o
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Fri Sep 9
16:30:54 2005
@@ -0,0 +1,738 @@
+/*
+ * Copyright (c) 2005, IBM Corporation
+ *
+ * Author: Stefan Berger, stefanb@xxxxxxxxxx
+ * Grant table support: Mahadevan Gomathisankaran
+ *
+ * This code has been derived from drivers/xen/netfront/netfront.c
+ *
+ * Copyright (c) 2002-2004, K A Fraser
+ *
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/tpmfe.h>
+
+#include <asm/semaphore.h>
+#include <asm/io.h>
+#include <asm-xen/evtchn.h>
+#include <asm-xen/xen-public/io/tpmif.h>
+#include <asm/uaccess.h>
+#include <asm-xen/xenbus.h>
+#include <asm-xen/xen-public/io/domain_controller.h>
+#include <asm-xen/xen-public/grant_table.h>
+
+#include "tpmfront.h"
+
+#undef DEBUG
+
+#if 1
+#define ASSERT(_p) \
+ if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \
+ __LINE__, __FILE__); *(int*)0=0; }
+#else
+#define ASSERT(_p)
+#endif
+
+/* locally visible variables */
+static grant_ref_t gref_head;
+static struct tpm_private my_private;
+
+/* local function prototypes */
+static irqreturn_t tpmif_int(int irq,
+ void *tpm_priv,
+ struct pt_regs *ptregs);
+static void tpmif_rx_action(unsigned long unused);
+static void tpmif_connect(u16 evtchn, domid_t domid);
+static DECLARE_TASKLET(tpmif_rx_tasklet, tpmif_rx_action, 0);
+static int tpm_allocate_buffers(struct tpm_private *tp);
+static void tpmif_set_connected_state(struct tpm_private *tp, int newstate);
+static int tpm_xmit(struct tpm_private *tp,
+ const u8 * buf, size_t count, int userbuffer,
+ void *remember);
+
+#if DEBUG
+#define DPRINTK(fmt, args...) \
+ printk(KERN_ALERT "xen_tpm_fr (%s:%d) " fmt, __FUNCTION__, __LINE__,
##args)
+#else
+#define DPRINTK(fmt, args...) ((void)0)
+#endif
+#define IPRINTK(fmt, args...) \
+ printk(KERN_INFO "xen_tpm_fr: " fmt, ##args)
+#define WPRINTK(fmt, args...) \
+ printk(KERN_WARNING "xen_tpm_fr: " fmt, ##args)
+
+
+static inline int
+tx_buffer_copy(struct tx_buffer *txb, const u8 * src, int len,
+ int isuserbuffer)
+{
+ int copied = len;
+
+ if (len > txb->size) {
+ copied = txb->size;
+ }
+ if (isuserbuffer) {
+ if (copy_from_user(txb->data,
+ src,
+ copied)) {
+ return -EFAULT;
+ }
+ } else {
+ memcpy(txb->data, src, copied);
+ }
+ txb->len = len;
+ return copied;
+}
+
+static inline struct tx_buffer *tx_buffer_alloc(void)
+{
+ struct tx_buffer *txb = kmalloc(sizeof (struct tx_buffer),
+ GFP_KERNEL);
+
+ if (txb) {
+ txb->len = 0;
+ txb->size = PAGE_SIZE;
+ txb->data = (unsigned char *)__get_free_page(GFP_KERNEL);
+ if (txb->data == NULL) {
+ kfree(txb);
+ txb = NULL;
+ }
+ }
+ return txb;
+}
+
+
+/**************************************************************
+
+ The interface to let the tpm plugin register its callback
+ function and send data to another partition using this module
+
+**************************************************************/
+
+static DECLARE_MUTEX(upperlayer_lock);
+static DECLARE_MUTEX(suspend_lock);
+static struct tpmfe_device *upperlayer_tpmfe;
+
+/*
+ * Send data via this module by calling this function
+ */
+int tpm_fe_send(const u8 * buf, size_t count, void *ptr)
+{
+ int sent = 0;
+ struct tpm_private *tp = &my_private;
+
+ down(&suspend_lock);
+ sent = tpm_xmit(tp, buf, count, 0, ptr);
+ up(&suspend_lock);
+
+ return sent;
+}
+EXPORT_SYMBOL(tpm_fe_send);
+
+/*
+ * Register a callback for receiving data from this module
+ */
+int tpm_fe_register_receiver(struct tpmfe_device *tpmfe_dev)
+{
+ int rc = 0;
+
+ down(&upperlayer_lock);
+ if (NULL == upperlayer_tpmfe) {
+ upperlayer_tpmfe = tpmfe_dev;
+ tpmfe_dev->max_tx_size = TPMIF_TX_RING_SIZE * PAGE_SIZE;
+ } else {
+ rc = -EBUSY;
+ }
+ up(&upperlayer_lock);
+ return rc;
+}
+EXPORT_SYMBOL(tpm_fe_register_receiver);
+
+/*
+ * Unregister the callback for receiving data from this module
+ */
+void tpm_fe_unregister_receiver(void)
+{
+ down(&upperlayer_lock);
+ upperlayer_tpmfe = NULL;
+ up(&upperlayer_lock);
+}
+EXPORT_SYMBOL(tpm_fe_unregister_receiver);
+
+/*
+ * Call this function to send data to the upper layer's
+ * registered receiver function.
+ */
+static int tpm_fe_send_upperlayer(const u8 * buf, size_t count,
+ const void *ptr)
+{
+ int rc;
+
+ down(&upperlayer_lock);
+
+ if (upperlayer_tpmfe && upperlayer_tpmfe->receive) {
+ rc = upperlayer_tpmfe->receive(buf, count, ptr);
+ } else {
+ rc = 0;
+ }
+
+ up(&upperlayer_lock);
+ return rc;
+}
+
+/**************************************************************
+ XENBUS support code
+**************************************************************/
+
+static void watch_for_status(struct xenbus_watch *watch, const char *node)
+{
+ struct tpmfront_info *info;
+ int err;
+ unsigned long ready;
+ struct tpm_private *tp = &my_private;
+
+ info = container_of(watch, struct tpmfront_info, watch);
+ node += strlen(watch->node);
+
+ if (tp->connected)
+ return;
+
+ err = xenbus_gather(watch->node,
+ "ready", "%lu", &ready,
+ NULL);
+ if (err) {
+ xenbus_dev_error(info->dev, err, "reading 'ready' field");
+ return;
+ }
+
+ tpmif_set_connected_state(tp, 1);
+
+ xenbus_dev_ok(info->dev);
+}
+
+
+static int setup_tpmring(struct xenbus_device *dev,
+ struct tpmfront_info * info,
+ domid_t backend_id)
+{
+ tpmif_tx_interface_t *sring;
+ struct tpm_private *tp = &my_private;
+
+ evtchn_op_t op = { .cmd = EVTCHNOP_alloc_unbound };
+ int err;
+
+ sring = (void *)__get_free_page(GFP_KERNEL);
+ if (!sring) {
+ xenbus_dev_error(dev, -ENOMEM, "allocating shared ring");
+ return -ENOMEM;
+ }
+ tp->tx = sring;
+
+ tpm_allocate_buffers(tp);
+
+ info->ring_ref = gnttab_claim_grant_reference(&gref_head);
+ ASSERT(info->ring_ref != -ENOSPC);
+ gnttab_grant_foreign_access_ref(info->ring_ref,
+ backend_id,
+ (virt_to_machine(tp->tx) >> PAGE_SHIFT),
+ 0);
+
+ op.u.alloc_unbound.dom = backend_id;
+ err = HYPERVISOR_event_channel_op(&op);
+ if (err) {
+ free_page((unsigned long)sring);
+ tp->tx = 0;
+ xenbus_dev_error(dev, err, "allocating event channel");
+ return err;
+ }
+ tpmif_connect(op.u.alloc_unbound.port, backend_id);
+ return 0;
+}
+
+
+static void destroy_tpmring(struct tpmfront_info *info, struct tpm_private *tp)
+{
+ tpmif_set_connected_state(tp,0);
+
+ if ( tp->tx != NULL ) {
+ free_page((unsigned long)tp->tx);
+ tp->tx = NULL;
+ }
+ unbind_evtchn_from_irqhandler(tp->evtchn, NULL);
+ tp->evtchn = 0;
+}
+
+
+static int talk_to_backend(struct xenbus_device *dev,
+ struct tpmfront_info *info)
+{
+ char *backend;
+ const char *message;
+ int err;
+ int backend_id;
+
+ backend = NULL;
+ err = xenbus_gather(dev->nodename,
+ "backend-id", "%i", &backend_id,
+ "backend", NULL, &backend,
+ NULL);
+ if (XENBUS_EXIST_ERR(err))
+ goto out;
+ if (backend && strlen(backend) == 0) {
+ err = -ENOENT;
+ goto out;
+ }
+ if (err < 0) {
+ xenbus_dev_error(dev, err, "reading %s/backend or backend-id",
+ dev->nodename);
+ goto out;
+ }
+
+ info->backend_id = backend_id;
+ my_private.backend_id = backend_id;
+
+ err = setup_tpmring(dev, info, backend_id);
+ if (err) {
+ xenbus_dev_error(dev, err, "setting up ring");
+ goto out;
+ }
+
+ err = xenbus_transaction_start(dev->nodename);
+ if (err) {
+ xenbus_dev_error(dev, err, "starting transaction");
+ goto destroy_tpmring;
+ }
+
+ err = xenbus_printf(dev->nodename,
+ "ring-ref","%u", info->ring_ref);
+ if (err) {
+ message = "writing ring-ref";
+ goto abort_transaction;
+ }
+
+ err = xenbus_printf(dev->nodename,
+ "event-channel", "%u", my_private.evtchn);
+ if (err) {
+ message = "writing event-channel";
+ goto abort_transaction;
+ }
+
+ info->backend = backend;
+ backend = NULL;
+
+ info->watch.node = info->backend;
+ info->watch.callback = watch_for_status;
+ err = register_xenbus_watch(&info->watch);
+ if (err) {
+ message = "registering watch on backend";
+ goto abort_transaction;
+ }
+
+ err = xenbus_transaction_end(0);
+ if (err) {
+ xenbus_dev_error(dev, err, "completing transaction");
+ goto destroy_tpmring;
+ }
+
+out:
+ if (backend)
+ kfree(backend);
+ return err;
+
+abort_transaction:
+ xenbus_transaction_end(1);
+ /* Have to do this *outside* transaction. */
+ xenbus_dev_error(dev, err, "%s", message);
+destroy_tpmring:
+ destroy_tpmring(info, &my_private);
+ goto out;
+}
+
+
+static int tpmfront_probe(struct xenbus_device *dev,
+ const struct xenbus_device_id *id)
+{
+ int err;
+ struct tpmfront_info *info;
+ int handle;
+
+ err = xenbus_scanf(dev->nodename,
+ "handle", "%i", &handle);
+ if (XENBUS_EXIST_ERR(err))
+ return err;
+
+ if (err < 0) {
+ xenbus_dev_error(dev,err,"reading virtual-device");
+ return err;
+ }
+
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (!info) {
+ xenbus_dev_error(dev,err,"allocating info structure");
+ return err;
+ }
+ memset(info, 0x0, sizeof(*info));
+
+ info->dev = dev;
+ info->handle = handle;
+ dev->data = info;
+
+ err = talk_to_backend(dev, info);
+ if (err) {
+ kfree(info);
+ dev->data = NULL;
+ return err;
+ }
+
+ watch_for_status(&info->watch, info->watch.node);
+ return 0;
+}
+
+static int tpmfront_remove(struct xenbus_device *dev)
+{
+ struct tpmfront_info *info = dev->data;
+ if (info->backend)
+ unregister_xenbus_watch(&info->watch);
+
+ destroy_tpmring(info, &my_private);
+
+ kfree(info->backend);
+ kfree(info);
+
+ return 0;
+}
+
+static int tpmfront_suspend(struct xenbus_device *dev)
+{
+ struct tpmfront_info *info = dev->data;
+ struct tpm_private *tp = &my_private;
+
+ /* lock so no app can send */
+ down(&suspend_lock);
+
+ while (atomic_read(&tp->tx_busy)) {
+ printk("---- TPMIF: Outstanding request.\n");
+#if 0
+ /*
+ * Would like to wait until the outstanding request
+ * has come back, but this does not work properly, yet.
+ */
+ interruptible_sleep_on_timeout(&tp->wait_q,
+ 100);
+#else
+ break;
+#endif
+ }
+
+ unregister_xenbus_watch(&info->watch);
+
+ kfree(info->backend);
+ info->backend = NULL;
+
+ destroy_tpmring(info, tp);
+
+ return 0;
+}
+
+static int tpmif_recover(void)
+{
+ return 0;
+}
+
+static int tpmfront_resume(struct xenbus_device *dev)
+{
+ struct tpmfront_info *info = dev->data;
+ int err;
+
+ err = talk_to_backend(dev, info);
+ if (!err) {
+ tpmif_recover();
+ }
+
+ /* unlock so apps can resume */
+ up(&suspend_lock);
+
+ return err;
+}
+
+static void tpmif_connect(u16 evtchn, domid_t domid)
+{
+ int err = 0;
+ struct tpm_private *tp = &my_private;
+
+ tp->evtchn = evtchn;
+ tp->backend_id = domid;
+
+ err = bind_evtchn_to_irqhandler(
+ tp->evtchn,
+ tpmif_int, SA_SAMPLE_RANDOM, "tpmif", tp);
+ if ( err != 0 ) {
+ WPRINTK("bind_evtchn_to_irqhandler failed (err=%d)\n", err);
+ return;
+ }
+}
+
+static struct xenbus_device_id tpmfront_ids[] = {
+ { "vtpm" },
+ { "" }
+};
+
+static struct xenbus_driver tpmfront = {
+ .name = "vtpm",
+ .owner = THIS_MODULE,
+ .ids = tpmfront_ids,
+ .probe = tpmfront_probe,
+ .remove = tpmfront_remove,
+ .resume = tpmfront_resume,
+ .suspend = tpmfront_suspend,
+};
+
+static void __init init_tpm_xenbus(void)
+{
+ xenbus_register_device(&tpmfront);
+}
+
+
+static int
+tpm_allocate_buffers(struct tpm_private *tp)
+{
+ unsigned int i;
+
+ i = 0;
+ while (i < TPMIF_TX_RING_SIZE) {
+ tp->tx_buffers[i] = tx_buffer_alloc();
+ i++;
+ }
+
+ return 1;
+}
+
+static void
+tpmif_rx_action(unsigned long unused)
+{
+ struct tpm_private *tp = &my_private;
+
+ int i = 0;
+ unsigned int received;
+ unsigned int offset = 0;
+ u8 *buffer;
+ tpmif_tx_request_t *tx;
+ tx = &tp->tx->ring[i].req;
+
+ received = tx->size;
+
+ buffer = kmalloc(received, GFP_KERNEL);
+ if (NULL == buffer) {
+ goto exit;
+ }
+
+ i = 0;
+ while (i < TPMIF_TX_RING_SIZE &&
+ offset < received) {
+ struct tx_buffer *txb = tp->tx_buffers[i];
+ tpmif_tx_request_t *tx;
+ unsigned int tocopy;
+
+ tx = &tp->tx->ring[i].req;
+ tocopy = tx->size;
+ if (tocopy > PAGE_SIZE) {
+ tocopy = PAGE_SIZE;
+ }
+
+ memcpy(&buffer[offset], txb->data, tocopy);
+
+ gnttab_release_grant_reference(&gref_head, tx->ref);
+
+ offset += tocopy;
+ i++;
+ }
+
+ tpm_fe_send_upperlayer(buffer, received, tp->tx_remember);
+ kfree(buffer);
+
+exit:
+ atomic_set(&tp->tx_busy, 0);
+ wake_up_interruptible(&tp->wait_q);
+}
+
+
+static irqreturn_t
+tpmif_int(int irq, void *tpm_priv, struct pt_regs *ptregs)
+{
+ struct tpm_private *tp = tpm_priv;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tp->tx_lock, flags);
+ tasklet_schedule(&tpmif_rx_tasklet);
+ spin_unlock_irqrestore(&tp->tx_lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+
+static int
+tpm_xmit(struct tpm_private *tp,
+ const u8 * buf, size_t count, int isuserbuffer,
+ void *remember)
+{
+ tpmif_tx_request_t *tx;
+ TPMIF_RING_IDX i;
+ unsigned int offset = 0;
+
+ spin_lock_irq(&tp->tx_lock);
+
+ if (unlikely(atomic_read(&tp->tx_busy))) {
+ printk("There's an outstanding request/response on the way!\n");
+ spin_unlock_irq(&tp->tx_lock);
+ return -EBUSY;
+ }
+
+ if (tp->connected != 1) {
+ spin_unlock_irq(&tp->tx_lock);
+ return -EIO;
+ }
+
+ i = 0;
+ while (count > 0 && i < TPMIF_TX_RING_SIZE) {
+ struct tx_buffer *txb = tp->tx_buffers[i];
+ int copied;
+
+ if (NULL == txb) {
+ DPRINTK("txb (i=%d) is NULL. buffers initilized?\n", i);
+ DPRINTK("Not transmittin anything!\n");
+ spin_unlock_irq(&tp->tx_lock);
+ return -EFAULT;
+ }
+ copied = tx_buffer_copy(txb, &buf[offset], count,
+ isuserbuffer);
+ if (copied < 0) {
+ /* An error occurred */
+ return copied;
+ }
+ count -= copied;
+ offset += copied;
+
+ tx = &tp->tx->ring[i].req;
+
+ tx->id = i;
+ tx->addr = virt_to_machine(txb->data);
+ tx->size = txb->len;
+
+ DPRINTK("First 4 characters sent by TPM-FE are 0x%02x 0x%02x
0x%02x 0x%02x\n",
+ txb->data[0],txb->data[1],txb->data[2],txb->data[3]);
+
+ /* get the granttable reference for this page */
+ tx->ref = gnttab_claim_grant_reference( &gref_head );
+
+ if(-ENOSPC == tx->ref ) {
+ DPRINTK(" Grant table claim reference failed in func:%s
line:%d file:%s\n", __FUNCTION__, __LINE__, __FILE__);
+ return -ENOSPC;
+ }
+ gnttab_grant_foreign_access_ref( tx->ref,
+ tp->backend_id,
+ (tx->addr >> PAGE_SHIFT),
+ 0 /*RW*/);
+ i++;
+ wmb();
+ }
+
+ atomic_set(&tp->tx_busy, 1);
+ tp->tx_remember = remember;
+ mb();
+
+ DPRINTK("Notifying backend via event channel %d\n",
+ tp->evtchn);
+
+ notify_via_evtchn(tp->evtchn);
+
+ spin_unlock_irq(&tp->tx_lock);
+ return offset;
+}
+
+
+static void tpmif_notify_upperlayer(struct tpm_private *tp)
+{
+ /*
+ * Notify upper layer about the state of the connection
+ * to the BE.
+ */
+ down(&upperlayer_lock);
+
+ if (upperlayer_tpmfe != NULL) {
+ switch (tp->connected) {
+ case 1:
+
upperlayer_tpmfe->status(TPMFE_STATUS_CONNECTED);
+ break;
+
+ default:
+ upperlayer_tpmfe->status(0);
+ break;
+ }
+ }
+ up(&upperlayer_lock);
+}
+
+
+static void tpmif_set_connected_state(struct tpm_private *tp, int newstate)
+{
+ if (newstate != tp->connected) {
+ tp->connected = newstate;
+ tpmif_notify_upperlayer(tp);
+ }
+}
+
+
+/* =================================================================
+ * Initialization function.
+ * =================================================================
+ */
+
+static int __init
+tpmif_init(void)
+{
+ IPRINTK("Initialising the vTPM driver.\n");
+ if ( gnttab_alloc_grant_references ( TPMIF_TX_RING_SIZE,
+ &gref_head ) < 0) {
+ return -EFAULT;
+ }
+ /*
+ * Only don't send the driver status when we are in the
+ * INIT domain.
+ */
+ spin_lock_init(&my_private.tx_lock);
+ init_waitqueue_head(&my_private.wait_q);
+
+ init_tpm_xenbus();
+
+ return 0;
+}
+
+__initcall(tpmif_init);
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h Fri Sep 9
16:30:54 2005
@@ -0,0 +1,38 @@
+#ifndef TPM_FRONT_H
+#define TPM_FRONT_H
+
+
+struct tpm_private {
+ tpmif_tx_interface_t *tx;
+ unsigned int evtchn;
+ int connected;
+
+ spinlock_t tx_lock;
+
+ struct tx_buffer *tx_buffers[TPMIF_TX_RING_SIZE];
+
+ atomic_t tx_busy;
+ void *tx_remember;
+ domid_t backend_id;
+ wait_queue_head_t wait_q;
+};
+
+
+struct tpmfront_info
+{
+ struct xenbus_watch watch;
+ int handle;
+ struct xenbus_device *dev;
+ char *backend;
+ int ring_ref;
+ domid_t backend_id;
+};
+
+
+struct tx_buffer {
+ unsigned int size; // available space in data
+ unsigned int len; // used space in data
+ unsigned char *data; // pointer to a page
+};
+
+#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Fri Sep 9
16:30:54 2005
@@ -0,0 +1,186 @@
+/*
+ * xenbus_dev.c
+ *
+ * Driver giving user-space access to the kernel's xenbus connection
+ * to xenstore.
+ *
+ * Copyright (c) 2005, Christian Limpach
+ *
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/uio.h>
+#include <linux/notifier.h>
+#include <linux/wait.h>
+#include <linux/fs.h>
+
+#include "xenstored.h"
+#include "xenbus_comms.h"
+
+#include <asm/uaccess.h>
+#include <asm-xen/xenbus.h>
+#include <asm-xen/linux-public/xenbus_dev.h>
+#include <asm-xen/xen_proc.h>
+
+struct xenbus_dev_data {
+ int in_transaction;
+};
+
+static struct proc_dir_entry *xenbus_dev_intf;
+
+void *xs_talkv(enum xsd_sockmsg_type type, const struct kvec *iovec,
+ unsigned int num_vecs, unsigned int *len);
+
+static int xenbus_dev_talkv(struct xenbus_dev_data *u, unsigned long data)
+{
+ struct xenbus_dev_talkv xt;
+ unsigned int len;
+ void *resp, *base;
+ struct kvec *iovec;
+ int ret = -EFAULT, v = 0;
+
+ if (copy_from_user(&xt, (void *)data, sizeof(xt)))
+ return -EFAULT;
+
+ iovec = kmalloc(xt.num_vecs * sizeof(struct kvec), GFP_KERNEL);
+ if (iovec == NULL)
+ return -ENOMEM;
+
+ if (copy_from_user(iovec, xt.iovec,
+ xt.num_vecs * sizeof(struct kvec)))
+ goto out;
+
+ for (v = 0; v < xt.num_vecs; v++) {
+ base = iovec[v].iov_base;
+ iovec[v].iov_base = kmalloc(iovec[v].iov_len, GFP_KERNEL);
+ if (iovec[v].iov_base == NULL ||
+ copy_from_user(iovec[v].iov_base, base, iovec[v].iov_len))
+ {
+ if (iovec[v].iov_base)
+ kfree(iovec[v].iov_base);
+ else
+ ret = -ENOMEM;
+ v--;
+ goto out;
+ }
+ }
+
+ resp = xs_talkv(xt.type, iovec, xt.num_vecs, &len);
+ if (IS_ERR(resp)) {
+ ret = PTR_ERR(resp);
+ goto out;
+ }
+
+ switch (xt.type) {
+ case XS_TRANSACTION_START:
+ u->in_transaction = 1;
+ break;
+ case XS_TRANSACTION_END:
+ u->in_transaction = 0;
+ break;
+ default:
+ break;
+ }
+
+ ret = len;
+ if (len > xt.len)
+ len = xt.len;
+
+ if (copy_to_user(xt.buf, resp, len))
+ ret = -EFAULT;
+
+ kfree(resp);
+ out:
+ while (v-- > 0)
+ kfree(iovec[v].iov_base);
+ kfree(iovec);
+ return ret;
+}
+
+static int xenbus_dev_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long data)
+{
+ struct xenbus_dev_data *u = filp->private_data;
+ int ret = -ENOSYS;
+
+ switch (cmd) {
+ case IOCTL_XENBUS_DEV_TALKV:
+ ret = xenbus_dev_talkv(u, data);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int xenbus_dev_open(struct inode *inode, struct file *filp)
+{
+ struct xenbus_dev_data *u;
+
+ u = kmalloc(sizeof(*u), GFP_KERNEL);
+ if (u == NULL)
+ return -ENOMEM;
+
+ memset(u, 0, sizeof(*u));
+
+ filp->private_data = u;
+
+ down(&xenbus_lock);
+
+ return 0;
+}
+
+static int xenbus_dev_release(struct inode *inode, struct file *filp)
+{
+ struct xenbus_dev_data *u = filp->private_data;
+
+ if (u->in_transaction)
+ xenbus_transaction_end(1);
+
+ up(&xenbus_lock);
+
+ kfree(u);
+
+ return 0;
+}
+
+static struct file_operations xenbus_dev_file_ops = {
+ ioctl: xenbus_dev_ioctl,
+ open: xenbus_dev_open,
+ release: xenbus_dev_release
+};
+
+static int __init
+xenbus_dev_init(void)
+{
+ xenbus_dev_intf = create_xen_proc_entry("xenbus", 0400);
+ if (xenbus_dev_intf)
+ xenbus_dev_intf->proc_fops = &xenbus_dev_file_ops;
+
+ return 0;
+}
+
+__initcall(xenbus_dev_init);
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/include/asm-xen/linux-public/xenbus_dev.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/linux-public/xenbus_dev.h Fri Sep
9 16:30:54 2005
@@ -0,0 +1,47 @@
+/*
+ * xenbus_dev.h
+ *
+ * Copyright (c) 2005, Christian Limpach
+ *
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef _XENBUS_DEV_H_
+#define _XENBUS_DEV_H_
+
+struct xenbus_dev_talkv {
+ enum xsd_sockmsg_type type;
+ const struct kvec *iovec;
+ unsigned int num_vecs;
+ char *buf;
+ unsigned int len;
+};
+
+/*
+ * @cmd: IOCTL_XENBUS_DEV_TALKV
+ * @arg: struct xenbus_dev_talkv
+ * Return: 0 on success, error code on failure.
+ */
+#define IOCTL_XENBUS_DEV_TALKV \
+ _IOC(_IOC_NONE, 'X', 0, sizeof(struct xenbus_dev_talkv))
+
+#endif /* _XENBUS_DEV_H_ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 linux-2.6-xen-sparse/include/linux/tpmfe.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/linux-2.6-xen-sparse/include/linux/tpmfe.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,33 @@
+#ifndef TPM_FE_H
+#define TPM_FE_H
+
+struct tpmfe_device {
+ /*
+ * Let upper layer receive data from front-end
+ */
+ int (*receive)(const u8 *buffer, size_t count, const void *ptr);
+ /*
+ * Indicate the status of the front-end to the upper
+ * layer.
+ */
+ void (*status)(unsigned int flags);
+
+ /*
+ * This field indicates the maximum size the driver can
+ * transfer in one chunk. It is filled out by the front-end
+ * driver and should be propagated to the generic tpm driver
+ * for allocation of buffers.
+ */
+ unsigned int max_tx_size;
+};
+
+enum {
+ TPMFE_STATUS_DISCONNECTED = 0x0,
+ TPMFE_STATUS_CONNECTED = 0x1
+};
+
+int tpm_fe_send(const u8 * buf, size_t count, void *ptr);
+int tpm_fe_register_receiver(struct tpmfe_device *);
+void tpm_fe_unregister_receiver(void);
+
+#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/blktap/README.sept05
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/blktap/README.sept05 Fri Sep 9 16:30:54 2005
@@ -0,0 +1,33 @@
+The blktap has been rewritten substantially based on the current
+blkback driver. I've removed passthrough support, as this is broken
+by the move to grant tables and the lack of transitive grants. A
+blktap VM is now only capable of terminating block requests in
+userspace.
+
+ublkback/ contains a _very_ initial cut at a user-level version of the block
+backend driver. It gives a working example of how the current tap
+interfaces are used, in particular w.r.t. the vbd directories in
+xenstore.
+
+parallax/ contains fairly recent parallax code. This does not run on
+the changed blktap interface, but should only be a couple of hours
+work to get going again.
+
+All of the tricky bits are done, but there is plenty of cleaning to
+do, and the top-level functionality is not here yet. At the moment,
+the daemon ignores the pdev requested by the tools and opens the file
+or device specified by TMP_IMAGE_FILE_NAME in ublkback.c.
+
+TODO:
+1. Fix to allow pdev in the store to specify the device to open.
+2. Add support (to tools as well) to mount arbitrary files...
+ just write the filename to mount into the store, instead of pdev.
+3. Reeximine blkif refcounting, it is almost certainly broken at the moment.
+ - creating a blkif should take a reference.
+ - each inflight request should take a reference on dequeue in blktaplib
+ - sending responses should drop refs.
+ - blkif should be implicitly freed when refcounts fall to 0.
+4. Modify the parallax req/rsp code as per ublkback to use the new tap
+ interfaces.
+5. Write a front end that allows parallax and normal mounts to coexist
+6. Allow blkback and blktap to run at the same time.
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/blktap/blkif.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/blktap/blkif.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,213 @@
+/*
+ * blkif.c
+ *
+ * The blkif interface for blktap. A blkif describes an in-use virtual disk.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <err.h>
+
+#include "blktaplib.h"
+
+#if 1
+#define DPRINTF(_f, _a...) printf ( _f , ## _a )
+#else
+#define DPRINTF(_f, _a...) ((void)0)
+#endif
+
+#define BLKIF_HASHSZ 1024
+#define BLKIF_HASH(_d,_h) (((int)(_d)^(int)(_h))&(BLKIF_HASHSZ-1))
+
+static blkif_t *blkif_hash[BLKIF_HASHSZ];
+
+blkif_t *blkif_find_by_handle(domid_t domid, unsigned int handle)
+{
+ blkif_t *blkif = blkif_hash[BLKIF_HASH(domid, handle)];
+ while ( (blkif != NULL) &&
+ ((blkif->domid != domid) || (blkif->handle != handle)) )
+ blkif = blkif->hash_next;
+ return blkif;
+}
+
+blkif_t *alloc_blkif(domid_t domid)
+{
+ blkif_t *blkif;
+
+ blkif = (blkif_t *)malloc(sizeof(blkif_t));
+ if (!blkif)
+ return NULL;
+
+ memset(blkif, 0, sizeof(*blkif));
+ blkif->domid = domid;
+
+ return blkif;
+}
+
+static int (*new_blkif_hook)(blkif_t *blkif) = NULL;
+void register_new_blkif_hook(int (*fn)(blkif_t *blkif))
+{
+ new_blkif_hook = fn;
+}
+
+int blkif_init(blkif_t *blkif, long int handle, long int pdev,
+ long int readonly)
+{
+ domid_t domid;
+ blkif_t **pblkif;
+
+ if (blkif == NULL)
+ return -EINVAL;
+
+ domid = blkif->domid;
+ blkif->handle = handle;
+ blkif->pdev = pdev;
+ blkif->readonly = readonly;
+
+ /*
+ * Call out to the new_blkif_hook. The tap application should define this,
+ * and it should return having set blkif->ops
+ *
+ */
+ if (new_blkif_hook == NULL)
+ {
+ warn("Probe detected a new blkif, but no new_blkif_hook!");
+ return -1;
+ }
+ new_blkif_hook(blkif);
+
+ /* Now wire it in. */
+ pblkif = &blkif_hash[BLKIF_HASH(domid, handle)];
+ while ( *pblkif != NULL )
+ {
+ if ( ((*pblkif)->domid == domid) && ((*pblkif)->handle == handle) )
+ {
+ DPRINTF("Could not create blkif: already exists\n");
+ return -1;
+ }
+ pblkif = &(*pblkif)->hash_next;
+ }
+ blkif->hash_next = NULL;
+ *pblkif = blkif;
+
+ return 0;
+}
+
+void free_blkif(blkif_t *blkif)
+{
+ blkif_t **pblkif, *curs;
+
+ pblkif = &blkif_hash[BLKIF_HASH(blkif->domid, blkif->handle)];
+ while ( (curs = *pblkif) != NULL )
+ {
+ if ( blkif == curs )
+ {
+ *pblkif = curs->hash_next;
+ }
+ pblkif = &curs->hash_next;
+ }
+ if (blkif != NULL)
+ free(blkif);
+}
+
+void blkif_register_request_hook(blkif_t *blkif, char *name,
+ int (*rh)(blkif_t *, blkif_request_t *, int))
+{
+ request_hook_t *rh_ent, **c;
+
+ rh_ent = (request_hook_t *)malloc(sizeof(request_hook_t));
+ if (!rh_ent)
+ {
+ warn("couldn't allocate a new hook");
+ return;
+ }
+
+ rh_ent->func = rh;
+ rh_ent->next = NULL;
+ if (asprintf(&rh_ent->name, "%s", name) == -1)
+ {
+ free(rh_ent);
+ warn("couldn't allocate a new hook name");
+ return;
+ }
+
+ c = &blkif->request_hook_chain;
+ while (*c != NULL) {
+ c = &(*c)->next;
+ }
+ *c = rh_ent;
+}
+
+void blkif_register_response_hook(blkif_t *blkif, char *name,
+ int (*rh)(blkif_t *, blkif_response_t *,
int))
+{
+ response_hook_t *rh_ent, **c;
+
+ rh_ent = (response_hook_t *)malloc(sizeof(response_hook_t));
+ if (!rh_ent)
+ {
+ warn("couldn't allocate a new hook");
+ return;
+ }
+
+ rh_ent->func = rh;
+ rh_ent->next = NULL;
+ if (asprintf(&rh_ent->name, "%s", name) == -1)
+ {
+ free(rh_ent);
+ warn("couldn't allocate a new hook name");
+ return;
+ }
+
+ c = &blkif->response_hook_chain;
+ while (*c != NULL) {
+ c = &(*c)->next;
+ }
+ *c = rh_ent;
+}
+
+void blkif_print_hooks(blkif_t *blkif)
+{
+ request_hook_t *req_hook;
+ response_hook_t *rsp_hook;
+
+ DPRINTF("Request Hooks:\n");
+ req_hook = blkif->request_hook_chain;
+ while (req_hook != NULL)
+ {
+ DPRINTF(" [0x%p] %s\n", req_hook->func, req_hook->name);
+ req_hook = req_hook->next;
+ }
+
+ DPRINTF("Response Hooks:\n");
+ rsp_hook = blkif->response_hook_chain;
+ while (rsp_hook != NULL)
+ {
+ DPRINTF(" [0x%p] %s\n", rsp_hook->func, rsp_hook->name);
+ rsp_hook = rsp_hook->next;
+ }
+}
+
+
+long int vbd_size(blkif_t *blkif)
+{
+ return 1000000000;
+}
+
+long int vbd_secsize(blkif_t *blkif)
+{
+ return 512;
+}
+
+unsigned vbd_info(blkif_t *blkif)
+{
+ return 0;
+}
+
+
+void __init_blkif(void)
+{
+ memset(blkif_hash, 0, sizeof(blkif_hash));
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/blktap/list.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/blktap/list.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,55 @@
+/*
+ * list.h
+ *
+ * This is a subset of linux's list.h intended to be used in user-space.
+ *
+ */
+
+#ifndef __LIST_H__
+#define __LIST_H__
+
+#define LIST_POISON1 ((void *) 0x00100100)
+#define LIST_POISON2 ((void *) 0x00200200)
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+ struct list_head name = LIST_HEAD_INIT(name)
+
+static inline void __list_add(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head, head->next);
+}
+static inline void __list_del(struct list_head * prev, struct list_head * next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+static inline void list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ entry->next = LIST_POISON1;
+ entry->prev = LIST_POISON2;
+}
+#define list_entry(ptr, type, member) \
+ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+#define list_for_each_entry(pos, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+#endif /* __LIST_H__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/blktap/ublkback/Makefile
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/blktap/ublkback/Makefile Fri Sep 9 16:30:54 2005
@@ -0,0 +1,42 @@
+
+XEN_ROOT = ../../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+INCLUDES += -I..
+
+INSTALL = install
+INSTALL_PROG = $(INSTALL) -m0755
+IBIN = ublkback
+INSTALL_DIR = /usr/sbin
+
+CFLAGS += -Wall
+CFLAGS += -Werror
+CFLAGS += -Wno-unused
+#CFLAGS += -O3
+CFLAGS += -g3
+CFLAGS += -fno-strict-aliasing
+CFLAGS += -I $(XEN_LIBXC)
+CFLAGS += $(INCLUDES) -I.
+CFLAGS += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
+# Get gcc to generate the dependencies for us.
+CFLAGS += -Wp,-MD,.$(@F).d
+DEPS = .*.d
+
+OBJS = $(patsubst %.c,%.o,$(SRCS))
+
+all: $(IBIN)
+
+LINUX_ROOT := $(wildcard $(XEN_ROOT)/linux-2.6.*-xen-sparse)
+
+install:
+ $(INSTALL_PROG) $(IBIN) $(DESTDIR)$(INSTALL_DIR)
+clean:
+ rm -rf *.o*~ $(DEPS) xen TAGS $(IBIN)
+
+ublkback:
+ $(CC) $(CFLAGS) -o ublkback -L$(XEN_LIBXC) -L. -L.. \
+ -lblktap -laio ublkback.c ublkbacklib.c -pg
+
+.PHONY: clean install
+
+-include $(DEPS)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/blktap/ublkback/ublkback.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/blktap/ublkback/ublkback.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,18 @@
+/* ublkback.c
+ *
+ * libaio-based userlevel backend.
+ */
+
+#include "blktaplib.h"
+#include "ublkbacklib.h"
+
+
+int main(int argc, char *argv[])
+{
+ ublkback_init();
+
+ register_new_blkif_hook(ublkback_new_blkif);
+ blktap_listen();
+
+ return 0;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/blktap/ublkback/ublkbacklib.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/blktap/ublkback/ublkbacklib.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,477 @@
+/* ublkbacklib.c
+ *
+ * file/device image-backed block device -- using linux libaio.
+ *
+ * (c) 2004 Andrew Warfield.
+ *
+ * Xend has been modified to use an amorfs:[fsid] disk tag.
+ * This will show up as device type (maj:240,min:0) = 61440.
+ *
+ * The fsid is placed in the sec_start field of the disk extent.
+ *
+ * NOTE: This doesn't work. Grrr.
+ */
+
+#define _GNU_SOURCE
+#define __USE_LARGEFILE64
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <db.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/poll.h>
+#include <unistd.h>
+#include <errno.h>
+#include <libaio.h>
+#include <pthread.h>
+#include <time.h>
+#include <err.h>
+#include "blktaplib.h"
+
+/* XXXX: */
+/* Current code just mounts this file/device to any requests that come in. */
+//#define TMP_IMAGE_FILE_NAME "/dev/sda1"
+#define TMP_IMAGE_FILE_NAME "fc3.image"
+
+#define MAX_REQUESTS 64 /* must be synced with the blkif drivers. */
+#define MAX_SEGMENTS_PER_REQ 11
+#define SECTOR_SHIFT 9
+#define MAX_AIO_REQS (MAX_REQUESTS * MAX_SEGMENTS_PER_REQ)
+
+#if 0
+#define DPRINTF(_f, _a...) printf ( _f , ## _a )
+#else
+#define DPRINTF(_f, _a...) ((void)0)
+#endif
+
+#if 1
+#define ASSERT(_p) \
+ if ( !(_p) ) { printf("Assertion '%s' failed, line %d, file %s", #_p , \
+ __LINE__, __FILE__); *(int*)0=0; }
+#else
+#define ASSERT(_p) ((void)0)
+#endif
+
+/* Note on pending_reqs: I assume all reqs are queued before they start to
+ * get filled. so count of 0 is an unused record.
+ */
+typedef struct {
+ blkif_request_t req;
+ blkif_t *blkif;
+ int count;
+} pending_req_t;
+
+static pending_req_t pending_list[MAX_REQUESTS];
+static io_context_t ctx;
+static struct iocb *iocb_free[MAX_AIO_REQS];
+static int iocb_free_count;
+
+/* ---[ Notification mecahnism ]--------------------------------------- */
+
+enum {
+ READ = 0,
+ WRITE = 1
+};
+
+static int aio_notify[2];
+static volatile int aio_listening = 0;
+static pthread_mutex_t notifier_sem = PTHREAD_MUTEX_INITIALIZER;
+
+static struct io_event aio_events[MAX_AIO_REQS];
+static int aio_event_count = 0;
+
+/* this is commented out in libaio.h for some reason. */
+extern int io_queue_wait(io_context_t ctx, struct timespec *timeout);
+
+static void *notifier_thread(void *arg)
+{
+ int ret;
+ int msg = 0x00feeb00;
+
+ DPRINTF("Notifier thread started.\n");
+ for (;;) {
+ pthread_mutex_lock(¬ifier_sem);
+ if ((ret = io_getevents(ctx, 1, MAX_AIO_REQS, aio_events, 0)) > 0) {
+ aio_event_count = ret;
+ write(aio_notify[WRITE], &msg, sizeof(msg));
+ } else {
+ printf("[io_queue_wait error! %d]\n", errno);
+ pthread_mutex_unlock(¬ifier_sem);
+ }
+ }
+}
+
+/* --- Talking to xenstore: ------------------------------------------- */
+
+int ublkback_request(blkif_t *blkif, blkif_request_t *req, int batch_done);
+int ublkback_response(blkif_t *blkif, blkif_response_t *rsp, int batch_done);
+
+typedef struct image {
+ /* These need to turn into an array/rbtree for multi-disk support. */
+ int fd;
+ u64 fsid;
+ blkif_vdev_t vdevice;
+ long int size;
+ long int secsize;
+ long int info;
+} image_t;
+
+long int ublkback_get_size(blkif_t *blkif)
+{
+ image_t *img = (image_t *)blkif->prv;
+ return img->size;
+}
+
+long int ublkback_get_secsize(blkif_t *blkif)
+{
+ image_t *img = (image_t *)blkif->prv;
+ return img->secsize;
+}
+
+unsigned ublkback_get_info(blkif_t *blkif)
+{
+ image_t *img = (image_t *)blkif->prv;
+ return img->info;
+}
+
+static struct blkif_ops ublkback_ops = {
+ get_size: ublkback_get_size,
+ get_secsize: ublkback_get_secsize,
+ get_info: ublkback_get_info,
+};
+
+int ublkback_new_blkif(blkif_t *blkif)
+{
+ image_t *image;
+ struct stat stat;
+ int ret;
+
+ image = (image_t *)malloc(sizeof(image_t));
+ if (image == NULL) {
+ printf("error allocating image record.\n");
+ return -ENOMEM;
+ }
+
+ /* Open it. */
+ image->fd = open(TMP_IMAGE_FILE_NAME,
+ O_RDWR | O_DIRECT | O_LARGEFILE);
+
+ if ((image->fd < 0) && (errno == EINVAL)) {
+ /* Maybe O_DIRECT isn't supported. */
+ warn("open() failed on '%s', trying again without O_DIRECT",
+ TMP_IMAGE_FILE_NAME);
+ image->fd = open(TMP_IMAGE_FILE_NAME, O_RDWR | O_LARGEFILE);
+ }
+
+ if (image->fd < 0) {
+ warn("Couldn't open image file!");
+ free(image);
+ return -EINVAL;
+ }
+
+ /* Size it. */
+ ret = fstat(image->fd, &stat);
+ if (ret != 0) {
+ printf("Couldn't stat image in PROBE!");
+ return -EINVAL;
+ }
+
+ image->size = (stat.st_size >> SECTOR_SHIFT);
+
+ /* TODO: IOCTL to get size of raw device. */
+/*
+ ret = ioctl(img->fd, BLKGETSIZE, &blksize);
+ if (ret != 0) {
+ printf("Couldn't ioctl image in PROBE!\n");
+ goto err;
+ }
+*/
+ if (image->size == 0)
+ image->size =((u64) 16836057);
+ image->secsize = 512;
+ image->info = 0;
+
+ /* Register the hooks */
+ blkif_register_request_hook(blkif, "Ublkback req.", ublkback_request);
+ blkif_register_response_hook(blkif, "Ublkback resp.", ublkback_response);
+
+
+ printf(">X<Created a new blkif! pdev was %ld, but you got %s\n",
+ blkif->pdev, TMP_IMAGE_FILE_NAME);
+
+ blkif->ops = &ublkback_ops;
+ blkif->prv = (void *)image;
+
+ return 0;
+}
+
+
+/* --- Moving the bits: ----------------------------------------------- */
+
+static int batch_count = 0;
+int ublkback_request(blkif_t *blkif, blkif_request_t *req, int batch_done)
+{
+ int fd;
+ u64 sector;
+ char *spage, *dpage;
+ int ret, i, idx;
+ blkif_response_t *rsp;
+ domid_t dom = ID_TO_DOM(req->id);
+ static struct iocb *ioq[MAX_SEGMENTS_PER_REQ*MAX_REQUESTS];
+ static int io_idx = 0;
+ struct iocb *io;
+ image_t *img;
+
+ img = (image_t *)blkif->prv;
+ fd = img->fd;
+
+ switch (req->operation)
+ {
+ case BLKIF_OP_WRITE:
+ {
+ unsigned long size;
+
+
+ batch_count++;
+
+ idx = ID_TO_IDX(req->id);
+ ASSERT(pending_list[idx].count == 0);
+ memcpy(&pending_list[idx].req, req, sizeof(*req));
+ pending_list[idx].count = req->nr_segments;
+ pending_list[idx].blkif = blkif;
+
+ for (i = 0; i < req->nr_segments; i++) {
+
+ sector = req->sector_number + (8*i);
+
+ size = blkif_last_sect (req->frame_and_sects[i]) -
+ blkif_first_sect(req->frame_and_sects[i]) + 1;
+
+ if (blkif_first_sect(req->frame_and_sects[i]) != 0)
+ DPRINTF("iWR: sec_nr: %10llu sec: %10llu (%1lu,%1lu) pos: %15lu\n",
+ req->sector_number, sector,
+ blkif_first_sect(req->frame_and_sects[i]),
+ blkif_last_sect (req->frame_and_sects[i]),
+ (long)(sector << SECTOR_SHIFT));
+
+ spage = (char *)MMAP_VADDR(ID_TO_IDX(req->id), i);
+ spage += blkif_first_sect(req->frame_and_sects[i]) << SECTOR_SHIFT;
+
+ /*convert size and sector to byte offsets */
+ size <<= SECTOR_SHIFT;
+ sector <<= SECTOR_SHIFT;
+
+ io = iocb_free[--iocb_free_count];
+ io_prep_pwrite(io, fd, spage, size, sector);
+ io->data = (void *)idx;
+ //ioq[i] = io;
+ ioq[io_idx++] = io;
+ }
+
+ if (batch_done) {
+ ret = io_submit(ctx, io_idx, ioq);
+ batch_count = 0;
+ if (ret < 0)
+ printf("BADNESS: io_submit error! (%d)\n", errno);
+ io_idx = 0;
+ }
+
+ return BLKTAP_STOLEN;
+
+ }
+ case BLKIF_OP_READ:
+ {
+ unsigned long size;
+
+ batch_count++;
+ idx = ID_TO_IDX(req->id);
+ ASSERT(pending_list[idx].count == 0);
+ memcpy(&pending_list[idx].req, req, sizeof(*req));
+ pending_list[idx].count = req->nr_segments;
+ pending_list[idx].blkif = blkif;
+
+ for (i = 0; i < req->nr_segments; i++) {
+
+ sector = req->sector_number + (8*i);
+
+ size = blkif_last_sect (req->frame_and_sects[i]) -
+ blkif_first_sect(req->frame_and_sects[i]) + 1;
+
+ dpage = (char *)MMAP_VADDR(ID_TO_IDX(req->id), i);
+ dpage += blkif_first_sect(req->frame_and_sects[i]) << SECTOR_SHIFT;
+
+ if (blkif_first_sect(req->frame_and_sects[i]) != 0)
+ DPRINTF("iRD : sec_nr: %10llu sec: %10llu (%1lu,%1lu) "
+ "pos: %15lu dpage: %p\n",
+ req->sector_number, sector,
+ blkif_first_sect(req->frame_and_sects[i]),
+ blkif_last_sect (req->frame_and_sects[i]),
+ (long)(sector << SECTOR_SHIFT), dpage);
+
+ /*convert size and sector to byte offsets */
+ size <<= SECTOR_SHIFT;
+ sector <<= SECTOR_SHIFT;
+
+
+ /*
+ * NB: Looks like AIO now has non-page aligned support, this path
+ * can probably be removed... Only really used for hunting
+ * superblocks anyway... ;)
+ */
+ if ( ((unsigned long)dpage % PAGE_SIZE) != 0 ) {
+ /* AIO to raw devices must be page aligned, so do this read
+ * synchronously. The OS is probably just looking for
+ * a superblock or something, so this won't hurt performance.
+ */
+ int ret;
+
+ printf("Slow path block read.\n");
+ /* Question: do in-progress aio ops modify the file cursor? */
+ ret = lseek(fd, sector, SEEK_SET);
+ if (ret == (off_t)-1)
+ printf("lseek failed!\n");
+ ret = read(fd, dpage, size);
+ if (ret < 0)
+ printf("read problem (%d)\n", ret);
+ printf("|\n|\n| read: %lld, %lu, %d\n|\n|\n", sector, size,
ret);
+
+ /* not an async request any more... */
+ pending_list[idx].count--;
+
+ rsp = (blkif_response_t *)req;
+ rsp->id = req->id;
+ rsp->operation = BLKIF_OP_READ;
+ rsp->status = BLKIF_RSP_OKAY;
+ return BLKTAP_RESPOND;
+ /* Doh -- need to flush aio if this is end-of-batch */
+ }
+
+ io = iocb_free[--iocb_free_count];
+
+ io_prep_pread(io, fd, dpage, size, sector);
+ io->data = (void *)idx;
+
+ ioq[io_idx++] = io;
+ //ioq[i] = io;
+ }
+
+ if (batch_done) {
+ ret = io_submit(ctx, io_idx, ioq);
+ batch_count = 0;
+ if (ret < 0)
+ printf("BADNESS: io_submit error! (%d)\n", errno);
+ io_idx = 0;
+ }
+
+ return BLKTAP_STOLEN;
+
+ }
+ }
+
+ printf("Unknown block operation!\n");
+err:
+ rsp = (blkif_response_t *)req;
+ rsp->id = req->id;
+ rsp->operation = req->operation;
+ rsp->status = BLKIF_RSP_ERROR;
+ return BLKTAP_RESPOND;
+}
+
+
+int ublkback_pollhook(int fd)
+{
+ struct io_event *ep;
+ int n, ret, idx;
+ blkif_request_t *req;
+ blkif_response_t *rsp;
+ int responses_queued = 0;
+ int pages=0;
+
+ for (ep = aio_events; aio_event_count-- > 0; ep++) {
+ struct iocb *io = ep->obj;
+ idx = (int) ep->data;
+
+ if ((idx > MAX_REQUESTS-1) || (pending_list[idx].count == 0)){
+ printf("invalid index returned(%u)!\n", idx);
+ break;
+ }
+
+ if ((int)ep->res < 0)
+ printf("***\n***aio request error! (%d,%d)\n***\n",
+ (int)ep->res, (int)ep->res2);
+
+ pending_list[idx].count--;
+ iocb_free[iocb_free_count++] = io;
+ pages++;
+
+ if (pending_list[idx].count == 0) {
+ blkif_request_t tmp = pending_list[idx].req;
+ rsp = (blkif_response_t *)&pending_list[idx].req;
+ rsp->id = tmp.id;
+ rsp->operation = tmp.operation;
+ rsp->status = BLKIF_RSP_OKAY;
+ blkif_inject_response(pending_list[idx].blkif, rsp);
+ responses_queued++;
+ }
+ }
+
+ if (responses_queued) {
+ blktap_kick_responses();
+ }
+
+ read(aio_notify[READ], &idx, sizeof(idx));
+ aio_listening = 1;
+ pthread_mutex_unlock(¬ifier_sem);
+
+ return 0;
+}
+
+/* the image library terminates the request stream. _resp is a noop. */
+int ublkback_response(blkif_t *blkif, blkif_response_t *rsp, int batch_done)
+{
+ return BLKTAP_PASS;
+}
+
+void ublkback_init(void)
+{
+ int i, rc;
+ pthread_t p;
+
+ for (i = 0; i < MAX_REQUESTS; i++)
+ pending_list[i].count = 0;
+
+ memset(&ctx, 0, sizeof(ctx));
+ rc = io_queue_init(MAX_AIO_REQS, &ctx);
+ if (rc != 0) {
+ printf("queue_init failed! (%d)\n", rc);
+ exit(0);
+ }
+
+ for (i=0; i<MAX_AIO_REQS; i++) {
+ if (!(iocb_free[i] = (struct iocb *)malloc(sizeof(struct iocb)))) {
+ printf("error allocating iocb array\n");
+ exit(0);
+ }
+ iocb_free_count = i;
+ }
+
+ rc = pipe(aio_notify);
+ if (rc != 0) {
+ printf("pipe failed! (%d)\n", errno);
+ exit(0);
+ }
+
+ rc = pthread_create(&p, NULL, notifier_thread, NULL);
+ if (rc != 0) {
+ printf("pthread_create failed! (%d)\n", errno);
+ exit(0);
+ }
+
+ aio_listening = 1;
+
+ blktap_attach_poll(aio_notify[READ], POLLIN, ublkback_pollhook);
+}
+
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/blktap/ublkback/ublkbacklib.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/blktap/ublkback/ublkbacklib.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,16 @@
+/* blkaiolib.h
+ *
+ * aio image-backed block device.
+ *
+ * (c) 2004 Andrew Warfield.
+ *
+ * Xend has been modified to use an amorfs:[fsid] disk tag.
+ * This will show up as device type (maj:240,min:0) = 61440.
+ *
+ * The fsid is placed in the sec_start field of the disk extent.
+ */
+
+int ublkback_request(blkif_request_t *req, int batch_done);
+int ublkback_response(blkif_response_t *rsp); /* noop */
+int ublkback_new_blkif(blkif_t *blkif);
+void ublkback_init(void);
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/blktap/xenbus.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/blktap/xenbus.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,578 @@
+/*
+ * xenbus.c
+ *
+ * xenbus interface to the blocktap.
+ *
+ * this handles the top-half of integration with block devices through the
+ * store -- the tap driver negotiates the device channel etc, while the
+ * userland tap clinet needs to sort out the disk parameters etc.
+ *
+ * A. Warfield 2005 Based primarily on the blkback and xenbus driver code.
+ * Comments there apply here...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <err.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <xs.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <poll.h>
+#include "blktaplib.h"
+#include "list.h"
+
+#if 0
+#define DPRINTF(_f, _a...) printf ( _f , ## _a )
+#else
+#define DPRINTF(_f, _a...) ((void)0)
+#endif
+
+/* --- Xenstore / Xenbus helpers ---------------------------------------- */
+/*
+ * These should all be pulled out into the xenstore API. I'm faulting commands
+ * in from the xenbus interface as i need them.
+ */
+
+
+/* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
+int xs_gather(struct xs_handle *xs, const char *dir, ...)
+{
+ va_list ap;
+ const char *name;
+ char *path;
+ int ret = 0;
+
+ va_start(ap, dir);
+ while (ret == 0 && (name = va_arg(ap, char *)) != NULL) {
+ const char *fmt = va_arg(ap, char *);
+ void *result = va_arg(ap, void *);
+ char *p;
+
+ if (asprintf(&path, "%s/%s", dir, name) == -1)
+ {
+ warn("allocation error in xs_gather!\n");
+ ret = ENOMEM;
+ break;
+ }
+ p = xs_read(xs, path, NULL);
+ free(path);
+ if (p == NULL) {
+ ret = ENOENT;
+ break;
+ }
+ if (fmt) {
+ if (sscanf(p, fmt, result) == 0)
+ ret = EINVAL;
+ free(p);
+ } else
+ *(char **)result = p;
+ }
+ va_end(ap);
+ return ret;
+}
+
+/* Single printf and write: returns -errno or 0. */
+int xs_printf(struct xs_handle *h, const char *dir, const char *node,
+ const char *fmt, ...)
+{
+ char *buf, *path;
+ va_list ap;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = vasprintf(&buf, fmt, ap);
+ va_end(ap);
+
+ asprintf(&path, "%s/%s", dir, node);
+
+ if ((path == NULL) || (buf == NULL))
+ return 0;
+
+ ret = xs_write(h, path, buf, strlen(buf)+1, O_CREAT);
+
+ free(buf);
+ free(path);
+
+ return ret;
+}
+
+
+int xs_exists(struct xs_handle *h, const char *path)
+{
+ char **d;
+ int num;
+
+ d = xs_directory(h, path, &num);
+ if (d == NULL)
+ return 0;
+ free(d);
+ return 1;
+}
+
+
+
+/* This assumes that the domain name we are looking for is unique! */
+char *get_dom_uuid(struct xs_handle *h, const char *name)
+{
+ char **e, *val, *uuid = NULL;
+ int num, i, len;
+ char *path;
+
+ e = xs_directory(h, "/domain", &num);
+
+ i=0;
+ while (i < num) {
+ asprintf(&path, "/domain/%s/name", e[i]);
+ val = xs_read(h, path, &len);
+ free(path);
+ if (val == NULL)
+ continue;
+ if (strcmp(val, name) == 0) {
+ /* match! */
+ asprintf(&path, "/domain/%s/uuid", e[i]);
+ uuid = xs_read(h, path, &len);
+ free(val);
+ free(path);
+ break;
+ }
+ free(val);
+ i++;
+ }
+
+ free(e);
+ return uuid;
+}
+
+static int strsep_len(const char *str, char c, unsigned int len)
+{
+ unsigned int i;
+
+ for (i = 0; str[i]; i++)
+ if (str[i] == c) {
+ if (len == 0)
+ return i;
+ len--;
+ }
+ return (len == 0) ? i : -ERANGE;
+}
+
+
+/* xenbus watches: */
+/* Register callback to watch this node. */
+struct xenbus_watch
+{
+ struct list_head list;
+ char *node;
+ void (*callback)(struct xs_handle *h,
+ struct xenbus_watch *,
+ const char *node);
+};
+
+static LIST_HEAD(watches);
+
+/* A little paranoia: we don't just trust token. */
+static struct xenbus_watch *find_watch(const char *token)
+{
+ struct xenbus_watch *i, *cmp;
+
+ cmp = (void *)strtoul(token, NULL, 16);
+
+ list_for_each_entry(i, &watches, list)
+ if (i == cmp)
+ return i;
+ return NULL;
+}
+
+/* Register callback to watch this node. like xs_watch, return 0 on failure */
+int register_xenbus_watch(struct xs_handle *h, struct xenbus_watch *watch)
+{
+ /* Pointer in ascii is the token. */
+ char token[sizeof(watch) * 2 + 1];
+ int er;
+
+ sprintf(token, "%lX", (long)watch);
+ if (find_watch(token))
+ {
+ warn("watch collision!");
+ return -EINVAL;
+ }
+
+ er = xs_watch(h, watch->node, token);
+ if (er != 0) {
+ list_add(&watch->list, &watches);
+ }
+
+ return er;
+}
+
+int unregister_xenbus_watch(struct xs_handle *h, struct xenbus_watch *watch)
+{
+ char token[sizeof(watch) * 2 + 1];
+ int er;
+
+ sprintf(token, "%lX", (long)watch);
+ if (!find_watch(token))
+ {
+ warn("no such watch!");
+ return -EINVAL;
+ }
+
+
+ er = xs_unwatch(h, watch->node, token);
+ list_del(&watch->list);
+
+ if (er == 0)
+ warn("XENBUS Failed to release watch %s: %i",
+ watch->node, er);
+ return 0;
+}
+
+/* Re-register callbacks to all watches. */
+void reregister_xenbus_watches(struct xs_handle *h)
+{
+ struct xenbus_watch *watch;
+ char token[sizeof(watch) * 2 + 1];
+
+ list_for_each_entry(watch, &watches, list) {
+ sprintf(token, "%lX", (long)watch);
+ xs_watch(h, watch->node, token);
+ }
+}
+
+/* based on watch_thread() */
+int xs_fire_next_watch(struct xs_handle *h)
+{
+ char **res;
+ char *token;
+ char *node = NULL;
+ struct xenbus_watch *w;
+ int er;
+
+ res = xs_read_watch(h);
+ if (res == NULL)
+ return -EAGAIN; /* in O_NONBLOCK, read_watch returns 0... */
+
+ node = res[0];
+ token = res[1];
+
+ er = xs_acknowledge_watch(h, token);
+ if (er == 0)
+ warn("Couldn't acknowledge watch (%s)", token);
+
+ w = find_watch(token);
+ if (!w)
+ {
+ warn("unregistered watch fired");
+ goto done;
+ }
+ w->callback(h, w, node);
+
+ done:
+ free(res);
+ return 1;
+}
+
+
+
+
+/* ---------------------------------------------------------------------- */
+
+struct backend_info
+{
+ /* our communications channel */
+ blkif_t *blkif;
+
+ long int frontend_id;
+ long int pdev;
+ long int readonly;
+
+ /* watch back end for changes */
+ struct xenbus_watch backend_watch;
+ char *backpath;
+
+ /* watch front end for changes */
+ struct xenbus_watch watch;
+ char *frontpath;
+
+ struct list_head list;
+};
+
+static LIST_HEAD(belist);
+
+static struct backend_info *be_lookup_be(const char *bepath)
+{
+ struct backend_info *be;
+
+ list_for_each_entry(be, &belist, list)
+ if (strcmp(bepath, be->backpath) == 0)
+ return be;
+ return (struct backend_info *)NULL;
+}
+
+static int be_exists_be(const char *bepath)
+{
+ return ( be_lookup_be(bepath) != NULL );
+}
+
+static struct backend_info *be_lookup_fe(const char *fepath)
+{
+ struct backend_info *be;
+
+ list_for_each_entry(be, &belist, list)
+ if (strcmp(fepath, be->frontpath) == 0)
+ return be;
+ return (struct backend_info *)NULL;
+}
+
+static int backend_remove(struct xs_handle *h, struct backend_info *be)
+{
+ /* Turn off watches. */
+ if (be->watch.node)
+ unregister_xenbus_watch(h, &be->watch);
+ if (be->backend_watch.node)
+ unregister_xenbus_watch(h, &be->backend_watch);
+
+ /* Unhook from be list. */
+ list_del(&be->list);
+
+ /* Free everything else. */
+ if (be->blkif)
+ free_blkif(be->blkif);
+ if (be->frontpath)
+ free(be->frontpath);
+ if (be->backpath)
+ free(be->backpath);
+ free(be);
+ return 0;
+}
+
+static void frontend_changed(struct xs_handle *h, struct xenbus_watch *w,
+ const char *fepath_im)
+{
+ struct backend_info *be;
+ char *fepath = NULL;
+ int er;
+
+ be = be_lookup_fe(w->node);
+ if (be == NULL)
+ {
+ warn("frontend changed called for nonexistent backend! (%s)", fepath);
+ goto fail;
+ }
+
+ /* If other end is gone, delete ourself. */
+ if (w->node && !xs_exists(h, be->frontpath)) {
+ DPRINTF("DELETING BE: %s\n", be->backpath);
+ backend_remove(h, be);
+ return;
+ }
+
+ if (be->blkif == NULL || (be->blkif->state == CONNECTED))
+ return;
+
+ /* Supply the information about the device the frontend needs */
+ er = xs_transaction_start(h, be->backpath);
+ if (er == 0) {
+ warn("starting transaction");
+ goto fail;
+ }
+
+ er = xs_printf(h, be->backpath, "sectors", "%lu",
+ be->blkif->ops->get_size(be->blkif));
+ if (er == 0) {
+ warn("writing sectors");
+ goto fail;
+ }
+
+ er = xs_printf(h, be->backpath, "info", "%u",
+ be->blkif->ops->get_info(be->blkif));
+ if (er == 0) {
+ warn("writing info");
+ goto fail;
+ }
+
+ er = xs_printf(h, be->backpath, "sector-size", "%lu",
+ be->blkif->ops->get_secsize(be->blkif));
+ if (er == 0) {
+ warn("writing sector-size");
+ goto fail;
+ }
+
+ be->blkif->state = CONNECTED;
+
+ xs_transaction_end(h, 0);
+
+ return;
+
+ fail:
+ if (fepath)
+ free(fepath);
+}
+
+
+static void backend_changed(struct xs_handle *h, struct xenbus_watch *w,
+ const char *bepath_im)
+{
+ struct backend_info *be;
+ char *path = NULL, *p;
+ int len, er;
+ long int pdev = 0, handle;
+
+ be = be_lookup_be(w->node);
+ if (be == NULL)
+ {
+ warn("backend changed called for nonexistent backend! (%s)", w->node);
+ goto fail;
+ }
+
+ er = xs_gather(h, be->backpath, "physical-device", "%li", &pdev, NULL);
+ if (er != 0)
+ goto fail;
+
+ if (be->pdev && be->pdev != pdev) {
+ warn("changing physical-device not supported");
+ goto fail;
+ }
+ be->pdev = pdev;
+
+ asprintf(&path, "%s/%s", w->node, "read-only");
+ if (xs_exists(h, path))
+ be->readonly = 1;
+
+ if (be->blkif == NULL) {
+ /* Front end dir is a number, which is used as the handle. */
+ p = strrchr(be->frontpath, '/') + 1;
+ handle = strtoul(p, NULL, 0);
+
+ be->blkif = alloc_blkif(be->frontend_id);
+ if (be->blkif == NULL)
+ goto fail;
+
+ er = blkif_init(be->blkif, handle, be->pdev, be->readonly);
+ if (er)
+ goto fail;
+
+ DPRINTF("[BECHG]: ADDED A NEW BLKIF (%s)\n", w->node);
+
+ /* Pass in NULL node to skip exist test. */
+ frontend_changed(h, &be->watch, NULL);
+ }
+
+ fail:
+ if (path)
+ free(path);
+
+}
+
+static void blkback_probe(struct xs_handle *h, struct xenbus_watch *w,
+ const char *bepath_im)
+{
+ struct backend_info *be = NULL;
+ char *frontend = NULL, *bepath = NULL;
+ int er, len;
+
+ bepath = strdup(bepath_im);
+ if (!bepath)
+ return;
+ len = strsep_len(bepath, '/', 6);
+ if (len < 0)
+ goto free_be;
+
+ bepath[len] = '\0'; /*truncate the passed-in string with predjudice. */
+
+ be = malloc(sizeof(*be));
+ if (!be) {
+ warn("allocating backend structure");
+ goto free_be;
+ }
+ memset(be, 0, sizeof(*be));
+
+ frontend = NULL;
+ er = xs_gather(h, bepath,
+ "frontend-id", "%li", &be->frontend_id,
+ "frontend", NULL, &frontend,
+ NULL);
+ if (er)
+ goto free_be;
+
+ if (strlen(frontend) == 0 || !xs_exists(h, frontend)) {
+ /* If we can't get a frontend path and a frontend-id,
+ * then our bus-id is no longer valid and we need to
+ * destroy the backend device.
+ */
+ DPRINTF("No frontend (%s)\n", frontend);
+ goto free_be;
+ }
+
+ /* Are we already tracking this device? */
+ if (be_exists_be(bepath))
+ goto free_be;
+
+ be->backpath = bepath;
+ be->backend_watch.node = be->backpath;
+ be->backend_watch.callback = backend_changed;
+ er = register_xenbus_watch(h, &be->backend_watch);
+ if (er == 0) {
+ be->backend_watch.node = NULL;
+ warn("error adding backend watch on %s", bepath);
+ goto free_be;
+ }
+
+ be->frontpath = frontend;
+ be->watch.node = be->frontpath;
+ be->watch.callback = frontend_changed;
+ er = register_xenbus_watch(h, &be->watch);
+ if (er == 0) {
+ be->watch.node = NULL;
+ warn("adding frontend watch on %s", be->frontpath);
+ goto free_be;
+ }
+
+ list_add(&be->list, &belist);
+
+ DPRINTF("[PROBE]: ADDED NEW DEVICE (%s)\n", bepath_im);
+
+ backend_changed(h, &be->backend_watch, bepath);
+ return;
+
+ free_be:
+ if ((be) && (be->backend_watch.node))
+ unregister_xenbus_watch(h, &be->backend_watch);
+ if (frontend)
+ free(frontend);
+ if (bepath)
+ free(bepath);
+ free(be);
+ return;
+}
+
+
+int add_blockdevice_probe_watch(struct xs_handle *h, const char *domname)
+{
+ char *uuid, *path;
+ struct xenbus_watch *vbd_watch;
+ int er;
+
+ uuid = get_dom_uuid(h, domname);
+
+ DPRINTF("%s: %s\n", domname, (uuid != NULL) ? uuid : "[ not found! ]");
+
+ asprintf(&path, "/domain/%s/backend/vbd", uuid);
+ if (path == NULL)
+ return -ENOMEM;
+
+ vbd_watch = (struct xenbus_watch *)malloc(sizeof(struct xenbus_watch));
+ vbd_watch->node = path;
+ vbd_watch->callback = blkback_probe;
+ er = register_xenbus_watch(h, vbd_watch);
+ if (er == 0) {
+ warn("Error adding vbd probe watch %s", path);
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/examples/xen-backend.agent
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/examples/xen-backend.agent Fri Sep 9 16:30:54 2005
@@ -0,0 +1,25 @@
+#! /bin/sh
+
+#ACTION=add
+#DEVPATH=/devices/xen-backend/vif-1-0
+#PHYSDEVDRIVER=vif
+#XENBUS_TYPE=vif
+
+PATH=/etc/xen/scripts:$PATH
+
+case "$ACTION" in
+ add)
+ ;;
+ remove)
+ ;;
+ online)
+ case "$PHYSDEVDRIVER" in
+ vif)
+ [ -n "$script" ] && $script up
+ ;;
+ esac
+ ;;
+ offline)
+ ;;
+esac
+
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/ioemu/hw/pcnet.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/ioemu/hw/pcnet.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,1209 @@
+/*
+ * QEMU AMD PC-Net II (Am79C970A) emulation
+ *
+ * Copyright (c) 2004 Antony T Curtis
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/* This software was written to be compatible with the specification:
+ * AMD Am79C970A PCnet-PCI II Ethernet Controller Data-Sheet
+ * AMD Publication# 19436 Rev:E Amendment/0 Issue Date: June 2000
+ */
+
+#include "vl.h"
+#include <sys/times.h>
+#include <arpa/inet.h>
+#include <net/ethernet.h>
+
+//#define PCNET_DEBUG
+//#define PCNET_DEBUG_IO
+//#define PCNET_DEBUG_BCR
+//#define PCNET_DEBUG_CSR
+//#define PCNET_DEBUG_RMD
+//#define PCNET_DEBUG_TMD
+//#define PCNET_DEBUG_MATCH
+
+
+#define PCNET_IOPORT_SIZE 0x20
+#define PCNET_PNPMMIO_SIZE 0x20
+
+
+typedef struct PCNetState_st PCNetState;
+
+struct PCNetState_st {
+ PCIDevice dev;
+ NetDriverState *nd;
+ QEMUTimer *poll_timer;
+ int mmio_io_addr, rap, isr, lnkst;
+ target_phys_addr_t rdra, tdra;
+ uint8_t prom[16];
+ uint16_t csr[128];
+ uint16_t bcr[32];
+ uint64_t timer;
+ int xmit_pos, recv_pos;
+ uint8_t buffer[4096];
+};
+
+#include "pcnet.h"
+
+static void pcnet_poll(PCNetState *s);
+static void pcnet_poll_timer(void *opaque);
+
+static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap);
+static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value);
+static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val);
+static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap);
+
+static void pcnet_s_reset(PCNetState *s)
+{
+#ifdef PCNET_DEBUG
+ printf("pcnet_s_reset\n");
+#endif
+
+ s->lnkst = 0x40;
+ s->rdra = 0;
+ s->tdra = 0;
+ s->rap = 0;
+
+ s->bcr[BCR_BSBC] &= ~0x0080;
+
+ s->csr[0] = 0x0004;
+ s->csr[3] = 0x0000;
+ s->csr[4] = 0x0115;
+ s->csr[5] = 0x0000;
+ s->csr[6] = 0x0000;
+ s->csr[8] = 0;
+ s->csr[9] = 0;
+ s->csr[10] = 0;
+ s->csr[11] = 0;
+ s->csr[12] = le16_to_cpu(((uint16_t *)&s->prom[0])[0]);
+ s->csr[13] = le16_to_cpu(((uint16_t *)&s->prom[0])[1]);
+ s->csr[14] = le16_to_cpu(((uint16_t *)&s->prom[0])[2]);
+ s->csr[15] &= 0x21c4;
+ s->csr[72] = 1;
+ s->csr[74] = 1;
+ s->csr[76] = 1;
+ s->csr[78] = 1;
+ s->csr[80] = 0x1410;
+ s->csr[88] = 0x1003;
+ s->csr[89] = 0x0262;
+ s->csr[94] = 0x0000;
+ s->csr[100] = 0x0200;
+ s->csr[103] = 0x0105;
+ s->csr[103] = 0x0105;
+ s->csr[112] = 0x0000;
+ s->csr[114] = 0x0000;
+ s->csr[122] = 0x0000;
+ s->csr[124] = 0x0000;
+}
+
+static void pcnet_update_irq(PCNetState *s)
+{
+ int isr = 0;
+ s->csr[0] &= ~0x0080;
+
+#if 1
+ if (((s->csr[0] & ~s->csr[3]) & 0x5f00) ||
+ (((s->csr[4]>>1) & ~s->csr[4]) & 0x0115) ||
+ (((s->csr[5]>>1) & s->csr[5]) & 0x0048))
+#else
+ if ((!(s->csr[3] & 0x4000) && !!(s->csr[0] & 0x4000)) /* BABL */ ||
+ (!(s->csr[3] & 0x1000) && !!(s->csr[0] & 0x1000)) /* MISS */ ||
+ (!(s->csr[3] & 0x0100) && !!(s->csr[0] & 0x0100)) /* IDON */ ||
+ (!(s->csr[3] & 0x0200) && !!(s->csr[0] & 0x0200)) /* TINT */ ||
+ (!(s->csr[3] & 0x0400) && !!(s->csr[0] & 0x0400)) /* RINT */ ||
+ (!(s->csr[3] & 0x0800) && !!(s->csr[0] & 0x0800)) /* MERR */ ||
+ (!(s->csr[4] & 0x0001) && !!(s->csr[4] & 0x0002)) /* JAB */ ||
+ (!(s->csr[4] & 0x0004) && !!(s->csr[4] & 0x0008)) /* TXSTRT */ ||
+ (!(s->csr[4] & 0x0010) && !!(s->csr[4] & 0x0020)) /* RCVO */ ||
+ (!(s->csr[4] & 0x0100) && !!(s->csr[4] & 0x0200)) /* MFCO */ ||
+ (!!(s->csr[5] & 0x0040) && !!(s->csr[5] & 0x0080)) /* EXDINT */ ||
+ (!!(s->csr[5] & 0x0008) && !!(s->csr[5] & 0x0010)) /* MPINT */)
+#endif
+ {
+
+ isr = CSR_INEA(s);
+ s->csr[0] |= 0x0080;
+ }
+
+ if (!!(s->csr[4] & 0x0080) && CSR_INEA(s)) { /* UINT */
+ s->csr[4] &= ~0x0080;
+ s->csr[4] |= 0x0040;
+ s->csr[0] |= 0x0080;
+ isr = 1;
+#ifdef PCNET_DEBUG
+ printf("pcnet user int\n");
+#endif
+ }
+
+#if 1
+ if (((s->csr[5]>>1) & s->csr[5]) & 0x0500)
+#else
+ if ((!!(s->csr[5] & 0x0400) && !!(s->csr[5] & 0x0800)) /* SINT */ ||
+ (!!(s->csr[5] & 0x0100) && !!(s->csr[5] & 0x0200)) /* SLPINT */ )
+#endif
+ {
+ isr = 1;
+ s->csr[0] |= 0x0080;
+ }
+
+ if (isr != s->isr) {
+#ifdef PCNET_DEBUG
+ printf("pcnet: INTA=%d\n", isr);
+#endif
+ }
+ pci_set_irq(&s->dev, 0, isr);
+ s->isr = isr;
+}
+
+static void pcnet_init(PCNetState *s)
+{
+#ifdef PCNET_DEBUG
+ printf("pcnet_init init_addr=0x%08x\n", PHYSADDR(s,CSR_IADR(s)));
+#endif
+
+#define PCNET_INIT() do { \
+ cpu_physical_memory_read(PHYSADDR(s,CSR_IADR(s)), \
+ (uint8_t *)&initblk, sizeof(initblk)); \
+ s->csr[15] = le16_to_cpu(initblk.mode); \
+ CSR_RCVRL(s) = (initblk.rlen < 9) ? (1 << initblk.rlen) : 512; \
+ CSR_XMTRL(s) = (initblk.tlen < 9) ? (1 << initblk.tlen) : 512; \
+ s->csr[ 6] = (initblk.tlen << 12) | (initblk.rlen << 8); \
+ s->csr[ 8] = le16_to_cpu(initblk.ladrf1); \
+ s->csr[ 9] = le16_to_cpu(initblk.ladrf2); \
+ s->csr[10] = le16_to_cpu(initblk.ladrf3); \
+ s->csr[11] = le16_to_cpu(initblk.ladrf4); \
+ s->csr[12] = le16_to_cpu(initblk.padr1); \
+ s->csr[13] = le16_to_cpu(initblk.padr2); \
+ s->csr[14] = le16_to_cpu(initblk.padr3); \
+ s->rdra = PHYSADDR(s,initblk.rdra); \
+ s->tdra = PHYSADDR(s,initblk.tdra); \
+} while (0)
+
+ if (BCR_SSIZE32(s)) {
+ struct pcnet_initblk32 initblk;
+ PCNET_INIT();
+#ifdef PCNET_DEBUG
+ printf("initblk.rlen=0x%02x, initblk.tlen=0x%02x\n",
+ initblk.rlen, initblk.tlen);
+#endif
+ } else {
+ struct pcnet_initblk16 initblk;
+ PCNET_INIT();
+#ifdef PCNET_DEBUG
+ printf("initblk.rlen=0x%02x, initblk.tlen=0x%02x\n",
+ initblk.rlen, initblk.tlen);
+#endif
+ }
+
+#undef PCNET_INIT
+
+ CSR_RCVRC(s) = CSR_RCVRL(s);
+ CSR_XMTRC(s) = CSR_XMTRL(s);
+
+#ifdef PCNET_DEBUG
+ printf("pcnet ss32=%d rdra=0x%08x[%d] tdra=0x%08x[%d]\n",
+ BCR_SSIZE32(s),
+ s->rdra, CSR_RCVRL(s), s->tdra, CSR_XMTRL(s));
+#endif
+
+ s->csr[0] |= 0x0101;
+ s->csr[0] &= ~0x0004; /* clear STOP bit */
+}
+
+static void pcnet_start(PCNetState *s)
+{
+#ifdef PCNET_DEBUG
+ printf("pcnet_start\n");
+#endif
+
+ if (!CSR_DTX(s))
+ s->csr[0] |= 0x0010; /* set TXON */
+
+ if (!CSR_DRX(s))
+ s->csr[0] |= 0x0020; /* set RXON */
+
+ s->csr[0] &= ~0x0004; /* clear STOP bit */
+ s->csr[0] |= 0x0002;
+}
+
+static void pcnet_stop(PCNetState *s)
+{
+#ifdef PCNET_DEBUG
+ printf("pcnet_stop\n");
+#endif
+ s->csr[0] &= ~0x7feb;
+ s->csr[0] |= 0x0014;
+ s->csr[4] &= ~0x02c2;
+ s->csr[5] &= ~0x0011;
+ pcnet_poll_timer(s);
+}
+
+static void pcnet_rdte_poll(PCNetState *s)
+{
+ s->csr[28] = s->csr[29] = 0;
+ if (s->rdra) {
+ int bad = 0;
+#if 1
+ target_phys_addr_t crda = pcnet_rdra_addr(s, CSR_RCVRC(s));
+ target_phys_addr_t nrda = pcnet_rdra_addr(s, -1 + CSR_RCVRC(s));
+ target_phys_addr_t nnrd = pcnet_rdra_addr(s, -2 + CSR_RCVRC(s));
+#else
+ target_phys_addr_t crda = s->rdra +
+ (CSR_RCVRL(s) - CSR_RCVRC(s)) *
+ (BCR_SWSTYLE(s) ? 16 : 8 );
+ int nrdc = CSR_RCVRC(s)<=1 ? CSR_RCVRL(s) : CSR_RCVRC(s)-1;
+ target_phys_addr_t nrda = s->rdra +
+ (CSR_RCVRL(s) - nrdc) *
+ (BCR_SWSTYLE(s) ? 16 : 8 );
+ int nnrc = nrdc<=1 ? CSR_RCVRL(s) : nrdc-1;
+ target_phys_addr_t nnrd = s->rdra +
+ (CSR_RCVRL(s) - nnrc) *
+ (BCR_SWSTYLE(s) ? 16 : 8 );
+#endif
+
+ CHECK_RMD(PHYSADDR(s,crda), bad);
+ if (!bad) {
+ CHECK_RMD(PHYSADDR(s,nrda), bad);
+ if (bad || (nrda == crda)) nrda = 0;
+ CHECK_RMD(PHYSADDR(s,nnrd), bad);
+ if (bad || (nnrd == crda)) nnrd = 0;
+
+ s->csr[28] = crda & 0xffff;
+ s->csr[29] = crda >> 16;
+ s->csr[26] = nrda & 0xffff;
+ s->csr[27] = nrda >> 16;
+ s->csr[36] = nnrd & 0xffff;
+ s->csr[37] = nnrd >> 16;
+#ifdef PCNET_DEBUG
+ if (bad) {
+ printf("pcnet: BAD RMD RECORDS AFTER 0x%08x\n",
+ PHYSADDR(s,crda));
+ }
+ } else {
+ printf("pcnet: BAD RMD RDA=0x%08x\n", PHYSADDR(s,crda));
+#endif
+ }
+ }
+
+ if (CSR_CRDA(s)) {
+ struct pcnet_RMD rmd;
+ RMDLOAD(&rmd, PHYSADDR(s,CSR_CRDA(s)));
+ CSR_CRBC(s) = rmd.rmd1.bcnt;
+ CSR_CRST(s) = ((uint32_t *)&rmd)[1] >> 16;
+#ifdef PCNET_DEBUG_RMD_X
+ printf("CRDA=0x%08x CRST=0x%04x RCVRC=%d RMD1=0x%08x RMD2=0x%08x\n",
+ PHYSADDR(s,CSR_CRDA(s)), CSR_CRST(s), CSR_RCVRC(s),
+ ((uint32_t *)&rmd)[1], ((uint32_t *)&rmd)[2]);
+ PRINT_RMD(&rmd);
+#endif
+ } else {
+ CSR_CRBC(s) = CSR_CRST(s) = 0;
+ }
+
+ if (CSR_NRDA(s)) {
+ struct pcnet_RMD rmd;
+ RMDLOAD(&rmd, PHYSADDR(s,CSR_NRDA(s)));
+ CSR_NRBC(s) = rmd.rmd1.bcnt;
+ CSR_NRST(s) = ((uint32_t *)&rmd)[1] >> 16;
+ } else {
+ CSR_NRBC(s) = CSR_NRST(s) = 0;
+ }
+
+}
+
+static int pcnet_tdte_poll(PCNetState *s)
+{
+ s->csr[34] = s->csr[35] = 0;
+ if (s->tdra) {
+ target_phys_addr_t cxda = s->tdra +
+ (CSR_XMTRL(s) - CSR_XMTRC(s)) *
+ (BCR_SWSTYLE(s) ? 16 : 8 );
+ int bad = 0;
+ CHECK_TMD(PHYSADDR(s, cxda),bad);
+ if (!bad) {
+ if (CSR_CXDA(s) != cxda) {
+ s->csr[60] = s->csr[34];
+ s->csr[61] = s->csr[35];
+ s->csr[62] = CSR_CXBC(s);
+ s->csr[63] = CSR_CXST(s);
+ }
+ s->csr[34] = cxda & 0xffff;
+ s->csr[35] = cxda >> 16;
+#ifdef PCNET_DEBUG
+ } else {
+ printf("pcnet: BAD TMD XDA=0x%08x\n", PHYSADDR(s,cxda));
+#endif
+ }
+ }
+
+ if (CSR_CXDA(s)) {
+ struct pcnet_TMD tmd;
+
+ TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));
+
+ CSR_CXBC(s) = tmd.tmd1.bcnt;
+ CSR_CXST(s) = ((uint32_t *)&tmd)[1] >> 16;
+ } else {
+ CSR_CXBC(s) = CSR_CXST(s) = 0;
+ }
+
+ return !!(CSR_CXST(s) & 0x8000);
+}
+
+static int pcnet_can_receive(void *opaque)
+{
+ PCNetState *s = opaque;
+ if (CSR_STOP(s) || CSR_SPND(s))
+ return 0;
+
+ if (s->recv_pos > 0)
+ return 0;
+
+ return sizeof(s->buffer)-16;
+}
+
+static void pcnet_receive(void *opaque, const uint8_t *buf, int size)
+{
+ PCNetState *s = opaque;
+ int is_padr = 0, is_bcast = 0, is_ladr = 0;
+
+ if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size)
+ return;
+
+#ifdef PCNET_DEBUG
+ printf("pcnet_receive size=%d\n", size);
+#endif
+
+ if (CSR_PROM(s)
+ || (is_padr=padr_match(s, buf, size))
+ || (is_bcast=padr_bcast(s, buf, size))
+ || (is_ladr=ladr_match(s, buf, size))) {
+
+ pcnet_rdte_poll(s);
+
+ if (!(CSR_CRST(s) & 0x8000) && s->rdra) {
+ struct pcnet_RMD rmd;
+ int rcvrc = CSR_RCVRC(s)-1,i;
+ target_phys_addr_t nrda;
+ for (i = CSR_RCVRL(s)-1; i > 0; i--, rcvrc--) {
+ if (rcvrc <= 1)
+ rcvrc = CSR_RCVRL(s);
+ nrda = s->rdra +
+ (CSR_RCVRL(s) - rcvrc) *
+ (BCR_SWSTYLE(s) ? 16 : 8 );
+ RMDLOAD(&rmd, PHYSADDR(s,nrda));
+ if (rmd.rmd1.own) {
+#ifdef PCNET_DEBUG_RMD
+ printf("pcnet - scan buffer: RCVRC=%d PREV_RCVRC=%d\n",
+ rcvrc, CSR_RCVRC(s));
+#endif
+ CSR_RCVRC(s) = rcvrc;
+ pcnet_rdte_poll(s);
+ break;
+ }
+ }
+ }
+
+ if (!(CSR_CRST(s) & 0x8000)) {
+#ifdef PCNET_DEBUG_RMD
+ printf("pcnet - no buffer: RCVRC=%d\n", CSR_RCVRC(s));
+#endif
+ s->csr[0] |= 0x1000; /* Set MISS flag */
+ CSR_MISSC(s)++;
+ } else {
+ uint8_t *src = &s->buffer[8];
+ target_phys_addr_t crda = CSR_CRDA(s);
+ struct pcnet_RMD rmd;
+ int pktcount = 0;
+
+ memcpy(src, buf, size);
+
+ if (!CSR_ASTRP_RCV(s)) {
+ uint32_t fcs = ~0;
+#if 0
+ uint8_t *p = s->buffer;
+
+ ((uint32_t *)p)[0] = ((uint32_t *)p)[1] = 0xaaaaaaaa;
+ p[7] = 0xab;
+#else
+ uint8_t *p = src;
+#endif
+
+ while (size < 46) {
+ src[size++] = 0;
+ }
+
+ while (p != &src[size]) {
+ CRC(fcs, *p++);
+ }
+ ((uint32_t *)&src[size])[0] = htonl(fcs);
+ size += 4; /* FCS at end of packet */
+ } else size += 4;
+
+#ifdef PCNET_DEBUG_MATCH
+ PRINT_PKTHDR(buf);
+#endif
+
+ RMDLOAD(&rmd, PHYSADDR(s,crda));
+ /*if (!CSR_LAPPEN(s))*/
+ rmd.rmd1.stp = 1;
+
+#define PCNET_RECV_STORE() do { \
+ int count = MIN(4096 - rmd.rmd1.bcnt,size); \
+ target_phys_addr_t rbadr = PHYSADDR(s, rmd.rmd0.rbadr); \
+ cpu_physical_memory_write(rbadr, src, count); \
+ cpu_physical_memory_set_dirty(rbadr); \
+ cpu_physical_memory_set_dirty(rbadr+count); \
+ src += count; size -= count; \
+ rmd.rmd2.mcnt = count; rmd.rmd1.own = 0; \
+ RMDSTORE(&rmd, PHYSADDR(s,crda)); \
+ pktcount++; \
+} while (0)
+
+ PCNET_RECV_STORE();
+ if ((size > 0) && CSR_NRDA(s)) {
+ target_phys_addr_t nrda = CSR_NRDA(s);
+ RMDLOAD(&rmd, PHYSADDR(s,nrda));
+ if (rmd.rmd1.own) {
+ crda = nrda;
+ PCNET_RECV_STORE();
+ if ((size > 0) && (nrda=CSR_NNRD(s))) {
+ RMDLOAD(&rmd, PHYSADDR(s,nrda));
+ if (rmd.rmd1.own) {
+ crda = nrda;
+ PCNET_RECV_STORE();
+ }
+ }
+ }
+ }
+
+#undef PCNET_RECV_STORE
+
+ RMDLOAD(&rmd, PHYSADDR(s,crda));
+ if (size == 0) {
+ rmd.rmd1.enp = 1;
+ rmd.rmd1.pam = !CSR_PROM(s) && is_padr;
+ rmd.rmd1.lafm = !CSR_PROM(s) && is_ladr;
+ rmd.rmd1.bam = !CSR_PROM(s) && is_bcast;
+ } else {
+ rmd.rmd1.oflo = 1;
+ rmd.rmd1.buff = 1;
+ rmd.rmd1.err = 1;
+ }
+ RMDSTORE(&rmd, PHYSADDR(s,crda));
+ s->csr[0] |= 0x0400;
+
+#ifdef PCNET_DEBUG
+ printf("RCVRC=%d CRDA=0x%08x BLKS=%d\n",
+ CSR_RCVRC(s), PHYSADDR(s,CSR_CRDA(s)), pktcount);
+#endif
+#ifdef PCNET_DEBUG_RMD
+ PRINT_RMD(&rmd);
+#endif
+
+ while (pktcount--) {
+ if (CSR_RCVRC(s) <= 1)
+ CSR_RCVRC(s) = CSR_RCVRL(s);
+ else
+ CSR_RCVRC(s)--;
+ }
+
+ pcnet_rdte_poll(s);
+
+ }
+ }
+
+ pcnet_poll(s);
+ pcnet_update_irq(s);
+}
+
+static void pcnet_transmit(PCNetState *s)
+{
+ target_phys_addr_t xmit_cxda = 0;
+ int count = CSR_XMTRL(s)-1;
+ s->xmit_pos = -1;
+
+ if (!CSR_TXON(s)) {
+ s->csr[0] &= ~0x0008;
+ return;
+ }
+
+ txagain:
+ if (pcnet_tdte_poll(s)) {
+ struct pcnet_TMD tmd;
+
+ TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));
+
+#ifdef PCNET_DEBUG_TMD
+ printf(" TMDLOAD 0x%08x\n", PHYSADDR(s,CSR_CXDA(s)));
+ PRINT_TMD(&tmd);
+#endif
+ if (tmd.tmd1.stp) {
+ s->xmit_pos = 0;
+ if (!tmd.tmd1.enp) {
+ cpu_physical_memory_read(PHYSADDR(s, tmd.tmd0.tbadr),
+ s->buffer, 4096 - tmd.tmd1.bcnt);
+ s->xmit_pos += 4096 - tmd.tmd1.bcnt;
+ }
+ xmit_cxda = PHYSADDR(s,CSR_CXDA(s));
+ }
+ if (tmd.tmd1.enp && (s->xmit_pos >= 0)) {
+ cpu_physical_memory_read(PHYSADDR(s, tmd.tmd0.tbadr),
+ s->buffer + s->xmit_pos, 4096 - tmd.tmd1.bcnt);
+ s->xmit_pos += 4096 - tmd.tmd1.bcnt;
+
+ tmd.tmd1.own = 0;
+ TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
+
+#ifdef PCNET_DEBUG
+ printf("pcnet_transmit size=%d\n", s->xmit_pos);
+#endif
+ if (CSR_LOOP(s))
+ pcnet_receive(s, s->buffer, s->xmit_pos);
+ else
+ qemu_send_packet(s->nd, s->buffer, s->xmit_pos);
+
+ s->csr[0] &= ~0x0008; /* clear TDMD */
+ s->csr[4] |= 0x0004; /* set TXSTRT */
+ s->xmit_pos = -1;
+ } else {
+ tmd.tmd1.own = 0;
+ TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
+ }
+ if (!CSR_TOKINTD(s) || (CSR_LTINTEN(s) && tmd.tmd1.ltint))
+ s->csr[0] |= 0x0200; /* set TINT */
+
+ if (CSR_XMTRC(s)<=1)
+ CSR_XMTRC(s) = CSR_XMTRL(s);
+ else
+ CSR_XMTRC(s)--;
+ if (count--)
+ goto txagain;
+
+ } else
+ if (s->xmit_pos >= 0) {
+ struct pcnet_TMD tmd;
+ TMDLOAD(&tmd, PHYSADDR(s,xmit_cxda));
+ tmd.tmd2.buff = tmd.tmd2.uflo = tmd.tmd1.err = 1;
+ tmd.tmd1.own = 0;
+ TMDSTORE(&tmd, PHYSADDR(s,xmit_cxda));
+ s->csr[0] |= 0x0200; /* set TINT */
+ if (!CSR_DXSUFLO(s)) {
+ s->csr[0] &= ~0x0010;
+ } else
+ if (count--)
+ goto txagain;
+ }
+}
+
+static void pcnet_poll(PCNetState *s)
+{
+ if (CSR_RXON(s)) {
+ pcnet_rdte_poll(s);
+ }
+
+ if (CSR_TDMD(s) ||
+ (CSR_TXON(s) && !CSR_DPOLL(s) && pcnet_tdte_poll(s)))
+ pcnet_transmit(s);
+}
+
+static void pcnet_poll_timer(void *opaque)
+{
+ PCNetState *s = opaque;
+
+ qemu_del_timer(s->poll_timer);
+
+ if (CSR_TDMD(s)) {
+ pcnet_transmit(s);
+ }
+
+ pcnet_update_irq(s);
+
+ if (!CSR_STOP(s) && !CSR_SPND(s) && !CSR_DPOLL(s)) {
+ uint64_t now = qemu_get_clock(vm_clock) * 33;
+ if (!s->timer || !now)
+ s->timer = now;
+ else {
+ uint64_t t = now - s->timer + CSR_POLL(s);
+ if (t > 0xffffLL) {
+ pcnet_poll(s);
+ CSR_POLL(s) = CSR_PINT(s);
+ } else
+ CSR_POLL(s) = t;
+ }
+ qemu_mod_timer(s->poll_timer,
+ pcnet_get_next_poll_time(s,qemu_get_clock(vm_clock)));
+ }
+}
+
+
+static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value)
+{
+ uint16_t val = new_value;
+#ifdef PCNET_DEBUG_CSR
+ printf("pcnet_csr_writew rap=%d val=0x%04x\n", rap, val);
+#endif
+ switch (rap) {
+ case 0:
+ s->csr[0] &= ~(val & 0x7f00); /* Clear any interrupt flags */
+
+ s->csr[0] = (s->csr[0] & ~0x0040) | (val & 0x0048);
+
+ val = (val & 0x007f) | (s->csr[0] & 0x7f00);
+
+ /* IFF STOP, STRT and INIT are set, clear STRT and INIT */
+ if ((val&7) == 7)
+ val &= ~3;
+
+ if (!CSR_STOP(s) && (val & 4))
+ pcnet_stop(s);
+
+ if (!CSR_INIT(s) && (val & 1))
+ pcnet_init(s);
+
+ if (!CSR_STRT(s) && (val & 2))
+ pcnet_start(s);
+
+ if (CSR_TDMD(s))
+ pcnet_transmit(s);
+
+ return;
+ case 1:
+ case 2:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 18: /* CRBAL */
+ case 19: /* CRBAU */
+ case 20: /* CXBAL */
+ case 21: /* CXBAU */
+ case 22: /* NRBAU */
+ case 23: /* NRBAU */
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 30:
+ case 31:
+ case 32:
+ case 33:
+ case 34:
+ case 35:
+ case 36:
+ case 37:
+ case 38:
+ case 39:
+ case 40: /* CRBC */
+ case 41:
+ case 42: /* CXBC */
+ case 43:
+ case 44:
+ case 45:
+ case 46: /* POLL */
+ case 47: /* POLLINT */
+ case 72:
+ case 74:
+ case 76: /* RCVRL */
+ case 78: /* XMTRL */
+ case 112:
+ if (CSR_STOP(s) || CSR_SPND(s))
+ break;
+ return;
+ case 3:
+ break;
+ case 4:
+ s->csr[4] &= ~(val & 0x026a);
+ val &= ~0x026a; val |= s->csr[4] & 0x026a;
+ break;
+ case 5:
+ s->csr[5] &= ~(val & 0x0a90);
+ val &= ~0x0a90; val |= s->csr[5] & 0x0a90;
+ break;
+ case 16:
+ pcnet_csr_writew(s,1,val);
+ return;
+ case 17:
+ pcnet_csr_writew(s,2,val);
+ return;
+ case 58:
+ pcnet_bcr_writew(s,BCR_SWS,val);
+ break;
+ default:
+ return;
+ }
+ s->csr[rap] = val;
+}
+
+static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap)
+{
+ uint32_t val;
+ switch (rap) {
+ case 0:
+ pcnet_update_irq(s);
+ val = s->csr[0];
+ val |= (val & 0x7800) ? 0x8000 : 0;
+ break;
+ case 16:
+ return pcnet_csr_readw(s,1);
+ case 17:
+ return pcnet_csr_readw(s,2);
+ case 58:
+ return pcnet_bcr_readw(s,BCR_SWS);
+ case 88:
+ val = s->csr[89];
+ val <<= 16;
+ val |= s->csr[88];
+ break;
+ default:
+ val = s->csr[rap];
+ }
+#ifdef PCNET_DEBUG_CSR
+ printf("pcnet_csr_readw rap=%d val=0x%04x\n", rap, val);
+#endif
+ return val;
+}
+
+static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val)
+{
+ rap &= 127;
+#ifdef PCNET_DEBUG_BCR
+ printf("pcnet_bcr_writew rap=%d val=0x%04x\n", rap, val);
+#endif
+ switch (rap) {
+ case BCR_SWS:
+ if (!(CSR_STOP(s) || CSR_SPND(s)))
+ return;
+ val &= ~0x0300;
+ switch (val & 0x00ff) {
+ case 0:
+ val |= 0x0200;
+ break;
+ case 1:
+ val |= 0x0100;
+ break;
+ case 2:
+ case 3:
+ val |= 0x0300;
+ break;
+ default:
+ printf("Bad SWSTYLE=0x%02x\n", val & 0xff);
+ val = 0x0200;
+ break;
+ }
+#ifdef PCNET_DEBUG
+ printf("BCR_SWS=0x%04x\n", val);
+#endif
+ case BCR_LNKST:
+ case BCR_LED1:
+ case BCR_LED2:
+ case BCR_LED3:
+ case BCR_MC:
+ case BCR_FDC:
+ case BCR_BSBC:
+ case BCR_EECAS:
+ case BCR_PLAT:
+ s->bcr[rap] = val;
+ break;
+ default:
+ break;
+ }
+}
+
+static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap)
+{
+ uint32_t val;
+ rap &= 127;
+ switch (rap) {
+ case BCR_LNKST:
+ case BCR_LED1:
+ case BCR_LED2:
+ case BCR_LED3:
+ val = s->bcr[rap] & ~0x8000;
+ val |= (val & 0x017f & s->lnkst) ? 0x8000 : 0;
+ break;
+ default:
+ val = rap < 32 ? s->bcr[rap] : 0;
+ break;
+ }
+#ifdef PCNET_DEBUG_BCR
+ printf("pcnet_bcr_readw rap=%d val=0x%04x\n", rap, val);
+#endif
+ return val;
+}
+
+static void pcnet_h_reset(PCNetState *s)
+{
+ int i;
+ uint16_t checksum;
+
+ /* Initialize the PROM */
+
+ memcpy(s->prom, s->nd->macaddr, 6);
+ s->prom[12] = s->prom[13] = 0x00;
+ s->prom[14] = s->prom[15] = 0x57;
+
+ for (i = 0,checksum = 0; i < 16; i++)
+ checksum += s->prom[i];
+ *(uint16_t *)&s->prom[12] = cpu_to_le16(checksum);
+
+
+ s->bcr[BCR_MSRDA] = 0x0005;
+ s->bcr[BCR_MSWRA] = 0x0005;
+ s->bcr[BCR_MC ] = 0x0002;
+ s->bcr[BCR_LNKST] = 0x00c0;
+ s->bcr[BCR_LED1 ] = 0x0084;
+ s->bcr[BCR_LED2 ] = 0x0088;
+ s->bcr[BCR_LED3 ] = 0x0090;
+ s->bcr[BCR_FDC ] = 0x0000;
+ s->bcr[BCR_BSBC ] = 0x9001;
+ s->bcr[BCR_EECAS] = 0x0002;
+ s->bcr[BCR_SWS ] = 0x0200;
+ s->bcr[BCR_PLAT ] = 0xff06;
+
+ pcnet_s_reset(s);
+}
+
+static void pcnet_aprom_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+ PCNetState *s = opaque;
+#ifdef PCNET_DEBUG
+ printf("pcnet_aprom_writeb addr=0x%08x val=0x%02x\n", addr, val);
+#endif
+ /* Check APROMWE bit to enable write access */
+ if (pcnet_bcr_readw(s,2) & 0x80)
+ s->prom[addr & 15] = val;
+}
+
+static uint32_t pcnet_aprom_readb(void *opaque, uint32_t addr)
+{
+ PCNetState *s = opaque;
+ uint32_t val = s->prom[addr &= 15];
+#ifdef PCNET_DEBUG
+ printf("pcnet_aprom_readb addr=0x%08x val=0x%02x\n", addr, val);
+#endif
+ return val;
+}
+
+static void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
+{
+ PCNetState *s = opaque;
+ pcnet_poll_timer(s);
+#ifdef PCNET_DEBUG_IO
+ printf("pcnet_ioport_writew addr=0x%08x val=0x%04x\n", addr, val);
+#endif
+ if (!BCR_DWIO(s)) {
+ switch (addr & 0x0f) {
+ case 0x00: /* RDP */
+ pcnet_csr_writew(s, s->rap, val);
+ break;
+ case 0x02:
+ s->rap = val & 0x7f;
+ break;
+ case 0x06:
+ pcnet_bcr_writew(s, s->rap, val);
+ break;
+ }
+ }
+ pcnet_update_irq(s);
+}
+
+static uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr)
+{
+ PCNetState *s = opaque;
+ uint32_t val = -1;
+ pcnet_poll_timer(s);
+ if (!BCR_DWIO(s)) {
+ switch (addr & 0x0f) {
+ case 0x00: /* RDP */
+ val = pcnet_csr_readw(s, s->rap);
+ break;
+ case 0x02:
+ val = s->rap;
+ break;
+ case 0x04:
+ pcnet_s_reset(s);
+ val = 0;
+ break;
+ case 0x06:
+ val = pcnet_bcr_readw(s, s->rap);
+ break;
+ }
+ }
+ pcnet_update_irq(s);
+#ifdef PCNET_DEBUG_IO
+ printf("pcnet_ioport_readw addr=0x%08x val=0x%04x\n", addr, val & 0xffff);
+#endif
+ return val;
+}
+
+static void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
+{
+ PCNetState *s = opaque;
+ pcnet_poll_timer(s);
+#ifdef PCNET_DEBUG_IO
+ printf("pcnet_ioport_writel addr=0x%08x val=0x%08x\n", addr, val);
+#endif
+ if (BCR_DWIO(s)) {
+ switch (addr & 0x0f) {
+ case 0x00: /* RDP */
+ pcnet_csr_writew(s, s->rap, val & 0xffff);
+ break;
+ case 0x04:
+ s->rap = val & 0x7f;
+ break;
+ case 0x0c:
+ pcnet_bcr_writew(s, s->rap, val & 0xffff);
+ break;
+ }
+ } else
+ if ((addr & 0x0f) == 0) {
+ /* switch device to dword i/o mode */
+ pcnet_bcr_writew(s, BCR_BSBC, pcnet_bcr_readw(s, BCR_BSBC) | 0x0080);
+#ifdef PCNET_DEBUG_IO
+ printf("device switched into dword i/o mode\n");
+#endif
+ }
+ pcnet_update_irq(s);
+}
+
+static uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr)
+{
+ PCNetState *s = opaque;
+ uint32_t val = -1;
+ pcnet_poll_timer(s);
+ if (BCR_DWIO(s)) {
+ switch (addr & 0x0f) {
+ case 0x00: /* RDP */
+ val = pcnet_csr_readw(s, s->rap);
+ break;
+ case 0x04:
+ val = s->rap;
+ break;
+ case 0x08:
+ pcnet_s_reset(s);
+ val = 0;
+ break;
+ case 0x0c:
+ val = pcnet_bcr_readw(s, s->rap);
+ break;
+ }
+ }
+ pcnet_update_irq(s);
+#ifdef PCNET_DEBUG_IO
+ printf("pcnet_ioport_readl addr=0x%08x val=0x%08x\n", addr, val);
+#endif
+ return val;
+}
+
+static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num,
+ uint32_t addr, uint32_t size, int type)
+{
+ PCNetState *d = (PCNetState *)pci_dev;
+
+#ifdef PCNET_DEBUG_IO
+ printf("pcnet_ioport_map addr=0x%04x size=0x%04x\n", addr, size);
+#endif
+
+ register_ioport_write(addr, 16, 1, pcnet_aprom_writeb, d);
+ register_ioport_read(addr, 16, 1, pcnet_aprom_readb, d);
+
+ register_ioport_write(addr + 0x10, 0x10, 2, pcnet_ioport_writew, d);
+ register_ioport_read(addr + 0x10, 0x10, 2, pcnet_ioport_readw, d);
+ register_ioport_write(addr + 0x10, 0x10, 4, pcnet_ioport_writel, d);
+ register_ioport_read(addr + 0x10, 0x10, 4, pcnet_ioport_readl, d);
+}
+
+static void pcnet_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t
val)
+{
+ PCNetState *d = opaque;
+#ifdef PCNET_DEBUG_IO
+ printf("pcnet_mmio_writeb addr=0x%08x val=0x%02x\n", addr, val);
+#endif
+ if (!(addr & 0x10))
+ pcnet_aprom_writeb(d, addr & 0x0f, val);
+}
+
+static uint32_t pcnet_mmio_readb(void *opaque, target_phys_addr_t addr)
+{
+ PCNetState *d = opaque;
+ uint32_t val = -1;
+ if (!(addr & 0x10))
+ val = pcnet_aprom_readb(d, addr & 0x0f);
+#ifdef PCNET_DEBUG_IO
+ printf("pcnet_mmio_readb addr=0x%08x val=0x%02x\n", addr, val & 0xff);
+#endif
+ return val;
+}
+
+static void pcnet_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t
val)
+{
+ PCNetState *d = opaque;
+#ifdef PCNET_DEBUG_IO
+ printf("pcnet_mmio_writew addr=0x%08x val=0x%04x\n", addr, val);
+#endif
+ if (addr & 0x10)
+ pcnet_ioport_writew(d, addr & 0x0f, val);
+ else {
+ addr &= 0x0f;
+ pcnet_aprom_writeb(d, addr, val & 0xff);
+ pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
+ }
+}
+
+static uint32_t pcnet_mmio_readw(void *opaque, target_phys_addr_t addr)
+{
+ PCNetState *d = opaque;
+ uint32_t val = -1;
+ if (addr & 0x10)
+ val = pcnet_ioport_readw(d, addr & 0x0f);
+ else {
+ addr &= 0x0f;
+ val = pcnet_aprom_readb(d, addr+1);
+ val <<= 8;
+ val |= pcnet_aprom_readb(d, addr);
+ }
+#ifdef PCNET_DEBUG_IO
+ printf("pcnet_mmio_readw addr=0x%08x val = 0x%04x\n", addr, val & 0xffff);
+#endif
+ return val;
+}
+
+static void pcnet_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t
val)
+{
+ PCNetState *d = opaque;
+#ifdef PCNET_DEBUG_IO
+ printf("pcnet_mmio_writel addr=0x%08x val=0x%08x\n", addr, val);
+#endif
+ if (addr & 0x10)
+ pcnet_ioport_writel(d, addr & 0x0f, val);
+ else {
+ addr &= 0x0f;
+ pcnet_aprom_writeb(d, addr, val & 0xff);
+ pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
+ pcnet_aprom_writeb(d, addr+2, (val & 0xff0000) >> 16);
+ pcnet_aprom_writeb(d, addr+3, (val & 0xff000000) >> 24);
+ }
+}
+
+static uint32_t pcnet_mmio_readl(void *opaque, target_phys_addr_t addr)
+{
+ PCNetState *d = opaque;
+ uint32_t val;
+ if (addr & 0x10)
+ val = pcnet_ioport_readl(d, addr & 0x0f);
+ else {
+ addr &= 0x0f;
+ val = pcnet_aprom_readb(d, addr+3);
+ val <<= 8;
+ val |= pcnet_aprom_readb(d, addr+2);
+ val <<= 8;
+ val |= pcnet_aprom_readb(d, addr+1);
+ val <<= 8;
+ val |= pcnet_aprom_readb(d, addr);
+ }
+#ifdef PCNET_DEBUG_IO
+ printf("pcnet_mmio_readl addr=0x%08x val=0x%08x\n", addr, val);
+#endif
+ return val;
+}
+
+
+static CPUWriteMemoryFunc *pcnet_mmio_write[] = {
+ (CPUWriteMemoryFunc *)&pcnet_mmio_writeb,
+ (CPUWriteMemoryFunc *)&pcnet_mmio_writew,
+ (CPUWriteMemoryFunc *)&pcnet_mmio_writel
+};
+
+static CPUReadMemoryFunc *pcnet_mmio_read[] = {
+ (CPUReadMemoryFunc *)&pcnet_mmio_readb,
+ (CPUReadMemoryFunc *)&pcnet_mmio_readw,
+ (CPUReadMemoryFunc *)&pcnet_mmio_readl
+};
+
+static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num,
+ uint32_t addr, uint32_t size, int type)
+{
+ PCNetState *d = (PCNetState *)pci_dev;
+
+#ifdef PCNET_DEBUG_IO
+ printf("pcnet_ioport_map addr=0x%08x 0x%08x\n", addr, size);
+#endif
+
+ cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->mmio_io_addr);
+}
+
+void pci_pcnet_init(PCIBus *bus, NetDriverState *nd)
+{
+ PCNetState *d;
+ uint8_t *pci_conf;
+
+#if 0
+ printf("sizeof(RMD)=%d, sizeof(TMD)=%d\n",
+ sizeof(struct pcnet_RMD), sizeof(struct pcnet_TMD));
+#endif
+
+ d = (PCNetState *)pci_register_device(bus, "PCNet", sizeof(PCNetState),
+ -1, NULL, NULL);
+
+ pci_conf = d->dev.config;
+
+ *(uint16_t *)&pci_conf[0x00] = cpu_to_le16(0x1022);
+ *(uint16_t *)&pci_conf[0x02] = cpu_to_le16(0x2000);
+ *(uint16_t *)&pci_conf[0x04] = cpu_to_le16(0x0007);
+ *(uint16_t *)&pci_conf[0x06] = cpu_to_le16(0x0280);
+ pci_conf[0x08] = 0x10;
+ pci_conf[0x09] = 0x00;
+ pci_conf[0x0a] = 0x00; // ethernet network controller
+ pci_conf[0x0b] = 0x02;
+ pci_conf[0x0e] = 0x00; // header_type
+
+ *(uint32_t *)&pci_conf[0x10] = cpu_to_le32(0x00000001);
+ *(uint32_t *)&pci_conf[0x14] = cpu_to_le32(0x00000000);
+
+ pci_conf[0x3d] = 1; // interrupt pin 0
+ pci_conf[0x3e] = 0x06;
+ pci_conf[0x3f] = 0xff;
+
+ /* Handler for memory-mapped I/O */
+ d->mmio_io_addr =
+ cpu_register_io_memory(0, pcnet_mmio_read, pcnet_mmio_write, d);
+
+ pci_register_io_region((PCIDevice *)d, 0, PCNET_IOPORT_SIZE,
+ PCI_ADDRESS_SPACE_IO, pcnet_ioport_map);
+
+ pci_register_io_region((PCIDevice *)d, 1, PCNET_PNPMMIO_SIZE,
+ PCI_ADDRESS_SPACE_MEM, pcnet_mmio_map);
+
+ d->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, d);
+
+ d->nd = nd;
+
+ pcnet_h_reset(d);
+
+ qemu_add_read_packet(nd, pcnet_can_receive, pcnet_receive, d);
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/ioemu/hw/pcnet.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/ioemu/hw/pcnet.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,583 @@
+/*
+ * QEMU AMD PC-Net II (Am79C970A) emulation
+ *
+ * Copyright (c) 2004 Antony T Curtis
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/* This software was written to be compatible with the specification:
+ * AMD Am79C970A PCnet-PCI II Ethernet Controller Data-Sheet
+ * AMD Publication# 19436 Rev:E Amendment/0 Issue Date: June 2000
+ */
+
+#ifdef __GNUC__
+#define PACKED(A) A __attribute__ ((packed))
+#else
+#error FixMe
+#endif
+
+/* BUS CONFIGURATION REGISTERS */
+#define BCR_MSRDA 0
+#define BCR_MSWRA 1
+#define BCR_MC 2
+#define BCR_LNKST 4
+#define BCR_LED1 5
+#define BCR_LED2 6
+#define BCR_LED3 7
+#define BCR_FDC 9
+#define BCR_BSBC 18
+#define BCR_EECAS 19
+#define BCR_SWS 20
+#define BCR_PLAT 22
+
+#define BCR_DWIO(S) !!((S)->bcr[BCR_BSBC] & 0x0080)
+#define BCR_SSIZE32(S) !!((S)->bcr[BCR_SWS ] & 0x0100)
+#define BCR_SWSTYLE(S) ((S)->bcr[BCR_SWS ] & 0x00FF)
+
+#define CSR_INIT(S) !!(((S)->csr[0])&0x0001)
+#define CSR_STRT(S) !!(((S)->csr[0])&0x0002)
+#define CSR_STOP(S) !!(((S)->csr[0])&0x0004)
+#define CSR_TDMD(S) !!(((S)->csr[0])&0x0008)
+#define CSR_TXON(S) !!(((S)->csr[0])&0x0010)
+#define CSR_RXON(S) !!(((S)->csr[0])&0x0020)
+#define CSR_INEA(S) !!(((S)->csr[0])&0x0040)
+#define CSR_LAPPEN(S) !!(((S)->csr[3])&0x0020)
+#define CSR_DXSUFLO(S) !!(((S)->csr[3])&0x0040)
+#define CSR_ASTRP_RCV(S) !!(((S)->csr[4])&0x0800)
+#define CSR_DPOLL(S) !!(((S)->csr[4])&0x1000)
+#define CSR_SPND(S) !!(((S)->csr[5])&0x0001)
+#define CSR_LTINTEN(S) !!(((S)->csr[5])&0x4000)
+#define CSR_TOKINTD(S) !!(((S)->csr[5])&0x8000)
+#define CSR_DRX(S) !!(((S)->csr[15])&0x0001)
+#define CSR_DTX(S) !!(((S)->csr[15])&0x0002)
+#define CSR_LOOP(S) !!(((S)->csr[15])&0x0004)
+#define CSR_DRCVPA(S) !!(((S)->csr[15])&0x2000)
+#define CSR_DRCVBC(S) !!(((S)->csr[15])&0x4000)
+#define CSR_PROM(S) !!(((S)->csr[15])&0x8000)
+
+#define CSR_CRBC(S) ((S)->csr[40])
+#define CSR_CRST(S) ((S)->csr[41])
+#define CSR_CXBC(S) ((S)->csr[42])
+#define CSR_CXST(S) ((S)->csr[43])
+#define CSR_NRBC(S) ((S)->csr[44])
+#define CSR_NRST(S) ((S)->csr[45])
+#define CSR_POLL(S) ((S)->csr[46])
+#define CSR_PINT(S) ((S)->csr[47])
+#define CSR_RCVRC(S) ((S)->csr[72])
+#define CSR_XMTRC(S) ((S)->csr[74])
+#define CSR_RCVRL(S) ((S)->csr[76])
+#define CSR_XMTRL(S) ((S)->csr[78])
+#define CSR_MISSC(S) ((S)->csr[112])
+
+#define CSR_IADR(S) ((S)->csr[ 1] | ((S)->csr[ 2] << 16))
+#define CSR_CRBA(S) ((S)->csr[18] | ((S)->csr[19] << 16))
+#define CSR_CXBA(S) ((S)->csr[20] | ((S)->csr[21] << 16))
+#define CSR_NRBA(S) ((S)->csr[22] | ((S)->csr[23] << 16))
+#define CSR_BADR(S) ((S)->csr[24] | ((S)->csr[25] << 16))
+#define CSR_NRDA(S) ((S)->csr[26] | ((S)->csr[27] << 16))
+#define CSR_CRDA(S) ((S)->csr[28] | ((S)->csr[29] << 16))
+#define CSR_BADX(S) ((S)->csr[30] | ((S)->csr[31] << 16))
+#define CSR_NXDA(S) ((S)->csr[32] | ((S)->csr[33] << 16))
+#define CSR_CXDA(S) ((S)->csr[34] | ((S)->csr[35] << 16))
+#define CSR_NNRD(S) ((S)->csr[36] | ((S)->csr[37] << 16))
+#define CSR_NNXD(S) ((S)->csr[38] | ((S)->csr[39] << 16))
+#define CSR_PXDA(S) ((S)->csr[60] | ((S)->csr[61] << 16))
+#define CSR_NXBA(S) ((S)->csr[64] | ((S)->csr[65] << 16))
+
+#define PHYSADDR(S,A) \
+ (BCR_SSIZE32(S) ? (A) : (A) | ((0xff00 & (uint32_t)(s)->csr[2])<<16))
+
+struct pcnet_initblk16 {
+ uint16_t mode;
+ uint16_t padr1;
+ uint16_t padr2;
+ uint16_t padr3;
+ uint16_t ladrf1;
+ uint16_t ladrf2;
+ uint16_t ladrf3;
+ uint16_t ladrf4;
+ unsigned PACKED(rdra:24);
+ unsigned PACKED(res1:5);
+ unsigned PACKED(rlen:3);
+ unsigned PACKED(tdra:24);
+ unsigned PACKED(res2:5);
+ unsigned PACKED(tlen:3);
+};
+
+struct pcnet_initblk32 {
+ uint16_t mode;
+ unsigned PACKED(res1:4);
+ unsigned PACKED(rlen:4);
+ unsigned PACKED(res2:4);
+ unsigned PACKED(tlen:4);
+ uint16_t padr1;
+ uint16_t padr2;
+ uint16_t padr3;
+ uint16_t _res;
+ uint16_t ladrf1;
+ uint16_t ladrf2;
+ uint16_t ladrf3;
+ uint16_t ladrf4;
+ uint32_t rdra;
+ uint32_t tdra;
+};
+
+struct pcnet_TMD {
+ struct {
+ unsigned tbadr:32;
+ } tmd0;
+ struct {
+ unsigned PACKED(bcnt:12), PACKED(ones:4), PACKED(res:7), PACKED(bpe:1);
+ unsigned PACKED(enp:1), PACKED(stp:1), PACKED(def:1), PACKED(one:1);
+ unsigned PACKED(ltint:1), PACKED(nofcs:1), PACKED(err:1),
PACKED(own:1);
+ } tmd1;
+ struct {
+ unsigned PACKED(trc:4), PACKED(res:12);
+ unsigned PACKED(tdr:10), PACKED(rtry:1), PACKED(lcar:1);
+ unsigned PACKED(lcol:1), PACKED(exdef:1), PACKED(uflo:1),
PACKED(buff:1);
+ } tmd2;
+ struct {
+ unsigned res:32;
+ } tmd3;
+};
+
+struct pcnet_RMD {
+ struct {
+ unsigned rbadr:32;
+ } rmd0;
+ struct {
+ unsigned PACKED(bcnt:12), PACKED(ones:4), PACKED(res:4);
+ unsigned PACKED(bam:1), PACKED(lafm:1), PACKED(pam:1), PACKED(bpe:1);
+ unsigned PACKED(enp:1), PACKED(stp:1), PACKED(buff:1), PACKED(crc:1);
+ unsigned PACKED(oflo:1), PACKED(fram:1), PACKED(err:1), PACKED(own:1);
+ } rmd1;
+ struct {
+ unsigned PACKED(mcnt:12), PACKED(zeros:4);
+ unsigned PACKED(rpc:8), PACKED(rcc:8);
+ } rmd2;
+ struct {
+ unsigned res:32;
+ } rmd3;
+};
+
+
+#define PRINT_TMD(T) printf( \
+ "TMD0 : TBADR=0x%08x\n" \
+ "TMD1 : OWN=%d, ERR=%d, FCS=%d, LTI=%d, " \
+ "ONE=%d, DEF=%d, STP=%d, ENP=%d,\n" \
+ " BPE=%d, BCNT=%d\n" \
+ "TMD2 : BUF=%d, UFL=%d, EXD=%d, LCO=%d, " \
+ "LCA=%d, RTR=%d,\n" \
+ " TDR=%d, TRC=%d\n", \
+ (T)->tmd0.tbadr, \
+ (T)->tmd1.own, (T)->tmd1.err, (T)->tmd1.nofcs, \
+ (T)->tmd1.ltint, (T)->tmd1.one, (T)->tmd1.def, \
+ (T)->tmd1.stp, (T)->tmd1.enp, (T)->tmd1.bpe, \
+ 4096-(T)->tmd1.bcnt, \
+ (T)->tmd2.buff, (T)->tmd2.uflo, (T)->tmd2.exdef,\
+ (T)->tmd2.lcol, (T)->tmd2.lcar, (T)->tmd2.rtry, \
+ (T)->tmd2.tdr, (T)->tmd2.trc)
+
+#define PRINT_RMD(R) printf( \
+ "RMD0 : RBADR=0x%08x\n" \
+ "RMD1 : OWN=%d, ERR=%d, FRAM=%d, OFLO=%d, " \
+ "CRC=%d, BUFF=%d, STP=%d, ENP=%d,\n " \
+ "BPE=%d, PAM=%d, LAFM=%d, BAM=%d, ONES=%d, BCNT=%d\n" \
+ "RMD2 : RCC=%d, RPC=%d, MCNT=%d, ZEROS=%d\n", \
+ (R)->rmd0.rbadr, \
+ (R)->rmd1.own, (R)->rmd1.err, (R)->rmd1.fram, \
+ (R)->rmd1.oflo, (R)->rmd1.crc, (R)->rmd1.buff, \
+ (R)->rmd1.stp, (R)->rmd1.enp, (R)->rmd1.bpe, \
+ (R)->rmd1.pam, (R)->rmd1.lafm, (R)->rmd1.bam, \
+ (R)->rmd1.ones, 4096-(R)->rmd1.bcnt, \
+ (R)->rmd2.rcc, (R)->rmd2.rpc, (R)->rmd2.mcnt, \
+ (R)->rmd2.zeros)
+
+static inline void pcnet_tmd_load(PCNetState *s, struct pcnet_TMD *tmd,
target_phys_addr_t addr)
+{
+ if (!BCR_SWSTYLE(s)) {
+ uint16_t xda[4];
+ cpu_physical_memory_read(addr,
+ (void *)&xda[0], sizeof(xda));
+ ((uint32_t *)tmd)[0] = (xda[0]&0xffff) |
+ ((xda[1]&0x00ff) << 16);
+ ((uint32_t *)tmd)[1] = (xda[2]&0xffff)|
+ ((xda[1] & 0xff00) << 16);
+ ((uint32_t *)tmd)[2] =
+ (xda[3] & 0xffff) << 16;
+ ((uint32_t *)tmd)[3] = 0;
+ }
+ else
+ if (BCR_SWSTYLE(s) != 3)
+ cpu_physical_memory_read(addr, (void *)tmd, 16);
+ else {
+ uint32_t xda[4];
+ cpu_physical_memory_read(addr,
+ (void *)&xda[0], sizeof(xda));
+ ((uint32_t *)tmd)[0] = xda[2];
+ ((uint32_t *)tmd)[1] = xda[1];
+ ((uint32_t *)tmd)[2] = xda[0];
+ ((uint32_t *)tmd)[3] = xda[3];
+ }
+}
+
+static inline void pcnet_tmd_store(PCNetState *s, struct pcnet_TMD *tmd,
target_phys_addr_t addr)
+{
+ cpu_physical_memory_set_dirty(addr);
+ if (!BCR_SWSTYLE(s)) {
+ uint16_t xda[4];
+ xda[0] = ((uint32_t *)tmd)[0] & 0xffff;
+ xda[1] = ((((uint32_t *)tmd)[0]>>16)&0x00ff) |
+ ((((uint32_t *)tmd)[1]>>16)&0xff00);
+ xda[2] = ((uint32_t *)tmd)[1] & 0xffff;
+ xda[3] = ((uint32_t *)tmd)[2] >> 16;
+ cpu_physical_memory_write(addr,
+ (void *)&xda[0], sizeof(xda));
+ cpu_physical_memory_set_dirty(addr+7);
+ }
+ else {
+ if (BCR_SWSTYLE(s) != 3)
+ cpu_physical_memory_write(addr, (void *)tmd, 16);
+ else {
+ uint32_t xda[4];
+ xda[0] = ((uint32_t *)tmd)[2];
+ xda[1] = ((uint32_t *)tmd)[1];
+ xda[2] = ((uint32_t *)tmd)[0];
+ xda[3] = ((uint32_t *)tmd)[3];
+ cpu_physical_memory_write(addr,
+ (void *)&xda[0], sizeof(xda));
+ }
+ cpu_physical_memory_set_dirty(addr+15);
+ }
+}
+
+static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd,
target_phys_addr_t addr)
+{
+ if (!BCR_SWSTYLE(s)) {
+ uint16_t rda[4];
+ cpu_physical_memory_read(addr,
+ (void *)&rda[0], sizeof(rda));
+ ((uint32_t *)rmd)[0] = (rda[0]&0xffff)|
+ ((rda[1] & 0x00ff) << 16);
+ ((uint32_t *)rmd)[1] = (rda[2]&0xffff)|
+ ((rda[1] & 0xff00) << 16);
+ ((uint32_t *)rmd)[2] = rda[3] & 0xffff;
+ ((uint32_t *)rmd)[3] = 0;
+ }
+ else
+ if (BCR_SWSTYLE(s) != 3)
+ cpu_physical_memory_read(addr, (void *)rmd, 16);
+ else {
+ uint32_t rda[4];
+ cpu_physical_memory_read(addr,
+ (void *)&rda[0], sizeof(rda));
+ ((uint32_t *)rmd)[0] = rda[2];
+ ((uint32_t *)rmd)[1] = rda[1];
+ ((uint32_t *)rmd)[2] = rda[0];
+ ((uint32_t *)rmd)[3] = rda[3];
+ }
+}
+
+static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd,
target_phys_addr_t addr)
+{
+ cpu_physical_memory_set_dirty(addr);
+ if (!BCR_SWSTYLE(s)) {
+ uint16_t rda[4]; \
+ rda[0] = ((uint32_t *)rmd)[0] & 0xffff; \
+ rda[1] = ((((uint32_t *)rmd)[0]>>16)&0xff)|\
+ ((((uint32_t *)rmd)[1]>>16)&0xff00);\
+ rda[2] = ((uint32_t *)rmd)[1] & 0xffff; \
+ rda[3] = ((uint32_t *)rmd)[2] & 0xffff; \
+ cpu_physical_memory_write(addr, \
+ (void *)&rda[0], sizeof(rda)); \
+ cpu_physical_memory_set_dirty(addr+7);
+ }
+ else {
+ if (BCR_SWSTYLE(s) != 3)
+ cpu_physical_memory_write(addr, (void *)rmd, 16);
+ else {
+ uint32_t rda[4];
+ rda[0] = ((uint32_t *)rmd)[2];
+ rda[1] = ((uint32_t *)rmd)[1];
+ rda[2] = ((uint32_t *)rmd)[0];
+ rda[3] = ((uint32_t *)rmd)[3];
+ cpu_physical_memory_write(addr,
+ (void *)&rda[0], sizeof(rda));
+ }
+ cpu_physical_memory_set_dirty(addr+15);
+ }
+}
+
+
+#define TMDLOAD(TMD,ADDR) pcnet_tmd_load(s,TMD,ADDR)
+
+#define TMDSTORE(TMD,ADDR) pcnet_tmd_store(s,TMD,ADDR)
+
+#define RMDLOAD(RMD,ADDR) pcnet_rmd_load(s,RMD,ADDR)
+
+#define RMDSTORE(RMD,ADDR) pcnet_rmd_store(s,RMD,ADDR)
+
+#if 1
+
+#define CHECK_RMD(ADDR,RES) do { \
+ struct pcnet_RMD rmd; \
+ RMDLOAD(&rmd,(ADDR)); \
+ (RES) |= (rmd.rmd1.ones != 15) \
+ || (rmd.rmd2.zeros != 0); \
+} while (0)
+
+#define CHECK_TMD(ADDR,RES) do { \
+ struct pcnet_TMD tmd; \
+ TMDLOAD(&tmd,(ADDR)); \
+ (RES) |= (tmd.tmd1.ones != 15); \
+} while (0)
+
+#else
+
+#define CHECK_RMD(ADDR,RES) do { \
+ switch (BCR_SWSTYLE(s)) { \
+ case 0x00: \
+ do { \
+ uint16_t rda[4]; \
+ cpu_physical_memory_read((ADDR), \
+ (void *)&rda[0], sizeof(rda)); \
+ (RES) |= (rda[2] & 0xf000)!=0xf000; \
+ (RES) |= (rda[3] & 0xf000)!=0x0000; \
+ } while (0); \
+ break; \
+ case 0x01: \
+ case 0x02: \
+ do { \
+ uint32_t rda[4]; \
+ cpu_physical_memory_read((ADDR), \
+ (void *)&rda[0], sizeof(rda)); \
+ (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
+ (RES) |= (rda[2] & 0x0000f000L)!=0x00000000L; \
+ } while (0); \
+ break; \
+ case 0x03: \
+ do { \
+ uint32_t rda[4]; \
+ cpu_physical_memory_read((ADDR), \
+ (void *)&rda[0], sizeof(rda)); \
+ (RES) |= (rda[0] & 0x0000f000L)!=0x00000000L; \
+ (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
+ } while (0); \
+ break; \
+ } \
+} while (0)
+
+#define CHECK_TMD(ADDR,RES) do { \
+ switch (BCR_SWSTYLE(s)) { \
+ case 0x00: \
+ do { \
+ uint16_t xda[4]; \
+ cpu_physical_memory_read((ADDR), \
+ (void *)&xda[0], sizeof(xda)); \
+ (RES) |= (xda[2] & 0xf000)!=0xf000;\
+ } while (0); \
+ break; \
+ case 0x01: \
+ case 0x02: \
+ case 0x03: \
+ do { \
+ uint32_t xda[4]; \
+ cpu_physical_memory_read((ADDR), \
+ (void *)&xda[0], sizeof(xda)); \
+ (RES) |= (xda[1] & 0x0000f000L)!=0x0000f000L; \
+ } while (0); \
+ break; \
+ } \
+} while (0)
+
+#endif
+
+#define PRINT_PKTHDR(BUF) do { \
+ struct ether_header *hdr = (void *)(BUF); \
+ printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, " \
+ "shost=%02x:%02x:%02x:%02x:%02x:%02x, " \
+ "type=0x%04x (bcast=%d)\n", \
+ hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2], \
+ hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5], \
+ hdr->ether_shost[0],hdr->ether_shost[1],hdr->ether_shost[2], \
+ hdr->ether_shost[3],hdr->ether_shost[4],hdr->ether_shost[5], \
+ htons(hdr->ether_type), \
+ !!ETHER_IS_MULTICAST(hdr->ether_dhost)); \
+} while (0)
+
+#define MULTICAST_FILTER_LEN 8
+
+static inline uint32_t lnc_mchash(const uint8_t *ether_addr)
+{
+#define LNC_POLYNOMIAL 0xEDB88320UL
+ uint32_t crc = 0xFFFFFFFF;
+ int idx, bit;
+ uint8_t data;
+
+ for (idx = 0; idx < ETHER_ADDR_LEN; idx++) {
+ for (data = *ether_addr++, bit = 0; bit < MULTICAST_FILTER_LEN; bit++)
{
+ crc = (crc >> 1) ^ (((crc ^ data) & 1) ? LNC_POLYNOMIAL : 0);
+ data >>= 1;
+ }
+ }
+ return crc;
+#undef LNC_POLYNOMIAL
+}
+
+#define MIN(X,Y) ((X>Y) ? (Y) : (X))
+
+#define CRC(crc, ch) (crc = (crc >> 8) ^ crctab[(crc ^ (ch)) & 0xff])
+
+/* generated using the AUTODIN II polynomial
+ * x^32 + x^26 + x^23 + x^22 + x^16 +
+ * x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
+ */
+static const uint32_t crctab[256] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+ 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+ 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+ 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+ 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+ 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+ 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+ 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+ 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+ 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+ 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+ 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+ 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+ 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+ 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+ 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+};
+
+static inline int padr_match(PCNetState *s, const uint8_t *buf, int size)
+{
+ struct ether_header *hdr = (void *)buf;
+ uint8_t padr[6] = {
+ s->csr[12] & 0xff, s->csr[12] >> 8,
+ s->csr[13] & 0xff, s->csr[13] >> 8,
+ s->csr[14] & 0xff, s->csr[14] >> 8
+ };
+ int result = (!CSR_DRCVPA(s)) && !bcmp(hdr->ether_dhost, padr, 6);
+#ifdef PCNET_DEBUG_MATCH
+ printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, "
+ "padr=%02x:%02x:%02x:%02x:%02x:%02x\n",
+ hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2],
+ hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5],
+ padr[0],padr[1],padr[2],padr[3],padr[4],padr[5]);
+ printf("padr_match result=%d\n", result);
+#endif
+ return result;
+}
+
+static inline int padr_bcast(PCNetState *s, const uint8_t *buf, int size)
+{
+ static uint8_t BCAST[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+ struct ether_header *hdr = (void *)buf;
+ int result = !CSR_DRCVBC(s) && !bcmp(hdr->ether_dhost, BCAST, 6);
+#ifdef PCNET_DEBUG_MATCH
+ printf("padr_bcast result=%d\n", result);
+#endif
+ return result;
+}
+
+static inline int ladr_match(PCNetState *s, const uint8_t *buf, int size)
+{
+ struct ether_header *hdr = (void *)buf;
+ if ((*(hdr->ether_dhost)&0x01) &&
+ ((uint64_t *)&s->csr[8])[0] != 0LL) {
+ uint8_t ladr[8] = {
+ s->csr[8] & 0xff, s->csr[8] >> 8,
+ s->csr[9] & 0xff, s->csr[9] >> 8,
+ s->csr[10] & 0xff, s->csr[10] >> 8,
+ s->csr[11] & 0xff, s->csr[11] >> 8
+ };
+ int index = lnc_mchash(hdr->ether_dhost) >> 26;
+ return !!(ladr[index >> 3] & (1 << (index & 7)));
+ }
+ return 0;
+}
+
+static inline target_phys_addr_t pcnet_rdra_addr(PCNetState *s, int idx)
+{
+ while (idx < 1) idx += CSR_RCVRL(s);
+ return s->rdra + ((CSR_RCVRL(s) - idx) * (BCR_SWSTYLE(s) ? 16 : 8));
+}
+
+static inline int64_t pcnet_get_next_poll_time(PCNetState *s, int64_t
current_time)
+{
+ int64_t next_time = current_time +
+ muldiv64(65536 - (CSR_SPND(s) ? 0 : CSR_POLL(s)),
+ ticks_per_sec, 33000000L);
+ if (next_time <= current_time)
+ next_time = current_time + 1;
+ return next_time;
+}
+
+
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/server/tpmif.py
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/python/xen/xend/server/tpmif.py Fri Sep 9 16:30:54 2005
@@ -0,0 +1,45 @@
+# Copyright (C) 2005 IBM Corporation
+# Authort: Stefan Berger, stefanb@xxxxxxxxxx
+# Derived from netif.py:
+# Copyright (C) 2004 Mike Wray <mike.wray@xxxxxx>
+"""Support for virtual TPM interfaces.
+"""
+
+import random
+
+from xen.xend import sxp
+from xen.xend.XendError import XendError, VmError
+from xen.xend.XendLogging import log
+from xen.xend.XendRoot import get_component
+from xen.xend.xenstore import DBVar
+
+from xen.xend.server.controller import Dev, DevController
+
+class TPMifController(DevController):
+ """TPM interface controller. Handles all TPM devices for a domain.
+ """
+
+ def __init__(self, vm, recreate=False):
+ DevController.__init__(self, vm, recreate=recreate)
+
+ def initController(self, recreate=False, reboot=False):
+ self.destroyed = False
+
+ def destroyController(self, reboot=False):
+ """Destroy the controller and all devices.
+ """
+ self.destroyed = True
+ self.destroyDevices(reboot=reboot)
+
+ def sxpr(self):
+ val = ['tpmif', ['dom', self.getDomain()]]
+ return val
+
+ def newDevice(self, id, config, recreate=False):
+ """Create a TPM device.
+
+ @param id: interface id
+ @param config: device configuration
+ @param recreate: recreate flag (true after xend restart)
+ """
+ return None
diff -r 10b1d30d3f66 -r b2f4823b6ff0
tools/python/xen/xend/xenstore/xstransact.py
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/python/xen/xend/xenstore/xstransact.py Fri Sep 9 16:30:54 2005
@@ -0,0 +1,113 @@
+# Copyright (C) 2005 Christian Limpach <Christian.Limpach@xxxxxxxxxxxx>
+
+# This file is subject to the terms and conditions of the GNU General
+# Public License. See the file "COPYING" in the main directory of
+# this archive for more details.
+
+import threading
+from xen.lowlevel import xs
+
+handles = {}
+
+# XXX need to g/c handles from dead threads
+def xshandle():
+ if not handles.has_key(threading.currentThread()):
+ handles[threading.currentThread()] = xs.open()
+ return handles[threading.currentThread()]
+
+class xstransact:
+
+ def __init__(self, path):
+ self.path = path.rstrip("/")
+ xshandle().transaction_start(path)
+ self.in_transaction = True
+
+ def __del__(self):
+ if self.in_transaction:
+ xshandle().transaction_end(True)
+
+ def commit(self):
+ if not self.in_transaction:
+ raise RuntimeError
+ self.in_transaction = False
+ return xshandle().transaction_end(False)
+
+ def abort(self):
+ if not self.in_transaction:
+ raise RuntimeError
+ self.in_transaction = False
+ return xshandle().transaction_end(True)
+
+ def _read(self, key):
+ path = "%s/%s" % (self.path, key)
+ return xshandle().read(path)
+
+ def read(self, *args):
+ if len(args) == 0:
+ raise TypeError
+ if len(args) == 1:
+ return self._read(args[0])
+ ret = []
+ for key in args:
+ ret.append(self._read(key))
+ return ret
+
+ def _write(self, key, data, create=True, excl=False):
+ path = "%s/%s" % (self.path, key)
+ xshandle().write(path, data, create=create, excl=excl)
+
+ def write(self, *args, **opts):
+ create = opts.get('create') or True
+ excl = opts.get('excl') or False
+ if len(args) == 0:
+ raise TypeError
+ if isinstance(args[0], dict):
+ for d in args:
+ if not isinstance(d, dict):
+ raise TypeError
+ for key in d.keys():
+ self._write(key, d[key], create, excl)
+ elif isinstance(args[0], list):
+ for l in args:
+ if not len(l) == 2:
+ raise TypeError
+ self._write(l[0], l[1], create, excl)
+ elif len(args) % 2 == 0:
+ for i in range(len(args) / 2):
+ self._write(args[i * 2], args[i * 2 + 1], create, excl)
+ else:
+ raise TypeError
+
+ def Read(cls, path, *args):
+ t = cls(path)
+ v = t.read(*args)
+ t.commit()
+ return v
+
+ Read = classmethod(Read)
+
+ def Write(cls, path, *args, **opts):
+ t = cls(path)
+ t.write(*args, **opts)
+ t.commit()
+
+ Write = classmethod(Write)
+
+ def SafeRead(cls, path, *args):
+ while True:
+ try:
+ return cls.Read(path, *args)
+ except RuntimeError, ex:
+ pass
+
+ SafeRead = classmethod(SafeRead)
+
+ def SafeWrite(cls, path, *args, **opts):
+ while True:
+ try:
+ cls.Write(path, *args, **opts)
+ return
+ except RuntimeError, ex:
+ pass
+
+ SafeWrite = classmethod(SafeWrite)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/xenstore/xswatch.py
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/python/xen/xend/xenstore/xswatch.py Fri Sep 9 16:30:54 2005
@@ -0,0 +1,65 @@
+# Copyright (C) 2005 Christian Limpach <Christian.Limpach@xxxxxxxxxxxx>
+
+# This file is subject to the terms and conditions of the GNU General
+# Public License. See the file "COPYING" in the main directory of
+# this archive for more details.
+
+import select
+import threading
+from xen.lowlevel import xs
+
+class xswatch:
+
+ watchThread = None
+ threadcond = threading.Condition()
+ xs = None
+ xslock = threading.Lock()
+
+ def __init__(self, path, fn, args=(), kwargs={}):
+ self.fn = fn
+ self.args = args
+ self.kwargs = kwargs
+ xswatch.watchStart()
+ xswatch.xslock.acquire()
+ xswatch.xs.watch(path, self)
+ xswatch.xslock.release()
+
+ def watchStart(cls):
+ cls.threadcond.acquire()
+ if cls.watchThread:
+ cls.threadcond.release()
+ return
+ cls.watchThread = threading.Thread(name="Watcher",
+ target=cls.watchMain)
+ cls.watchThread.setDaemon(True)
+ cls.watchThread.start()
+ while cls.xs == None:
+ cls.threadcond.wait()
+ cls.threadcond.release()
+
+ watchStart = classmethod(watchStart)
+
+ def watchMain(cls):
+ cls.threadcond.acquire()
+ cls.xs = xs.open()
+ cls.threadcond.notifyAll()
+ cls.threadcond.release()
+ while True:
+ try:
+ (ord, owr, oer) = select.select([ cls.xs ], [], [])
+ cls.xslock.acquire()
+ # reconfirm ready to read with lock
+ (ord, owr, oer) = select.select([ cls.xs ], [], [], 0.001)
+ if not cls.xs in ord:
+ cls.xslock.release()
+ continue
+ we = cls.xs.read_watch()
+ watch = we[1]
+ cls.xs.acknowledge_watch(watch)
+ cls.xslock.release()
+ except RuntimeError, ex:
+ print ex
+ raise
+ watch.fn(*watch.args, **watch.kwargs)
+
+ watchMain = classmethod(watchMain)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/security/getlabel.sh
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/security/getlabel.sh Fri Sep 9 16:30:54 2005
@@ -0,0 +1,130 @@
+#!/bin/sh
+# *
+# * getlabel
+# *
+# * Copyright (C) 2005 IBM Corporation
+# *
+# * Authors:
+# * Stefan Berger <stefanb@xxxxxxxxxx>
+# *
+# * This program is free software; you can redistribute it and/or
+# * modify it under the terms of the GNU General Public License as
+# * published by the Free Software Foundation, version 2 of the
+# * License.
+# *
+# * 'getlabel' tries to find the labels corresponding to the ssidref
+# *
+# * 'getlabel -?' shows the usage of the program
+# *
+# * 'getlabel -sid <ssidref> [<policy name>]' lists the label corresponding
+# * to the given ssidref.
+# *
+# * 'getlabel -dom <domain id> [<policy name>]' lists the label of the
+# * domain with given id
+# *
+#
+
+if [ -z "$runbash" ]; then
+ runbash="1"
+ export runbash
+ exec sh -c "bash $0 $*"
+fi
+
+
+export PATH=$PATH:.
+source labelfuncs.sh
+
+usage ()
+{
+ echo "Usage: $0 -sid <ssidref> [<policy name>] or"
+ echo " $0 -dom <domid> [<policy name>] "
+ echo ""
+ echo "policy name : the name of the policy, i.e. 'chwall'"
+ echo " If the policy name is omitted, the grub.conf"
+ echo " entry of the running system is tried to be read"
+ echo " and the policy name determined from there."
+ echo "ssidref : an ssidref in hex or decimal format, i.e.,
'0x00010002'"
+ echo " or '65538'"
+ echo "domid : id of the domain, i.e., '1'; Use numbers from the
2nd"
+ echo " column shown when invoking 'xm list'"
+ echo ""
+}
+
+
+
+if [ "$1" == "-?" ]; then
+ mode="usage"
+elif [ "$1" == "-dom" ]; then
+ mode="domid"
+ shift
+elif [ "$1" == "-sid" ]; then
+ mode="sid"
+ shift
+elif [ "$1" == "" ]; then
+ usage
+ exit -1
+fi
+
+
+if [ "$mode" == "usage" ]; then
+ usage
+elif [ "$mode" == "domid" ]; then
+ if [ "$2" == "" ]; then
+ findGrubConf
+ ret=$?
+ if [ $ret -eq 0 ]; then
+ echo "Could not find grub.conf"
+ exit -1;
+ fi
+ findPolicyInGrub $grubconf
+ if [ "$policy" != "" ]; then
+ echo "Assuming policy to be '$policy'.";
+ else
+ echo "Could not find policy."
+ exit -1;
+ fi
+ else
+ policy=$2
+ fi
+ findMapFile $policy
+ res=$?
+ if [ "$res" != "0" ]; then
+ getSSIDUsingSecpolTool $1
+ res=$?
+ if [ "$res" != "0" ]; then
+ translateSSIDREF $ssid $mapfile
+ else
+ echo "Could not determine the SSID of the domain."
+ fi
+ else
+ echo "Could not find map file for policy '$policy'."
+ fi
+elif [ "$mode" == "sid" ]; then
+ if [ "$2" == "" ]; then
+ findGrubConf
+ ret=$?
+ if [ $ret -eq 0 ]; then
+ echo "Could not find grub.conf"
+ exit -1;
+ fi
+ findPolicyInGrub $grubconf
+ if [ "$policy" != "" ]; then
+ echo "Assuming policy to be '$policy'.";
+ else
+ echo "Could not find policy."
+ exit -1;
+ fi
+ else
+ policy=$2
+ fi
+ findMapFile $policy
+ res=$?
+ if [ "$res" != "0" ]; then
+ translateSSIDREF $1 $mapfile
+ else
+ echo "Could not find map file for policy '$policy'."
+ fi
+
+else
+ usage
+fi
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/security/labelfuncs.sh
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/security/labelfuncs.sh Fri Sep 9 16:30:54 2005
@@ -0,0 +1,675 @@
+# *
+# * labelfuncs.sh
+# *
+# * Copyright (C) 2005 IBM Corporation
+# *
+# * Authors:
+# * Stefan Berger <stefanb@xxxxxxxxxx>
+# *
+# * This program is free software; you can redistribute it and/or
+# * modify it under the terms of the GNU General Public License as
+# * published by the Free Software Foundation, version 2 of the
+# * License.
+# *
+# *
+# * A collection of functions to handle polcies, mapfiles,
+# * and ssidrefs.
+#
+
+
+# Find the mapfile given a policy nmame
+# Parameters:
+# 1st : the name of the policy whose map file is to be found, i.e.,
+# chwall
+# Results:
+# The variable mapfile will hold the realtive path to the mapfile
+# for the given policy.
+# In case the mapfile could be found, the functions returns a '1',
+# a '0' otherwise.
+findMapFile ()
+{
+ mapfile="./$1.map"
+ if [ -r "$mapfile" ]; then
+ return 1
+ fi
+
+ mapfile="./policies/$1/$1.map"
+ if [ -r "$mapfile" ]; then
+ return 1
+ fi
+
+ return 0
+}
+
+
+# Determine the name of the primary policy
+# Parameters
+# 1st : the path to the mapfile; the path may be relative
+# to the current directory
+# Results
+# The variable primary will hold the name of the primary policy
+getPrimaryPolicy ()
+{
+ mapfile=$1
+ primary=`cat $mapfile | \
+ awk ' \
+ { \
+ if ( $1 == "PRIMARY" ) { \
+ res=$2; \
+ } \
+ } END { \
+ print res; \
+ } '`
+}
+
+
+# Determine the name of the secondary policy
+# Parameters
+# 1st : the path to the mapfile; the path may be relative
+# to the current directory
+# Results
+# The variable secondary will hold the name of the secondary policy
+getSecondaryPolicy ()
+{
+ mapfile=$1
+ secondary=`cat $mapfile | \
+ awk ' \
+ { \
+ if ( $1 == "SECONDARY" ) { \
+ res=$2; \
+ } \
+ } END { \
+ print res; \
+ } '`
+}
+
+
+#Return where the grub.conf file is.
+#I only know of one place it can be.
+findGrubConf()
+{
+ grubconf="/boot/grub/grub.conf"
+ if [ -w $grubconf ]; then
+ return 1
+ fi
+ if [ -r $grubconf ]; then
+ return 2
+ fi
+ return 0
+}
+
+
+# This function sets the global variable 'linux'
+# to the name and version of the Linux kernel that was compiled
+# for domain 0.
+# If this variable could not be found, the variable 'linux'
+# will hold a pattern
+# Parameters:
+# 1st: the path to reach the root directory of the XEN build tree
+# where linux-*-xen0 is located at
+# Results:
+# The variable linux holds then name and version of the compiled
+# kernel, i.e., 'vmlinuz-2.6.12-xen0'
+getLinuxVersion ()
+{
+ path=$1
+ linux=""
+ for f in $path/linux-*-xen0 ; do
+ versionfile=$f/include/linux/version.h
+ if [ -r $versionfile ]; then
+ lnx=`cat $versionfile | \
+ grep UTS_RELEASE | \
+ awk '{ \
+ len=length($3); \
+ print substr($3,2,len-2) }'`
+ fi
+ if [ "$lnx" != "" ]; then
+ linux="[./0-9a-zA-z]*$lnx"
+ return;
+ fi
+ done
+
+ #Last resort.
+ linux="vmlinuz-2.[45678].[0-9]*[.0-9]*-xen0$"
+}
+
+
+# Find out with which policy the hypervisor was booted with.
+# Parameters
+# 1st : The complete path to grub.conf, i.e., /boot/grub/grub.conf
+#
+findPolicyInGrub ()
+{
+ grubconf=$1
+ linux=`uname -r`
+ policy=`cat $grubconf | \
+ awk -vlinux=$linux '{ \
+ if ( $1 == "title" ) { \
+ kernelfound = 0; \
+ policymaycome = 0; \
+ } \
+ else if ( $1 == "kernel" ) { \
+ if ( match($2,"xen.gz$") ) { \
+ pathlen=RSTART; \
+ kernelfound = 1; \
+ } \
+ } \
+ else if ( $1 == "module" && \
+ kernelfound == 1 && \
+ match($2,linux) ) { \
+ policymaycome = 1; \
+ } \
+ else if ( $1 == "module" && \
+ kernelfound == 1 && \
+ policymaycome == 1 && \
+ match($2,"[0-9a-zA-Z_]*.bin$") ) { \
+ policymaycome = 0; \
+ kernelfound = 0; \
+ polname = substr($2,pathlen); \
+ len=length(polname); \
+ polname = substr(polname,0,len-4); \
+ } \
+ } END { \
+ print polname \
+ }'`
+}
+
+
+# Get the SSID of a domain
+# Parameters:
+# 1st : domain ID, i.e. '1'
+# Results
+# If the ssid could be found, the variable 'ssid' will hold
+# the currently used ssid in the hex format, i.e., '0x00010001'.
+# The funtion returns '1' on success, '0' on failure
+getSSIDUsingSecpolTool ()
+{
+ domid=$1
+ export PATH=$PATH:.
+ ssid=`secpol_tool getssid -d $domid -f | \
+ grep -E "SSID:" | \
+ awk '{ print $4 }'`
+
+ if [ "$ssid" != "" ]; then
+ return 1
+ fi
+ return 0
+}
+
+
+# Break the ssid identifier into its high and low values,
+# which are equal to the secondary and primary policy references.
+# Parameters:
+# 1st: ssid to break into high and low value, i.e., '0x00010002'
+# Results:
+# The variable ssidlo_int and ssidhi_int will hold the low and
+# high ssid values as integers.
+getSSIDLOHI ()
+{
+ ssid=$1
+ ssidlo_int=`echo $ssid | awk \
+ '{ \
+ len=length($0); \
+ beg=substr($0,1,2); \
+ if ( beg == "0x" ) { \
+ dig = len - 2; \
+ if (dig <= 0) { \
+ exit; \
+ } \
+ if (dig > 4) { \
+ dig=4; \
+ } \
+ lo=sprintf("0x%s",substr($0,len-dig+1,dig)); \
+ print strtonum(lo);\
+ } else { \
+ lo=strtonum($0); \
+ if (lo < 65536) { \
+ print lo; \
+ } else { \
+ hi=lo; \
+ hi2= (hi / 65536);\
+ hi2_str=sprintf("%d",hi2); \
+ hi2=strtonum(hi2_str);\
+ lo=hi-(hi2*65536); \
+ printf("%d",lo); \
+ } \
+ } \
+ }'`
+ ssidhi_int=`echo $ssid | awk \
+ '{ \
+ len=length($0); \
+ beg=substr($0,1,2); \
+ if ( beg == "0x" ) { \
+ dig = len - 2; \
+ if (dig <= 0 || \
+ dig > 8) { \
+ exit; \
+ } \
+ if (dig < 4) { \
+ print 0; \
+ exit; \
+ } \
+ dig -= 4; \
+ hi=sprintf("0x%s",substr($0,len-4-dig+1,dig)); \
+ print strtonum(hi);\
+ } else { \
+ hi=strtonum($0); \
+ if (hi >= 65536) { \
+ hi = hi / 65536; \
+ printf ("%d",hi);\
+ } else { \
+ printf ("0"); \
+ } \
+ } \
+ }'`
+ if [ "$ssidhi_int" == "" -o \
+ "$ssidlo_int" == "" ]; then
+ return 0;
+ fi
+ return 1
+}
+
+
+#Update the grub configuration file.
+#Search for existing entries and replace the current
+#policy entry with the policy passed to this script
+#
+#Arguments passed to this function
+# 1st : the grub configuration file with full path
+# 2nd : the binary policy file name, i.e. chwall.bin
+# 3rd : the name or pattern of the linux kernel name to match
+# (this determines where the module entry will be made)
+#
+# The algorithm here is based on pattern matching
+# and is working correctly if
+# - under a title a line beginning with 'kernel' is found
+# whose following item ends with "xen.gz"
+# Example: kernel /xen.gz dom0_mem=....
+# - a module line matching the 3rd parameter is found
+#
+updateGrub ()
+{
+ grubconf=$1
+ policyfile=$2
+ linux=$3
+
+ tmpfile="/tmp/new_grub.conf"
+
+ cat $grubconf | \
+ awk -vpolicy=$policyfile \
+ -vlinux=$linux '{ \
+ if ( $1 == "title" ) { \
+ kernelfound = 0; \
+ if ( policymaycome == 1 ){ \
+ printf ("\tmodule %s%s\n", path, policy); \
+ } \
+ policymaycome = 0; \
+ } \
+ else if ( $1 == "kernel" ) { \
+ if ( match($2,"xen.gz$") ) { \
+ path=substr($2,1,RSTART-1); \
+ kernelfound = 1; \
+ } \
+ } \
+ else if ( $1 == "module" && \
+ kernelfound == 1 && \
+ match($2,linux) ) { \
+ policymaycome = 1; \
+ } \
+ else if ( $1 == "module" && \
+ kernelfound == 1 && \
+ policymaycome == 1 && \
+ match($2,"[0-9a-zA-Z]*.bin$") ) { \
+ printf ("\tmodule %s%s\n", path, policy); \
+ policymaycome = 0; \
+ kernelfound = 0; \
+ dontprint = 1; \
+ } \
+ else if ( $1 == "" && \
+ kernelfound == 1 && \
+ policymaycome == 1) { \
+ dontprint = 1; \
+ } \
+ if (dontprint == 0) { \
+ printf ("%s\n", $0); \
+ } \
+ dontprint = 0; \
+ } END { \
+ if ( policymaycome == 1 ) { \
+ printf ("\tmodule %s%s\n", path, policy); \
+ } \
+ }' > $tmpfile
+ if [ ! -r $tmpfile ]; then
+ echo "Could not create temporary file! Aborting."
+ exit -1
+ fi
+ mv -f $tmpfile $grubconf
+}
+
+
+# Display all the labels in a given mapfile
+# Parameters
+# 1st: Full or relative path to the policy's mapfile
+showLabels ()
+{
+ mapfile=$1
+ if [ ! -r "$mapfile" -o "$mapfile" == "" ]; then
+ echo "Cannot read from vm configuration file $vmfile."
+ return -1
+ fi
+
+ getPrimaryPolicy $mapfile
+ getSecondaryPolicy $mapfile
+
+ echo "The following labels are available:"
+ let line=1
+ while [ 1 ]; do
+ ITEM=`cat $mapfile | \
+ awk -vline=$line \
+ -vprimary=$primary \
+ '{ \
+ if ($1 == "LABEL->SSID" && \
+ $2 == "VM" && \
+ $3 == primary ) { \
+ ctr++; \
+ if (ctr == line) { \
+ print $4; \
+ } \
+ } \
+ } END { \
+ }'`
+
+ if [ "$ITEM" == "" ]; then
+ break
+ fi
+ if [ "$secondary" != "NULL" ]; then
+ LABEL=`cat $mapfile | \
+ awk -vitem=$ITEM \
+ '{
+ if ($1 == "LABEL->SSID" && \
+ $2 == "VM" && \
+ $3 == "CHWALL" && \
+ $4 == item ) { \
+ result = item; \
+ } \
+ } END { \
+ print result \
+ }'`
+ else
+ LABEL=$ITEM
+ fi
+
+ if [ "$LABEL" != "" ]; then
+ echo "$LABEL"
+ found=1
+ fi
+ let line=line+1
+ done
+ if [ "$found" != "1" ]; then
+ echo "No labels found."
+ fi
+}
+
+
+# Get the default SSID given a mapfile and the policy name
+# Parameters
+# 1st: Full or relative path to the policy's mapfile
+# 2nd: the name of the policy
+getDefaultSsid ()
+{
+ mapfile=$1
+ pol=$2
+ RES=`cat $mapfile \
+ awk -vpol=$pol \
+ { \
+ if ($1 == "LABEL->SSID" && \
+ $2 == "ANY" && \
+ $3 == pol && \
+ $4 == "DEFAULT" ) {\
+ res=$5; \
+ } \
+ } END { \
+ printf "%04x", strtonum(res) \
+ }'`
+ echo "default NULL mapping is $RES"
+ defaultssid=$RES
+}
+
+
+#Relabel a VM configuration file
+# Parameters
+# 1st: Full or relative path to the VM configuration file
+# 2nd: The label to translate into an ssidref
+# 3rd: Full or relative path to the policy's map file
+# 4th: The mode this function is supposed to operate in:
+# 'relabel' : Relabels the file without querying the user
+# other : Prompts the user whether to proceed
+relabel ()
+{
+ vmfile=$1
+ label=$2
+ mapfile=$3
+ mode=$4
+
+ if [ ! -r "$vmfile" ]; then
+ echo "Cannot read from vm configuration file $vmfile."
+ return -1
+ fi
+
+ if [ ! -w "$vmfile" ]; then
+ echo "Cannot write to vm configuration file $vmfile."
+ return -1
+ fi
+
+ if [ ! -r "$mapfile" ] ; then
+ echo "Cannot read mapping file $mapfile."
+ return -1
+ fi
+
+ # Determine which policy is primary, which sec.
+ getPrimaryPolicy $mapfile
+ getSecondaryPolicy $mapfile
+
+ # Calculate the primary policy's SSIDREF
+ if [ "$primary" == "NULL" ]; then
+ SSIDLO="0001"
+ else
+ SSIDLO=`cat $mapfile | \
+ awk -vlabel=$label \
+ -vprimary=$primary \
+ '{ \
+ if ( $1 == "LABEL->SSID" && \
+ $2 == "VM" && \
+ $3 == primary && \
+ $4 == label ) { \
+ result=$5 \
+ } \
+ } END { \
+ if (result != "" ) \
+ {printf "%04x", strtonum(result)}\
+ }'`
+ fi
+
+ # Calculate the secondary policy's SSIDREF
+ if [ "$secondary" == "NULL" ]; then
+ if [ "$primary" == "NULL" ]; then
+ SSIDHI="0001"
+ else
+ SSIDHI="0000"
+ fi
+ else
+ SSIDHI=`cat $mapfile | \
+ awk -vlabel=$label \
+ -vsecondary=$secondary \
+ '{ \
+ if ( $1 == "LABEL->SSID" && \
+ $2 == "VM" && \
+ $3 == secondary && \
+ $4 == label ) { \
+ result=$5 \
+ } \
+ } END { \
+ if (result != "" ) \
+ {printf "%04x", strtonum(result)}\
+ }'`
+ fi
+
+ if [ "$SSIDLO" == "" -o \
+ "$SSIDHI" == "" ]; then
+ echo "Could not map the given label '$label'."
+ return -1
+ fi
+
+ ACM_POLICY=`cat $mapfile | \
+ awk ' { if ( $1 == "POLICY" ) { \
+ result=$2 \
+ } \
+ } \
+ END { \
+ if (result != "") { \
+ printf result \
+ } \
+ }'`
+
+ if [ "$ACM_POLICY" == "" ]; then
+ echo "Could not find 'POLICY' entry in map file."
+ return -1
+ fi
+
+ SSIDREF="0x$SSIDHI$SSIDLO"
+
+ if [ "$mode" != "relabel" ]; then
+ RES=`cat $vmfile | \
+ awk '{ \
+ if ( substr($1,0,7) == "ssidref" ) {\
+ print $0; \
+ } \
+ }'`
+ if [ "$RES" != "" ]; then
+ echo "Do you want to overwrite the existing mapping
($RES)? (y/N)"
+ read user
+ if [ "$user" != "y" -a "$user" != "Y" ]; then
+ echo "Aborted."
+ return 0
+ fi
+ fi
+ fi
+
+ #Write the output
+ vmtmp1="/tmp/__setlabel.tmp1"
+ vmtmp2="/tmp/__setlabel.tmp2"
+ touch $vmtmp1
+ touch $vmtmp2
+ if [ ! -w "$vmtmp1" -o ! -w "$vmtmp2" ]; then
+ echo "Cannot create temporary files. Aborting."
+ return -1
+ fi
+ RES=`sed -e '/^#ACM_POLICY/d' $vmfile > $vmtmp1`
+ RES=`sed -e '/^#ACM_LABEL/d' $vmtmp1 > $vmtmp2`
+ RES=`sed -e '/^ssidref/d' $vmtmp2 > $vmtmp1`
+ echo "#ACM_POLICY=$ACM_POLICY" >> $vmtmp1
+ echo "#ACM_LABEL=$label" >> $vmtmp1
+ echo "ssidref = $SSIDREF" >> $vmtmp1
+ mv -f $vmtmp1 $vmfile
+ rm -rf $vmtmp1 $vmtmp2
+ echo "Mapped label '$label' to ssidref '$SSIDREF'."
+}
+
+
+# Translate an ssidref into its label. This does the reverse lookup
+# to the relabel function above.
+# This function displays the results.
+# Parameters:
+# 1st: The ssidref to translate; must be in the form '0x00010002'
+# 2nd: Full or relative path to the policy's mapfile
+translateSSIDREF ()
+{
+ ssidref=$1
+ mapfile=$2
+
+ if [ ! -r "$mapfile" -o "$mapfile" == "" ]; then
+ echo "Cannot read from vm configuration file $vmfile."
+ return -1
+ fi
+
+ getPrimaryPolicy $mapfile
+ getSecondaryPolicy $mapfile
+
+ if [ "$primary" == "NULL" -a "$secondary" == "NULL" ]; then
+ echo "There are no labels for the NULL policy."
+ return
+ fi
+
+ getSSIDLOHI $ssidref
+ ret=$?
+ if [ $ret -ne 1 ]; then
+ echo "Error while parsing the ssid ref number '$ssidref'."
+ fi;
+
+ let line1=0
+ let line2=0
+ while [ 1 ]; do
+ ITEM1=`cat $mapfile | \
+ awk -vprimary=$primary \
+ -vssidlo=$ssidlo_int \
+ -vline=$line1 \
+ '{ \
+ if ( $1 == "LABEL->SSID" && \
+ $3 == primary && \
+ int($5) == ssidlo ) { \
+ if (l == line) { \
+ print $4; \
+ exit; \
+ } \
+ l++; \
+ } \
+ }'`
+
+ ITEM2=`cat $mapfile | \
+ awk -vsecondary=$secondary \
+ -vssidhi=$ssidhi_int \
+ -vline=$line2 \
+ '{ \
+ if ( $1 == "LABEL->SSID" && \
+ $3 == secondary && \
+ int($5) == ssidhi ) { \
+ if (l == line) { \
+ print $4; \
+ exit; \
+ } \
+ l++; \
+ } \
+ }'`
+
+ if [ "$secondary" != "NULL" ]; then
+ if [ "$ITEM1" == "" ]; then
+ let line1=0
+ let line2=line2+1
+ else
+ let line1=line1+1
+ fi
+
+ if [ "$ITEM1" == "" -a \
+ "$ITEM2" == "" ]; then
+ echo "Could not determine the referenced label."
+ break
+ fi
+
+ if [ "$ITEM1" == "$ITEM2" ]; then
+ echo "Label: $ITEM1"
+ break
+ fi
+ else
+ if [ "$ITEM1" != "" ]; then
+ echo "Label: $ITEM1"
+ else
+ if [ "$found" == "0" ]; then
+ found=1
+ else
+ break
+ fi
+ fi
+ let line1=line1+1
+ fi
+ done
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm/Makefile
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm/Makefile Fri Sep 9 16:30:54 2005
@@ -0,0 +1,63 @@
+XEN_ROOT = ../..
+
+# Base definitions and rules
+include $(XEN_ROOT)/tools/vtpm/Rules.mk
+
+# Dir name for emulator (as dom0 tpm driver)
+TPM_EMULATOR_DIR = tpm_emulator-0.2
+# Dir name for vtpm instance
+VTPM_DIR = vtpm
+
+# Emulator tarball name
+TPM_EMULATOR_TARFILE = tpm_emulator-0.2b.tar.gz
+
+all: build
+
+build: $(TPM_EMULATOR_TARFILE) extract patch build_sub
+
+install: build
+ $(MAKE) -C $(TPM_EMULATOR_DIR) $@
+ $(MAKE) -C $(VTPM_DIR) $@
+
+clean:
+ if [ -d $(TPM_EMULATOR_DIR) ]; \
+ then $(MAKE) -C $(TPM_EMULATOR_DIR) clean; \
+ fi
+ if [ -d $(VTPM_DIR) ]; \
+ then $(MAKE) -C $(VTPM_DIR) clean; \
+ fi
+ rm -rf $(TPM_EMULATOR_DIR)
+ rm -rf $(VTPM_DIR)
+
+mrproper: clean
+ rm -f $(TPM_EMULATOR_TARFILE)
+
+# Download Swiss emulator
+$(TPM_EMULATOR_TARFILE):
+ wget http://download.berlios.de/tpm-emulator/$(TPM_EMULATOR_TARFILE)
+
+# Create vtpm and TPM emulator dirs
+extract: $(TPM_EMULATOR_DIR)/README $(VTPM_DIR)/README
+
+$(TPM_EMULATOR_DIR)/README:
+ -rm -rf $(TPM_EMULATOR_DIR)
+ tar -xzf $(TPM_EMULATOR_TARFILE)
+
+$(VTPM_DIR)/README:
+ -rm -rf $(VTPM_DIR)
+ cp -r --preserve $(TPM_EMULATOR_DIR) $(VTPM_DIR)
+
+# apply patches for 1) used as dom0 tpm driver 2) used as vtpm device instance
+patch: $(TPM_EMULATOR_DIR)/Makefile $(VTPM_DIR)/Makefile
+
+$(TPM_EMULATOR_DIR)/Makefile: tpm_emulator.patch
+ -cd $(TPM_EMULATOR_DIR); \
+ patch -p1 <../tpm_emulator.patch
+
+$(VTPM_DIR)/Makefile: vtpm.patch
+ -cd $(VTPM_DIR); \
+ patch -p1 <../vtpm.patch
+
+build_sub:
+ $(MAKE) -C $(TPM_EMULATOR_DIR)
+ $(MAKE) -C $(VTPM_DIR)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm/README
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm/README Fri Sep 9 16:30:54 2005
@@ -0,0 +1,44 @@
+
+Directory Structure
+===================
+tools/vtpm/tpm_emulator-0.2b.tar.gz -> TPM Emulator downloaded at build
time that will
+ be patched and used for our vtpms
+tools/vtpm/vtpm.patch -> patch applied to tpm_emulator to
make vtpm
+tools/vtpm/vtpm/ -> (created on build) tpm_emulator
moved to ring 3,
+ listens on a pair of fifos for TPM
commands,
+ persistent state is sent via named
fifo to vtpm
+ manager, which encrypts it and
protects it.
+tools/vtpm/tpm_emulator.patch -> To allow for debugging and testing
on non-TPM
+ platforms, this patches the emulator
to allow
+ it to be inserted into the dom0
kernel
+tools/vtpm/tpm_emulator-0.2 -> (created on build) directory
containing patched emulator
+
+Compile Flags
+===================
+VTPM_MULTI_VM -> Defined (not finished): VTPMs run in their own
VMs
+ Not Defined (default): VTPMs are processes
+
+Requirements
+============
+- xen-unstable
+- IBM frontend/backend vtpm driver patch
+- vtpm_managerd
+
+vtpmd Flow (for vtpm_manager. vtpmd never run by default)
+============================
+- Launch the VTPM manager (vtpm_managerd) which which begins listening to the
BE with one thread
+ and listens to a named fifo that is shared by the vtpms to commuincate with
the manager.
+- VTPM Manager listens to TPM BE.
+- When xend launches a tpm frontend equipped VM it contacts the manager over
the vtpm backend.
+- When the manager receives the open message from the BE, it launches a vtpm
+- Xend allows the VM to continue booting.
+- When a TPM request is issued to the front end, the front end transmits the
TPM request to the backend.
+- The manager receives the TPM requests and uses a named fifo to forward the
request to the vtpm.
+- The fifo listener begins listening for the reply from vtpm for the request.
+- Vtpm processes request and replies to manager over shared named fifo.
+- If needed, the vtpm may send a request to the vtpm_manager at any time to
save it's secrets to disk.
+- Manager receives response from vtpm and passes it back to backend for
forwarding to guest.
+
+tpm_emulator flow
+==================
+Read documentation in tpm_emulator-0.2 directory
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm/Rules.mk
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm/Rules.mk Fri Sep 9 16:30:54 2005
@@ -0,0 +1,37 @@
+# Base definitions and rules (XEN_ROOT must be defined in including Makefile)
+include $(XEN_ROOT)/tools/Rules.mk
+
+#
+# Tool definitions
+#
+
+# Installation program and options
+INSTALL = install
+INSTALL_PROG = $(INSTALL) -m0755
+INSTALL_DIR = $(INSTALL) -d -m0755
+
+# Xen tools installation directory
+TOOLS_INSTALL_DIR = $(DESTDIR)/usr/bin
+
+# General compiler flags
+CFLAGS = -Wall -Werror -g3 -I.
+
+# For generating dependencies
+CFLAGS += -Wp,-MD,.$(@F).d
+
+DEP_FILES = .*.d
+
+# Generic project files
+HDRS = $(wildcard *.h)
+SRCS = $(wildcard *.c)
+OBJS = $(patsubst %.c,%.o,$(SRCS))
+
+# Generic (non-header) dependencies
+$(SRCS): Makefile $(XEN_ROOT)/tools/Rules.mk $(XEN_ROOT)/tools/vtpm/Rules.mk
+
+$(OBJS): $(SRCS)
+
+-include $(DEP_FILES)
+
+# Make sure these are just rules
+.PHONY : all build install clean
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm/tpm_emulator.patch
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm/tpm_emulator.patch Fri Sep 9 16:30:54 2005
@@ -0,0 +1,151 @@
+diff -uprN orig/tpm_emulator-0.2/AUTHORS tpm_emulator-0.2/AUTHORS
+--- orig/tpm_emulator-0.2/AUTHORS 2005-08-17 10:58:36.000000000 -0700
++++ tpm_emulator-0.2/AUTHORS 2005-08-17 10:55:52.000000000 -0700
+@@ -1 +1,2 @@
+ Mario Strasser <mast@xxxxxxx>
++INTEL Corp <>
+diff -uprN orig/tpm_emulator-0.2/ChangeLog tpm_emulator-0.2/ChangeLog
+--- orig/tpm_emulator-0.2/ChangeLog 2005-08-17 10:58:36.000000000 -0700
++++ tpm_emulator-0.2/ChangeLog 2005-08-17 10:55:52.000000000 -0700
+@@ -1,3 +1,7 @@
++2005-08-16: INTEL Corp
++ * Set default permissions to PCRs
++ * Changed device to /dev/tpm0
++
+ 2005-08-15 Mario Strasser <mast@xxxxxxx>
+ * all: some typos corrected
+ * tpm_integrity.c: bug in TPM_Extend fixed
+diff -uprN orig/tpm_emulator-0.2/Makefile tpm_emulator-0.2/Makefile
+--- orig/tpm_emulator-0.2/Makefile 2005-08-17 10:58:36.000000000 -0700
++++ tpm_emulator-0.2/Makefile 2005-08-17 10:55:52.000000000 -0700
+@@ -1,15 +1,19 @@
+ # Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ # Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>
++# Copyright (C) 2005 INTEL Corp.
+ #
+ # $Id: Makefile 10 2005-04-26 20:59:50Z mast $
+
++XEN_ROOT := ../../..
++EUID := $(shell id -u)
++
+ # kernel settings
+ KERNEL_RELEASE := $(shell uname -r)
+-KERNEL_BUILD := /lib/modules/$(KERNEL_RELEASE)/build
++KERNEL_BUILD := $(XEN_ROOT)/linux-2.6.12-xen0
+ MOD_SUBDIR := misc
+
+ # module settings
+-MODULE_NAME := tpm_emulator
++BIN := tpm_emulator
+ VERSION_MAJOR := 0
+ VERSION_MINOR := 2
+ VERSION_BUILD := $(shell date +"%s")
+@@ -27,11 +30,9 @@ DIRS := . crypto tpm
+ SRCS := $(foreach dir, $(DIRS), $(wildcard $(src)/$(dir)/*.c))
+ OBJS := $(patsubst %.c, %.o, $(SRCS))
+ SRCS += $(foreach dir, $(DIRS), $(wildcard $(src)/$(dir)/*.h))
+-DISTSRC := ./README ./AUTHORS ./ChangeLog ./Makefile $(SRCS)
+-DISTDIR := tpm_emulator-$(VERSION_MAJOR).$(VERSION_MINOR)
+
+-obj-m := $(MODULE_NAME).o
+-$(MODULE_NAME)-objs := $(patsubst $(src)/%.o, %.o, $(OBJS)) crypto/libgmp.a
++obj-m := $(BIN).o
++$(BIN)-objs := $(patsubst $(src)/%.o, %.o, $(OBJS)) crypto/libgmp.a
+
+ EXTRA_CFLAGS += -I$(src) -I$(src)/crypto -I$(src)/tpm
+
+@@ -42,23 +43,17 @@ all: $(src)/crypto/gmp.h $(src)/crypto/l
+ @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) modules
+
+ install:
+- @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) modules_install
+- test -d /var/tpm || mkdir /var/tpm
+- test -c /dev/tpm || mknod /dev/tpm c 10 224
+- chmod 666 /dev/tpm
+- depmod -a
++ @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) INSTALL_MOD_PATH=$(DESTDIR)
modules_install
++ test -d $(DESTDIR)/var/tpm || mkdir $(DESTDIR)/var/tpm
++ test -d $(DESTDIR)/dev || mkdir $(DESTDIR)/dev
++ test -c $(DESTDIR)/dev/tpm0 || [ $(EUID) -ne 0 ] || mknod
$(DESTDIR)/dev/tpm0 c 10 224
++ [ $(EUID) -ne 0 ] || chmod 666 $(DESTDIR)/dev/tpm0
+
+ clean:
+ @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) clean
+ rm -f $(src)/crypto/gmp.h $(src)/crypto/libgmp.a
+
+-dist: $(DISTSRC)
+- rm -rf $(DISTDIR)
+- mkdir $(DISTDIR)
+- cp --parents $(DISTSRC) $(DISTDIR)/
+- rm -f $(DISTDIR)/crypto/gmp.h
+- tar -chzf $(DISTDIR).tar.gz $(DISTDIR)
+- rm -rf $(DISTDIR)
++mrproper: clean
+
+ $(src)/crypto/libgmp.a:
+ test -f $(src)/crypto/libgmp.a || ln -s $(GMP_LIB)
$(src)/crypto/libgmp.a
+diff -uprN orig/tpm_emulator-0.2/README tpm_emulator-0.2/README
+--- orig/tpm_emulator-0.2/README 2005-08-17 10:58:36.000000000 -0700
++++ tpm_emulator-0.2/README 2005-08-17 10:55:52.000000000 -0700
+@@ -13,7 +13,8 @@ $Id: README 8 2005-01-25 21:11:45Z jmoli
+ Copyright
+ --------------------------------------------------------------------------
+ Copyright (C) 2004 Mario Strasser <mast@xxxxxxx> and Swiss Federal
+-Institute of Technology (ETH) Zurich.
++ Institute of Technology (ETH) Zurich.
++Copyright (C) 2005
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+diff -uprN orig/tpm_emulator-0.2/linux_module.h tpm_emulator-0.2/linux_module.h
+--- orig/tpm_emulator-0.2/linux_module.h 2005-08-17 10:58:36.000000000
-0700
++++ tpm_emulator-0.2/linux_module.h 2005-08-17 10:55:52.000000000 -0700
+@@ -1,5 +1,6 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
++ * Copyright (C) 2005 INTEL Corp.
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -33,7 +34,7 @@
+ #include "tpm_version.h"
+
+ #define TPM_DEVICE_MINOR 224
+-#define TPM_DEVICE_NAME "tpm"
++#define TPM_DEVICE_NAME "tpm0"
+ #define TPM_MODULE_NAME "tpm_emulator"
+
+ /* debug and log output functions */
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_data.c tpm_emulator-0.2/tpm/tpm_data.c
+--- orig/tpm_emulator-0.2/tpm/tpm_data.c 2005-08-17 10:58:36.000000000
-0700
++++ tpm_emulator-0.2/tpm/tpm_data.c 2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+ * Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -85,6 +86,11 @@ void tpm_init_data(void)
+ tpmData.permanent.data.version.revMinor = VERSION_MINOR;
+ /* setup PCR attributes */
+ for (i = 0; i < TPM_NUM_PCR; i++) {
++ int j;
++ for (j=0; j < TPM_NUM_LOCALITY; j++) {
++ tpmData.permanent.data.pcrAttrib[i].pcrExtendLocal[j] = TRUE;
++ }
++
+ tpmData.permanent.data.pcrAttrib[i].pcrReset = TRUE;
+ }
+ /* set tick type */
+diff -uprN orig/tpm_emulator-0.2/tpm_version.h tpm_emulator-0.2/tpm_version.h
+--- orig/tpm_emulator-0.2/tpm_version.h 2005-08-17 10:58:36.000000000
-0700
++++ tpm_emulator-0.2/tpm_version.h 2005-08-17 10:55:53.000000000 -0700
+@@ -2,5 +2,5 @@
+ #define _TPM_VERSION_H_
+ #define VERSION_MAJOR 0
+ #define VERSION_MINOR 2
+-#define VERSION_BUILD 1123950310
++#define VERSION_BUILD 1124301353
+ #endif /* _TPM_VERSION_H_ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm/vtpm.patch
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm/vtpm.patch Fri Sep 9 16:30:54 2005
@@ -0,0 +1,1645 @@
+diff -uprN orig/tpm_emulator-0.2/AUTHORS vtpm/AUTHORS
+--- orig/tpm_emulator-0.2/AUTHORS 2005-08-17 10:58:36.000000000 -0700
++++ vtpm/AUTHORS 2005-08-17 10:55:52.000000000 -0700
+@@ -1 +1,2 @@
+ Mario Strasser <mast@xxxxxxx>
++INTEL Corp <>
+diff -uprN orig/tpm_emulator-0.2/ChangeLog vtpm/ChangeLog
+--- orig/tpm_emulator-0.2/ChangeLog 2005-08-17 10:58:36.000000000 -0700
++++ vtpm/ChangeLog 2005-08-17 10:55:52.000000000 -0700
+@@ -1,3 +1,7 @@
++2005-08-16 Intel Corp
++ Moved module out of kernel to run as a ring 3 app
++ Modified save_to_file and load_from_file to call a xen backend driver
to call a VTPM manager
++
+ 2005-08-15 Mario Strasser <mast@xxxxxxx>
+ * all: some typos corrected
+ * tpm_integrity.c: bug in TPM_Extend fixed
+diff -uprN orig/tpm_emulator-0.2/Makefile vtpm/Makefile
+--- orig/tpm_emulator-0.2/Makefile 2005-08-17 10:58:36.000000000 -0700
++++ vtpm/Makefile 2005-08-17 10:55:52.000000000 -0700
+@@ -1,21 +1,29 @@
+ # Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ # Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>
++# Copyright (C) 2005 INTEL Corp.
+ #
+ # $Id: Makefile 10 2005-04-26 20:59:50Z mast $
+
+-# kernel settings
+-KERNEL_RELEASE := $(shell uname -r)
+-KERNEL_BUILD := /lib/modules/$(KERNEL_RELEASE)/build
+-MOD_SUBDIR := misc
+-
+ # module settings
+-MODULE_NAME := tpm_emulator
++BIN := vtpmd
+ VERSION_MAJOR := 0
+ VERSION_MINOR := 2
+ VERSION_BUILD := $(shell date +"%s")
+
+-# enable/disable DEBUG messages
+-EXTRA_CFLAGS += -DDEBUG -g
++# Installation program and options
++INSTALL = install
++INSTALL_PROG = $(INSTALL) -m0755
++INSTALL_DIR = $(INSTALL) -d -m0755
++
++# Xen tools installation directory
++TOOLS_INSTALL_DIR = $(DESTDIR)/usr/bin
++
++CC := gcc
++CFLAGS += -g -Wall $(INCLUDE) -DDEBUG
++CFLAGS += -I. -Itpm
++
++# Is the simulator running in it's own vm?
++#CFLAGS += -DVTPM_MULTI_VM
+
+ # GNU MP configuration
+ GMP_LIB := /usr/lib/libgmp.a
+@@ -27,38 +35,31 @@ DIRS := . crypto tpm
+ SRCS := $(foreach dir, $(DIRS), $(wildcard $(src)/$(dir)/*.c))
+ OBJS := $(patsubst %.c, %.o, $(SRCS))
+ SRCS += $(foreach dir, $(DIRS), $(wildcard $(src)/$(dir)/*.h))
+-DISTSRC := ./README ./AUTHORS ./ChangeLog ./Makefile $(SRCS)
+-DISTDIR := tpm_emulator-$(VERSION_MAJOR).$(VERSION_MINOR)
+
+-obj-m := $(MODULE_NAME).o
+-$(MODULE_NAME)-objs := $(patsubst $(src)/%.o, %.o, $(OBJS)) crypto/libgmp.a
++obj-m := $(BIN)
++$(BIN)-objs := $(patsubst $(src)/%.o, %.o, $(OBJS)) crypto/libgmp.a
+
+ EXTRA_CFLAGS += -I$(src) -I$(src)/crypto -I$(src)/tpm
+
+ # do not print "Entering directory ..."
+ MAKEFLAGS += --no-print-directory
+
+-all: $(src)/crypto/gmp.h $(src)/crypto/libgmp.a version
+- @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) modules
++all: $(BIN)
++
++$(BIN): $(src)/crypto/gmp.h $(src)/crypto/libgmp.a version $(SRCS)
$(OBJS)
++ $(CC) $(CFLAGS) $(OBJS) $(src)/crypto/libgmp.a -o $(BIN)
++
++%.o: %.c
++ $(CC) $(CFLAGS) -c $< -o $@
+
+ install:
+- @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) modules_install
+- test -d /var/tpm || mkdir /var/tpm
+- test -c /dev/tpm || mknod /dev/tpm c 10 224
+- chmod 666 /dev/tpm
+- depmod -a
++ $(INSTALL_PROG) $(BIN) $(TOOLS_INSTALL_DIR)
+
+ clean:
+- @$(MAKE) -C $(KERNEL_BUILD) M=$(CURDIR) clean
+- rm -f $(src)/crypto/gmp.h $(src)/crypto/libgmp.a
++ rm -f $(src)/crypto/gmp.h $(src)/crypto/libgmp.a $(OBJS)
+
+-dist: $(DISTSRC)
+- rm -rf $(DISTDIR)
+- mkdir $(DISTDIR)
+- cp --parents $(DISTSRC) $(DISTDIR)/
+- rm -f $(DISTDIR)/crypto/gmp.h
+- tar -chzf $(DISTDIR).tar.gz $(DISTDIR)
+- rm -rf $(DISTDIR)
++mrproper: clean
++ rm -f $(BIN)
+
+ $(src)/crypto/libgmp.a:
+ test -f $(src)/crypto/libgmp.a || ln -s $(GMP_LIB)
$(src)/crypto/libgmp.a
+diff -uprN orig/tpm_emulator-0.2/README vtpm/README
+--- orig/tpm_emulator-0.2/README 2005-08-17 10:58:36.000000000 -0700
++++ vtpm/README 2005-08-17 10:55:52.000000000 -0700
+@@ -13,7 +13,8 @@ $Id: README 8 2005-01-25 21:11:45Z jmoli
+ Copyright
+ --------------------------------------------------------------------------
+ Copyright (C) 2004 Mario Strasser <mast@xxxxxxx> and Swiss Federal
+-Institute of Technology (ETH) Zurich.
++ Institute of Technology (ETH) Zurich.
++Copyright (C) 2005 INTEL Corp
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+diff -uprN orig/tpm_emulator-0.2/crypto/gmp_kernel_wrapper.c
vtpm/crypto/gmp_kernel_wrapper.c
+--- orig/tpm_emulator-0.2/crypto/gmp_kernel_wrapper.c 2005-08-17
10:58:36.000000000 -0700
++++ vtpm/crypto/gmp_kernel_wrapper.c 2005-08-17 10:55:52.000000000 -0700
+@@ -1,5 +1,6 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -24,15 +25,10 @@ int __gmp_junk;
+ void __attribute__ ((regparm(0))) __gmp_assert_fail(const char *filename,
+ int linenum, const char *expr)
+ {
+- panic(KERN_CRIT TPM_MODULE_NAME "%s:%d: GNU MP assertion failed: %s\n",
++ error("%s:%d: GNU MP assertion failed: %s\n",
+ filename, linenum, expr);
+ }
+
+-void __attribute__ ((regparm(0))) abort(void)
+-{
+- panic(KERN_CRIT TPM_MODULE_NAME "GNU MP abort() was called\n");
+-}
+-
+ /* overwrite GNU MP random functions (used by mpz/millerrabin.c) */
+
+ void __attribute__ ((regparm(0))) gmp_randinit(gmp_randstate_t rstate,
+@@ -77,20 +73,19 @@ void __attribute__ ((regparm(0))) mpz_ur
+
+ void __attribute__ ((regparm(0))) *kernel_allocate(size_t size)
+ {
+- void *ret = (void*)kmalloc(size, GFP_KERNEL);
+- if (!ret) panic(KERN_CRIT TPM_MODULE_NAME
+- "GMP: cannot allocate memory (size=%u)\n", size);
++ void *ret = (void*)malloc(size);
++ if (!ret) error("GMP: cannot allocate memory (size=%u)\n", size);
+ return ret;
+ }
+
+ void __attribute__ ((regparm(0))) *kernel_reallocate(void *oldptr,
+ size_t old_size, size_t new_size)
+ {
+- void *ret = (void*)kmalloc(new_size, GFP_KERNEL);
+- if (!ret) panic(KERN_CRIT TPM_MODULE_NAME "GMP: Cannot reallocate memory "
++ void *ret = (void*)malloc(new_size);
++ if (!ret) error("GMP: Cannot reallocate memory "
+ "(old_size=%u new_size=%u)\n", old_size, new_size);
+ memcpy(ret, oldptr, old_size);
+- kfree(oldptr);
++ free(oldptr);
+ return ret;
+ }
+
+@@ -99,7 +94,7 @@ void __attribute__ ((regparm(0))) kernel
+ /* overwrite used memory */
+ if (blk_ptr != NULL) {
+ memset(blk_ptr, 0, blk_size);
+- kfree(blk_ptr);
++ free(blk_ptr);
+ }
+ }
+
+diff -uprN orig/tpm_emulator-0.2/crypto/rsa.c vtpm/crypto/rsa.c
+--- orig/tpm_emulator-0.2/crypto/rsa.c 2005-08-17 10:58:36.000000000 -0700
++++ vtpm/crypto/rsa.c 2005-08-17 10:55:52.000000000 -0700
+@@ -1,5 +1,6 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -363,7 +364,7 @@ static int encode_message(int type, uint
+ msg[0] = 0x00;
+ get_random_bytes(&msg[1], SHA1_DIGEST_LENGTH);
+ sha1_init(&ctx);
+- sha1_update(&ctx, "TCPA", 4);
++ sha1_update(&ctx, (uint8_t *) "TCPA", 4);
+ sha1_final(&ctx, &msg[1 + SHA1_DIGEST_LENGTH]);
+ memset(&msg[1 + 2 * SHA1_DIGEST_LENGTH], 0x00,
+ msg_len - data_len - 2 * SHA1_DIGEST_LENGTH - 2);
+@@ -411,7 +412,7 @@ static int decode_message(int type, uint
+ mask_generation(&msg[1], SHA1_DIGEST_LENGTH,
+ &msg[1 + SHA1_DIGEST_LENGTH], msg_len - SHA1_DIGEST_LENGTH - 1);
+ sha1_init(&ctx);
+- sha1_update(&ctx, "TCPA", 4);
++ sha1_update(&ctx, (uint8_t *) "TCPA", 4);
+ sha1_final(&ctx, &msg[1]);
+ if (memcmp(&msg[1], &msg[1 + SHA1_DIGEST_LENGTH],
+ SHA1_DIGEST_LENGTH) != 0) return -1;
+diff -uprN orig/tpm_emulator-0.2/linux_module.c vtpm/linux_module.c
+--- orig/tpm_emulator-0.2/linux_module.c 2005-08-17 10:58:36.000000000
-0700
++++ vtpm/linux_module.c 1969-12-31 16:00:00.000000000 -0800
+@@ -1,163 +0,0 @@
+-/* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+- * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+- *
+- * This module is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published
+- * by the Free Software Foundation; either version 2 of the License,
+- * or (at your option) any later version.
+- *
+- * This module is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * $Id: linux_module.c 19 2005-05-18 08:29:37Z mast $
+- */
+-
+-#include <linux/module.h>
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/miscdevice.h>
+-#include <linux/poll.h>
+-#include "linux_module.h"
+-#include "tpm/tpm_emulator.h"
+-
+-MODULE_LICENSE("GPL");
+-MODULE_AUTHOR("Mario Strasser <mast@xxxxxxx>");
+-MODULE_DESCRIPTION("Trusted Platform Module (TPM) Emulator");
+-MODULE_SUPPORTED_DEVICE(TPM_DEVICE_NAME);
+-
+-/* module startup parameters */
+-char *startup = "save";
+-MODULE_PARM(startup, "s");
+-MODULE_PARM_DESC(startup, " Sets the startup mode of the TPM. "
+- "Possible values are 'clear', 'save' (default) and 'deactivated.");
+-char *storage_file = "/var/tpm/tpm_emulator-1.2.0.1";
+-MODULE_PARM(storage_file, "s");
+-MODULE_PARM_DESC(storage_file, " Sets the persistent-data storage "
+- "file of the TPM.");
+-
+-/* TPM lock */
+-static struct semaphore tpm_mutex;
+-
+-/* TPM command response */
+-static struct {
+- uint8_t *data;
+- uint32_t size;
+-} tpm_response;
+-
+-/* module state */
+-#define STATE_IS_OPEN 0
+-static uint32_t module_state;
+-
+-static int tpm_open(struct inode *inode, struct file *file)
+-{
+- debug("%s()", __FUNCTION__);
+- if (test_and_set_bit(STATE_IS_OPEN, (void*)&module_state)) return -EBUSY;
+- return 0;
+-}
+-
+-static int tpm_release(struct inode *inode, struct file *file)
+-{
+- debug("%s()", __FUNCTION__);
+- clear_bit(STATE_IS_OPEN, (void*)&module_state);
+- return 0;
+-}
+-
+-static ssize_t tpm_read(struct file *file, char *buf, size_t count, loff_t
*ppos)
+-{
+- debug("%s(%d)", __FUNCTION__, count);
+- down(&tpm_mutex);
+- if (tpm_response.data != NULL) {
+- count = min(count, (size_t)tpm_response.size - (size_t)*ppos);
+- count -= copy_to_user(buf, &tpm_response.data[*ppos], count);
+- *ppos += count;
+- } else {
+- count = 0;
+- }
+- up(&tpm_mutex);
+- return count;
+-}
+-
+-static ssize_t tpm_write(struct file *file, const char *buf, size_t count,
loff_t *ppos)
+-{
+- debug("%s(%d)", __FUNCTION__, count);
+- down(&tpm_mutex);
+- *ppos = 0;
+- if (tpm_response.data != NULL) kfree(tpm_response.data);
+- if (tpm_handle_command(buf, count, &tpm_response.data,
+- &tpm_response.size) != 0) {
+- count = -EILSEQ;
+- tpm_response.data = NULL;
+- }
+- up(&tpm_mutex);
+- return count;
+-}
+-
+-static int tpm_ioctl(struct inode *inode, struct file *file, unsigned int
cmd, unsigned long arg)
+-{
+- debug("%s(%d, %ld)", __FUNCTION__, cmd, arg);
+- return -1;
+-}
+-
+-struct file_operations fops = {
+- .owner = THIS_MODULE,
+- .open = tpm_open,
+- .release = tpm_release,
+- .read = tpm_read,
+- .write = tpm_write,
+- .ioctl = tpm_ioctl,
+-};
+-
+-static struct miscdevice tpm_dev = {
+- .minor = TPM_DEVICE_MINOR,
+- .name = TPM_DEVICE_NAME,
+- .fops = &fops,
+-};
+-
+-int __init init_tpm_module(void)
+-{
+- int res = misc_register(&tpm_dev);
+- if (res != 0) {
+- error("misc_register() failed for minor %d\n", TPM_DEVICE_MINOR);
+- return res;
+- }
+- /* initialize variables */
+- sema_init(&tpm_mutex, 1);
+- module_state = 0;
+- tpm_response.data = NULL;
+- /* initialize TPM emulator */
+- if (!strcmp(startup, "clear")) {
+- tpm_emulator_init(1);
+- } else if (!strcmp(startup, "save")) {
+- tpm_emulator_init(2);
+- } else if (!strcmp(startup, "deactivated")) {
+- tpm_emulator_init(3);
+- } else {
+- error("invalid startup mode '%s'; must be 'clear', "
+- "'save' (default) or 'deactivated", startup);
+- misc_deregister(&tpm_dev);
+- return -EINVAL;
+- }
+- return 0;
+-}
+-
+-void __exit cleanup_tpm_module(void)
+-{
+- tpm_emulator_shutdown();
+- misc_deregister(&tpm_dev);
+-}
+-
+-module_init(init_tpm_module);
+-module_exit(cleanup_tpm_module);
+-
+-uint64_t tpm_get_ticks(void)
+-{
+- static struct timespec old_time = {0, 0};
+- struct timespec new_time = current_kernel_time();
+- uint64_t ticks = (uint64_t)(old_time.tv_sec - new_time.tv_sec) * 1000000
+- + (old_time.tv_nsec - new_time.tv_nsec) / 1000;
+- old_time = new_time;
+- return (ticks > 0) ? ticks : 1;
+-}
+-
+diff -uprN orig/tpm_emulator-0.2/linux_module.h vtpm/linux_module.h
+--- orig/tpm_emulator-0.2/linux_module.h 2005-08-17 10:58:36.000000000
-0700
++++ vtpm/linux_module.h 2005-08-17 10:55:52.000000000 -0700
+@@ -1,5 +1,6 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -17,17 +18,22 @@
+ #ifndef _LINUX_MODULE_H_
+ #define _LINUX_MODULE_H_
+
+-#include <linux/version.h>
+-#include <linux/kernel.h>
+-#include <linux/slab.h>
++#include <malloc.h>
++#include <stdint.h>
++#include <stdio.h>
++#include <string.h>
+ #include <linux/types.h>
+-#include <linux/string.h>
+-#include <linux/random.h>
+-#include <linux/time.h>
+-#include <asm/byteorder.h>
+
+-/* module settings */
++#include <endian.h>
++#define __BYTEORDER_HAS_U64__
++#ifdef LITTLE_ENDIAN
++ #include <linux/byteorder/little_endian.h>
++#else
++ #include <linux/byteorder/big_endian.h>
++#endif
+
++/* module settings */
++#define min(A,B) ((A)<(B)?(A):(B))
+ #define STR(s) __STR__(s)
+ #define __STR__(s) #s
+ #include "tpm_version.h"
+@@ -39,32 +45,35 @@
+ /* debug and log output functions */
+
+ #ifdef DEBUG
+-#define debug(fmt, ...) printk(KERN_DEBUG "%s %s:%d: Debug: " fmt "\n", \
+- TPM_MODULE_NAME, __FILE__, __LINE__, ## __VA_ARGS__)
++#define debug(fmt, ...) printf("%s:%d: Debug: " fmt "\n", \
++ __FILE__, __LINE__, ## __VA_ARGS__)
+ #else
+ #define debug(fmt, ...)
+ #endif
+-#define info(fmt, ...) printk(KERN_INFO "%s %s:%d: Info: " fmt "\n", \
+- TPM_MODULE_NAME, __FILE__, __LINE__, ## __VA_ARGS__)
+-#define error(fmt, ...) printk(KERN_ERR "%s %s:%d: Error: " fmt "\n", \
+- TPM_MODULE_NAME, __FILE__, __LINE__, ## __VA_ARGS__)
+-#define alert(fmt, ...) printk(KERN_ALERT "%s %s:%d: Alert: " fmt "\n", \
+- TPM_MODULE_NAME, __FILE__, __LINE__, ## __VA_ARGS__)
++#define info(fmt, ...) printf("%s:%d: Info: " fmt "\n", \
++ __FILE__, __LINE__, ## __VA_ARGS__)
++#define error(fmt, ...) printf("%s:%d: Error: " fmt "\n", \
++ __FILE__, __LINE__, ## __VA_ARGS__)
++#define alert(fmt, ...) printf("%s:%d: Alert: " fmt "\n", \
++ __FILE__, __LINE__, ## __VA_ARGS__)
+
+ /* memory allocation */
+
+ static inline void *tpm_malloc(size_t size)
+ {
+- return kmalloc(size, GFP_KERNEL);
++ return malloc(size);
+ }
+
+ static inline void tpm_free(const void *ptr)
+ {
+- if (ptr != NULL) kfree(ptr);
++ if (ptr != NULL) free( (void *) ptr);
+ }
+
+ /* random numbers */
+
++//FIXME;
++void get_random_bytes(void *buf, int nbytes);
++
+ static inline void tpm_get_random_bytes(void *buf, int nbytes)
+ {
+ get_random_bytes(buf, nbytes);
+@@ -84,9 +93,9 @@ uint64_t tpm_get_ticks(void);
+ #define CPU_TO_LE16(x) __cpu_to_le16(x)
+
+ #define BE64_TO_CPU(x) __be64_to_cpu(x)
+-#define LE64_TO_CPU(x) __be64_to_cpu(x)
++#define LE64_TO_CPU(x) __le64_to_cpu(x)
+ #define BE32_TO_CPU(x) __be32_to_cpu(x)
+-#define LE32_TO_CPU(x) __be32_to_cpu(x)
++#define LE32_TO_CPU(x) __le32_to_cpu(x)
+ #define BE16_TO_CPU(x) __be16_to_cpu(x)
+ #define LE16_TO_CPU(x) __le16_to_cpu(x)
+
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_audit.c vtpm/tpm/tpm_audit.c
+--- orig/tpm_emulator-0.2/tpm/tpm_audit.c 2005-08-17 10:58:36.000000000
-0700
++++ vtpm/tpm/tpm_audit.c 2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+ * Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -45,14 +46,14 @@ void tpm_audit_request(TPM_COMMAND_CODE
+ tpmData.permanent.data.auditMonotonicCounter++;
+ }
+ /* update audit digest */
+- *((UINT16*)&buf[0]) = cpu_to_be16(TPM_TAG_AUDIT_EVENT_IN);
+- *((UINT32*)&buf[2]) = cpu_to_be32(ordinal);
++ *((UINT16*)&buf[0]) = CPU_TO_BE16(TPM_TAG_AUDIT_EVENT_IN);
++ *((UINT32*)&buf[2]) = CPU_TO_BE32(ordinal);
+ sha1_init(&sha1_ctx);
+ sha1_update(&sha1_ctx, req->param, req->paramSize);
+ sha1_final(&sha1_ctx, &buf[6]);
+- *((UINT16*)&buf[26]) = cpu_to_be16(TPM_TAG_COUNTER_VALUE);
++ *((UINT16*)&buf[26]) = CPU_TO_BE16(TPM_TAG_COUNTER_VALUE);
+ memset(&buf[30], 0, 4);
+- *((UINT32*)&buf[34]) =
cpu_to_be32(tpmData.permanent.data.auditMonotonicCounter);
++ *((UINT32*)&buf[34]) =
CPU_TO_BE32(tpmData.permanent.data.auditMonotonicCounter);
+ sha1_init(&sha1_ctx);
+ sha1_update(&sha1_ctx, tpmData.stany.data.auditDigest.digest,
+ sizeof(TPM_DIGEST));
+@@ -70,15 +71,15 @@ void tpm_audit_response(TPM_COMMAND_CODE
+ && (AUDIT_STATUS[ord / 8] & (1 << (ord & 0x07)))) {
+ info("tpm_audit_response()");
+ /* update audit digest */
+- *((UINT16*)&buf[0]) = cpu_to_be16(TPM_TAG_AUDIT_EVENT_OUT);
+- *((UINT32*)&buf[2]) = cpu_to_be32(ordinal);
++ *((UINT16*)&buf[0]) = CPU_TO_BE16(TPM_TAG_AUDIT_EVENT_OUT);
++ *((UINT32*)&buf[2]) = CPU_TO_BE32(ordinal);
+ sha1_init(&sha1_ctx);
+ sha1_update(&sha1_ctx, rsp->param, rsp->paramSize);
+ sha1_final(&sha1_ctx, &buf[6]);
+- *((UINT16*)&buf[26]) = cpu_to_be16(TPM_TAG_COUNTER_VALUE);
++ *((UINT16*)&buf[26]) = CPU_TO_BE16(TPM_TAG_COUNTER_VALUE);
+ memset(&buf[30], 0, 4);
+- *((UINT32*)&buf[34]) =
cpu_to_be32(tpmData.permanent.data.auditMonotonicCounter);
+- *((UINT32*)&buf[34]) = cpu_to_be32(rsp->result);
++ *((UINT32*)&buf[34]) =
CPU_TO_BE32(tpmData.permanent.data.auditMonotonicCounter);
++ *((UINT32*)&buf[34]) = CPU_TO_BE32(rsp->result);
+ sha1_init(&sha1_ctx);
+ sha1_update(&sha1_ctx, tpmData.stany.data.auditDigest.digest,
+ sizeof(TPM_DIGEST));
+@@ -158,7 +159,7 @@ TPM_RESULT TPM_GetAuditDigestSigned(TPM_
+ }
+ memcpy(&buf[0], "\x05\x00ADIG", 6);
+ memcpy(&buf[6], antiReplay->nonce, 20);
+- *(UINT32*)&buf[26] = cpu_to_be32(buf_size - 30);
++ *(UINT32*)&buf[26] = CPU_TO_BE32(buf_size - 30);
+ memcpy(&buf[30], auditDigest->digest, 20);
+ ptr = &buf[50];
+ len = buf_size - 50;
+@@ -198,4 +199,3 @@ TPM_RESULT TPM_SetOrdinalAuditStatus(TPM
+ }
+ return TPM_SUCCESS;
+ }
+-
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_authorization.c
vtpm/tpm/tpm_authorization.c
+--- orig/tpm_emulator-0.2/tpm/tpm_authorization.c 2005-08-17
10:58:36.000000000 -0700
++++ vtpm/tpm/tpm_authorization.c 2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+ * Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -268,7 +269,7 @@ TPM_RESULT tpm_verify_auth(TPM_AUTH *aut
+ {
+ hmac_ctx_t ctx;
+ TPM_SESSION_DATA *session;
+- UINT32 auth_handle = cpu_to_be32(auth->authHandle);
++ UINT32 auth_handle = CPU_TO_BE32(auth->authHandle);
+
+ info("tpm_verify_auth(%08x)", auth->authHandle);
+ /* get dedicated authorization session */
+@@ -316,5 +317,3 @@ void tpm_decrypt_auth_secret(TPM_ENCAUTH
+ for (i = 0; i < sizeof(TPM_SECRET); i++)
+ plainAuth[i] ^= encAuth[i];
+ }
+-
+-
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_capability.c vtpm/tpm/tpm_capability.c
+--- orig/tpm_emulator-0.2/tpm/tpm_capability.c 2005-08-17 10:58:36.000000000
-0700
++++ vtpm/tpm/tpm_capability.c 2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+ * Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -398,7 +399,7 @@ TPM_RESULT TPM_GetCapability(TPM_CAPABIL
+
+ case TPM_CAP_KEY_HANDLE:
+ debug("[TPM_CAP_KEY_HANDLE]");
+- subCapSize = cpu_to_be32(TPM_RT_KEY);
++ subCapSize = CPU_TO_BE32(TPM_RT_KEY);
+ return cap_handle(4, (BYTE*)&subCapSize, respSize, resp);
+
+ case TPM_CAP_CHECK_LOADED:
+@@ -472,4 +473,3 @@ TPM_RESULT TPM_GetCapability(TPM_CAPABIL
+ return TPM_BAD_MODE;
+ }
+ }
+-
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_cmd_handler.c
vtpm/tpm/tpm_cmd_handler.c
+--- orig/tpm_emulator-0.2/tpm/tpm_cmd_handler.c 2005-08-17
10:58:36.000000000 -0700
++++ vtpm/tpm/tpm_cmd_handler.c 2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+ * Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -26,7 +27,7 @@ static void tpm_compute_in_param_digest(
+ {
+ sha1_ctx_t sha1;
+ UINT32 offset;
+- UINT32 ord = cpu_to_be32(req->ordinal);
++ UINT32 ord = CPU_TO_BE32(req->ordinal);
+
+ /* skip all key-handles at the beginning */
+ switch (req->ordinal) {
+@@ -82,8 +83,8 @@ static void tpm_compute_in_param_digest(
+ static void tpm_compute_out_param_digest(TPM_COMMAND_CODE ordinal,
TPM_RESPONSE *rsp)
+ {
+ sha1_ctx_t sha1;
+- UINT32 res = cpu_to_be32(rsp->result);
+- UINT32 ord = cpu_to_be32(ordinal);
++ UINT32 res = CPU_TO_BE32(rsp->result);
++ UINT32 ord = CPU_TO_BE32(ordinal);
+
+ /* compute SHA1 hash */
+ sha1_init(&sha1);
+@@ -3081,7 +3082,7 @@ static void tpm_setup_rsp_auth(TPM_COMMA
+ hmac_update(&hmac, rsp->auth2->digest, sizeof(rsp->auth2->digest));
+ #if 0
+ if (tpm_get_auth(rsp->auth2->authHandle)->type == TPM_ST_OIAP) {
+- UINT32 handle = cpu_to_be32(rsp->auth2->authHandle);
++ UINT32 handle = CPU_TO_BE32(rsp->auth2->authHandle);
+ hmac_update(&hmac, (BYTE*)&handle, 4);
+ }
+ #endif
+@@ -3096,7 +3097,7 @@ static void tpm_setup_rsp_auth(TPM_COMMA
+ hmac_update(&hmac, rsp->auth1->digest, sizeof(rsp->auth1->digest));
+ #if 0
+ if (tpm_get_auth(rsp->auth1->authHandle)->type == TPM_ST_OIAP) {
+- UINT32 handle = cpu_to_be32(rsp->auth1->authHandle);
++ UINT32 handle = CPU_TO_BE32(rsp->auth1->authHandle);
+ hmac_update(&hmac, (BYTE*)&handle, 4);
+ }
+ #endif
+@@ -3179,7 +3180,9 @@ extern const char *tpm_error_to_string(T
+ static void tpm_execute_command(TPM_REQUEST *req, TPM_RESPONSE *rsp)
+ {
+ TPM_RESULT res;
+-
++
++ req->tag = (BYTE) req->tag; // VIN HACK!!!
++
+ /* setup authorisation as well as response tag and size */
+ memset(rsp, 0, sizeof(*rsp));
+ switch (req->tag) {
+@@ -3878,4 +3881,3 @@ int tpm_handle_command(const uint8_t *in
+ tpm_free(rsp.param);
+ return 0;
+ }
+-
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_crypto.c vtpm/tpm/tpm_crypto.c
+--- orig/tpm_emulator-0.2/tpm/tpm_crypto.c 2005-08-17 10:58:36.000000000
-0700
++++ vtpm/tpm/tpm_crypto.c 2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+ * Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -106,7 +107,7 @@ TPM_RESULT tpm_sign(TPM_KEY_DATA *key, T
+ /* setup TPM_SIGN_INFO structure */
+ memcpy(&buf[0], "\x05\x00SIGN", 6);
+ memcpy(&buf[6], auth->nonceOdd.nonce, 20);
+- *(UINT32*)&buf[26] = cpu_to_be32(areaToSignSize);
++ *(UINT32*)&buf[26] = CPU_TO_BE32(areaToSignSize);
+ memcpy(&buf[30], areaToSign, areaToSignSize);
+ if (rsa_sign(&key->key, RSA_SSA_PKCS1_SHA1,
+ buf, areaToSignSize + 30, *sig)) {
+@@ -379,4 +380,3 @@ TPM_RESULT TPM_CertifyKey2(TPM_KEY_HANDL
+ }
+ return TPM_SUCCESS;
+ }
+-
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_data.c vtpm/tpm/tpm_data.c
+--- orig/tpm_emulator-0.2/tpm/tpm_data.c 2005-08-17 10:58:36.000000000
-0700
++++ vtpm/tpm/tpm_data.c 2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+ * Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -15,9 +16,15 @@
+ * $Id: tpm_data.c 9 2005-04-26 18:15:31Z mast $
+ */
+
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <unistd.h>
++
+ #include "tpm_emulator.h"
+ #include "tpm_structures.h"
+ #include "tpm_marshalling.h"
++#include "vtpm_manager.h"
+
+ TPM_DATA tpmData;
+
+@@ -28,6 +35,7 @@ BOOL tpm_get_physical_presence(void)
+
+ void tpm_init_data(void)
+ {
++#ifndef TPM_GENERATE_EK
+ /* endorsement key */
+ uint8_t ek_n[] = "\xa8\xdb\xa9\x42\xa8\xf3\xb8\x06\x85\x90\x76\x93\xad\xf7"
+ "\x74\xec\x3f\xd3\x3d\x9d\xe8\x2e\xff\x15\xed\x0e\xce\x5f\x93"
+@@ -66,6 +74,8 @@ void tpm_init_data(void)
+ "\xd1\xc0\x8b\x5b\xa2\x2e\xa7\x15\xca\x50\x75\x10\x48\x9c\x2b"
+ "\x18\xb9\x67\x8f\x5d\x64\xc3\x28\x9f\x2f\x16\x2f\x08\xda\x47"
+ "\xec\x86\x43\x0c\x80\x99\x07\x34\x0f";
++#endif
++
+ int i;
+ /* reset all data to NULL, FALSE or 0 */
+ memset(&tpmData, 0, sizeof(tpmData));
+@@ -85,6 +95,10 @@ void tpm_init_data(void)
+ tpmData.permanent.data.version.revMinor = VERSION_MINOR;
+ /* setup PCR attributes */
+ for (i = 0; i < TPM_NUM_PCR; i++) {
++ int j;
++ for (j=0; j < TPM_NUM_LOCALITY; j++) {
++ tpmData.permanent.data.pcrAttrib[i].pcrExtendLocal[j] = TRUE;
++ }
+ tpmData.permanent.data.pcrAttrib[i].pcrReset = TRUE;
+ }
+ /* set tick type */
+@@ -115,49 +129,235 @@ void tpm_release_data(void)
+
+ #ifdef TPM_STORE_TO_FILE
+
+-#include <linux/fs.h>
+-#include <linux/unistd.h>
+-#include <asm/uaccess.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++
++ static int vtpm_tx_fh=-1, vtpm_rx_fh=-1;
+
+-#define TPM_STORAGE_FILE "/var/tpm/tpm_emulator-1.2." STR(VERSION_MAJOR) "."
STR(VERSION_MINOR)
++#ifdef VTPM_MUTLI_VM
++ #define DEV_FE "/dev/tpm"
++#else
++ #define VTPM_RX_FIFO_D "/var/vtpm/fifos/vtpm-to-%d.fifo"
++ #define VTPM_TX_FIFO "/var/vtpm/fifos/vtpm-from-all.fifo"
++
++ extern int dmi_id;
++ static char *vtpm_rx_name=NULL;
++#endif
+
+ static int write_to_file(uint8_t *data, size_t data_length)
+ {
+- int res;
+- struct file *fp;
+- mm_segment_t old_fs = get_fs();
+- fp = filp_open(TPM_STORAGE_FILE, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR |
S_IWUSR);
+- if (IS_ERR(fp)) return -1;
+- set_fs(get_ds());
+- res = fp->f_op->write(fp, data, data_length, &fp->f_pos);
+- set_fs(old_fs);
+- filp_close(fp, NULL);
+- return (res == data_length) ? 0 : -1;
++ int res, out_data_size, in_header_size;
++ BYTE *ptr, *out_data, *in_header;
++ UINT32 result, len, in_rsp_size;
++ UINT16 tag = VTPM_TAG_REQ;
++
++ printf("Saving NVM\n");
++ if (vtpm_tx_fh < 0) {
++#ifdef VTPM_MUTLI_VM
++ vtpm_tx_fh = open(DEV_FE, O_RDWR);
++#else
++ vtpm_tx_fh = open(VTPM_TX_FIFO, O_WRONLY);
++#endif
++ }
++
++ if (vtpm_tx_fh < 0) {
++ return -1;
++ }
++
++ // Send request to VTPM Manager to encrypt data
++#ifdef VTPM_MUTLI_VM
++ out_data_size = len = VTPM_COMMAND_HEADER_SIZE_CLT + data_length;
++#else
++ out_data_size = len = VTPM_COMMAND_HEADER_SIZE_SRV + data_length;
++#endif
++
++ out_data = ptr = (BYTE *) malloc(len);
++
++ if (ptr == NULL
++#ifndef VTPM_MUTLI_VM
++ || tpm_marshal_UINT32(&ptr, &len, dmi_id)
++#endif
++ || tpm_marshal_UINT16(&ptr, &len, tag)
++#ifdef VTPM_MUTLI_VM
++ || tpm_marshal_UINT32(&ptr, &len, out_data_size)
++#else
++ || tpm_marshal_UINT32(&ptr, &len, out_data_size - sizeof(uint32_t))
++#endif
++ || tpm_marshal_UINT32(&ptr, &len, VTPM_ORD_SAVENVM)
++ || tpm_marshal_BYTE_ARRAY(&ptr, &len, data, data_length)) {
++ free(out_data);
++ return -1;
++ }
++
++ printf("\tSending SaveNVM Command.\n");
++ res = write(vtpm_tx_fh, out_data, out_data_size);
++ free(out_data);
++ if (res != out_data_size) return -1;
++
++ if (vtpm_rx_fh < 0) {
++#ifdef VTPM_MUTLI_VM
++ vtpm_rx_fh = vtpm_tx_fh
++#else
++ if (vtpm_rx_name == NULL) {
++ vtpm_rx_name = malloc(10 + strlen(VTPM_RX_FIFO_D));
++ sprintf(vtpm_rx_name, VTPM_RX_FIFO_D, (uint32_t) dmi_id);
++ }
++ vtpm_rx_fh = open(vtpm_rx_name, O_RDONLY);
++#endif
++ }
++
++ if (vtpm_rx_fh < 0) {
++ return -1;
++ }
++
++ // Read Header of response so we can get the size & status
++#ifdef VTPM_MUTLI_VM
++ in_header_size = len = VTPM_COMMAND_HEADER_SIZE_CLT;
++#else
++ in_header_size = len = VTPM_COMMAND_HEADER_SIZE_SRV;
++#endif
++ in_header = ptr = malloc(in_header_size);
++
++ printf("\tReading SaveNVM header.\n");
++ res = read(vtpm_rx_fh, in_header, in_header_size);
++
++ if ( (res != in_header_size)
++#ifndef VTPM_MUTLI_VM
++ || tpm_unmarshal_UINT32(&ptr, &len, (UINT32*)&dmi_id)
++#endif
++ || tpm_unmarshal_UINT16(&ptr, &len, &tag)
++ || tpm_unmarshal_UINT32(&ptr, &len, &in_rsp_size)
++ || tpm_unmarshal_UINT32(&ptr, &len, &result) ) {
++ free(in_header);
++ return -1;
++ }
++ free(in_header);
++
++ if (result != VTPM_SUCCESS) {
++ return -1;
++ }
++
++#ifdef VTPM_MUTLI_VM
++ close(vtpm_tx_fh); close(vtpm_rx_fh);
++#endif
++
++ printf("\tFinishing up SaveNVM\n");
++ return (0);
+ }
+
+ static int read_from_file(uint8_t **data, size_t *data_length)
+ {
+- int res;
+- struct file *fp;
+- mm_segment_t old_fs = get_fs();
+- fp = filp_open(TPM_STORAGE_FILE, O_RDONLY, 0);
+- if (IS_ERR(fp)) return -1;
+- *data_length = (size_t)fp->f_dentry->d_inode->i_size;
+- /* *data_length = i_size_read(fp->f_dentry->d_inode); */
+- *data = tpm_malloc(*data_length);
+- if (*data == NULL) {
+- filp_close(fp, NULL);
++ int res, out_data_size, in_header_size;
++ uint8_t *ptr, *out_data, *in_header;
++ UINT16 tag = VTPM_TAG_REQ;
++ UINT32 len, in_rsp_size, result;
++#ifdef VTPM_MUTLI_VM
++ int vtpm_rx_fh, vtpm_tx_fh;
++#endif
++
++ printf("Loading NVM.\n");
++ if (vtpm_tx_fh < 0) {
++#ifdef VTPM_MUTLI_VM
++ vtpm_tx_fh = open(DEV_FE, O_RDWR);
++#else
++ vtpm_tx_fh = open(VTPM_TX_FIFO, O_WRONLY);
++#endif
++ }
++
++ if (vtpm_tx_fh < 0) {
++ return -1;
++ }
++
++ // Send request to VTPM Manager to encrypt data
++#ifdef VTPM_MUTLI_VM
++ out_data_size = len = VTPM_COMMAND_HEADER_SIZE_CLT;
++#else
++ out_data_size = len = VTPM_COMMAND_HEADER_SIZE_SRV;
++#endif
++ out_data = ptr = (BYTE *) malloc(len);
++
++ if (ptr == NULL
++#ifndef VTPM_MUTLI_VM
++ || tpm_marshal_UINT32(&ptr, &len, dmi_id)
++#endif
++ || tpm_marshal_UINT16(&ptr, &len, tag)
++#ifdef VTPM_MUTLI_VM
++ || tpm_marshal_UINT32(&ptr, &len, out_data_size)
++#else
++ || tpm_marshal_UINT32(&ptr, &len, out_data_size - sizeof(uint32_t))
++#endif
++ || tpm_marshal_UINT32(&ptr, &len, VTPM_ORD_LOADNVM)) {
++ free(out_data);
+ return -1;
+ }
+- set_fs(get_ds());
+- res = fp->f_op->read(fp, *data, *data_length, &fp->f_pos);
+- set_fs(old_fs);
+- filp_close(fp, NULL);
++
++ printf("\tSending LoadNVM command\n");
++ res = write(vtpm_tx_fh, out_data, out_data_size);
++ free(out_data);
++ if (res != out_data_size) return -1;
++
++ if (vtpm_rx_fh < 0) {
++#ifdef VTPM_MUTLI_VM
++ vtpm_rx_fh = vtpm_tx_fh;
++#else
++ if (vtpm_rx_name == NULL) {
++ vtpm_rx_name = malloc(10 + strlen(VTPM_RX_FIFO_D));
++ sprintf(vtpm_rx_name, VTPM_RX_FIFO_D, (uint32_t) dmi_id);
++ }
++ vtpm_rx_fh = open(vtpm_rx_name, O_RDONLY);
++#endif
++ }
++
++ if (vtpm_rx_fh < 0) {
++ return -1;
++ }
++
++ // Read Header of response so we can get the size & status
++#ifdef VTPM_MUTLI_VM
++ in_header_size = len = VTPM_COMMAND_HEADER_SIZE_CLT;
++#else
++ in_header_size = len = VTPM_COMMAND_HEADER_SIZE_SRV;
++#endif
++ in_header = ptr = malloc(in_header_size);
++
++ printf("\tReading LoadNVM header\n");
++ res = read(vtpm_rx_fh, in_header, in_header_size);
++
++ if ( (res != in_header_size)
++#ifndef VTPM_MUTLI_VM
++ || tpm_unmarshal_UINT32(&ptr, &len, (UINT32*)&dmi_id)
++#endif
++ || tpm_unmarshal_UINT16(&ptr, &len, &tag)
++ || tpm_unmarshal_UINT32(&ptr, &len, &in_rsp_size)
++ || tpm_unmarshal_UINT32(&ptr, &len, &result) ) {
++ free(in_header);
++ return -1;
++ }
++ free(in_header);
++
++ if (result != VTPM_SUCCESS) {
++ return -1;
++ }
++
++ // Read Encrypted data from VTPM Manager
++ *data_length = in_rsp_size - VTPM_COMMAND_HEADER_SIZE_CLT;
++ *data = (uint8_t *) malloc(*data_length);
++
++ printf("\tReading clear data from LoadNVM.\n");
++ res = read(vtpm_rx_fh, *data, *data_length);
++#ifdef VTPM_MUTLI_VM
++ close(vtpm_rx_fh);close(vtpm_tx_fh);
++#endif
++
++ printf("\tReturing from loading NVM\n");
+ if (res != *data_length) {
+- tpm_free(*data);
+- return -1;
++ free(*data);
++ return -1;
++ } else {
++ return 0;
+ }
+- return 0;
++
+ }
+
+ #else
+@@ -231,7 +431,6 @@ int tpm_restore_permanent_data(void)
+
+ int tpm_erase_permanent_data(void)
+ {
+- int res = write_to_file("", 0);
++ int res = write_to_file((uint8_t*)"", 0);
+ return res;
+ }
+-
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_deprecated.c vtpm/tpm/tpm_deprecated.c
+--- orig/tpm_emulator-0.2/tpm/tpm_deprecated.c 2005-08-17 10:58:36.000000000
-0700
++++ vtpm/tpm/tpm_deprecated.c 2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+ * Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -50,7 +51,7 @@ TPM_RESULT TPM_SaveKeyContext(TPM_KEY_HA
+ BYTE *ptr;
+ UINT32 len;
+ info("TPM_SaveKeyContext()");
+- res = TPM_SaveContext(keyHandle, TPM_RT_KEY, "SaveKeyContext..",
++ res = TPM_SaveContext(keyHandle, TPM_RT_KEY, (BYTE*)"SaveKeyContext..",
+ keyContextSize, &contextBlob);
+ if (res != TPM_SUCCESS) return res;
+ len = *keyContextSize;
+@@ -82,7 +83,7 @@ TPM_RESULT TPM_SaveAuthContext(TPM_AUTHH
+ BYTE *ptr;
+ UINT32 len;
+ info("TPM_SaveAuthContext()");
+- res = TPM_SaveContext(authHandle, TPM_RT_KEY, "SaveAuthContext.",
++ res = TPM_SaveContext(authHandle, TPM_RT_KEY, (BYTE*)"SaveAuthContext.",
+ authContextSize, &contextBlob);
+ if (res != TPM_SUCCESS) return res;
+ len = *authContextSize;
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_emulator.h vtpm/tpm/tpm_emulator.h
+--- orig/tpm_emulator-0.2/tpm/tpm_emulator.h 2005-08-17 10:58:36.000000000
-0700
++++ vtpm/tpm/tpm_emulator.h 2005-08-17 10:55:52.000000000 -0700
+@@ -1,5 +1,6 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -22,7 +23,8 @@
+ /* TPM configuration */
+ #define TPM_STORE_TO_FILE 1
+ #undef TPM_STRONG_PERSISTENCE
+-#undef TPM_GENERATE_EK
++//#undef TPM_GENERATE_EK
++#define TPM_GENERATE_EK
+
+ /**
+ * tpm_emulator_init - initialises and starts the TPM emulator
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_integrity.c vtpm/tpm/tpm_integrity.c
+--- orig/tpm_emulator-0.2/tpm/tpm_integrity.c 2005-08-17 10:58:36.000000000
-0700
++++ vtpm/tpm/tpm_integrity.c 2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+ * Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -194,4 +195,3 @@ TPM_RESULT tpm_verify_pcr(TPM_KEY_DATA *
+ }
+ return TPM_SUCCESS;
+ }
+-
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_structures.h vtpm/tpm/tpm_structures.h
+--- orig/tpm_emulator-0.2/tpm/tpm_structures.h 2005-08-17 10:58:36.000000000
-0700
++++ vtpm/tpm/tpm_structures.h 2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+ * Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -18,7 +19,7 @@
+ #ifndef _TPM_STRUCTURES_H_
+ #define _TPM_STRUCTURES_H_
+
+-#include <linux/types.h>
++//#include <linux/types.h>
+ #include "crypto/rsa.h"
+
+ /*
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_testing.c vtpm/tpm/tpm_testing.c
+--- orig/tpm_emulator-0.2/tpm/tpm_testing.c 2005-08-17 10:58:36.000000000
-0700
++++ vtpm/tpm/tpm_testing.c 2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+ * Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -95,24 +96,24 @@ static int tpm_test_sha1(void)
+ struct {
+ uint8_t *data; uint32_t repetitions; uint8_t *digest;
+ } test_cases[] = {{
+- "abc", 1,
+-
"\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E\x25\x71\x78\x50\xC2\x6C\x9C\xD0\xD8\x9D"
++ (uint8_t*)"abc", 1,
++
(uint8_t*)"\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E\x25\x71\x78\x50\xC2\x6C\x9C\xD0\xD8\x9D"
+ }, {
+- "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
+-
"\x84\x98\x3E\x44\x1C\x3B\xD2\x6E\xBA\xAE\x4A\xA1\xF9\x51\x29\xE5\xE5\x46\x70\xF1"
++ (uint8_t*)"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
++
(uint8_t*)"\x84\x98\x3E\x44\x1C\x3B\xD2\x6E\xBA\xAE\x4A\xA1\xF9\x51\x29\xE5\xE5\x46\x70\xF1"
+ }, {
+- "a", 1000000,
+-
"\x34\xAA\x97\x3C\xD4\xC4\xDA\xA4\xF6\x1E\xEB\x2B\xDB\xAD\x27\x31\x65\x34\x01\x6F"
++ (uint8_t*)"a", 1000000,
++
(uint8_t*)"\x34\xAA\x97\x3C\xD4\xC4\xDA\xA4\xF6\x1E\xEB\x2B\xDB\xAD\x27\x31\x65\x34\x01\x6F"
+ }, {
+- "0123456701234567012345670123456701234567012345670123456701234567", 10,
+-
"\xDE\xA3\x56\xA2\xCD\xDD\x90\xC7\xA7\xEC\xED\xC5\xEB\xB5\x63\x93\x4F\x46\x04\x52"
++
(uint8_t*)"0123456701234567012345670123456701234567012345670123456701234567",
10,
++
(uint8_t*)"\xDE\xA3\x56\xA2\xCD\xDD\x90\xC7\xA7\xEC\xED\xC5\xEB\xB5\x63\x93\x4F\x46\x04\x52"
+ }};
+
+ debug("tpm_test_sha1()");
+ for (i = 0; i < sizeof(test_cases) / sizeof(test_cases[0]); i++) {
+ sha1_init(&ctx);
+ for (j = 0; j < test_cases[i].repetitions; j++)
+- sha1_update(&ctx, test_cases[i].data, strlen(test_cases[i].data));
++ sha1_update(&ctx, test_cases[i].data,
strlen((char*)test_cases[i].data));
+ sha1_final(&ctx, digest);
+ if (memcmp(digest, test_cases[i].digest, SHA1_DIGEST_LENGTH) != 0) return
-1;
+ }
+@@ -128,41 +129,41 @@ static int tpm_test_hmac(void)
+ struct {
+ uint8_t *key, key_len, *data, data_len, *digest;
+ } test_cases[] = {{
+- "\x0b", 20, "Hi There", 8,
+-
"\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1\x46\xbe\x00"
++ (uint8_t*)"\x0b", 20, (uint8_t*)"Hi There", 8,
++
(uint8_t*)"\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1\x46\xbe\x00"
+ }, {
+- "Jefe", 4, "what do ya want for nothing?", 28,
+-
"\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf\x9c\x25\x9a\x7c\x79"
++ (uint8_t*)"Jefe", 4, (uint8_t*)"what do ya want for nothing?", 28,
++
(uint8_t*)"\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf\x9c\x25\x9a\x7c\x79"
+ }, {
+- "\xaa", 20, "\xdd", 50,
+-
"\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b\x4f\x63\xf1\x75\xd3"
++ (uint8_t*)"\xaa", 20, (uint8_t*)"\xdd", 50,
++
(uint8_t*)"\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b\x4f\x63\xf1\x75\xd3"
+ }, {
+-
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14"
+- "\x15\x16\x17\x18\x19", 25, "\xcd", 50,
+-
"\x4c\x90\x07\xf4\x02\x62\x50\xc6\xbc\x84\x14\xf9\xbf\x50\xc8\x6c\x2d\x72\x35\xda"
++
(uint8_t*)"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14"
++ "\x15\x16\x17\x18\x19", 25, (uint8_t*)"\xcd", 50,
++
(uint8_t*)"\x4c\x90\x07\xf4\x02\x62\x50\xc6\xbc\x84\x14\xf9\xbf\x50\xc8\x6c\x2d\x72\x35\xda"
+ }, {
+- "\x0c", 20, "Test With Truncation", 20,
+-
"\x4c\x1a\x03\x42\x4b\x55\xe0\x7f\xe7\xf2\x7b\xe1\xd5\x8b\xb9\x32\x4a\x9a\x5a\x04"
++ (uint8_t*)"\x0c", 20, (uint8_t*)"Test With Truncation", 20,
++
(uint8_t*)"\x4c\x1a\x03\x42\x4b\x55\xe0\x7f\xe7\xf2\x7b\xe1\xd5\x8b\xb9\x32\x4a\x9a\x5a\x04"
+ }, {
+- "\xaa", 80, "Test Using Larger Than Block-Size Key - Hash Key First", 54,
+-
"\xaa\x4a\xe5\xe1\x52\x72\xd0\x0e\x95\x70\x56\x37\xce\x8a\x3b\x55\xed\x40\x21\x12"
++ (uint8_t*)"\xaa", 80, (uint8_t*)"Test Using Larger Than Block-Size Key -
Hash Key First", 54,
++
(uint8_t*)"\xaa\x4a\xe5\xe1\x52\x72\xd0\x0e\x95\x70\x56\x37\xce\x8a\x3b\x55\xed\x40\x21\x12"
+ }, {
+- "\xaa", 80,
+- "Test Using Larger Than Block-Size Key and Larger Than One Block-Size
Data", 73,
+-
"\xe8\xe9\x9d\x0f\x45\x23\x7d\x78\x6d\x6b\xba\xa7\x96\x5c\x78\x08\xbb\xff\x1a\x91"
++ (uint8_t*)"\xaa", 80,
++ (uint8_t*)"Test Using Larger Than Block-Size Key and Larger Than One
Block-Size Data", 73,
++
(uint8_t*)"\xe8\xe9\x9d\x0f\x45\x23\x7d\x78\x6d\x6b\xba\xa7\x96\x5c\x78\x08\xbb\xff\x1a\x91"
+ }};
+
+ debug("tpm_test_hmac()");
+ for (i = 0; i < sizeof(test_cases) / sizeof(test_cases[0]); i++) {
+- if (strlen(test_cases[i].key) < test_cases[i].key_len) {
++ if (strlen((char*)test_cases[i].key) < test_cases[i].key_len) {
+ uint8_t key[test_cases[i].key_len];
+ memset(key, test_cases[i].key[0], test_cases[i].key_len);
+ hmac_init(&ctx, key, test_cases[i].key_len);
+ } else {
+ hmac_init(&ctx, test_cases[i].key, test_cases[i].key_len);
+ }
+- for (j = 0; j < test_cases[i].data_len; j += strlen(test_cases[i].data)) {
+- hmac_update(&ctx, test_cases[i].data, strlen(test_cases[i].data));
++ for (j = 0; j < test_cases[i].data_len; j +=
strlen((char*)test_cases[i].data)) {
++ hmac_update(&ctx, test_cases[i].data,
strlen((char*)test_cases[i].data));
+ }
+ hmac_final(&ctx, digest);
+ if (memcmp(digest, test_cases[i].digest, SHA1_DIGEST_LENGTH) != 0) return
-1;
+@@ -173,9 +174,9 @@ static int tpm_test_hmac(void)
+ static int tpm_test_rsa_EK(void)
+ {
+ int res = 0;
+- char *data = "RSA PKCS #1 v1.5 Test-String";
++ uint8_t *data = (uint8_t*)"RSA PKCS #1 v1.5 Test-String";
+ uint8_t buf[256];
+- size_t buf_len, data_len = strlen(data);
++ size_t buf_len, data_len = strlen((char*)data);
+ rsa_private_key_t priv_key;
+ rsa_public_key_t pub_key;
+
+diff -uprN orig/tpm_emulator-0.2/tpm/tpm_ticks.c vtpm/tpm/tpm_ticks.c
+--- orig/tpm_emulator-0.2/tpm/tpm_ticks.c 2005-08-17 10:58:36.000000000
-0700
++++ vtpm/tpm/tpm_ticks.c 2005-08-17 10:55:52.000000000 -0700
+@@ -1,6 +1,7 @@
+ /* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2004 Mario Strasser <mast@xxxxxxx>,
+ * Swiss Federal Institute of Technology (ETH) Zurich
++ * Copyright (C) 2005 INTEL Corp
+ *
+ * This module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+@@ -37,9 +38,7 @@ TPM_RESULT TPM_SetTickType(TPM_TICKTYPE
+ TPM_RESULT TPM_GetTicks(TPM_CURRENT_TICKS *currentTime)
+ {
+ info("TPM_GetTicks()");
+- memcpy(currentTime, &tpmData.stany.data.currentTicks,
+- sizeof(TPM_CURRENT_TICKS));
+- return TPM_SUCCESS;
++ return TPM_DISABLED_CMD;
+ }
+
+ TPM_RESULT TPM_TickStampBlob(TPM_KEY_HANDLE keyHandle, TPM_NONCE *antiReplay,
+@@ -47,61 +46,12 @@ TPM_RESULT TPM_TickStampBlob(TPM_KEY_HAN
+ TPM_CURRENT_TICKS *currentTicks,
+ UINT32 *sigSize, BYTE **sig)
+ {
+- TPM_RESULT res;
+- TPM_KEY_DATA *key;
+- BYTE *info, *p;
+- UINT32 info_length, length;
+ info("TPM_TickStampBlob()");
+- /* get key */
+- key = tpm_get_key(keyHandle);
+- if (key == NULL) return TPM_INVALID_KEYHANDLE;
+- /* verify authorization */
+- res = tpm_verify_auth(auth1, key->usageAuth, keyHandle);
+- if (res != TPM_SUCCESS) return res;
+- if (key->keyUsage != TPM_KEY_SIGNING && key->keyUsage != TPM_KEY_LEGACY
+- && key->keyUsage != TPM_KEY_IDENTITY) return TPM_INVALID_KEYUSAGE;
+- /* get current ticks */
+- TPM_GetTicks(currentTicks);
+- /* sign data using signature scheme PKCS1_SHA1 and TPM_SIGN_INFO container
*/
+- *sigSize = key->key.size >> 3;
+- *sig = tpm_malloc(*sigSize);
+- if (*sig == NULL) return TPM_FAIL;
+- /* setup TPM_SIGN_INFO structure */
+- info_length = 30 + sizeof(TPM_DIGEST) +
sizeof_TPM_CURRENT_TICKS(currentTicks);
+- info = tpm_malloc(info_length);
+- if (info == NULL) {
+- tpm_free(*sig);
+- return TPM_FAIL;
+- }
+- memcpy(&info[0], "\x05\x00TSTP", 6);
+- memcpy(&info[6], antiReplay->nonce, 20);
+- *(UINT32*)&info[26] = cpu_to_be32(20
+- + sizeof_TPM_CURRENT_TICKS(currentTicks));
+- memcpy(&info[30], digestToStamp->digest, sizeof(TPM_DIGEST));
+- p = &info[30 + sizeof(TPM_DIGEST)];
+- length = sizeof_TPM_CURRENT_TICKS(currentTicks);
+- if (tpm_marshal_TPM_CURRENT_TICKS(&p, &length, currentTicks)
+- || rsa_sign(&key->key, RSA_SSA_PKCS1_SHA1, info, info_length, *sig)) {
+- tpm_free(*sig);
+- tpm_free(info);
+- return TPM_FAIL;
+- }
+- return TPM_SUCCESS;
++ return TPM_DISABLED_CMD;
+ }
+
+ void tpm_update_ticks(void)
+ {
+- if (tpmData.stany.data.currentTicks.tag == 0) {
+- tpmData.stany.data.currentTicks.tag = TPM_TAG_CURRENT_TICKS;
+- tpmData.stany.data.currentTicks.currentTicks += tpm_get_ticks();
+- tpmData.stany.data.currentTicks.tickType =
tpmData.permanent.data.tickType;
+- tpm_get_random_bytes(tpmData.stany.data.currentTicks.tickNonce.nonce,
+- sizeof(TPM_NONCE));
+- tpmData.stany.data.currentTicks.tickRate = 1;
+- tpmData.stany.data.currentTicks.tickSecurity = TICK_SEC_NO_CHECK;
+- } else {
+- tpmData.stany.data.currentTicks.currentTicks += tpm_get_ticks();
+- }
+ }
+
+
+diff -uprN orig/tpm_emulator-0.2/tpm/vtpm_manager.h vtpm/tpm/vtpm_manager.h
+--- orig/tpm_emulator-0.2/tpm/vtpm_manager.h 1969-12-31 16:00:00.000000000
-0800
++++ vtpm/tpm/vtpm_manager.h 2005-08-17 10:55:52.000000000 -0700
+@@ -0,0 +1,126 @@
++// ===================================================================
++//
++// Copyright (c) 2005, Intel Corp.
++// 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 Intel Corporation nor the names of its
++// 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.
++// ===================================================================
++//
++// vtpm_manager.h
++//
++// Public Interface header for VTPM Manager
++//
++// ==================================================================
++
++#ifndef __VTPM_MANAGER_H__
++#define __VTPM_MANAGER_H__
++
++#define VTPM_TAG_REQ 0x01c1
++#define VTPM_TAG_RSP 0x01c4
++#define COMMAND_BUFFER_SIZE 4096
++
++// Header sizes. Note Header MAY include the DMI
++#define VTPM_COMMAND_HEADER_SIZE_SRV ( sizeof(UINT32) + sizeof(TPM_TAG) +
sizeof(UINT32) + sizeof(TPM_COMMAND_CODE))
++#define VTPM_COMMAND_HEADER_SIZE_CLT ( sizeof(TPM_TAG) +
sizeof(UINT32) + sizeof(TPM_COMMAND_CODE))
++
++//************************ Command Codes ****************************
++#define VTPM_ORD_OPEN 1 // ULM Creates New DMI
++#define VTPM_ORD_CLOSE 2 // ULM Closes a DMI
++#define VTPM_ORD_DELETE 3 // ULM Permemently Deletes DMI
++#define VTPM_ORD_SAVENVM 4 // DMI requests Secrets Unseal
++#define VTPM_ORD_LOADNVM 5 // DMI requests Secrets Saved
++#define VTPM_ORD_TPMCOMMAND 6 // DMI issues HW TPM Command
++
++//************************ Return Codes ****************************
++#define VTPM_SUCCESS 0
++#define VTPM_FAIL 1
++#define VTPM_UNSUPPORTED 2
++#define VTPM_FORBIDDEN 3
++#define VTPM_RESTORE_CONTEXT_FAILED 4
++#define VTPM_INVALID_REQUEST 5
++
++/******************* Command Parameter API *************************
++
++VTPM Command Format
++ dmi: 4 bytes // Source of message.
++ // WARNING: This is prepended by the channel.
++ // Thus it is received by VTPM Manager,
++ // but not sent by DMI
++ tpm tag: 2 bytes
++ command size: 4 bytes // Size of command including header but not
DMI
++ ord: 4 bytes // Command ordinal above
++ parameters: size - 10 bytes // Command Parameter
++
++VTPM Response Format
++ tpm tag: 2 bytes
++ response_size: 4 bytes
++ status: 4 bytes
++ parameters: size - 10 bytes
++
++
++VTPM_Open:
++ Input Parameters:
++ Domain_type: 1 byte
++ domain_id: 4 bytes
++ instance_id: 4 bytes
++ Output Parameters:
++ None
++
++VTPM_Close
++ Input Parameters:
++ instance_id: 4 bytes
++ Output Parameters:
++ None
++
++VTPM_Delete
++ Input Parameters:
++ instance_id: 4 bytes
++ Output Parameters:
++ None
++
++VTPM_SaveNVM
++ Input Parameters:
++ data: n bytes (Header indicates size of data)
++ Output Parameters:
++ None
++
++VTPM_LoadNVM
++ Input Parameters:
++ None
++ Output Parameters:
++ data: n bytes (Header indicates size of data)
++
++VTPM_TPMCommand
++ Input Parameters:
++ TPM Command Byte Stream: n bytes
++ Output Parameters:
++ TPM Reponse Byte Stream: n bytes
++
++*********************************************************************/
++
++#endif //_VTPM_MANAGER_H_
+diff -uprN orig/tpm_emulator-0.2/tpmd.c vtpm/tpmd.c
+--- orig/tpm_emulator-0.2/tpmd.c 1969-12-31 16:00:00.000000000 -0800
++++ vtpm/tpmd.c 2005-08-17 10:55:52.000000000 -0700
+@@ -0,0 +1,207 @@
++/* Software-Based Trusted Platform Module (TPM) Emulator for Linux
++ * Copyright (C) 2005 INTEL Corp
++ *
++ * This module is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published
++ * by the Free Software Foundation; either version 2 of the License,
++ * or (at your option) any later version.
++ *
++ * This module is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <string.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <sys/time.h>
++
++#include "tpm_emulator.h"
++#include "vtpm_manager.h"
++
++#ifdef VTPM_MULTI_VM
++ #define DEV_BE "/dev/vtpm"
++#else
++ #define GUEST_RX_FIFO_D "/var/vtpm/fifos/guest-to-%d.fifo"
++ #define GUEST_TX_FIFO "/var/vtpm/fifos/guest-from-all.fifo"
++
++ int dmi_id;
++#endif
++
++#define BUFFER_SIZE 2048
++
++static uint8_t ctrl_msg[] = { 0, 0, 0, 0, // destination
++ 1, 193, // VTPM_TAG
++ 0, 0, 0, 10, // Size
++ 0, 0, 0, 0}; // TPM_SUCCESS
++
++
++static int devurandom=0;
++
++
++void get_random_bytes(void *buf, int nbytes) {
++
++ if (devurandom == 0) {
++ devurandom = open("/dev/urandom", O_RDONLY);
++ }
++
++ if (read(devurandom, buf, nbytes) != nbytes) {
++ printf("Can't get random number.\n");
++ exit(-1);
++ }
++}
++
++uint64_t tpm_get_ticks(void)
++{
++ //struct timeval tv;
++ //int gettimeofday(&tv, struct timezone *tz);
++ return 0;
++}
++
++int main(int argc, char **argv)
++{
++ uint8_t in[BUFFER_SIZE], *out, *addressed_out;
++ uint32_t out_size;
++ int in_size, written ;
++ int i, guest_id=-1;
++
++ int vtpm_tx_fh=-1, vtpm_rx_fh=-1;
++#ifdef VTPM_MULTI_VM
++ if (argc < 2) {
++ printf("Usage: tpmd clear|save|deactivated\n" );
++#else
++ if (argc < 3) {
++ printf("Usage: tpmd clear|save|deactivated vtpmid\n" );
++#endif
++ return -1;
++ }
++
++#ifndef VTPM_MULTI_VM
++ dmi_id = atoi(argv[2]);
++#endif
++
++ /* initialize TPM emulator */
++ if (!strcmp(argv[1], "clear")) {
++ printf("Initializing tpm: %s\n", argv[1]);
++ tpm_emulator_init(1);
++ } else if (!strcmp(argv[1], "save")) {
++ printf("Initializing tpm: %s\n", argv[1]);
++ tpm_emulator_init(2);
++ } else if (!strcmp(argv[1], "deactivated")) {
++ printf("Initializing tpm: %s\n", argv[1]);
++ tpm_emulator_init(3);
++ } else {
++ printf("invalid startup mode '%s'; must be 'clear', "
++ "'save' (default) or 'deactivated", argv[1]);
++ return -1;
++ }
++
++ char *guest_rx_file = malloc(10 + strlen(GUEST_RX_FIFO_D));
++ sprintf(guest_rx_file, GUEST_RX_FIFO_D, (uint32_t) dmi_id);
++
++ while (1) {
++abort_command:
++ if (vtpm_rx_fh < 0) {
++#ifdef VTPM_MUTLI_VM
++ vtpm_rx_fh = open(DEV_BE, O_RDWR);
++#else
++ vtpm_rx_fh = open(guest_rx_file, O_RDONLY);
++#endif
++ }
++
++ if (vtpm_rx_fh < 0) {
++ printf("ERROR: failed to open devices to listen to guest.\n");
++ return -1;
++ }
++
++ in_size = read(vtpm_rx_fh, in, BUFFER_SIZE);
++ if (in_size < 6) { // Magic size of minium TPM command
++ printf("Recv[%d] to small: 0x", in_size);
++ if (in_size <= 0) {
++ close(vtpm_rx_fh);
++ vtpm_rx_fh = -1;
++ goto abort_command;
++ }
++ } else {
++ printf("Recv[%d]: 0x", in_size);
++ for (i=0; i< in_size; i++)
++ printf("%x ", in[i]);
++ printf("\n");
++ }
++
++ if (guest_id == -1) {
++ guest_id = *((uint32_t *) in);
++ *((uint32_t *) ctrl_msg) = *((uint32_t *) in);
++ } else {
++ if (guest_id != *((uint32_t *) in) ) {
++ printf("WARNING: More than one guest attached\n");
++ }
++ }
++
++ if (vtpm_tx_fh < 0) {
++#ifdef VTPM_MUTLI_VM
++ vtpm_tx_fh = open(DEV_BE, O_RDWR);
++ vtpm_rx_fh = vtpm_tx_fh;
++#else
++ vtpm_tx_fh = open(GUEST_TX_FIFO, O_WRONLY);
++#endif
++ }
++
++ if (vtpm_tx_fh < 0) {
++ printf("ERROR: failed to open devices to respond to guest.\n");
++ return -1;
++ }
++
++ // Handle command, but we need to skip the identifier
++ if ( BE16_TO_CPU( ((uint16_t *) in)[2] ) == VTPM_TAG_REQ ) { // Control
message from xend
++ // This DM doesn't really care about ctrl messages. Just ACK the message
++ written = write(vtpm_tx_fh, ctrl_msg, sizeof(ctrl_msg));
++
++ if (written != sizeof(ctrl_msg)) {
++ printf("ERROR: Part of response not written %d/%d.\n", written,
sizeof(ctrl_msg));
++ } else {
++ printf("Send Ctrl Message confermation\n");
++ }
++ } else { // Message from Guest
++ if (tpm_handle_command(in + sizeof(uint32_t), in_size -
sizeof(uint32_t), &out, &out_size) != 0) {
++ printf("ERROR: Handler Failed.\n");
++ }
++
++ addressed_out = (uint8_t *) tpm_malloc(sizeof(uint32_t) + out_size);
++ *(uint32_t *) addressed_out = *(uint32_t *) in;
++ memcpy(addressed_out + sizeof(uint32_t), out, out_size);
++
++ written = write(vtpm_tx_fh, addressed_out, out_size + sizeof(uint32_t));
++
++ if (written != out_size + sizeof(uint32_t)) {
++ printf("ERROR: Part of response not written %d/%d.\n", written,
out_size);
++ for (i=0; i< out_size+ sizeof(uint32_t); i++)
++ printf("%x ", addressed_out[i]);
++ printf("\n");
++ } else {
++ printf("Sent[%d]: ", out_size + sizeof(uint32_t));
++ for (i=0; i< out_size+ sizeof(uint32_t); i++)
++ printf("%x ", addressed_out[i]);
++ printf("\n");
++ }
++ tpm_free(out);
++ tpm_free(addressed_out);
++ }
++
++ } // loop
++
++ tpm_emulator_shutdown();
++
++ close(vtpm_tx_fh);
++#ifndef VTPM_MUTLI_VM
++ close(vtpm_rx_fh);
++ free (guest_rx_file);
++#endif
++
++}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/COPYING
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/COPYING Fri Sep 9 16:30:54 2005
@@ -0,0 +1,32 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/Makefile
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/Makefile Fri Sep 9 16:30:54 2005
@@ -0,0 +1,31 @@
+XEN_ROOT = ../..
+
+# Base definitions and rules
+include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk
+
+SUBDIRS = crypto tcs util manager
+
+all: build
+
+build:
+ @set -e; for subdir in $(SUBDIRS); do \
+ $(MAKE) -C $$subdir $@; \
+ done
+
+install: build
+ @set -e; for subdir in $(SUBDIRS); do \
+ $(MAKE) -C $$subdir $@; \
+ done
+
+clean:
+ @set -e; for subdir in $(SUBDIRS); do \
+ $(MAKE) -C $$subdir $@; \
+ done
+
+
+mrproper:
+ @set -e; for subdir in $(SUBDIRS); do \
+ $(MAKE) -C $$subdir $@; \
+ done
+
+
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/README
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/README Fri Sep 9 16:30:54 2005
@@ -0,0 +1,89 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+
+Directory Structure
+===================
+tools/vtpm_manager/crypto -> crypto files
+tools/vtpm_manager/TCS -> TCS implementation
+tools/vtpm_manager/util -> Utility Library. Include disk-io and buffers.
+tools/vtpm_manager/manager -> VTPM Manager
+
+Compile Flags
+===================
+LOGGING_MODULES -> How extensive logging happens
+ see util/log.h for more info
+
+VTPM_MULTI_VM -> Defined: VTPMs run in their own VMs
+ Not Defined (default): VTPMs are processes
+
+# Debugging flags that may disappear without notice in the future
+
+DUMMY_BACKEND -> vtpm_manager listens on /tmp/in.fifo and
+ /tmp/out.fifo rather than backend
+
+MANUAL_DM_LAUNCH -> User must manually launch & kill VTPMs
+
+USE_FIXED_SRK_AUTH -> Do not randomly generate a random SRK & Owner
auth
+
+Requirements
+============
+- xen-unstable
+- IBM frontend/backend vtpm driver patch
+
+Single-VM Flow
+============================
+- Launch the VTPM manager (vtpm_managerd) which which begins listening to the
BE with one thread
+ and listens to a named fifo that is shared by the vtpms to commuincate with
the manager.
+- VTPM Manager listens to TPM BE.
+- When xend launches a tpm frontend equipped VM it contacts the manager over
the vtpm backend.
+- When the manager receives the open message from the BE, it launches a vtpm
+- Xend allows the VM to continue booting.
+- When a TPM request is issued to the front end, the front end transmits the
TPM request to the backend.
+- The manager receives the TPM requests and uses a named fifo to forward the
request to the vtpm.
+- The fifo listener begins listening for the reply from vtpm for the request.
+- Vtpm processes request and replies to manager over shared named fifo.
+- If needed, the vtpm may send a request to the vtpm_manager at any time to
save it's secrets to disk.
+- Manager receives response from vtpm and passes it back to backend for
forwarding to guest.
+
+NOTES:
+* SaveService SHOULD seal it's table before saving it to disk. However,
+ the current Xen infrastructure does not provide a mechanism for this to be
+ unsealed later. Specifically, the auth and wrapped key must be available ONLY
+ to the service, or it's not even worth encrypting
+
+ In the future the vtpm manager will be protected by an early boot mechanism
+ that will allow for better protection of it's data.
+
+TODO:
+- Timeout on crashed vtpms
+- create lock for shared fifo for talking to vtpms.
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/Rules.mk
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/Rules.mk Fri Sep 9 16:30:54 2005
@@ -0,0 +1,68 @@
+# Base definitions and rules (XEN_ROOT must be defined in including Makefile)
+include $(XEN_ROOT)/tools/Rules.mk
+
+#
+# Tool definitions
+#
+
+# Installation program and options
+INSTALL = install
+INSTALL_PROG = $(INSTALL) -m0755
+INSTALL_DIR = $(INSTALL) -d -m0755
+
+# Xen tools installation directory
+TOOLS_INSTALL_DIR = $(DESTDIR)/usr/bin
+
+# General compiler flags
+CFLAGS = -Wall -Werror -g3 -I.
+
+# For generating dependencies
+CFLAGS += -Wp,-MD,.$(@F).d
+
+DEP_FILES = .*.d
+
+# Generic project files
+HDRS = $(wildcard *.h)
+SRCS = $(wildcard *.c)
+OBJS = $(patsubst %.c,%.o,$(SRCS))
+
+# Generic (non-header) dependencies
+$(SRCS): Makefile $(XEN_ROOT)/tools/Rules.mk
$(XEN_ROOT)/tools/vtpm_manager/Rules.mk
+
+$(OBJS): $(SRCS)
+
+-include $(DEP_FILES)
+
+# Make sure these are just rules
+.PHONY : all build install clean
+
+#
+# Project-specific definitions
+#
+
+# Logging Level. See utils/tools.h for usage
+CFLAGS +=
-DLOGGING_MODULES="(BITMASK(VTPM_LOG_TCS)|BITMASK(VTPM_LOG_VTSP)|BITMASK(VTPM_LOG_VTPM)|BITMASK(VTPM_LOG_VTPM_DEEP))"
+
+# Silent Mode
+#CFLAGS += -DLOGGING_MODULES=0x0
+#CFLAGS += -DLOGGING_MODULES=0xff
+
+# Use frontend/backend pairs between manager & DMs?
+#CFLAGS += -DVTPM_MULTI_VM
+
+# vtpm_manager listens on /tmp/in.fifo and /tmp/out.fifo rather than backend
+#CFLAGS += -DDUMMY_BACKEND
+
+# Do not have manager launch DMs.
+#CFLAGS += -DMANUAL_DM_LAUNCH
+
+# Fixed SRK
+CFLAGS += -DUSE_FIXED_SRK_AUTH
+
+# TPM Hardware Device or TPM Simulator
+#CFLAGS += -DTPM_HWDEV
+
+# Include
+CFLAGS += -I$(XEN_ROOT)/tools/vtpm_manager/crypto
+CFLAGS += -I$(XEN_ROOT)/tools/vtpm_manager/util
+CFLAGS += -I$(XEN_ROOT)/tools/vtpm_manager/tcs
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/crypto/Makefile
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/crypto/Makefile Fri Sep 9 16:30:54 2005
@@ -0,0 +1,18 @@
+XEN_ROOT = ../../..
+include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk
+
+BIN = libtcpaCrypto.a
+
+all: build
+
+build: $(BIN)
+
+install: build
+
+clean:
+ rm -f *.a *.so *.o *.rpm $(DEP_FILES)
+
+mrproper: clean
+
+$(BIN): $(OBJS)
+ $(AR) rcs $(BIN) $(OBJS)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/crypto/crypto.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/crypto/crypto.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,88 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+//
+// crypto.c
+//
+// This file will handle all the TPM Crypto functionality
+//
+// ==================================================================
+
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include "crypto.h"
+#include "log.h"
+
+/**
+ * Initialize cryptography library
+ * @rand: random seed
+ * @size: size of @rand
+ */
+void Crypto_Init(const BYTE* rand, int size) {
+ ERR_load_crypto_strings();
+ CRYPTO_malloc_init();
+ OpenSSL_add_all_algorithms();
+ SYM_CIPHER = EVP_aes_128_cbc();
+ RAND_poll();
+ if (rand == NULL)
+ return;
+
+ RAND_add(rand, size, size);
+}
+
+/**
+ * Shutdown cryptography library
+ */
+void Crypto_Exit() {
+ ERR_free_strings();
+ ERR_remove_state(0);
+ EVP_cleanup();
+}
+
+
+/**
+ * Get random data
+ * @data: (OUT) Random data
+ * @size: Size of @data
+ */
+void Crypto_GetRandom(void* data, int size) {
+ int result;
+
+ result = RAND_pseudo_bytes((BYTE*) data, size);
+
+ if (result <= 0)
+ vtpmlogerror (VTPM_LOG_CRYPTO, "RAND_pseudo_bytes failed: %s\n",
+ ERR_error_string (ERR_get_error(), NULL));
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/crypto/crypto.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/crypto/crypto.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,175 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+//
+// crypto.h
+//
+// This file defines the TPM Crypto API
+//
+// ==================================================================
+
+#ifndef __CRYPTO_H__
+#define __CRYPTO_H__
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "tcg.h"
+#include "sym_crypto.h"
+
+#define CRYPTO_MAX_SIG_SIZE (2048 / 8)
+#define CRYPTO_MAX_RSA_KEY_SIZE (4096 / 8) //in bytes
+
+#define OAEP_P "TCPA"
+#define OAEP_P_SIZE 4
+
+// Algorithms supported by crypto. Stored in CRYPTO_INFO.algorithmID
+#define CRYPTO_ALGORITH_RSA 0x01
+
+// Supported Encryption Schemes CRYPTO_INFO.encScheme
+#define CRYPTO_ES_NONE 0x0001
+#define CRYPTO_ES_RSAESPKCSv15 0x0002
+#define CRYPTO_ES_RSAESOAEP_SHA1_MGF1 0x0003
+
+// Supported Signature schemes CRYPTO_INFO.sigScheme
+#define CRYPTO_SS_NONE 0x0001
+#define CRYPTO_SS_RSASSAPKCS1v15_SHA1 0x0002
+#define CRYPTO_SS_RSASSAPKCS1v15_DER 0x0003
+
+typedef struct CRYPTO_INFO {
+ void *keyInfo;
+ UINT32 algorithmID;
+ UINT32 encScheme;
+ UINT32 sigScheme;
+} CRYPTO_INFO;
+
+
+void Crypto_Init(const BYTE* rand, int size);
+
+void Crypto_Exit();
+
+void Crypto_GetRandom(void* data, int size);
+
+void Crypto_HMAC( const BYTE* text,
+ int text_len,
+ const BYTE* key,
+ int key_len,
+ BYTE* digest);
+
+TPM_RESULT Crypto_HMAC_buf (const buffer_t * text,
+ const buffer_t * key,
+ BYTE * o_digest); /* presumably of 20 bytes */
+
+void Crypto_SHA1Full( const BYTE* text,
+ UINT32 size,
+ BYTE* hash); //Complete 3part SHA1
+
+// o_hash needs to be large enough to hold the digest, ie 20 bytes
+TPM_RESULT Crypto_SHA1Full_buf (const buffer_t * buf,
+ BYTE * o_hash);
+
+void Crypto_SHA1Start(UINT32* maxNumBytes);
+void Crypto_SHA1Update(int numBytes, const BYTE* hashData);
+void Crypto_SHA1Complete( int hashDataSize,
+ const BYTE* hashData,
+ BYTE* hashValue);
+
+void Crypto_RSACreateKey( /*in*/ UINT32 keySize,
+ /*in*/ UINT32 pubExpSize,
+ /*in*/ BYTE *pubExp,
+ /*out*/ UINT32 *privExpSize,
+ /*out*/ BYTE *privExp,
+ /*out*/ UINT32 *modulusSize,
+ /*out*/ BYTE *modulus,
+ /*out*/ CRYPTO_INFO *keys);
+
+void Crypto_RSABuildCryptoInfo( /*[IN]*/ UINT32 pubExpSize,
+ /*[IN]*/ BYTE *pubExp,
+ /*[IN]*/ UINT32 privExpSize,
+ /*[IN]*/ BYTE *privExp,
+ /*[IN]*/ UINT32 modulusSize,
+ /*[IN]*/ BYTE *modulus,
+ /*[OUT]*/ CRYPTO_INFO* cryptoInfo);
+
+void Crypto_RSABuildCryptoInfoPublic( /*[IN]*/ UINT32 pubExpSize,
+ /*[IN]*/ BYTE *pubExp,
+ /*[IN]*/ UINT32 modulusSize,
+ /*[IN]*/ BYTE *modulus,
+ CRYPTO_INFO* cryptoInfo);
+
+//
+// symmetric pack and unpack operations
+//
+TPM_RESULT Crypto_RSAPackCryptoInfo (const CRYPTO_INFO* cryptoInfo,
+ BYTE ** io_buf, UINT32 * io_buflen);
+
+TPM_RESULT Crypto_RSAUnpackCryptoInfo (CRYPTO_INFO * ci,
+ BYTE * in, UINT32 len,
+ UINT32 * o_lenread);
+
+
+// return 0 on success, -1 on error
+int Crypto_RSAEnc( CRYPTO_INFO *keys,
+ UINT32 inDataSize,
+ BYTE *inData,
+ /*out*/ UINT32 *outDataSize,
+ /*out*/ BYTE *outData);
+
+// return 0 on success, -1 on error
+int Crypto_RSADec( CRYPTO_INFO *keys,
+ UINT32 inDataSize,
+ BYTE *inData,
+ /*out*/ UINT32 *outDataSize,
+ /*out*/ BYTE *outData);
+
+// return 0 on success, -1 on error
+int Crypto_RSASign( CRYPTO_INFO *keys,
+ UINT32 inDataSize,
+ BYTE *inData,
+ /*out*/ UINT32 *sigSize,
+ /*out*/ BYTE *sig);
+
+bool Crypto_RSAVerify( CRYPTO_INFO *keys,
+ UINT32 inDataSize,
+ BYTE *inData,
+ UINT32 sigSize,
+ BYTE *sig);
+
+//private:
+int RSA_verify_DER(int dtype, unsigned char *m, unsigned int m_len,
+ unsigned char *sigbuf, unsigned int siglen, CRYPTO_INFO
*key);
+
+int RSA_sign_DER(int type, unsigned char *m, unsigned int m_len,
+ unsigned char *sigret, unsigned int *siglen, CRYPTO_INFO *key);
+
+#endif // __CRYPTO_H__
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/crypto/hash.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/crypto/hash.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,153 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+//
+// hash.c
+//
+// This file will handle all the TPM Hash functionality
+//
+// ==================================================================
+
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/hmac.h>
+#include <openssl/sha.h>
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+
+#include "tcg.h" // for TPM_SUCCESS
+#include "crypto.h"
+
+static SHA_CTX g_shaContext;
+
+void Crypto_HMAC( const BYTE* text,
+ int text_len,
+ const BYTE* key,
+ int key_len,
+ BYTE* digest) {
+ if (text == NULL || key == NULL || text_len == 0 || key_len == 0)
+ return;
+
+ HMAC(EVP_sha1(), key, key_len, text, text_len, digest, NULL);
+}
+
+TPM_RESULT Crypto_HMAC_buf (const buffer_t * text,
+ const buffer_t * key,
+ BYTE * o_digest) { /* presumably of 20 bytes */
+
+ Crypto_HMAC (text->bytes, text->size,
+ key->bytes, key->size,
+ o_digest);
+
+ return TPM_SUCCESS;
+}
+
+
+/*
+ * SHA1
+ * (OUT) Create a SHA1 hash of text. Calls all three SHA1 steps internally
+ */
+void Crypto_SHA1Full( const BYTE* text,
+ uint32_t size,
+ BYTE* hash) {
+
+ if (text == NULL || size == 0)
+ return;
+
+ // Run SHA1Start + SHAUpdate (if necessary) + SHAComplete
+ uint32_t maxBytes; // Not used for anything
+ Crypto_SHA1Start(&maxBytes);
+
+ while (size > 64){
+ Crypto_SHA1Update(64, text);
+ size -= 64;
+ text += 64;
+ }
+
+ Crypto_SHA1Complete(size, text, hash);
+}
+
+// same thing using buffer_t
+TPM_RESULT Crypto_SHA1Full_buf (const buffer_t * buf,
+ BYTE * o_digest) {
+
+ if (buf->bytes == NULL || buf->size == 0)
+ return TPM_BAD_PARAMETER;
+
+ Crypto_SHA1Full (buf->bytes, buf->size, o_digest);
+
+ return TPM_SUCCESS;
+}
+
+
+/*
+ * Initialize SHA1
+ * (OUT) Maximum number of bytes that can be sent to SHA1Update.
+ * Must be a multiple of 64 bytes.
+ */
+void Crypto_SHA1Start(uint32_t* maxNumBytes) {
+ int max = SHA_CBLOCK;
+ // Initialize the crypto library
+ SHA1_Init(&g_shaContext);
+ *maxNumBytes = max;
+}
+
+/*
+ * Process SHA1
+ * @numBytes: (IN) The number of bytes in hashData.
+ * Must be a multiple of 64 bytes.
+ * @hashData: (IN) Bytes to be hashed.
+ */
+void Crypto_SHA1Update(int numBytes, const BYTE* hashData) {
+
+ if (hashData == NULL || numBytes == 0 || numBytes%64 != 0)
+ return;
+
+ SHA1_Update(&g_shaContext, hashData, numBytes);
+}
+
+/*
+ * Complete the SHA1 process
+ * @hashDataSize: (IN) Number of bytes in hashData.
+ * Must be a multiple of 64 bytes.
+ * @hashData: (IN) Final bytes to be hashed.
+ * @hashValue: (OUT) The output of the SHA-1 hash.
+ */
+void Crypto_SHA1Complete(int hashDataSize,
+ const BYTE* hashData,
+ BYTE* hashValue) {
+ SHA1_Update(&g_shaContext, hashData, hashDataSize);
+ SHA1_Final(hashValue, &g_shaContext);
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/crypto/rsa.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/crypto/rsa.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,434 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+//
+// rsa.c
+//
+// This file will handle all the TPM RSA crypto functionality
+//
+// ==================================================================
+
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/evp.h>
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+#include <openssl/rand.h>
+#include <openssl/x509.h>
+
+#include <openssl/err.h>
+#include <stdio.h>
+
+#include "tcg.h"
+#include "buffer.h"
+#include "crypto.h"
+#include "log.h"
+
+void Crypto_RSACreateKey( /*in*/ UINT32 keySize,
+ /*in*/ UINT32 pubExpSize,
+ /*in*/ BYTE *pubExp,
+ /*out*/ UINT32 *privExpSize,
+ /*out*/ BYTE *privExp,
+ /*out*/ UINT32 *modulusSize,
+ /*out*/ BYTE *modulus,
+ /*out*/ CRYPTO_INFO *keys) {
+ unsigned long e_value;
+
+ if (pubExpSize == 0) // Default e = 2^16+1
+ e_value = (0x01 << 16) + 1;
+ else {
+ // This is not supported, but the following line MIGHT work
+ // under then assumption that the format is BigNum compatable
+ // Though it's not in the spec, so who knows what it is.
+ // Forcing the default.
+ //BN_bin2bn(pubExp, pubExpSize, NULL);
+ e_value = (0x01 << 16) + 1;
+ }
+
+ RSA *rsa = RSA_generate_key(keySize, e_value, NULL, NULL);
+
+ if (keys) {
+ keys->keyInfo = rsa;
+ keys->algorithmID = CRYPTO_ALGORITH_RSA;
+ }
+
+ if (modulus) *modulusSize = BN_bn2bin(rsa->n, modulus);
+ if (privExp) *privExpSize = BN_bn2bin(rsa->d, privExp);
+}
+
+// Create a CRYPTO_INFO struct from the BYTE * key parts.
+// If pubExp info is NULL, use TCG default.
+// If there is a remainder while calculating the privExp, return FALSE.
+
+void Crypto_RSABuildCryptoInfo( /*[IN]*/ UINT32 pubExpSize,
+ /*[IN]*/ BYTE *pubExp,
+ /*[IN]*/ UINT32 privExpSize,
+ /*[IN]*/ BYTE *privExp,
+ /*[IN]*/ UINT32 modulusSize,
+ /*[IN]*/ BYTE *modulus,
+ CRYPTO_INFO* cryptoInfo) {
+ cryptoInfo->keyInfo = RSA_new();
+ RSA *rsa = (RSA *) cryptoInfo->keyInfo;
+
+ rsa->e = BN_new();
+
+ if (pubExpSize == 0) { // Default e = 2^16+1
+ BN_set_bit(rsa->e, 16);
+ BN_set_bit(rsa->e, 0);
+ } else {
+ // This is not supported, but the following line MIGHT work
+ // under then assumption that the format is BigNum compatable
+ // Though it's not in the spec, so who knows what it is.
+ // Forcing the default.
+ //BN_bin2bn(pubExp, pubExpSize, NULL);
+ BN_set_bit(rsa->e, 16);
+ BN_set_bit(rsa->e, 0);
+ }
+
+ rsa->n = BN_bin2bn(modulus, modulusSize, NULL);
+ rsa->d = BN_bin2bn(privExp, privExpSize, NULL);
+}
+
+// Create a CRYPTO_INFO struct from the BYTE * key parts.
+// If pubExp info is NULL, use TCG default.
+// If there is a remainder while calculating the privExp, return FALSE.
+
+void Crypto_RSABuildCryptoInfoPublic( /*[IN]*/ UINT32 pubExpSize,
+ /*[IN]*/ BYTE *pubExp,
+ /*[IN]*/ UINT32 modulusSize,
+ /*[IN]*/ BYTE *modulus,
+ CRYPTO_INFO* cryptoInfo) {
+ cryptoInfo->keyInfo = RSA_new();
+ RSA *rsa = (RSA *) cryptoInfo->keyInfo;
+
+ rsa->e = BN_new();
+
+ if (pubExpSize == 0) { // Default e = 2^16+1
+ BN_set_bit(rsa->e, 16);
+ BN_set_bit(rsa->e, 0);
+ } else {
+ // This is not supported, but the following line MIGHT work
+ // under then assumption that the format is BigNum compatable
+ // Though it's not in the spec, so who knows what it is.
+ // Forcing the default.
+ //BN_bin2bn(pubExp, pubExpSize, NULL);
+ BN_set_bit(rsa->e, 16);
+ BN_set_bit(rsa->e, 0);
+ }
+
+ rsa->n = BN_bin2bn(modulus, modulusSize, NULL);
+
+}
+
+int Crypto_RSAEnc( CRYPTO_INFO *key,
+ UINT32 inDataSize,
+ BYTE *inData,
+ /*out*/ UINT32 *outDataSize,
+ /*out*/ BYTE *outData) {
+ RSA *rsa = (RSA *) key->keyInfo;
+ UINT32 paddedDataSize = RSA_size (rsa);
+ BYTE *paddedData = (BYTE *)malloc(sizeof(BYTE) * paddedDataSize);
+ int rc;
+
+ if (paddedData == NULL)
+ return -1;
+
+ *outDataSize = 0;
+
+ switch (key->encScheme) {
+ case CRYPTO_ES_RSAESPKCSv15:
+ if (RSA_padding_add_PKCS1_type_2(paddedData, paddedDataSize, inData,
inDataSize) <= 0) {
+ rc = -1;
+ goto abort_egress;
+ }
+ break;
+ case CRYPTO_ES_RSAESOAEP_SHA1_MGF1:
+ if
(RSA_padding_add_PKCS1_OAEP(paddedData,paddedDataSize,inData,inDataSize, (BYTE
*) OAEP_P,OAEP_P_SIZE) <= 0 ) {
+ rc = -1;
+ goto abort_egress;
+ }
+ break;
+ default:
+ rc = -1;
+ goto abort_egress;
+ }
+
+ rc = RSA_public_encrypt(paddedDataSize, paddedData, outData, rsa,
RSA_NO_PADDING);
+ if (rc == -1)
+ goto abort_egress;
+
+ *outDataSize = rc;
+
+ if (rc > 0) rc = 0;
+
+ goto egress;
+
+ abort_egress:
+ egress:
+
+ if (paddedData)
+ free (paddedData);
+ return rc;
+
+}
+
+int Crypto_RSADec( CRYPTO_INFO *key,
+ UINT32 inDataSize,
+ BYTE *inData,
+ /*out*/ UINT32 *outDataSize,
+ /*out*/ BYTE *outData) {
+
+ RSA *rsa = (RSA *) key->keyInfo;
+ UINT32 paddedDataSize = RSA_size (rsa);
+ BYTE *paddedData = (BYTE *)malloc(sizeof(BYTE) * paddedDataSize);
+ int rc;
+
+ if (paddedData == NULL)
+ goto abort_egress;
+
+ rc = RSA_private_decrypt(inDataSize, inData, paddedData, rsa,
RSA_NO_PADDING);
+ if (rc == -1) {
+ vtpmlogerror(VTPM_LOG_CRYPTO, "RSA_private_decrypt: %s\n",
ERR_error_string(ERR_get_error(), NULL));
+ goto abort_egress;
+ }
+
+ paddedDataSize = rc;
+
+ switch (key->encScheme) {
+ case CRYPTO_ES_RSAESPKCSv15:
+ rc = RSA_padding_check_PKCS1_type_2 (outData, paddedDataSize,
+ paddedData + 1, paddedDataSize - 1,
+ RSA_size(rsa));
+ if (rc == -1) {
+ vtpmlogerror(VTPM_LOG_CRYPTO, "RSA_padding_check_PKCS1_type_2: %s\n",
+ ERR_error_string(ERR_get_error(), NULL));
+ goto abort_egress;
+ }
+ *outDataSize = rc;
+ break;
+ case CRYPTO_ES_RSAESOAEP_SHA1_MGF1:
+ rc = RSA_padding_check_PKCS1_OAEP(outData, paddedDataSize,
+ paddedData + 1, paddedDataSize - 1,
+ RSA_size(rsa),
+ (BYTE *) OAEP_P, OAEP_P_SIZE);
+ if (rc == -1) {
+ vtpmlogerror(VTPM_LOG_CRYPTO, "RSA_padding_check_PKCS1_OAEP: %s\n",
+ ERR_error_string(ERR_get_error(), NULL));
+ goto abort_egress;
+ }
+ *outDataSize = rc;
+ break;
+ default:
+ *outDataSize = 0;
+ }
+
+ free(paddedData); paddedData = NULL;
+ goto egress;
+
+ abort_egress:
+
+ if (paddedData)
+ free (paddedData);
+ return -1;
+
+ egress:
+ return 0;
+}
+
+// Signs either a SHA1 digest of a message or a DER encoding of a message
+// Textual messages MUST be encoded or Hashed before sending into this function
+// It will NOT SHA the message.
+int Crypto_RSASign( CRYPTO_INFO *key,
+ UINT32 inDataSize,
+ BYTE *inData,
+ /*out*/ UINT32 *sigSize,
+ /*out*/ BYTE *sig) {
+ int status;
+ unsigned int intSigSize;
+
+ switch(key->sigScheme) {
+ case CRYPTO_SS_RSASSAPKCS1v15_SHA1:
+ status = RSA_sign(NID_sha1, inData, inDataSize, sig, &intSigSize, (RSA *)
key->keyInfo);
+ break;
+ case CRYPTO_SS_RSASSAPKCS1v15_DER:
+ // status = Crypto_RSA_sign_DER(NID_md5_sha1, inData, inDataSize,
sig, &intSigSize, key);
+ vtpmlogerror(VTPM_LOG_CRYPTO, "Crypto: Unimplemented sign type (%d)\n",
key->sigScheme);
+ status = 0;
+ break;
+ default:
+ status = 0;
+ }
+
+ if (status == 0) {
+ *sigSize = 0;
+ vtpmlogerror(VTPM_LOG_CRYPTO, "%s\n", ERR_error_string(ERR_get_error(),
NULL));
+ return -1;
+ }
+
+ *sigSize = (UINT32) intSigSize;
+ return 0;
+}
+
+bool Crypto_RSAVerify( CRYPTO_INFO *key,
+ UINT32 inDataSize,
+ BYTE *inData,
+ UINT32 sigSize,
+ BYTE *sig) {
+ int status;
+
+ switch(key->sigScheme){
+ case CRYPTO_SS_RSASSAPKCS1v15_SHA1:
+ status = RSA_verify(NID_sha1, inData, inDataSize, sig, sigSize, (RSA *)
key->keyInfo);
+ break;
+ case CRYPTO_SS_RSASSAPKCS1v15_DER:
+ //status = Crypto_RSA_verify_DER(NID_md5_sha1, inData, inDataSize, sig,
sigSize, key);
+ vtpmlogerror(VTPM_LOG_CRYPTO, "Crypto: Unimplemented sign type (%d)\n",
key->sigScheme);
+ status = 0;
+ break;
+ default:
+ status = 0;
+ }
+
+ if (status)
+ return(1);
+ else {
+ vtpmlogerror(VTPM_LOG_CRYPTO, "RSA verify: %s\n",
ERR_error_string(ERR_get_error(), NULL));
+ return(0);
+ }
+
+}
+
+// helper which packs everything into a BIO!
+
+// packs the parameters first, then the private key, then the public key
+// if *io_buf is NULL, allocate it here as needed. otherwise its size is in
+// *io_buflen
+TPM_RESULT Crypto_RSAPackCryptoInfo (const CRYPTO_INFO* cryptoInfo,
+ BYTE ** io_buf, UINT32 * io_buflen) {
+ TPM_RESULT status = TPM_SUCCESS;
+ BYTE * buf;
+ long len, outlen = *io_buflen;
+
+ const long PARAMSLEN = 3*sizeof(UINT32);
+
+ RSA *rsa = (RSA *) cryptoInfo->keyInfo;
+
+ BIO *mem = BIO_new(BIO_s_mem());
+
+
+ // write the openssl keys to the BIO
+ if ( i2d_RSAPrivateKey_bio (mem, rsa) == 0 ) {
+ ERR_print_errors_fp (stderr);
+ ERRORDIE (TPM_SIZE);
+ }
+ if ( i2d_RSAPublicKey_bio (mem, rsa) == 0 ) {
+ ERR_print_errors_fp (stderr);
+ ERRORDIE (TPM_SIZE);
+ }
+
+ // get the buffer out
+ len = BIO_get_mem_data (mem, &buf);
+
+ // see if we need to allocate a return buffer
+ if (*io_buf == NULL) {
+ *io_buf = (BYTE*) malloc (PARAMSLEN + len);
+ if (*io_buf == NULL)
+ ERRORDIE (TPM_SIZE);
+ } else { // *io_buf is already allocated
+ if (outlen < len + PARAMSLEN)
+ ERRORDIE (TPM_SIZE); // but not large enough!
+ }
+
+ // copy over the parameters (three UINT32's starting at algorithmID)
+ memcpy (*io_buf, &cryptoInfo->algorithmID, PARAMSLEN);
+
+ // copy over the DER keys
+ memcpy (*io_buf + PARAMSLEN, buf, len);
+
+ *io_buflen = len + PARAMSLEN;
+
+ goto egress;
+
+
+ abort_egress:
+ egress:
+
+ BIO_free (mem);
+
+ return status;
+}
+
+
+
+// sets up ci, and returns the number of bytes read in o_lenread
+TPM_RESULT Crypto_RSAUnpackCryptoInfo (CRYPTO_INFO * ci,
+ BYTE * in, UINT32 len,
+ UINT32 * o_lenread) {
+
+ TPM_RESULT status = TPM_SUCCESS;
+ long l;
+ BIO *mem;
+ RSA *rsa;
+
+ // first load up the params
+ l = 3 * sizeof(UINT32);
+ memcpy (&ci->algorithmID, in, l);
+ len -= l;
+ in += l;
+
+ // and now the openssl keys, private first
+ mem = BIO_new_mem_buf (in, len);
+
+ if ( (rsa = d2i_RSAPrivateKey_bio (mem, NULL)) == NULL ) {
+ ERR_print_errors_fp (stderr);
+ ERRORDIE (TPM_BAD_PARAMETER);
+ }
+ // now use the same RSA object and fill in the private key
+ if ( d2i_RSAPublicKey_bio (mem, &rsa) == NULL ) {
+ ERR_print_errors_fp (stderr);
+ ERRORDIE (TPM_BAD_PARAMETER);
+ }
+
+ ci->keyInfo = rsa; // needs to be freed somehow later
+
+ // FIXME: havent figured out yet how to tell how many bytes were read in the
+ // above oprations! so o_lenread is not set
+
+ goto egress;
+
+ abort_egress:
+ egress:
+
+ BIO_free (mem);
+
+ return status;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/crypto/sym_crypto.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/crypto/sym_crypto.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,242 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+//
+// sym_crypto.c
+//
+// Symmetric crypto portion of crypto
+//
+// ==================================================================
+
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+
+#include "tcg.h"
+#include "sym_crypto.h"
+
+typedef enum crypt_op_type_t {
+ CRYPT_ENCRYPT,
+ CRYPT_DECRYPT
+} crypt_op_type_t;
+
+TPM_RESULT ossl_symcrypto_op (symkey_t* key,
+ const buffer_t* in,
+ const buffer_t* iv,
+ buffer_t * out,
+ crypt_op_type_t optype);
+
+
+// this is initialized in Crypto_Init()
+const EVP_CIPHER * SYM_CIPHER = NULL;
+
+const BYTE ZERO_IV[EVP_MAX_IV_LENGTH] = {0};
+
+
+TPM_RESULT Crypto_symcrypto_initkey (symkey_t * key, const buffer_t* keybits) {
+ TPM_RESULT status = TPM_SUCCESS;
+
+ EVP_CIPHER_CTX_init (&key->context);
+
+ key->cipher = SYM_CIPHER;
+
+ status = buffer_init_copy (&key->key, keybits);
+ STATUSCHECK(status);
+
+ goto egress;
+
+ abort_egress:
+ EVP_CIPHER_CTX_cleanup (&key->context);
+
+ egress:
+
+ return status;
+}
+
+
+
+TPM_RESULT Crypto_symcrypto_genkey (symkey_t * key) {
+ int res;
+ TPM_RESULT status = TPM_SUCCESS;
+
+ // hmm, EVP_CIPHER_CTX_init does not return a value
+ EVP_CIPHER_CTX_init (&key->context);
+
+ key->cipher = SYM_CIPHER;
+
+ status = buffer_init (&key->key, EVP_CIPHER_key_length(key->cipher), NULL);
+ STATUSCHECK (status);
+
+ // and generate the key material
+ res = RAND_pseudo_bytes (key->key.bytes, key->key.size);
+ if (res < 0)
+ ERRORDIE (TPM_SHORTRANDOM);
+
+
+ goto egress;
+
+ abort_egress:
+ EVP_CIPHER_CTX_cleanup (&key->context);
+ buffer_free (&key->key);
+
+ egress:
+ return status;
+}
+
+
+TPM_RESULT Crypto_symcrypto_encrypt (symkey_t* key,
+ const buffer_t* clear,
+ buffer_t* o_cipher) {
+ TPM_RESULT status = TPM_SUCCESS;
+
+ buffer_t iv, cipher_alias;
+
+ buffer_init_const (&iv, EVP_MAX_IV_LENGTH, ZERO_IV);
+
+ buffer_init (o_cipher,
+ clear->size +
+ EVP_CIPHER_iv_length(key->cipher) +
+ EVP_CIPHER_block_size (key->cipher),
+ 0);
+
+ // copy the IV into the front
+ buffer_copy (o_cipher, &iv);
+
+ // make an alias into which we'll put the ciphertext
+ buffer_init_alias (&cipher_alias, o_cipher,
EVP_CIPHER_iv_length(key->cipher), 0);
+
+ status = ossl_symcrypto_op (key, clear, &iv, &cipher_alias, CRYPT_ENCRYPT);
+ STATUSCHECK (status);
+
+ // set the output size correctly
+ o_cipher->size += cipher_alias.size;
+
+ goto egress;
+
+ abort_egress:
+
+ egress:
+
+ return status;
+
+}
+
+
+
+TPM_RESULT Crypto_symcrypto_decrypt (symkey_t* key,
+ const buffer_t* cipher,
+ buffer_t* o_clear) {
+ TPM_RESULT status = TPM_SUCCESS;
+
+ buffer_t iv, cipher_alias;
+
+ // alias for the IV
+ buffer_init_alias (&iv, cipher, 0, EVP_CIPHER_iv_length(key->cipher));
+
+ // make an alias to where the ciphertext is, after the IV
+ buffer_init_alias (&cipher_alias, cipher, EVP_CIPHER_iv_length(key->cipher),
0);
+
+ // prepare the output buffer
+ status = buffer_init (o_clear,
+ cipher->size
+ - EVP_CIPHER_iv_length(key->cipher)
+ + EVP_CIPHER_block_size(key->cipher),
+ 0);
+ STATUSCHECK(status);
+
+ // and decrypt
+ status = ossl_symcrypto_op (key, &cipher_alias, &iv, o_clear, CRYPT_DECRYPT);
+ STATUSCHECK (status);
+
+ goto egress;
+
+ abort_egress:
+ buffer_free (o_clear);
+
+ egress:
+
+ return status;
+}
+
+
+
+TPM_RESULT Crypto_symcrypto_freekey (symkey_t * key) {
+ buffer_memset (&key->key, 0);
+ buffer_free (&key->key);
+
+ EVP_CIPHER_CTX_cleanup (&key->context);
+
+ return TPM_SUCCESS;
+}
+
+
+TPM_RESULT ossl_symcrypto_op (symkey_t* key,
+ const buffer_t* in,
+ const buffer_t* iv,
+ buffer_t * out,
+ crypt_op_type_t optype) {
+ TPM_RESULT status = TPM_SUCCESS;
+
+ int inlen, outlen;
+ tpm_size_t running;
+
+ if ( ! EVP_CipherInit_ex (&key->context,
+ key->cipher, NULL, key->key.bytes, iv->bytes,
+ optype == CRYPT_ENCRYPT ? 1 : 0) )
+ ERRORDIE (TPM_FAIL);
+
+
+
+ inlen = in->size;
+
+ outlen = 0;
+ running = 0;
+
+
+ if ( ! EVP_CipherUpdate (&key->context, out->bytes, &outlen, in->bytes,
inlen) )
+ ERRORDIE (TPM_FAIL);
+
+ running += outlen;
+
+ if ( ! EVP_CipherFinal_ex (&key->context, out->bytes + running, &outlen) )
+ ERRORDIE (TPM_FAIL);
+
+ running += outlen;
+
+ out->size = running;
+
+ goto egress;
+
+ abort_egress:
+ egress:
+
+ return status;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/crypto/sym_crypto.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/crypto/sym_crypto.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,72 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+//
+// sym_crypto.h
+//
+// Symmetric Crypto
+//
+// ==================================================================
+
+#ifndef _SYM_CRYPTO_H
+#define _SYM_CRYPTO_H
+
+#include <openssl/evp.h>
+#include "buffer.h"
+
+typedef struct symkey_t {
+ buffer_t key;
+
+ EVP_CIPHER_CTX context;
+ const EVP_CIPHER * cipher;
+} symkey_t;
+
+extern const EVP_CIPHER * SYM_CIPHER;
+
+TPM_RESULT Crypto_symcrypto_genkey (symkey_t * key);
+
+TPM_RESULT Crypto_symcrypto_initkey (symkey_t * key, const buffer_t* keybits);
+
+
+// these functions will allocate their output buffers
+TPM_RESULT Crypto_symcrypto_encrypt (symkey_t* key,
+ const buffer_t* clear,
+ buffer_t* o_cipher);
+
+TPM_RESULT Crypto_symcrypto_decrypt (symkey_t* key,
+ const buffer_t* cipher,
+ buffer_t* o_clear);
+
+// only free the internal parts, not the 'key' ptr
+TPM_RESULT Crypto_symcrypto_freekey (symkey_t * key);
+
+#endif /* _SYM_CRYPTO_H */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/manager/Makefile
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/manager/Makefile Fri Sep 9 16:30:54 2005
@@ -0,0 +1,27 @@
+XEN_ROOT = ../../..
+include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk
+
+BIN = vtpm_managerd
+
+all: build
+
+build: $(BIN)
+
+install: build
+ if [ ! -d "$(DESTDIR)/var/vtpm/fifos" ]; \
+ then mkdir -p $(DESTDIR)/var/vtpm/fifos; \
+ fi
+ $(INSTALL_PROG) $(BIN) $(TOOLS_INSTALL_DIR)
+
+clean:
+ rm -f *.a *.so *.o *.rpm $(DEP_FILES)
+
+mrproper: clean
+ rm -f $(BIN)
+
+$(BIN): $(OBJS)
+ $(CC) $(LDFLAGS) $^ $(LIBS) -o $@
+
+# libraries
+LIBS += ../tcs/libTCS.a ../util/libTCGUtils.a ../crypto/libtcpaCrypto.a
+LIBS += -lcrypto -lpthread -lrt -lm
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/manager/dmictl.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/manager/dmictl.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,339 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+//
+// dmictl.c
+//
+// Functions for creating and destroying DMIs
+//
+// ==================================================================
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+#ifndef VTPM_MUTLI_VM
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>
+ #include <signal.h>
+ #include <wait.h>
+#endif
+
+#include "vtpmpriv.h"
+#include "bsg.h"
+#include "buffer.h"
+#include "log.h"
+#include "hashtable.h"
+#include "hashtable_itr.h"
+
+#define TPM_EMULATOR_PATH "/usr/bin/vtpmd"
+
+TPM_RESULT close_dmi( VTPM_DMI_RESOURCE *dmi_res) {
+ TPM_RESULT status = TPM_FAIL;
+
+ if (dmi_res == NULL)
+ return TPM_SUCCESS;
+
+ status = TCS_CloseContext(dmi_res->TCSContext);
+ free ( dmi_res->NVMLocation );
+ dmi_res->connected = FALSE;
+
+#ifndef VTPM_MULTI_VM
+ free(dmi_res->guest_tx_fname);
+ free(dmi_res->vtpm_tx_fname);
+
+ close(dmi_res->guest_tx_fh); dmi_res->guest_tx_fh = -1;
+ close(dmi_res->vtpm_tx_fh); dmi_res->vtpm_tx_fh = -1;
+
+
+ #ifndef MANUAL_DM_LAUNCH
+ if (dmi_res->dmi_id != VTPM_CTL_DM) {
+ if (dmi_res->dmi_pid != 0) {
+ vtpmloginfo(VTPM_LOG_VTPM, "Killing dmi on pid %d.\n", dmi_res->dmi_pid);
+ if ((kill(dmi_res->dmi_pid, SIGKILL) !=0) ||
+ (waitpid(dmi_res->dmi_pid, NULL, 0) != dmi_res->dmi_pid)){
+ vtpmlogerror(VTPM_LOG_VTPM, "Could not kill dmi on pid %d.\n",
dmi_res->dmi_pid);
+ status = TPM_FAIL;
+ }
+ } else
+ vtpmlogerror(VTPM_LOG_VTPM, "Could not kill dmi because it's pid was
0.\n");
+ }
+ #endif
+#endif
+
+ return status;
+}
+
+TPM_RESULT VTPM_Handle_New_DMI( const buffer_t *param_buf) {
+
+ VTPM_DMI_RESOURCE *new_dmi=NULL;
+ TPM_RESULT status=TPM_FAIL;
+ BYTE type;
+ UINT32 dmi_id, domain_id, *dmi_id_key;
+ int fh;
+
+#ifndef VTPM_MUTLI_VM
+ char dmi_id_str[11]; // UINT32s are up to 10 digits + NULL
+ struct stat file_info;
+#endif
+
+ if (param_buf == NULL) { // Assume creation of Dom 0 control
+ type = 0;
+ domain_id = VTPM_CTL_DM;
+ dmi_id = VTPM_CTL_DM;
+ } else if (buffer_len(param_buf) != sizeof(BYTE) + sizeof(UINT32) *2) {
+ vtpmloginfo(VTPM_LOG_VTPM, "New DMI command wrong length: %d.\n",
buffer_len(param_buf));
+ status = TPM_BAD_PARAMETER;
+ goto abort_egress;
+ } else {
+ BSG_UnpackList( param_buf->bytes, 3,
+ BSG_TYPE_BYTE, &type,
+ BSG_TYPE_UINT32, &domain_id,
+ BSG_TYPE_UINT32, &dmi_id);
+ }
+
+ new_dmi = (VTPM_DMI_RESOURCE *) hashtable_search(vtpm_globals->dmi_map,
&dmi_id);
+ if (new_dmi == NULL) {
+ vtpmloginfo(VTPM_LOG_VTPM, "Creating new DMI instance %d attached on
domain %d.\n", dmi_id, domain_id);
+ // Brand New DMI. Initialize the persistent pieces
+ if ((new_dmi = (VTPM_DMI_RESOURCE *) malloc (sizeof(VTPM_DMI_RESOURCE)))
== NULL) {
+ status = TPM_RESOURCES;
+ goto abort_egress;
+ }
+ memset(new_dmi, 0, sizeof(VTPM_DMI_RESOURCE));
+ new_dmi->dmi_id = dmi_id;
+ new_dmi->connected = FALSE;
+
+ if ((dmi_id_key = (UINT32 *) malloc (sizeof(UINT32))) == NULL) {
+ status = TPM_RESOURCES;
+ goto abort_egress;
+ }
+ *dmi_id_key = new_dmi->dmi_id;
+
+ // install into map
+ if (!hashtable_insert(vtpm_globals->dmi_map, dmi_id_key, new_dmi)){
+ free(new_dmi);
+ free(dmi_id_key);
+ status = TPM_FAIL;
+ goto egress;
+ }
+
+ } else
+ vtpmloginfo(VTPM_LOG_VTPM, "Re-attaching DMI instance %d on domain %d
.\n", dmi_id, domain_id);
+
+ if (new_dmi->connected) {
+ vtpmlogerror(VTPM_LOG_VTPM, "Attempt to re-attach, currently attached
instance %d. Ignoring\n", dmi_id);
+ status = TPM_BAD_PARAMETER;
+ goto egress;
+ }
+
+ // Initialize the Non-persistent pieces
+ new_dmi->dmi_domain_id = domain_id;
+ new_dmi->NVMLocation = NULL;
+
+ new_dmi->TCSContext = 0;
+ TPMTRYRETURN( TCS_OpenContext(&new_dmi->TCSContext) );
+
+ new_dmi->NVMLocation = (char *) malloc(11 + strlen(DMI_NVM_FILE));
+ sprintf(new_dmi->NVMLocation, DMI_NVM_FILE, (uint32_t) new_dmi->dmi_id);
+
+ // Measure DMI
+ // FIXME: This will measure DMI. Until then use a fixed DMI_Measurement value
+ /*
+ fh = open(TPM_EMULATOR_PATH, O_RDONLY);
+ stat_ret = fstat(fh, &file_stat);
+ if (stat_ret == 0)
+ dmi_size = file_stat.st_size;
+ else {
+ vtpmlogerror(VTPM_LOG_VTPM, "Could not open tpm_emulator!!\n");
+ status = TPM_IOERROR;
+ goto abort_egress;
+ }
+ dmi_buffer
+ */
+ memset(&new_dmi->DMI_measurement, 0xcc, sizeof(TPM_DIGEST));
+
+#ifndef VTPM_MULTI_VM
+ if (dmi_id != VTPM_CTL_DM) {
+ // Create a pair of fifo pipes
+ if( (new_dmi->guest_tx_fname = (char *) malloc(11 +
strlen(GUEST_TX_FIFO))) == NULL){
+ status = TPM_RESOURCES;
+ goto abort_egress;
+ }
+ sprintf(new_dmi->guest_tx_fname, GUEST_TX_FIFO, (uint32_t)
dmi_id);
+
+ if ((new_dmi->vtpm_tx_fname = (char *) malloc(11 +
strlen(VTPM_TX_FIFO))) == NULL) {
+ status = TPM_RESOURCES;
+ goto abort_egress;
+ }
+ sprintf(new_dmi->vtpm_tx_fname, VTPM_TX_FIFO, (uint32_t)
dmi_id);
+
+ new_dmi->guest_tx_fh = -1;
+ new_dmi->vtpm_tx_fh= -1;
+
+ if ( stat(new_dmi->guest_tx_fname, &file_info) == -1) {
+ if ( mkfifo(new_dmi->guest_tx_fname, S_IWUSR | S_IRUSR ) ){
+ status = TPM_FAIL;
+ goto abort_egress;
+ }
+ }
+
+ if ( (fh = open(new_dmi->vtpm_tx_fname, O_RDWR)) == -1) {
+ if ( mkfifo(new_dmi->vtpm_tx_fname, S_IWUSR | S_IRUSR ) ) {
+ status = TPM_FAIL;
+ goto abort_egress;
+ }
+ }
+
+ // Launch DMI
+ sprintf(dmi_id_str, "%d", (int) dmi_id);
+#ifdef MANUAL_DM_LAUNCH
+ vtpmlogerror(VTPM_LOG_VTPM, "FAKING starting vtpm with dmi=%s\n",
dmi_id_str);
+ new_dmi->dmi_pid = 0;
+#else
+ pid_t pid = fork();
+
+ if (pid == -1) {
+ vtpmlogerror(VTPM_LOG_VTPM, "Could not fork to launch
vtpm\n");
+ status = TPM_RESOURCES;
+ goto abort_egress;
+ } else if (pid == 0) {
+ if ( stat(new_dmi->NVMLocation, &file_info) == -1)
+ execl (TPM_EMULATOR_PATH, "vtmpd", "clear",
dmi_id_str, NULL);
+ else
+ execl (TPM_EMULATOR_PATH, "vtpmd", "save",
dmi_id_str, NULL);
+
+ // Returning from these at all is an error.
+ vtpmlogerror(VTPM_LOG_VTPM, "Could not exec to launch
vtpm\n");
+ } else {
+ new_dmi->dmi_pid = pid;
+ vtpmloginfo(VTPM_LOG_VTPM, "Launching DMI on PID = %d\n", pid);
+ }
+#endif // MANUAL_DM_LAUNCH
+ }
+#else // VTPM_MUTLI_VM
+ // FIXME: Measure DMI through call to Measurement agent in platform.
+#endif
+
+ vtpm_globals->DMI_table_dirty = TRUE;
+ new_dmi->connected = TRUE;
+ status=TPM_SUCCESS;
+ goto egress;
+
+ abort_egress:
+ close_dmi( new_dmi );
+
+ egress:
+ return status;
+}
+
+TPM_RESULT VTPM_Handle_Close_DMI( const buffer_t *param_buf) {
+
+ TPM_RESULT status=TPM_FAIL;
+ VTPM_DMI_RESOURCE *dmi_res=NULL;
+ UINT32 dmi_id;
+
+ if ((param_buf == NULL) || (buffer_len(param_buf) != sizeof(UINT32)) ) {
+ vtpmlogerror(VTPM_LOG_VTPM, "Closing DMI has bad size.");
+ status = TPM_BAD_PARAMETER;
+ goto abort_egress;
+ }
+
+ BSG_UnpackList( param_buf->bytes, 1,
+ BSG_TYPE_UINT32, &dmi_id);
+
+ vtpmloginfo(VTPM_LOG_VTPM, "Closing DMI %d.\n", dmi_id);
+
+ dmi_res = (VTPM_DMI_RESOURCE *) hashtable_search(vtpm_globals->dmi_map,
&dmi_id);
+ if (dmi_res == NULL ) {
+ vtpmlogerror(VTPM_LOG_VTPM, "Trying to close nonexistent DMI.\n");
+ status = TPM_BAD_PARAMETER;
+ goto abort_egress;
+ }
+
+ if (!dmi_res->connected) {
+ vtpmlogerror(VTPM_LOG_VTPM, "Closing non-connected DMI.\n");
+ status = TPM_BAD_PARAMETER;
+ goto abort_egress;
+ }
+
+ // Close Dmi
+ TPMTRYRETURN(close_dmi( dmi_res ));
+
+ status=TPM_SUCCESS;
+ goto egress;
+
+ abort_egress:
+ egress:
+
+ return status;
+}
+
+TPM_RESULT VTPM_Handle_Delete_DMI( const buffer_t *param_buf) {
+
+ TPM_RESULT status=TPM_FAIL;
+ VTPM_DMI_RESOURCE *dmi_res=NULL;
+ UINT32 dmi_id;
+
+ if ((param_buf == NULL) || (buffer_len(param_buf) != sizeof(UINT32)) ) {
+ vtpmlogerror(VTPM_LOG_VTPM, "Closing DMI has bad size.\n");
+ status = TPM_BAD_PARAMETER;
+ goto abort_egress;
+ }
+
+ BSG_UnpackList( param_buf->bytes, 1,
+ BSG_TYPE_UINT32, &dmi_id);
+
+ vtpmloginfo(VTPM_LOG_VTPM, "Deleting DMI %d.\n", dmi_id);
+
+ dmi_res = (VTPM_DMI_RESOURCE *) hashtable_remove(vtpm_globals->dmi_map,
&dmi_id);
+ if (dmi_res == NULL) {
+ vtpmlogerror(VTPM_LOG_VTPM, "Closing non-existent DMI.\n");
+ status = TPM_BAD_PARAMETER;
+ goto abort_egress;
+ }
+
+ //TODO: Automatically delete file dmi_res->NVMLocation
+
+ // Close DMI first
+ TPMTRYRETURN(close_dmi( dmi_res ));
+ free ( dmi_res );
+
+ status=TPM_SUCCESS;
+ goto egress;
+
+ abort_egress:
+ egress:
+
+ return status;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/manager/securestorage.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/manager/securestorage.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,401 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+//
+// securestorage.c
+//
+// Functions regarding securely storing DMI secrets.
+//
+// ==================================================================
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "tcg.h"
+#include "vtpm_manager.h"
+#include "vtpmpriv.h"
+#include "vtsp.h"
+#include "bsg.h"
+#include "crypto.h"
+#include "hashtable.h"
+#include "hashtable_itr.h"
+#include "buffer.h"
+#include "log.h"
+
+TPM_RESULT VTPM_Handle_Save_NVM(VTPM_DMI_RESOURCE *myDMI,
+ const buffer_t *inbuf,
+ buffer_t *outbuf) {
+
+ TPM_RESULT status = TPM_SUCCESS;
+ symkey_t symkey;
+ buffer_t state_cipher = NULL_BUF,
+ symkey_cipher = NULL_BUF;
+ int fh;
+ long bytes_written;
+ BYTE *sealed_NVM=NULL;
+ UINT32 sealed_NVM_size, i;
+ struct pack_constbuf_t symkey_cipher32, state_cipher32;
+
+ vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Save_NVMing[%d]: 0x", buffer_len(inbuf));
+ for (i=0; i< buffer_len(inbuf); i++)
+ vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", inbuf->bytes[i]);
+ vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+
+ // Generate a sym key and encrypt state with it
+ TPMTRY(TPM_ENCRYPT_ERROR, Crypto_symcrypto_genkey (&symkey) );
+ TPMTRY(TPM_ENCRYPT_ERROR, Crypto_symcrypto_encrypt (&symkey, inbuf,
&state_cipher) );
+
+ // Encrypt symmetric key
+ TPMTRYRETURN( VTSP_Bind( &vtpm_globals->storageKey,
+ &symkey.key,
+ &symkey_cipher) );
+
+ // Create output blob: symkey_size + symkey_cipher + state_cipher_size +
state_cipher
+
+ symkey_cipher32.size = buffer_len(&symkey_cipher);
+ symkey_cipher32.data = symkey_cipher.bytes;
+
+ state_cipher32.size = buffer_len(&state_cipher);
+ state_cipher32.data = state_cipher.bytes;
+
+ sealed_NVM = (BYTE *) malloc( 2 * sizeof(UINT32) + symkey_cipher32.size +
state_cipher32.size);
+
+ sealed_NVM_size = BSG_PackList(sealed_NVM, 2,
+ BSG_TPM_SIZE32_DATA, &symkey_cipher32,
+ BSG_TPM_SIZE32_DATA, &state_cipher32);
+
+ // Mark DMI Table so new save state info will get pushed to disk on return.
+ vtpm_globals->DMI_table_dirty = TRUE;
+
+ // Write sealed blob off disk from NVMLocation
+ // TODO: How to properly return from these. Do we care if we return failure
+ // after writing the file? We can't get the old one back.
+ // TODO: Backup old file and try and recover that way.
+ fh = open(myDMI->NVMLocation, O_WRONLY | O_CREAT, S_IREAD | S_IWRITE);
+ if ( (bytes_written = write(fh, sealed_NVM, sealed_NVM_size) ) != (long)
sealed_NVM_size) {
+ vtpmlogerror(VTPM_LOG_VTPM, "We just overwrote a DMI_NVM and failed to
finish. %ld/%ld bytes.\n", bytes_written, (long)sealed_NVM_size);
+ status = TPM_IOERROR;
+ goto abort_egress;
+ }
+ close(fh);
+
+ Crypto_SHA1Full (sealed_NVM, sealed_NVM_size, (BYTE *)
&myDMI->NVM_measurement);
+
+ vtpmloginfo(VTPM_LOG_VTPM, "Saved %d bytes of E(symkey) + %d bytes of
E(NVM)\n", buffer_len(&symkey_cipher), buffer_len(&state_cipher));
+ goto egress;
+
+ abort_egress:
+ vtpmlogerror(VTPM_LOG_VTPM, "Failed to load NVM\n.");
+
+ egress:
+
+ buffer_free ( &state_cipher);
+ buffer_free ( &symkey_cipher);
+ free(sealed_NVM);
+ Crypto_symcrypto_freekey (&symkey);
+
+ return status;
+}
+
+
+/* inbuf = null outbuf = sealed blob size, sealed blob.*/
+TPM_RESULT VTPM_Handle_Load_NVM(VTPM_DMI_RESOURCE *myDMI,
+ const buffer_t *inbuf,
+ buffer_t *outbuf) {
+
+ TPM_RESULT status = TPM_SUCCESS;
+ symkey_t symkey;
+ buffer_t state_cipher = NULL_BUF,
+ symkey_clear = NULL_BUF,
+ symkey_cipher = NULL_BUF;
+ struct pack_buf_t symkey_cipher32, state_cipher32;
+
+ UINT32 sealed_NVM_size;
+ BYTE *sealed_NVM = NULL;
+ long fh_size;
+ int fh, stat_ret, i;
+ struct stat file_stat;
+ TPM_DIGEST sealedNVMHash;
+
+ memset(&symkey, 0, sizeof(symkey_t));
+
+ if (myDMI->NVMLocation == NULL) {
+ vtpmlogerror(VTPM_LOG_VTPM, "Unable to load NVM because the file name
NULL.\n");
+ status = TPM_AUTHFAIL;
+ goto abort_egress;
+ }
+
+ //Read sealed blob off disk from NVMLocation
+ fh = open(myDMI->NVMLocation, O_RDONLY);
+ stat_ret = fstat(fh, &file_stat);
+ if (stat_ret == 0)
+ fh_size = file_stat.st_size;
+ else {
+ status = TPM_IOERROR;
+ goto abort_egress;
+ }
+
+ sealed_NVM = (BYTE *) malloc(fh_size);
+ if (read(fh, sealed_NVM, fh_size) != fh_size) {
+ status = TPM_IOERROR;
+ goto abort_egress;
+ }
+ close(fh);
+
+ vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Load_NVMing[%ld]: 0x", fh_size);
+ for (i=0; i< fh_size; i++)
+ vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", sealed_NVM[i]);
+ vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+
+ sealed_NVM_size = BSG_UnpackList(sealed_NVM, 2,
+ BSG_TPM_SIZE32_DATA, &symkey_cipher32,
+ BSG_TPM_SIZE32_DATA, &state_cipher32);
+
+ TPMTRYRETURN( buffer_init_convert (&symkey_cipher,
+ symkey_cipher32.size,
+ symkey_cipher32.data) );
+
+ TPMTRYRETURN( buffer_init_convert (&state_cipher,
+ state_cipher32.size,
+ state_cipher32.data) );
+
+ Crypto_SHA1Full(sealed_NVM, sealed_NVM_size, (BYTE *) &sealedNVMHash);
+
+ // Verify measurement of sealed blob.
+ if (memcmp(&sealedNVMHash, &myDMI->NVM_measurement, sizeof(TPM_DIGEST)) ) {
+ vtpmlogerror(VTPM_LOG_VTPM, "VTPM LoadNVM NVM measurement check
failed.\n");
+ vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Correct hash: ");
+ for (i=0; i< sizeof(TPM_DIGEST); i++)
+ vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ",
((BYTE*)&myDMI->NVM_measurement)[i]);
+ vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+
+ vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Measured hash: ");
+ for (i=0; i< sizeof(TPM_DIGEST); i++)
+ vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", ((BYTE*)&sealedNVMHash)[i]);
+ vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+
+ status = TPM_AUTHFAIL;
+ goto abort_egress;
+ }
+
+ // Decrypt Symmetric Key
+ TPMTRYRETURN( VTSP_Unbind( myDMI->TCSContext,
+ vtpm_globals->storageKeyHandle,
+ &symkey_cipher,
+ (const
TPM_AUTHDATA*)&vtpm_globals->storage_key_usage_auth,
+ &symkey_clear,
+ &(vtpm_globals->keyAuth) ) );
+
+ // create symmetric key using saved bits
+ Crypto_symcrypto_initkey (&symkey, &symkey_clear);
+
+ // Decrypt State
+ TPMTRY(TPM_DECRYPT_ERROR, Crypto_symcrypto_decrypt (&symkey, &state_cipher,
outbuf) );
+
+ goto egress;
+
+ abort_egress:
+ vtpmlogerror(VTPM_LOG_VTPM, "Failed to load NVM\n.");
+
+ egress:
+
+ buffer_free ( &state_cipher);
+ buffer_free ( &symkey_clear);
+ buffer_free ( &symkey_cipher);
+ free( sealed_NVM );
+ Crypto_symcrypto_freekey (&symkey);
+
+ return status;
+}
+
+TPM_RESULT VTPM_SaveService(void) {
+ TPM_RESULT status=TPM_SUCCESS;
+ int fh, dmis=-1;
+
+ BYTE *flat_global;
+ int flat_global_size, bytes_written;
+ UINT32 storageKeySize = buffer_len(&vtpm_globals->storageKeyWrap);
+ struct pack_buf_t storage_key_pack = {storageKeySize,
vtpm_globals->storageKeyWrap.bytes};
+
+ struct hashtable_itr *dmi_itr;
+ VTPM_DMI_RESOURCE *dmi_res;
+
+ UINT32 flat_global_full_size;
+
+ // Global Values needing to be saved
+ flat_global_full_size = 3*sizeof(TPM_DIGEST) + // Auths
+ sizeof(UINT32) + // storagekeysize
+ storageKeySize + // storage key
+ hashtable_count(vtpm_globals->dmi_map) * // num DMIS
+ (sizeof(UINT32) + 2*sizeof(TPM_DIGEST)); // Per DMI info
+
+
+ flat_global = (BYTE *) malloc( flat_global_full_size);
+
+ flat_global_size = BSG_PackList(flat_global, 4,
+ BSG_TPM_AUTHDATA,
&vtpm_globals->owner_usage_auth,
+ BSG_TPM_AUTHDATA,
&vtpm_globals->srk_usage_auth,
+ BSG_TPM_SECRET,
&vtpm_globals->storage_key_usage_auth,
+ BSG_TPM_SIZE32_DATA, &storage_key_pack);
+
+ // Per DMI values to be saved
+ if (hashtable_count(vtpm_globals->dmi_map) > 0) {
+
+ dmi_itr = hashtable_iterator(vtpm_globals->dmi_map);
+ do {
+ dmi_res = (VTPM_DMI_RESOURCE *) hashtable_iterator_value(dmi_itr);
+ dmis++;
+
+ // No need to save dmi0.
+ if (dmi_res->dmi_id == 0)
+ continue;
+
+
+ flat_global_size += BSG_PackList( flat_global + flat_global_size, 3,
+ BSG_TYPE_UINT32, &dmi_res->dmi_id,
+ BSG_TPM_DIGEST,
&dmi_res->NVM_measurement,
+ BSG_TPM_DIGEST,
&dmi_res->DMI_measurement);
+
+ } while (hashtable_iterator_advance(dmi_itr));
+ }
+
+ //FIXME: Once we have a way to protect a TPM key, we should use it to
+ // encrypt this blob. BUT, unless there is a way to ensure the key is
+ // not used by other apps, this encryption is useless.
+ fh = open(STATE_FILE, O_WRONLY | O_CREAT, S_IREAD | S_IWRITE);
+ if (fh == -1) {
+ vtpmlogerror(VTPM_LOG_VTPM, "Unable to open %s file for write.\n",
STATE_FILE);
+ status = TPM_IOERROR;
+ goto abort_egress;
+ }
+
+ if ( (bytes_written = write(fh, flat_global, flat_global_size)) !=
flat_global_size ) {
+ vtpmlogerror(VTPM_LOG_VTPM, "Failed to save service data. %d/%d bytes
written.\n", bytes_written, flat_global_size);
+ status = TPM_IOERROR;
+ goto abort_egress;
+ }
+ vtpm_globals->DMI_table_dirty = FALSE;
+
+ goto egress;
+
+ abort_egress:
+ egress:
+
+ free(flat_global);
+ close(fh);
+
+ vtpmloginfo(VTPM_LOG_VTPM, "Saved VTPM Service state (status = %d, dmis =
%d)\n", (int) status, dmis);
+ return status;
+}
+
+TPM_RESULT VTPM_LoadService(void) {
+
+ TPM_RESULT status=TPM_SUCCESS;
+ int fh, stat_ret, dmis=0;
+ long fh_size = 0, step_size;
+ BYTE *flat_global=NULL;
+ struct pack_buf_t storage_key_pack;
+ UINT32 *dmi_id_key;
+
+ VTPM_DMI_RESOURCE *dmi_res;
+ struct stat file_stat;
+
+ fh = open(STATE_FILE, O_RDONLY );
+ stat_ret = fstat(fh, &file_stat);
+ if (stat_ret == 0)
+ fh_size = file_stat.st_size;
+ else {
+ status = TPM_IOERROR;
+ goto abort_egress;
+ }
+
+ flat_global = (BYTE *) malloc(fh_size);
+
+ if ((long) read(fh, flat_global, fh_size) != fh_size ) {
+ status = TPM_IOERROR;
+ goto abort_egress;
+ }
+
+ // Global Values needing to be saved
+ step_size = BSG_UnpackList( flat_global, 4,
+ BSG_TPM_AUTHDATA, &vtpm_globals->owner_usage_auth,
+ BSG_TPM_AUTHDATA, &vtpm_globals->srk_usage_auth,
+ BSG_TPM_SECRET,
&vtpm_globals->storage_key_usage_auth,
+ BSG_TPM_SIZE32_DATA, &storage_key_pack);
+
+ TPMTRYRETURN(buffer_init(&vtpm_globals->storageKeyWrap, 0, 0) );
+ TPMTRYRETURN(buffer_append_raw(&vtpm_globals->storageKeyWrap,
storage_key_pack.size, storage_key_pack.data) );
+
+ // Per DMI values to be saved
+ while ( step_size < fh_size ){
+ if (fh_size - step_size < (long) (sizeof(UINT32) + 2*sizeof(TPM_DIGEST))) {
+ vtpmlogerror(VTPM_LOG_VTPM, "Encountered %ld extra bytes at end of
manager state.\n", fh_size-step_size);
+ step_size = fh_size;
+ } else {
+ dmi_res = (VTPM_DMI_RESOURCE *) malloc(sizeof(VTPM_DMI_RESOURCE));
+ dmis++;
+
+ dmi_res->connected = FALSE;
+
+ step_size += BSG_UnpackList(flat_global + step_size, 3,
+ BSG_TYPE_UINT32, &dmi_res->dmi_id,
+ BSG_TPM_DIGEST, &dmi_res->NVM_measurement,
+ BSG_TPM_DIGEST, &dmi_res->DMI_measurement);
+
+ // install into map
+ dmi_id_key = (UINT32 *) malloc (sizeof(UINT32));
+ *dmi_id_key = dmi_res->dmi_id;
+ if (!hashtable_insert(vtpm_globals->dmi_map, dmi_id_key, dmi_res)) {
+ status = TPM_FAIL;
+ goto abort_egress;
+ }
+
+ }
+
+ }
+
+ goto egress;
+
+ abort_egress:
+ vtpmlogerror(VTPM_LOG_VTPM, "Failed to save service data\n");
+ egress:
+
+ if (flat_global)
+ free(flat_global);
+ close(fh);
+
+ vtpmloginfo(VTPM_LOG_VTPM, "Previously saved state reloaded (status = %d,
dmis = %d).\n", (int) status, dmis);
+ return status;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/manager/tpmpassthrough.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/manager/tpmpassthrough.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,110 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+//
+// tpmpassthrough.c
+//
+// Functions regarding passing DMI requests to HWTPM
+//
+// ==================================================================
+
+#include "tcg.h"
+#include "vtpm_manager.h"
+#include "vtpmpriv.h"
+#include "vtsp.h"
+#include "log.h"
+
+TPM_RESULT VTPM_Handle_TPM_Command( VTPM_DMI_RESOURCE *dmi,
+ buffer_t *inbuf,
+ buffer_t *outbuf) {
+
+ TPM_RESULT status = TPM_SUCCESS;
+ TPM_COMMAND_CODE *ord;
+
+ ord = (TPM_COMMAND_CODE *) (inbuf->bytes + sizeof(TPM_TAG) + sizeof(UINT32));
+
+ switch (*ord) {
+
+ // Forbidden for DMI use
+ case TPM_ORD_TakeOwnership:
+ case TPM_ORD_ChangeAuthOwner:
+ case TPM_ORD_DirWriteAuth:
+ case TPM_ORD_DirRead:
+ case TPM_ORD_AuthorizeMigrationKey:
+ case TPM_ORD_CreateMaintenanceArchive:
+ case TPM_ORD_LoadMaintenanceArchive:
+ case TPM_ORD_KillMaintenanceFeature:
+ case TPM_ORD_LoadManuMaintPub:
+ case TPM_ORD_ReadManuMaintPub:
+ case TPM_ORD_SelfTestFull:
+ case TPM_ORD_SelfTestStartup:
+ case TPM_ORD_CertifySelfTest:
+ case TPM_ORD_ContinueSelfTest:
+ case TPM_ORD_GetTestResult:
+ case TPM_ORD_Reset:
+ case TPM_ORD_OwnerClear:
+ case TPM_ORD_DisableOwnerClear:
+ case TPM_ORD_ForceClear:
+ case TPM_ORD_DisableForceClear:
+ case TPM_ORD_GetCapabilityOwner:
+ case TPM_ORD_OwnerSetDisable:
+ case TPM_ORD_PhysicalEnable:
+ case TPM_ORD_PhysicalDisable:
+ case TPM_ORD_SetOwnerInstall:
+ case TPM_ORD_PhysicalSetDeactivated:
+ case TPM_ORD_SetTempDeactivated:
+ case TPM_ORD_CreateEndorsementKeyPair:
+ case TPM_ORD_GetAuditEvent:
+ case TPM_ORD_GetAuditEventSigned:
+ case TPM_ORD_GetOrdinalAuditStatus:
+ case TPM_ORD_SetOrdinalAuditStatus:
+ case TPM_ORD_SetRedirection:
+ case TPM_ORD_FieldUpgrade:
+ case TSC_ORD_PhysicalPresence:
+ status = TPM_DISABLED_CMD;
+ goto abort_egress;
+ break;
+
+ } // End ORD Switch
+
+ // Call TCS with command
+
+ TPMTRY(TPM_IOERROR, VTSP_RawTransmit( dmi->TCSContext,inbuf, outbuf) );
+
+ goto egress;
+
+ abort_egress:
+ vtpmloginfo(VTPM_LOG_VTPM, "TPM Command Failed in tpmpassthrough.\n");
+ egress:
+
+ return status;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/manager/vtpm_manager.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/manager/vtpm_manager.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,735 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+//
+// vtpm_manager.c
+//
+// This file will house the main logic of the VTPM Manager
+//
+// ==================================================================
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+
+#ifndef VTPM_MULTI_VM
+#include <pthread.h>
+#include <errno.h>
+#include <aio.h>
+#include <time.h>
+#endif
+
+#include "vtpm_manager.h"
+#include "vtpmpriv.h"
+#include "vtsp.h"
+#include "bsg.h"
+#include "hashtable.h"
+#include "hashtable_itr.h"
+
+#include "log.h"
+#include "buffer.h"
+
+VTPM_GLOBALS *vtpm_globals=NULL;
+
+#ifdef VTPM_MULTI_VM
+ #define vtpmhandlerloginfo(module,fmt,args...) vtpmloginfo (module, fmt,
##args );
+ #define vtpmhandlerloginfomore(module,fmt,args...) vtpmloginfomore (module,
fmt, ##args );
+ #define vtpmhandlerlogerror(module,fmt,args...) vtpmlogerror (module, fmt,
##args );
+#else
+ #define vtpmhandlerloginfo(module,fmt,args...) vtpmloginfo (module, "[%d]: "
fmt, threadType, ##args );
+ #define vtpmhandlerloginfomore(module,fmt,args...) vtpmloginfomore (module,
fmt, ##args );
+ #define vtpmhandlerlogerror(module,fmt,args...) vtpmlogerror (module, "[%d]:
" fmt, threadType, ##args );
+#endif
+
+// --------------------------- Static Auths --------------------------
+#ifdef USE_FIXED_SRK_AUTH
+
+static BYTE FIXED_SRK_AUTH[20] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff};
+
+static BYTE FIXED_EK_AUTH[20] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff};
+
+#endif
+
+// -------------------------- Hash table functions --------------------
+
+static unsigned int hashfunc32(void *ky) {
+ return (* (UINT32 *) ky);
+}
+
+static int equals32(void *k1, void *k2) {
+ return (*(UINT32 *) k1 == *(UINT32 *) k2);
+}
+
+// --------------------------- Functions ------------------------------
+
+TPM_RESULT VTPM_Create_Service(){
+
+ TPM_RESULT status = TPM_SUCCESS;
+
+ // Generate Auth's for SRK & Owner
+#ifdef USE_FIXED_SRK_AUTH
+ memcpy(vtpm_globals->owner_usage_auth, FIXED_SRK_AUTH, sizeof(TPM_AUTHDATA));
+ memcpy(vtpm_globals->srk_usage_auth, FIXED_EK_AUTH, sizeof(TPM_AUTHDATA));
+#else
+ Crypto_GetRandom(vtpm_globals->owner_usage_auth, sizeof(TPM_AUTHDATA) );
+ Crypto_GetRandom(vtpm_globals->srk_usage_auth, sizeof(TPM_AUTHDATA) );
+#endif
+
+ // Take Owership of TPM
+ CRYPTO_INFO ek_cryptoInfo;
+
+ vtpmloginfo(VTPM_LOG_VTPM, "Attempting Pubek Read. NOTE: Failure is ok.\n");
+ status = VTSP_ReadPubek(vtpm_globals->manager_tcs_handle, &ek_cryptoInfo);
+
+ // If we can read PubEK then there is no owner and we should take it.
+ if (status == TPM_SUCCESS) {
+ TPMTRYRETURN(VTSP_TakeOwnership(vtpm_globals->manager_tcs_handle,
+ (const
TPM_AUTHDATA*)&vtpm_globals->owner_usage_auth,
+ (const
TPM_AUTHDATA*)&vtpm_globals->srk_usage_auth,
+ &ek_cryptoInfo,
+ &vtpm_globals->keyAuth));
+
+ TPMTRYRETURN(VTSP_DisablePubekRead(vtpm_globals->manager_tcs_handle,
+ (const
TPM_AUTHDATA*)&vtpm_globals->owner_usage_auth,
+ &vtpm_globals->keyAuth));
+ }
+
+ // Generate storage key's auth
+ Crypto_GetRandom( &vtpm_globals->storage_key_usage_auth,
+ sizeof(TPM_AUTHDATA) );
+
+ TCS_AUTH osap;
+ TPM_AUTHDATA sharedsecret;
+
+ TPMTRYRETURN( VTSP_OSAP(vtpm_globals->manager_tcs_handle,
+ TPM_ET_SRK,
+ 0,
+ (const TPM_AUTHDATA*)&vtpm_globals->srk_usage_auth,
+ &sharedsecret,
+ &osap) );
+
+ TPMTRYRETURN( VTSP_CreateWrapKey( vtpm_globals->manager_tcs_handle,
+ TPM_KEY_BIND,
+ (const
TPM_AUTHDATA*)&vtpm_globals->storage_key_usage_auth,
+ TPM_SRK_KEYHANDLE,
+ (const TPM_AUTHDATA*)&sharedsecret,
+ &vtpm_globals->storageKeyWrap,
+ &osap) );
+
+ vtpm_globals->keyAuth.fContinueAuthSession = TRUE;
+
+ goto egress;
+
+ abort_egress:
+ exit(1);
+
+ egress:
+ vtpmloginfo(VTPM_LOG_VTPM, "New VTPM Service initialized (Status = %d).\n",
status);
+ return status;
+
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+#ifdef VTPM_MULTI_VM
+int VTPM_Service_Handler(){
+#else
+void *VTPM_Service_Handler(void *threadTypePtr){
+#endif
+ TPM_RESULT status = TPM_FAIL; // Should never return
+ UINT32 dmi, in_param_size, cmd_size, out_param_size,
out_message_size, out_message_size_full, dmi_cmd_size;
+ BYTE *cmd_header, *in_param, *out_message, *dmi_cmd;
+ buffer_t *command_buf=NULL, *result_buf=NULL;
+ TPM_TAG tag;
+ TPM_COMMAND_CODE ord;
+ VTPM_DMI_RESOURCE *dmi_res;
+ int size_read, size_write, i;
+
+#ifndef VTPM_MULTI_VM
+ int threadType = *(int *) threadTypePtr;
+
+ // async io structures
+ struct aiocb dmi_aio;
+ struct aiocb *dmi_aio_a[1];
+ dmi_aio_a[0] = &dmi_aio;
+#endif
+
+#ifdef DUMMY_BACKEND
+ int dummy_rx;
+#endif
+
+ // TODO: Reinsert ifdefs to enable support for MULTI-VM
+
+ cmd_header = (BYTE *) malloc(VTPM_COMMAND_HEADER_SIZE_SRV);
+ command_buf = (buffer_t *) malloc(sizeof(buffer_t));
+ result_buf = (buffer_t *) malloc(sizeof(buffer_t));
+
+#ifndef VTPM_MULTI_VM
+ TPM_RESULT *ret_value = (TPM_RESULT *) malloc(sizeof(TPM_RESULT));
+#endif
+
+ int *tx_fh, *rx_fh;
+
+#ifdef VTPM_MULTI_VM
+ rx_fh = &vtpm_globals->be_fh;
+#else
+ if (threadType == BE_LISTENER_THREAD) {
+#ifdef DUMMY_BACKEND
+ dummy_rx = -1;
+ rx_fh = &dummy_rx;
+#else
+ rx_fh = &vtpm_globals->be_fh;
+#endif
+ } else { // DMI_LISTENER_THREAD
+ rx_fh = &vtpm_globals->vtpm_rx_fh;
+ }
+#endif
+
+#ifndef VTPM_MULTI_VM
+ int fh;
+ if (threadType == BE_LISTENER_THREAD) {
+ tx_fh = &vtpm_globals->be_fh;
+ if ( (fh = open(GUEST_RX_FIFO, O_RDWR)) == -1) {
+ if ( mkfifo(GUEST_RX_FIFO, S_IWUSR | S_IRUSR ) ){
+ *ret_value = TPM_FAIL;
+ pthread_exit(ret_value);
+ }
+ } else
+ close(fh);
+
+ } else { // else DMI_LISTENER_THREAD
+ // tx_fh will be set once the DMI is identified
+ // But we need to make sure the read pip is created.
+ if ( (fh = open(VTPM_RX_FIFO, O_RDWR)) == -1) {
+ if ( mkfifo(VTPM_RX_FIFO, S_IWUSR | S_IRUSR ) ){
+ *ret_value = TPM_FAIL;
+ pthread_exit(ret_value);
+ }
+ } else
+ close(fh);
+
+ }
+#endif
+
+ while(1) {
+
+ if (threadType == BE_LISTENER_THREAD) {
+ vtpmhandlerloginfo(VTPM_LOG_VTPM, "Waiting for Guest requests & ctrl
messages.\n");
+ } else
+ vtpmhandlerloginfo(VTPM_LOG_VTPM, "Waiting for DMI messages.\n");
+
+
+ if (*rx_fh < 0) {
+ if (threadType == BE_LISTENER_THREAD)
+#ifdef DUMMY_BACKEND
+ *rx_fh = open("/tmp/in.fifo", O_RDWR);
+#else
+ *rx_fh = open(VTPM_BE_DEV, O_RDWR);
+#endif
+ else // DMI Listener
+ *rx_fh = open(VTPM_RX_FIFO, O_RDWR);
+
+ }
+
+ if (*rx_fh < 0) {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Can't open inbound fh.\n");
+#ifdef VTPM_MULTI_VM
+ return TPM_IOERROR;
+#else
+ *ret_value = TPM_IOERROR;
+ pthread_exit(ret_value);
+#endif
+ }
+
+ size_read = read(*rx_fh, cmd_header, VTPM_COMMAND_HEADER_SIZE_SRV);
+ if (size_read > 0) {
+ vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "RECV[%d}: 0x", size_read);
+ for (i=0; i<size_read; i++)
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ",
cmd_header[i]);
+ } else {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Can't read from BE. Aborting... \n");
+ close(*rx_fh);
+ *rx_fh = -1;
+ goto abort_command;
+ }
+
+ if (size_read < (int) VTPM_COMMAND_HEADER_SIZE_SRV) {
+ vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "\n");
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Command shorter than normal header
(%d bytes). Aborting...\n", size_read);
+ goto abort_command;
+ }
+
+ BSG_UnpackList(cmd_header, 4,
+ BSG_TYPE_UINT32, &dmi,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, &in_param_size,
+ BSG_TPM_COMMAND_CODE, &ord );
+
+ // Note that in_param_size is in the client's context
+ cmd_size = in_param_size - VTPM_COMMAND_HEADER_SIZE_CLT;
+ if (cmd_size > 0) {
+ in_param = (BYTE *) malloc(cmd_size);
+ size_read = read( *rx_fh, in_param, cmd_size);
+ if (size_read > 0) {
+ for (i=0; i<size_read; i++)
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", in_param[i]);
+
+ } else {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Error reading from BE. Aborting...
\n");
+ close(*rx_fh);
+ *rx_fh = -1;
+ goto abort_command;
+ }
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+
+ if (size_read < (int) cmd_size) {
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Command read(%d) is shorter than
header indicates(%d). Aborting...\n", size_read, cmd_size);
+ goto abort_command;
+ }
+ } else {
+ in_param = NULL;
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+ }
+
+ if ((threadType != BE_LISTENER_THREAD) && (dmi == 0)) {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Attempt to access dom0 commands from
DMI interface. Aborting...\n");
+ goto abort_command;
+ }
+
+ dmi_res = (VTPM_DMI_RESOURCE *) hashtable_search(vtpm_globals->dmi_map,
&dmi);
+ if (dmi_res == NULL) {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Attempted access to non-existent DMI
in domain: %d. Aborting...\n", dmi);
+ goto abort_command;
+ }
+ if (!dmi_res->connected) {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Attempted access to disconnected DMI
in domain: %d. Aborting...\n", dmi);
+ goto abort_command;
+ }
+
+ if (threadType != BE_LISTENER_THREAD)
+ tx_fh = &dmi_res->vtpm_tx_fh;
+ // else we set this before the while loop since it doesn't change.
+
+ if ( (buffer_init_convert(command_buf, cmd_size, in_param) != TPM_SUCCESS)
||
+ (buffer_init(result_buf, 0, 0) != TPM_SUCCESS) ) {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Failed to setup buffers.
Aborting...\n");
+ goto abort_command;
+ }
+
+ // Dispatch it as either control or user request.
+ if (tag == VTPM_TAG_REQ) {
+ if (dmi_res->dmi_id == VTPM_CTL_DM){
+ switch (ord) {
+ case VTPM_ORD_OPEN:
+ status = VTPM_Handle_New_DMI(command_buf);
+ break;
+
+ case VTPM_ORD_CLOSE:
+ status = VTPM_Handle_Close_DMI(command_buf);
+ break;
+
+ case VTPM_ORD_DELETE:
+ status = VTPM_Handle_Delete_DMI(command_buf);
+ break;
+ default:
+ status = TPM_BAD_ORDINAL;
+ } // switch
+ } else {
+
+ switch (ord) {
+ case VTPM_ORD_SAVENVM:
+ status= VTPM_Handle_Save_NVM(dmi_res,
+ command_buf,
+ result_buf);
+ break;
+ case VTPM_ORD_LOADNVM:
+ status= VTPM_Handle_Load_NVM(dmi_res,
+ command_buf,
+ result_buf);
+ break;
+
+ case VTPM_ORD_TPMCOMMAND:
+ status= VTPM_Handle_TPM_Command(dmi_res,
+ command_buf,
+ result_buf);
+ break;
+
+ default:
+ status = TPM_BAD_ORDINAL;
+ } // switch
+ }
+ } else { // This is not a VTPM Command at all
+
+ if (threadType == BE_LISTENER_THREAD) {
+ if (dmi == 0) {
+ // This usually indicates a FE/BE driver.
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Illegal use of TPM command from
dom0\n");
+ status = TPM_FAIL;
+ } else {
+ vtpmhandlerloginfo(VTPM_LOG_VTPM, "Forwarding command to DMI.\n");
+
+ if (dmi_res->guest_tx_fh < 0)
+ dmi_res->guest_tx_fh = open(dmi_res->guest_tx_fname, O_WRONLY |
O_NONBLOCK);
+
+ if (dmi_res->guest_tx_fh < 0){
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "VTPM ERROR: Can't open outbound
fh to dmi.\n");
+ status = TPM_IOERROR;
+ goto abort_with_error;
+ }
+
+ //Note: Send message + dmi_id
+ if (cmd_size) {
+ dmi_cmd = (BYTE *) malloc(VTPM_COMMAND_HEADER_SIZE_SRV + cmd_size);
+ dmi_cmd_size = VTPM_COMMAND_HEADER_SIZE_SRV + cmd_size;
+ memcpy(dmi_cmd, cmd_header, VTPM_COMMAND_HEADER_SIZE_SRV);
+ memcpy(dmi_cmd + VTPM_COMMAND_HEADER_SIZE_SRV, in_param, cmd_size);
+ size_write = write(dmi_res->guest_tx_fh, dmi_cmd, dmi_cmd_size);
+
+ if (size_write > 0) {
+ vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "SENT (DMI): 0x");
+ for (i=0; i<VTPM_COMMAND_HEADER_SIZE_SRV + cmd_size; i++) {
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", dmi_cmd[i]);
+ }
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+ } else {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Error writing to DMI.
Aborting... \n");
+ close(dmi_res->guest_tx_fh);
+ dmi_res->guest_tx_fh = -1;
+ status = TPM_IOERROR;
+ goto abort_with_error;
+ }
+ free(dmi_cmd);
+ } else {
+ dmi_cmd_size = VTPM_COMMAND_HEADER_SIZE_SRV;
+ size_write = write(dmi_res->guest_tx_fh, cmd_header,
VTPM_COMMAND_HEADER_SIZE_SRV );
+ if (size_write > 0) {
+ for (i=0; i<VTPM_COMMAND_HEADER_SIZE_SRV; i++)
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ",
cmd_header[i]);
+
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+ } else {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Error writing to DMI.
Aborting... \n");
+ close(dmi_res->guest_tx_fh);
+ dmi_res->guest_tx_fh = -1;
+ status = TPM_IOERROR;
+ goto abort_with_error;
+ }
+ }
+
+ if (size_write != (int) dmi_cmd_size)
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Could not write entire command
to DMI (%d/%d)\n", size_write, dmi_cmd_size);
+ buffer_free(command_buf);
+
+ if (vtpm_globals->guest_rx_fh < 0)
+ vtpm_globals->guest_rx_fh = open(GUEST_RX_FIFO, O_RDONLY);
+
+ if (vtpm_globals->guest_rx_fh < 0){
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Can't open inbound fh to
dmi.\n");
+ status = TPM_IOERROR;
+ goto abort_with_error;
+ }
+
+ size_read = read( vtpm_globals->guest_rx_fh, cmd_header,
VTPM_COMMAND_HEADER_SIZE_SRV);
+ if (size_read > 0) {
+ vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "RECV (DMI): 0x");
+ for (i=0; i<size_read; i++)
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", cmd_header[i]);
+
+ } else {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Error reading from DMI.
Aborting... \n");
+ close(vtpm_globals->guest_rx_fh);
+ vtpm_globals->guest_rx_fh = -1;
+ status = TPM_IOERROR;
+ goto abort_with_error;
+ }
+
+ if (size_read < (int) VTPM_COMMAND_HEADER_SIZE_SRV) {
+ //vtpmdeepsublog("\n");
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Command from DMI shorter than
normal header. Aborting...\n");
+ status = TPM_IOERROR;
+ goto abort_with_error;
+ }
+
+ BSG_UnpackList(cmd_header, 4,
+ BSG_TYPE_UINT32, &dmi,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, &in_param_size,
+ BSG_TPM_COMMAND_CODE, &status );
+
+ // Note that in_param_size is in the client's context
+ cmd_size = in_param_size - VTPM_COMMAND_HEADER_SIZE_CLT;
+ if (cmd_size > 0) {
+ in_param = (BYTE *) malloc(cmd_size);
+ size_read = read( vtpm_globals->guest_rx_fh, in_param, cmd_size);
+ if (size_read > 0) {
+ for (i=0; i<size_read; i++)
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", in_param[i]);
+
+ } else {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Error reading from BE.
Aborting... \n");
+ close(vtpm_globals->guest_rx_fh);
+ vtpm_globals->guest_rx_fh = -1;
+ status = TPM_IOERROR;
+ goto abort_with_error;
+ }
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM, "\n");
+
+ if (size_read < (int)cmd_size) {
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM, "\n");
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Command read(%d) from DMI is
shorter than header indicates(%d). Aborting...\n", size_read, cmd_size);
+ status = TPM_IOERROR;
+ goto abort_with_error;
+ }
+ } else {
+ in_param = NULL;
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM, "\n");
+ }
+
+ if (buffer_init_convert(result_buf, cmd_size, in_param) !=
TPM_SUCCESS) {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Failed to setup buffers.
Aborting...\n");
+ status = TPM_FAIL;
+ goto abort_with_error;
+ }
+
+ vtpmhandlerloginfo(VTPM_LOG_VTPM, "Sending DMI's response to
guest.\n");
+ } // end else for if (dmi==0)
+
+ } else { // This is a DMI lister thread. Thus this is from a DMI
+#ifdef VTPM_MULTI_VM
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Attempt to use unsupported direct
access to TPM.\n");
+ vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "Bad Command. dmi:%d, tag:%d,
size:%d, ord:%d, Params: ", dmi, tag, in_param_size, ord);
+ for (UINT32 q=0; q<cmd_size; q++)
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", in_param[q]);
+
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+
+ status = TPM_FAIL;
+#else
+
+#endif
+ } // end else for if BE Listener
+ } // end else for is VTPM Command
+
+ // Send response to Backend
+ if (*tx_fh < 0) {
+ if (threadType == BE_LISTENER_THREAD)
+#ifdef DUMMY_BACKEND
+ *tx_fh = open("/tmp/out.fifo", O_RDWR);
+#else
+ *tx_fh = open(VTPM_BE_DEV, O_RDWR);
+#endif
+ else // DMI Listener
+ *tx_fh = open(dmi_res->vtpm_tx_fname, O_WRONLY);
+ }
+
+ if (*tx_fh < 0) {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "VTPM ERROR: Can't open outbound
fh.\n");
+#ifdef VTPM_MULTI_VM
+ return TPM_IOERROR;
+#else
+ *ret_value = TPM_IOERROR;
+ pthread_exit(ret_value);
+#endif
+ }
+
+ abort_with_error:
+ // Prepend VTPM header with destination DM stamped
+ out_param_size = buffer_len(result_buf);
+ out_message_size = VTPM_COMMAND_HEADER_SIZE_CLT + out_param_size;
+ out_message_size_full = VTPM_COMMAND_HEADER_SIZE_SRV + out_param_size;
+ out_message = (BYTE *) malloc (out_message_size_full);
+
+ BSG_PackList(out_message, 4,
+ BSG_TYPE_UINT32, (BYTE *) &dmi,
+ BSG_TPM_TAG, (BYTE *) &tag,
+ BSG_TYPE_UINT32, (BYTE *) &out_message_size,
+ BSG_TPM_RESULT, (BYTE *) &status);
+
+ if (buffer_len(result_buf) > 0)
+ memcpy(out_message + VTPM_COMMAND_HEADER_SIZE_SRV, result_buf->bytes,
out_param_size);
+
+
+ //Note: Send message + dmi_id
+ size_write = write(*tx_fh, out_message, out_message_size_full );
+ if (size_write > 0) {
+ vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "SENT: 0x");
+ for (i=0; i < out_message_size_full; i++)
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", out_message[i]);
+
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+ } else {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Error writing to BE. Aborting...
\n");
+ close(*tx_fh);
+ *tx_fh = -1;
+ goto abort_command;
+ }
+ free(out_message);
+
+ if (size_write < (int)out_message_size_full) {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Unable to write full command to BE
(%d/%d)\n", size_write, out_message_size_full);
+ goto abort_command;
+ }
+
+ abort_command:
+ //free buffers
+ bzero(cmd_header, VTPM_COMMAND_HEADER_SIZE_SRV);
+ //free(in_param); // This was converted to command_buf. No need to free
+ if (command_buf != result_buf)
+ buffer_free(result_buf);
+
+ buffer_free(command_buf);
+
+#ifndef VTPM_MULTI_VM
+ if (threadType != BE_LISTENER_THREAD) {
+#endif
+ if ( (vtpm_globals->DMI_table_dirty) &&
+ (VTPM_SaveService() != TPM_SUCCESS) ) {
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "ERROR: Unable to save manager
data.\n");
+ }
+#ifndef VTPM_MULTI_VM
+ }
+#endif
+
+ } // End while(1)
+
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+TPM_RESULT VTPM_Init_Service() {
+ TPM_RESULT status = TPM_FAIL;
+ BYTE *randomsead;
+ UINT32 randomsize;
+
+ if ((vtpm_globals = (VTPM_GLOBALS *) malloc(sizeof(VTPM_GLOBALS))) == NULL){
+ status = TPM_FAIL;
+ goto abort_egress;
+ }
+ memset(vtpm_globals, 0, sizeof(VTPM_GLOBALS));
+ vtpm_globals->be_fh = -1;
+
+#ifndef VTPM_MULTI_VM
+ vtpm_globals->vtpm_rx_fh = -1;
+ vtpm_globals->guest_rx_fh = -1;
+#endif
+ if ((vtpm_globals->dmi_map = create_hashtable(10, hashfunc32, equals32)) ==
NULL){
+ status = TPM_FAIL;
+ goto abort_egress;
+ }
+
+ vtpm_globals->DMI_table_dirty = FALSE;
+
+ // Create new TCS Object
+ vtpm_globals->manager_tcs_handle = 0;
+
+ TPMTRYRETURN(TCS_create());
+
+ // Create TCS Context for service
+ TPMTRYRETURN( TCS_OpenContext(&vtpm_globals->manager_tcs_handle ) );
+
+ TPMTRYRETURN( TCSP_GetRandom(vtpm_globals->manager_tcs_handle,
+
&randomsize,
+
&randomsead));
+
+ Crypto_Init(randomsead, randomsize);
+ TPMTRYRETURN( TCS_FreeMemory (vtpm_globals->manager_tcs_handle,
randomsead));
+
+ // Create OIAP session for service's authorized commands
+ TPMTRYRETURN( VTSP_OIAP( vtpm_globals->manager_tcs_handle,
+ &vtpm_globals->keyAuth) );
+ vtpm_globals->keyAuth.fContinueAuthSession = TRUE;
+
+ // If failed, create new Service.
+ if (VTPM_LoadService() != TPM_SUCCESS)
+ TPMTRYRETURN( VTPM_Create_Service() );
+
+
+ //Load Storage Key
+ TPMTRYRETURN( VTSP_LoadKey( vtpm_globals->manager_tcs_handle,
+ TPM_SRK_KEYHANDLE,
+ &vtpm_globals->storageKeyWrap,
+ (const
TPM_AUTHDATA*)&vtpm_globals->srk_usage_auth,
+ &vtpm_globals->storageKeyHandle,
+ &vtpm_globals->keyAuth,
+ &vtpm_globals->storageKey) );
+
+ // Create entry for Dom0 for control messages
+ TPMTRYRETURN( VTPM_Handle_New_DMI(NULL) );
+
+ // --------------------- Command handlers ---------------------------
+
+ goto egress;
+
+ abort_egress:
+ egress:
+
+ return(status);
+}
+
+void VTPM_Stop_Service() {
+ VTPM_DMI_RESOURCE *dmi_res;
+ struct hashtable_itr *dmi_itr;
+
+ // Close all the TCS contexts. TCS should evict keys based on this
+ if (hashtable_count(vtpm_globals->dmi_map) > 0) {
+ dmi_itr = hashtable_iterator(vtpm_globals->dmi_map);
+ do {
+ dmi_res = (VTPM_DMI_RESOURCE *) hashtable_iterator_value(dmi_itr);
+ if (dmi_res->connected)
+ if (close_dmi( dmi_res ) != TPM_SUCCESS)
+ vtpmlogerror(VTPM_LOG_VTPM, "Failed to
close dmi %d properly.\n", dmi_res->dmi_id);
+
+ } while (hashtable_iterator_advance(dmi_itr));
+ free (dmi_itr);
+ }
+
+
+ TCS_CloseContext(vtpm_globals->manager_tcs_handle);
+
+ if ( (vtpm_globals->DMI_table_dirty) &&
+ (VTPM_SaveService() != TPM_SUCCESS) )
+ vtpmlogerror(VTPM_LOG_VTPM, "Unable to save manager data.\n");
+
+ hashtable_destroy(vtpm_globals->dmi_map, 1);
+ free(vtpm_globals);
+
+ close(vtpm_globals->be_fh);
+ Crypto_Exit();
+
+ vtpmloginfo(VTPM_LOG_VTPM, "VTPM Manager stopped.\n");
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/manager/vtpm_manager.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/manager/vtpm_manager.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,137 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+//
+// vtpm_manager.h
+//
+// Public Interface header for VTPM Manager
+//
+// ==================================================================
+
+#ifndef __VTPM_MANAGER_H__
+#define __VTPM_MANAGER_H__
+
+#include "tcg.h"
+
+#define VTPM_TAG_REQ 0x01c1
+#define VTPM_TAG_RSP 0x01c4
+#define COMMAND_BUFFER_SIZE 4096
+
+// Header sizes. Note Header MAY include the DMI
+#define VTPM_COMMAND_HEADER_SIZE_SRV ( sizeof(UINT32) + sizeof(TPM_TAG) +
sizeof(UINT32) + sizeof(TPM_COMMAND_CODE))
+#define VTPM_COMMAND_HEADER_SIZE_CLT ( sizeof(TPM_TAG) +
sizeof(UINT32) + sizeof(TPM_COMMAND_CODE))
+
+// ********************** Public Functions *************************
+TPM_RESULT VTPM_Init_Service(); // Start VTPM Service
+void VTPM_Stop_Service(); // Stop VTPM Service
+#ifdef VTPM_MULTI_VM
+int VTPM_Service_Handler();
+#else
+void *VTPM_Service_Handler(void *threadTypePtr);
+#endif
+
+//************************ Command Codes ****************************
+#define VTPM_ORD_OPEN 1 // ULM Creates New DMI
+#define VTPM_ORD_CLOSE 2 // ULM Closes a DMI
+#define VTPM_ORD_DELETE 3 // ULM Permemently Deletes DMI
+#define VTPM_ORD_SAVENVM 4 // DMI requests Secrets Unseal
+#define VTPM_ORD_LOADNVM 5 // DMI requests Secrets Saved
+#define VTPM_ORD_TPMCOMMAND 6 // DMI issues HW TPM Command
+
+//************************ Return Codes ****************************
+#define VTPM_SUCCESS 0
+#define VTPM_FAIL 1
+#define VTPM_UNSUPPORTED 2
+#define VTPM_FORBIDDEN 3
+#define VTPM_RESTORE_CONTEXT_FAILED 4
+#define VTPM_INVALID_REQUEST 5
+
+/******************* Command Parameter API *************************
+
+VTPM Command Format
+ dmi: 4 bytes // Source of message.
+ // WARNING: This is prepended by the channel.
+ // Thus it is received by VTPM Manager,
+ // but not sent by DMI
+ tpm tag: 2 bytes
+ command size: 4 bytes // Size of command including header but not DMI
+ ord: 4 bytes // Command ordinal above
+ parameters: size - 10 bytes // Command Parameter
+
+VTPM Response Format
+ tpm tag: 2 bytes
+ response_size: 4 bytes
+ status: 4 bytes
+ parameters: size - 10 bytes
+
+
+VTPM_Open:
+ Input Parameters:
+ Domain_type: 1 byte
+ domain_id: 4 bytes
+ instance_id: 4 bytes
+ Output Parameters:
+ None
+
+VTPM_Close
+ Input Parameters:
+ instance_id: 4 bytes
+ Output Parameters:
+ None
+
+VTPM_Delete
+ Input Parameters:
+ instance_id: 4 bytes
+ Output Parameters:
+ None
+
+VTPM_SaveNVM
+ Input Parameters:
+ data: n bytes (Header indicates size of data)
+ Output Parameters:
+ None
+
+VTPM_LoadNVM
+ Input Parameters:
+ None
+ Output Parameters:
+ data: n bytes (Header indicates size of data)
+
+VTPM_TPMCommand
+ Input Parameters:
+ TPM Command Byte Stream: n bytes
+ Output Parameters:
+ TPM Reponse Byte Stream: n bytes
+
+*********************************************************************/
+
+#endif //_VTPM_MANAGER_H_
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/manager/vtpmd.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/manager/vtpmd.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,134 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+//
+// vtpmd.c
+//
+// Application
+//
+// ===================================================================
+
+#include <stdio.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "vtpm_manager.h"
+#include "vtpmpriv.h"
+#include "tcg.h"
+#include "log.h"
+
+#ifndef VTPM_MULTI_VM
+ #include <pthread.h>
+#endif
+
+void signal_handler(int reason) {
+#ifndef VTPM_MULTI_VM
+
+ if (pthread_equal(pthread_self(), vtpm_globals->master_pid)) {
+ if (reason >= 0) { // Reason is a signal
+ vtpmloginfo(VTPM_LOG_VTPM, "VTPM Manager shutting down for signal
%d.\n", reason);
+ } else {// Reason is a TPM_RESULT * -1
+ vtpmloginfo(VTPM_LOG_VTPM,"VTPM Manager shuting down for: %s\n",
tpm_get_error_name(-1 * reason) );
+ }
+
+ return;
+ } else {
+ vtpmloginfo(VTPM_LOG_VTPM, "Child shutting down\n");
+ pthread_exit(NULL);
+ }
+#else
+ VTPM_Stop_Service();
+ exit(-1);
+#endif
+}
+
+struct sigaction ctl_c_handler;
+
+int main(int argc, char **argv) {
+
+ vtpmloginfo(VTPM_LOG_VTPM, "Starting VTPM.\n");
+
+ if (VTPM_Init_Service() != TPM_SUCCESS) {
+ vtpmlogerror(VTPM_LOG_VTPM, "Closing vtpmd due to error during
startup.\n");
+ return -1;
+ }
+
+ ctl_c_handler.sa_handler = signal_handler;
+ sigemptyset(&ctl_c_handler.sa_mask);
+ ctl_c_handler.sa_flags = 0;
+
+ if (sigaction(SIGINT, &ctl_c_handler, NULL) == -1)
+ vtpmlogerror(VTPM_LOG_VTPM, "Could not install SIGINT handler. Ctl+break
will not stop service gently.\n");
+
+ // For easier debuggin with gdb
+ if (sigaction(SIGHUP, &ctl_c_handler, NULL) == -1)
+ vtpmlogerror(VTPM_LOG_VTPM, "Could not install SIGHUP handler. Ctl+break
will not stop service gently.\n");
+
+#ifdef VTPM_MULTI_VM
+ TPM_RESULT status = VTPM_Service_Handler();
+
+ if (status != TPM_SUCCESS)
+ vtpmlogerror(VTPM_LOG_VTPM, "VTPM Manager exited with status %s. It never
should exit.\n", tpm_get_error_name(status));
+
+ return -1;
+#else
+ sigset_t sig_mask;
+
+ sigemptyset(&sig_mask);
+ sigaddset(&sig_mask, SIGPIPE);
+ sigprocmask(SIG_BLOCK, &sig_mask, NULL);
+ //pthread_mutex_init(&vtpm_globals->dmi_mutex, NULL);
+ pthread_t be_thread, dmi_thread;
+ int betype_be, dmitype_dmi;
+
+ vtpm_globals->master_pid = pthread_self();
+
+ betype_be = BE_LISTENER_THREAD;
+ if (pthread_create(&be_thread, NULL, VTPM_Service_Handler, &betype_be) != 0)
{
+ vtpmlogerror(VTPM_LOG_VTPM, "Failed to launch BE Thread.\n");
+ exit(-1);
+ }
+
+ dmitype_dmi = DMI_LISTENER_THREAD;
+ if (pthread_create(&dmi_thread, NULL, VTPM_Service_Handler, &dmitype_dmi) !=
0) {
+ vtpmlogerror(VTPM_LOG_VTPM, "Failed to launch DMI Thread.\n");
+ exit(-1);
+ }
+
+ //Join the other threads until exit time.
+ pthread_join(be_thread, NULL);
+ pthread_join(dmi_thread, NULL);
+
+ VTPM_Stop_Service();
+ return 0;
+#endif
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/manager/vtpmpriv.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/manager/vtpmpriv.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,151 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+//
+// vtpmpriv.h
+//
+// Structures and functions private to the manager
+//
+// ==================================================================
+
+#ifndef __VTPMPRIV_H__
+#define __VTPMPRIV_H__
+
+#include "tcg.h"
+#include "tcs.h"
+#include "buffer.h"
+#include "crypto.h"
+
+#define STATE_FILE "/var/vtpm/VTPM"
+#define DMI_NVM_FILE "/var/vtpm/vtpm_dm_%d.data"
+#define VTPM_BE_DEV "/dev/vtpm"
+#define VTPM_CTL_DM 0
+
+#ifndef VTPM_MUTLI_VM
+ #include <sys/types.h>
+ #define GUEST_TX_FIFO "/var/vtpm/fifos/guest-to-%d.fifo"
+ #define GUEST_RX_FIFO "/var/vtpm/fifos/guest-from-all.fifo"
+
+ #define VTPM_TX_FIFO "/var/vtpm/fifos/vtpm-to-%d.fifo"
+ #define VTPM_RX_FIFO "/var/vtpm/fifos/vtpm-from-all.fifo"
+
+ #define BE_LISTENER_THREAD 1
+ #define DMI_LISTENER_THREAD 2
+
+ // Seconds until DMI timeout. Timeouts result in DMI being out
+ // of sync, which may require a reboot of DMI and guest to recover
+ // from. Don't set this to low. Also note that DMI may issue a TPM
+ // call so we should expect time to process at DMI + TPM processing.
+ #define DMI_TIMEOUT 90
+#endif
+
+
+// ------------------------ Private Structures -----------------------
+typedef struct VTPM_DMI_RESOURCE_T {
+ // I/O info for Manager to talk to DMI's over FIFOs
+#ifndef VTPM_MUTLI_VM
+ int guest_tx_fh; // open GUEST_TX_FIFO
+ int vtpm_tx_fh; // open VTPM_TX_FIFO
+ char *guest_tx_fname; // open GUEST_TX_FIFO
+ char *vtpm_tx_fname; // open VTPM_TX_FIFO
+
+ pid_t dmi_pid;
+#endif
+ // Non-persistent Information
+ bool connected;
+ UINT32 dmi_domain_id;
+ TCS_CONTEXT_HANDLE TCSContext; // TCS Handle
+ char *NVMLocation; // NULL term string indicating location
+ // of NVM.
+ // Persistent Information about DMI
+ UINT32 dmi_id;
+ TPM_DIGEST NVM_measurement; // Equal to the SHA1 of the blob
+ TPM_DIGEST DMI_measurement; // Correct measurement of the owning
DMI
+} VTPM_DMI_RESOURCE;
+
+typedef struct tdVTPM_GLOBALS {
+ // Non-persistent data
+ int be_fh; // File handle to ipc used to
communicate with backend
+#ifndef VTPM_MULTI_VM
+ int vtpm_rx_fh;
+ int guest_rx_fh;
+
+ pid_t master_pid;
+#endif
+ struct hashtable *dmi_map; // Table of all DMI's known
indexed by persistent instance #
+#ifndef VTPM_MULTI_VM
+ pthread_mutex_t dmi_map_mutex; //
+#endif
+ TCS_CONTEXT_HANDLE manager_tcs_handle; // TCS Handle used by manager
+ TPM_HANDLE storageKeyHandle; // Key used by persistent store
+ CRYPTO_INFO storageKey; // For software encryption
+ TCS_AUTH keyAuth; // OIAP session for storageKey
+ BOOL DMI_table_dirty; // Indicates that a command
+ // has updated the DMI table
+
+
+ // Persistent Data
+ TPM_AUTHDATA owner_usage_auth; // OwnerAuth of real TPM
+ TPM_AUTHDATA srk_usage_auth; // SRK Auth of real TPM
+ buffer_t storageKeyWrap; // Wrapped copy of storageKey
+
+ TPM_AUTHDATA storage_key_usage_auth;
+
+}VTPM_GLOBALS;
+
+//Global dmi map
+extern VTPM_GLOBALS *vtpm_globals;
+
+// ********************** Command Handler Prototypes ***********************
+TPM_RESULT VTPM_Handle_Load_NVM( VTPM_DMI_RESOURCE *myDMI,
+ const buffer_t *inbuf,
+ buffer_t *outbuf);
+
+TPM_RESULT VTPM_Handle_Save_NVM( VTPM_DMI_RESOURCE *myDMI,
+ const buffer_t *inbuf,
+ buffer_t *outbuf);
+
+TPM_RESULT VTPM_Handle_TPM_Command( VTPM_DMI_RESOURCE *dmi,
+ buffer_t *inbuf,
+ buffer_t *outbuf);
+
+TPM_RESULT VTPM_Handle_New_DMI(const buffer_t *param_buf);
+
+TPM_RESULT VTPM_Handle_Close_DMI(const buffer_t *param_buf);
+
+TPM_RESULT VTPM_Handle_Delete_DMI(const buffer_t *param_buf);
+
+TPM_RESULT VTPM_SaveService(void);
+TPM_RESULT VTPM_LoadService(void);
+
+TPM_RESULT close_dmi( VTPM_DMI_RESOURCE *dmi_res);
+#endif // __VTPMPRIV_H__
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/manager/vtsp.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/manager/vtsp.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,810 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+//
+// vtsp.c
+//
+// Higher level interface to TCS for use in service.
+//
+// ==================================================================
+
+#include <string.h>
+#include "tcg.h"
+#include "tcs.h"
+#include "bsg.h"
+#include "log.h"
+#include "crypto.h"
+#include "vtsp.h"
+#include "buffer.h"
+
+#define RSA_KEY_SIZE 0x0800
+
+/***********************************************************************************
+ * GenerateAuth: Generate authorization info to be sent back to application
+ *
+ * Parameters: outParamDigestText The concatenation of output parameters to
be SHA1ed
+ * outParamDigestTextSize Size of inParamDigestText
+ * HMACkey Key to be used for HMACing
+ * For OIAP use key.authUsage or PersistStore.ownerAuth
+ * For OSAP use shared secret
+ * pAuth Authorization information from the application
+ *
+ * Return: TPM_SUCCESS Authorization data created
+ * TPM_AUTHFAIL Invalid (NULL) HMACkey presented for OSAP
+
*************************************************************************************/
+TPM_RESULT GenerateAuth( /*[IN]*/ const BYTE *inParamDigestText,
+ /*[IN]*/ UINT32 inParamDigestTextSize,
+ /*[IN]*/ const TPM_SECRET *HMACkey,
+ /*[IN,OUT]*/ TCS_AUTH *auth) {
+
+ if (inParamDigestText == NULL || auth == NULL)
+ return (TPM_AUTHFAIL);
+ else {
+
+ //Generate new OddNonce
+ Crypto_GetRandom(auth->NonceOdd.nonce, sizeof(TPM_NONCE));
+
+ // Create SHA1 inParamDigest
+ TPM_DIGEST inParamDigest;
+ Crypto_SHA1Full(inParamDigestText, inParamDigestTextSize, (BYTE *)
&inParamDigest);
+
+ // Create HMAC text. (Concat inParamsDigest with inAuthSetupParams).
+ BYTE hmacText[sizeof(TPM_DIGEST) + (2 * sizeof(TPM_NONCE)) + sizeof(BOOL)];
+
+ BSG_PackList( hmacText, 4,
+ BSG_TPM_DIGEST, &inParamDigest,
+ BSG_TPM_NONCE, &(auth->NonceEven),
+ BSG_TPM_NONCE, &(auth->NonceOdd),
+ BSG_TYPE_BOOL, &(auth->fContinueAuthSession) );
+
+ Crypto_HMAC((BYTE *) hmacText, sizeof(hmacText), (BYTE *) HMACkey,
sizeof(TPM_DIGEST), (BYTE *) &(auth->HMAC));
+
+ return(TPM_SUCCESS);
+
+ }
+}
+
+/***********************************************************************************
+ * VerifyAuth: Verify the authdata for a command requiring authorization
+ *
+ * Parameters: inParamDigestText The concatenation of parameters to be SHA1ed
+ * inParamDigestTextSize Size of inParamDigestText
+ * authDataUsage AuthDataUsage for the Entity being used
+ * Key->authDataUsage or TPM_AUTH_OWNER
+ * HMACkey Key to be used for HMACing
+ * For OIAP use key.authUsage or PersistStore.ownerAuth
+ * For OSAP use NULL (It will be aquired from the Auth Session)
+ * If unknown (default), assume OIAP
+ * sessionAuth A TCS_AUTH info for the session
+ * pAuth Authorization information from the application
+ * hContext If specified, on failed Auth, VerifyAuth will
+ * generate a new OIAP session in place
of themselves
+ * destroyed session.
+ *
+ * Return: TPM_SUCCESS Authorization Verified
+ * TPM_AUTHFAIL Authorization Failed
+ * TPM_FAIL Failure during SHA1 routines
+
*************************************************************************************/
+TPM_RESULT VerifyAuth( /*[IN]*/ const BYTE *outParamDigestText,
+ /*[IN]*/ UINT32 outParamDigestTextSize,
+ /*[IN]*/ const TPM_SECRET *HMACkey,
+ /*[IN,OUT]*/ TCS_AUTH *auth,
+ /*[IN]*/ TCS_CONTEXT_HANDLE hContext) {
+ if (outParamDigestText == NULL || auth == NULL)
+ return (TPM_AUTHFAIL);
+
+
+ // Create SHA1 inParamDigest
+ TPM_DIGEST outParamDigest;
+ Crypto_SHA1Full(outParamDigestText, outParamDigestTextSize, (BYTE *)
&outParamDigest);
+
+ // Create HMAC text. (Concat inParamsDigest with inAuthSetupParams).
+ TPM_DIGEST hm;
+ BYTE hmacText[sizeof(TPM_DIGEST) + (2 * sizeof(TPM_NONCE)) + sizeof(BOOL)];
+
+ BSG_PackList( hmacText, 4,
+ BSG_TPM_DIGEST, &outParamDigest,
+ BSG_TPM_NONCE, &(auth->NonceEven),
+ BSG_TPM_NONCE, &(auth->NonceOdd),
+ BSG_TYPE_BOOL, &(auth->fContinueAuthSession) );
+
+ Crypto_HMAC((BYTE *) hmacText, sizeof(hmacText),
+ (BYTE *) HMACkey, sizeof(TPM_DIGEST), (BYTE *) &hm);
+
+ // Compare correct HMAC with provided one.
+ if (memcmp (&hm, &(auth->HMAC), sizeof(TPM_DIGEST)) == 0) // 0 indicates
equality
+ return (TPM_SUCCESS);
+ else {
+ VTSP_OIAP( hContext, auth);
+ return (TPM_AUTHFAIL);
+ }
+}
+
+TPM_RESULT VTSP_OIAP(const TCS_CONTEXT_HANDLE hContext,
+ TCS_AUTH *auth) {
+
+ vtpmloginfo(VTPM_LOG_VTSP, "OIAP.\n");
+ TPM_RESULT status = TPM_SUCCESS;
+ TPMTRYRETURN( TCSP_OIAP(hContext,
+ &auth->AuthHandle,
+ &auth->NonceEven) );
+ goto egress;
+
+ abort_egress:
+
+ egress:
+
+ return status;
+}
+
+TPM_RESULT VTSP_OSAP(const TCS_CONTEXT_HANDLE hContext,
+ const TPM_ENTITY_TYPE entityType,
+ const UINT32 entityValue,
+ const TPM_AUTHDATA *usageAuth,
+ TPM_SECRET *sharedSecret,
+ TCS_AUTH *auth) {
+
+ vtpmloginfo(VTPM_LOG_VTSP, "OSAP.\n");
+ TPM_RESULT status = TPM_SUCCESS;
+ TPM_NONCE nonceEvenOSAP, nonceOddOSAP;
+
+ Crypto_GetRandom((BYTE *) &nonceOddOSAP, sizeof(TPM_NONCE) );
+
+ TPMTRYRETURN( TCSP_OSAP( hContext,
+ TPM_ET_SRK,
+ 0,
+ nonceOddOSAP,
+ &auth->AuthHandle,
+ &auth->NonceEven,
+ &nonceEvenOSAP) );
+
+ // Calculating Session Secret
+ BYTE sharedSecretText[TPM_DIGEST_SIZE * 2];
+
+ BSG_PackList( sharedSecretText, 2,
+ BSG_TPM_NONCE, &nonceEvenOSAP,
+ BSG_TPM_NONCE, &nonceOddOSAP);
+
+ Crypto_HMAC(sharedSecretText, sizeof(sharedSecretText), (BYTE *) usageAuth,
TPM_DIGEST_SIZE, (BYTE *) sharedSecret);
+
+ goto egress;
+
+ abort_egress:
+
+ egress:
+
+ return status;
+}
+
+
+
+TPM_RESULT VTSP_ReadPubek( const TCS_CONTEXT_HANDLE hContext,
+ CRYPTO_INFO *crypto_info) {
+
+ TPM_RESULT status;
+ TPM_NONCE antiReplay;
+ TPM_DIGEST checksum;
+ BYTE *pubEKtext;
+ UINT32 pubEKtextsize;
+
+ vtpmloginfo(VTPM_LOG_VTSP, "Reading Public EK.\n");
+
+ // GenerateAuth new nonceOdd
+ Crypto_GetRandom(&antiReplay, sizeof(TPM_NONCE) );
+
+
+ TPMTRYRETURN( TCSP_ReadPubek( hContext,
+ antiReplay,
+ &pubEKtextsize,
+ &pubEKtext,
+ &checksum) );
+
+
+ // Extract the remaining output parameters
+ TPM_PUBKEY pubEK;
+
+ BSG_Unpack(BSG_TPM_PUBKEY, pubEKtext, (BYTE *) &pubEK);
+
+ // Build CryptoInfo for the bindingKey
+ TPM_RSA_KEY_PARMS rsaKeyParms;
+
+ BSG_Unpack(BSG_TPM_RSA_KEY_PARMS,
+ pubEK.algorithmParms.parms,
+ &rsaKeyParms);
+
+ Crypto_RSABuildCryptoInfoPublic(rsaKeyParms.exponentSize,
+ rsaKeyParms.exponent,
+ pubEK.pubKey.keyLength,
+ pubEK.pubKey.key,
+ crypto_info);
+
+ // Destroy rsaKeyParms
+ BSG_Destroy(BSG_TPM_RSA_KEY_PARMS, &rsaKeyParms);
+
+ // Set encryption scheme
+ crypto_info->encScheme = CRYPTO_ES_RSAESOAEP_SHA1_MGF1;
+ //crypto_info->encScheme = pubEK.algorithmParms.encScheme;
+ crypto_info->algorithmID = pubEK.algorithmParms.algorithmID;
+
+ goto egress;
+
+ abort_egress:
+
+ egress:
+
+ return status;
+}
+
+TPM_RESULT VTSP_TakeOwnership( const TCS_CONTEXT_HANDLE hContext,
+ const TPM_AUTHDATA *ownerAuth,
+ const TPM_AUTHDATA *srkAuth,
+ CRYPTO_INFO *ek_cryptoInfo,
+ TCS_AUTH *auth) {
+
+ vtpmloginfo(VTPM_LOG_VTSP, "Taking Ownership of TPM.\n");
+
+ TPM_RESULT status = TPM_SUCCESS;
+ TPM_COMMAND_CODE command = TPM_ORD_TakeOwnership;
+ TPM_PROTOCOL_ID proto_id = TPM_PID_OWNER;
+ BYTE *new_srk;
+
+ BYTE *paramText; // Digest to make Auth.
+ UINT32 paramTextSize;
+
+ // vars for srkpubkey parameter
+ TPM_KEY srkPub;
+ TPM_KEY_PARMS srkKeyInfo = {TPM_ALG_RSA, TPM_ES_RSAESOAEP_SHA1_MGF1,
TPM_SS_NONE, 12, 0};
+ BYTE srkRSAkeyInfo[12] = { 0x00, 0x00, (RSA_KEY_SIZE >> 8), 0x00, 0x00,
0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00};
+ srkKeyInfo.parms = (BYTE *) &srkRSAkeyInfo;
+
+ struct pack_buf_t srkText;
+
+ // GenerateAuth new nonceOdd
+ Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
+
+ //These values are accurate for an enc(AuthData).
+ struct pack_buf_t encOwnerAuth, encSrkAuth;
+
+ encOwnerAuth.data = (BYTE *)malloc(sizeof(BYTE) * 256);
+ encSrkAuth.data = (BYTE *)malloc(sizeof(BYTE) * 256);
+
+ if (encOwnerAuth.data == NULL || encSrkAuth.data == NULL) {
+ vtpmloginfo(VTPM_LOG_VTSP, "Could not malloc encrypted auths.\n");
+ status = TPM_RESOURCES;
+ goto abort_egress;
+ }
+
+ Crypto_RSAEnc(ek_cryptoInfo, sizeof(TPM_SECRET), (BYTE *) ownerAuth,
&encOwnerAuth.size, encOwnerAuth.data);
+ Crypto_RSAEnc(ek_cryptoInfo, sizeof(TPM_SECRET), (BYTE *) srkAuth,
&encSrkAuth.size, encSrkAuth.data);
+
+
+ // Build srk public key struct
+ srkPub.ver = TPM_STRUCT_VER_1_1;
+ srkPub.keyUsage = TPM_KEY_STORAGE;
+ srkPub.keyFlags = 0x00;
+ srkPub.authDataUsage = TPM_AUTH_ALWAYS;
+ memcpy(&srkPub.algorithmParms, &srkKeyInfo, sizeof(TPM_KEY_PARMS));
+ srkPub.PCRInfoSize = 0;
+ srkPub.PCRInfo = 0;
+ srkPub.pubKey.keyLength= 0;
+ srkPub.encDataSize = 0;
+
+ srkText.data = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+ srkText.size = BSG_Pack(BSG_TPM_KEY, (BYTE *) &srkPub, srkText.data);
+
+ paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+
+ paramTextSize = BSG_PackList(paramText, 5,
+ BSG_TPM_COMMAND_CODE,&command,
+ BSG_TPM_PROTOCOL_ID, &proto_id,
+ BSG_TPM_SIZE32_DATA, &encOwnerAuth,
+ BSG_TPM_SIZE32_DATA, &encSrkAuth,
+ BSG_TPM_KEY, &srkPub);
+
+ TPMTRYRETURN( GenerateAuth( paramText, paramTextSize, ownerAuth, auth) );
+
+ new_srk = srkText.data;
+ TPMTRYRETURN( TCSP_TakeOwnership ( hContext,
+ proto_id,
+ encOwnerAuth.size,
+ encOwnerAuth.data,
+ encSrkAuth.size,
+ encSrkAuth.data,
+ &srkText.size,
+ &new_srk,
+ auth ) );
+
+
+ paramTextSize = BSG_PackList(paramText, 2,
+ BSG_TPM_RESULT, &status,
+ BSG_TPM_COMMAND_CODE, &command);
+ memcpy(paramText + paramTextSize, new_srk, srkText.size);
+ paramTextSize += srkText.size;
+
+
+ TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
+ ownerAuth, auth,
+ hContext) );
+
+ goto egress;
+
+ abort_egress:
+
+ egress:
+
+ free(srkText.data);
+ free(encSrkAuth.data);
+ free(encOwnerAuth.data);
+ free(paramText);
+
+ TCS_FreeMemory(hContext, new_srk);
+
+ return status;
+}
+
+TPM_RESULT VTSP_DisablePubekRead( const TCS_CONTEXT_HANDLE hContext,
+ const TPM_AUTHDATA *ownerAuth,
+ TCS_AUTH *auth) {
+
+ vtpmloginfo(VTPM_LOG_VTSP, "Disabling Pubek Read.\n");
+
+ TPM_RESULT status = TPM_SUCCESS;
+ TPM_COMMAND_CODE command = TPM_ORD_DisablePubekRead;
+
+ BYTE *paramText; // Digest to make Auth.
+ UINT32 paramTextSize;
+
+ // Generate HMAC
+ Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
+
+ paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+
+ paramTextSize = BSG_PackList(paramText, 1,
+ BSG_TPM_COMMAND_CODE, &command);
+
+ TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
+ ownerAuth, auth) );
+
+ // Call TCS
+ TPMTRYRETURN( TCSP_DisablePubekRead ( hContext, // in
+ auth) );
+
+ // Verify Auth
+ paramTextSize = BSG_PackList(paramText, 2,
+ BSG_TPM_RESULT, &status,
+ BSG_TPM_COMMAND_CODE, &command);
+
+ TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
+ ownerAuth, auth,
+ hContext) );
+ goto egress;
+
+ abort_egress:
+ egress:
+ free(paramText);
+ return status;
+}
+
+TPM_RESULT VTSP_CreateWrapKey( const TCS_CONTEXT_HANDLE hContext,
+ const TPM_KEY_USAGE usage,
+ const TPM_AUTHDATA *newKeyAuth,
+ const TCS_KEY_HANDLE parentHandle,
+ const TPM_AUTHDATA *osapSharedSecret,
+ buffer_t *pubKeyBuf,
+ TCS_AUTH *auth) {
+
+ int i;
+ TPM_RESULT status = TPM_SUCCESS;
+ TPM_COMMAND_CODE command = TPM_ORD_CreateWrapKey;
+
+ vtpmloginfo(VTPM_LOG_VTSP, "Creating new key of type %d.\n", usage);
+
+ // vars for Calculate encUsageAuth
+ BYTE *paramText;
+ UINT32 paramTextSize;
+
+ // vars for Calculate encUsageAuth
+ BYTE XORbuffer[sizeof(TPM_SECRET) + sizeof(TPM_NONCE)];
+ TPM_DIGEST XORKey1;
+ UINT32 XORbufferSize;
+ TPM_SECRET encUsageAuth, encMigrationAuth;
+
+ // vars for Flatten newKey prototype
+ BYTE *flatKey = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+ UINT32 flatKeySize = TCPA_MAX_BUFFER_LENGTH;
+ struct pack_buf_t newKeyText;
+
+ // Fill in newKey
+ TPM_KEY newKey;
+
+ BYTE RSAkeyInfo[12] = { 0x00, 0x00, (RSA_KEY_SIZE >> 8), 0x00, 0x00, 0x00,
0x00, 0x02, 0x00, 0x00, 0x00, 0x00};
+ newKey.algorithmParms.algorithmID = TPM_ALG_RSA;
+ newKey.algorithmParms.parms = (BYTE *) &RSAkeyInfo;
+ newKey.algorithmParms.parmSize = 12;
+
+ switch (usage) {
+ case TPM_KEY_SIGNING:
+ vtpmloginfo(VTPM_LOG_VTSP, "Creating Signing Key...\n");
+ newKey.keyUsage = TPM_KEY_SIGNING;
+ newKey.algorithmParms.encScheme = TPM_ES_NONE;
+ newKey.algorithmParms.sigScheme = TPM_SS_RSASSAPKCS1v15_SHA1;
+ break;
+ case TPM_KEY_STORAGE:
+ vtpmloginfo(VTPM_LOG_VTSP, "Creating Storage Key...\n");
+ newKey.keyUsage = TPM_KEY_STORAGE;
+ newKey.algorithmParms.encScheme = TPM_ES_RSAESOAEP_SHA1_MGF1;
+ newKey.algorithmParms.sigScheme = TPM_SS_NONE;
+ break;
+ case TPM_KEY_BIND:
+ vtpmloginfo(VTPM_LOG_VTSP, "Creating Binding Key...\n");
+ newKey.keyUsage = TPM_KEY_BIND;
+ newKey.algorithmParms.encScheme = TPM_ES_RSAESOAEP_SHA1_MGF1;
+ newKey.algorithmParms.sigScheme = TPM_SS_NONE;
+ break;
+ default:
+ vtpmloginfo(VTPM_LOG_VTSP, "Cannot create key. Invalid Key Type.\n");
+ status = TPM_BAD_PARAMETER;
+ goto abort_egress;
+ }
+
+
+ newKey.ver = TPM_STRUCT_VER_1_1;
+
+ newKey.keyFlags = 0;
+ newKey.authDataUsage = TPM_AUTH_ALWAYS;
+ newKey.pubKey.keyLength= 0;
+ newKey.encDataSize = 0;
+ newKey.encData = NULL;
+
+ // FIXME: Support PCR bindings
+ newKey.PCRInfoSize = 0;
+ newKey.PCRInfo = NULL;
+
+ // Calculate encUsageAuth
+ XORbufferSize = BSG_PackList( XORbuffer, 2,
+ BSG_TPM_SECRET, osapSharedSecret,
+ BSG_TPM_NONCE, &auth->NonceEven);
+ Crypto_SHA1Full(XORbuffer, XORbufferSize, (BYTE *) &XORKey1);
+
+ // FIXME: No support for migratable keys.
+ for (i=0; i < TPM_DIGEST_SIZE; i++)
+ ((BYTE *) &encUsageAuth)[i] = ((BYTE *) &XORKey1)[i] ^ ((BYTE *)
newKeyAuth)[i];
+
+ // Flatten newKey prototype
+ flatKeySize = BSG_Pack(BSG_TPM_KEY, (BYTE *) &newKey, flatKey);
+ newKeyText.data = flatKey;
+ newKeyText.size = flatKeySize;
+
+ // GenerateAuth new nonceOdd
+ Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
+
+ // Generate HMAC
+ paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+
+ paramTextSize = BSG_PackList(paramText, 3,
+ BSG_TPM_COMMAND_CODE, &command,
+ BSG_TPM_AUTHDATA, &encUsageAuth,
+ BSG_TPM_AUTHDATA, &encMigrationAuth);
+ memcpy(paramText + paramTextSize, newKeyText.data, newKeyText.size);
+ paramTextSize += newKeyText.size;
+
+
+ TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
+ osapSharedSecret, auth) );
+
+ // Call TCS
+ TPMTRYRETURN( TCSP_CreateWrapKey( hContext,
+ parentHandle,
+ encUsageAuth,
+ encMigrationAuth,
+ &newKeyText.size,
+ &newKeyText.data,
+ auth) );
+
+ // Verify Auth
+ paramTextSize = BSG_PackList(paramText, 2,
+ BSG_TPM_RESULT, &status,
+ BSG_TPM_COMMAND_CODE, &command);
+ memcpy(paramText + paramTextSize, newKeyText.data, newKeyText.size);
+ paramTextSize += newKeyText.size;
+
+ TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
+ osapSharedSecret, auth, 0) );
+
+ // Unpack/return key structure
+ TPMTRYRETURN(buffer_init(pubKeyBuf, 0, 0) );
+ TPMTRYRETURN(buffer_append_raw(pubKeyBuf, newKeyText.size, newKeyText.data)
);
+
+ goto egress;
+
+ abort_egress:
+
+ egress:
+
+ free(flatKey);
+ free(paramText);
+ TCS_FreeMemory(hContext, newKeyText.data);
+
+ return status;
+}
+
+TPM_RESULT VTSP_LoadKey(const TCS_CONTEXT_HANDLE hContext,
+ const TCS_KEY_HANDLE hUnwrappingKey,
+ const buffer_t *rgbWrappedKeyBlob,
+ const TPM_AUTHDATA *parentAuth,
+ TPM_HANDLE *newKeyHandle,
+ TCS_AUTH *auth,
+ CRYPTO_INFO *cryptoinfo /*= NULL*/) {
+
+
+ vtpmloginfo(VTPM_LOG_VTSP, "Loading Key.\n%s","");
+
+ TPM_RESULT status = TPM_SUCCESS;
+ TPM_COMMAND_CODE command = TPM_ORD_LoadKey;
+
+ BYTE *paramText; // Digest to make Auth.
+ UINT32 paramTextSize;
+
+ if ((rgbWrappedKeyBlob == NULL) || (parentAuth == NULL) ||
+ (newKeyHandle==NULL) || (auth==NULL)) {
+ status = TPM_BAD_PARAMETER;
+ goto abort_egress;
+ }
+
+ // Generate Extra TCS Parameters
+ TPM_HANDLE phKeyHMAC;
+
+ // Generate HMAC
+ Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
+
+ paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+
+ paramTextSize = BSG_PackList(paramText, 1,
+ BSG_TPM_COMMAND_CODE, &command);
+
+ memcpy(paramText + paramTextSize, rgbWrappedKeyBlob->bytes,
buffer_len(rgbWrappedKeyBlob));
+ paramTextSize += buffer_len(rgbWrappedKeyBlob);
+
+ TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
+ parentAuth, auth) );
+
+ // Call TCS
+ TPMTRYRETURN( TCSP_LoadKeyByBlob( hContext,
+ hUnwrappingKey,
+ buffer_len(rgbWrappedKeyBlob),
+ rgbWrappedKeyBlob->bytes,
+ auth,
+ newKeyHandle,
+ &phKeyHMAC) );
+
+ // Verify Auth
+ paramTextSize = BSG_PackList(paramText, 3,
+ BSG_TPM_RESULT, &status,
+ BSG_TPM_COMMAND_CODE, &command,
+ BSG_TPM_HANDLE, newKeyHandle);
+
+ TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
+ parentAuth, auth,
+ hContext) );
+
+ // Unpack/return key structure
+ if (cryptoinfo != NULL) {
+ TPM_KEY newKey;
+
+ BSG_Unpack(BSG_TPM_KEY, rgbWrappedKeyBlob->bytes , &newKey);
+ TPM_RSA_KEY_PARMS rsaKeyParms;
+
+ BSG_Unpack(BSG_TPM_RSA_KEY_PARMS,
+ newKey.algorithmParms.parms,
+ &rsaKeyParms);
+
+ Crypto_RSABuildCryptoInfoPublic(rsaKeyParms.exponentSize,
+ rsaKeyParms.exponent,
+ newKey.pubKey.keyLength,
+ newKey.pubKey.key,
+ cryptoinfo);
+
+ // Destroy rsaKeyParms
+ BSG_Destroy(BSG_TPM_RSA_KEY_PARMS, &rsaKeyParms);
+
+ // Set encryption scheme
+ cryptoinfo->encScheme = CRYPTO_ES_RSAESOAEP_SHA1_MGF1;
+ }
+
+ goto egress;
+
+ abort_egress:
+
+ egress:
+
+ free(paramText);
+ return status;
+}
+
+TPM_RESULT VTSP_Unbind( const TCS_CONTEXT_HANDLE hContext,
+ const TPM_KEY_HANDLE key_handle,
+ const buffer_t *bound_data,
+ const TPM_AUTHDATA *usage_auth,
+ buffer_t *clear_data,
+ TCS_AUTH *auth) {
+
+ vtpmloginfo(VTPM_LOG_VTSP, "Unbinding %d bytes of data.\n",
buffer_len(bound_data));
+
+ TPM_RESULT status = TPM_SUCCESS;
+ TPM_COMMAND_CODE command = TPM_ORD_UnBind;
+
+ BYTE *paramText; // Digest to make Auth.
+ UINT32 paramTextSize;
+
+ // Generate Extra TCS Parameters
+ struct pack_buf_t clear_data32;
+ BYTE *clear_data_text;
+ UINT32 clear_data_size;
+
+ // Generate HMAC
+ Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
+
+ struct pack_buf_t bound_data32 = {bound_data->size, bound_data->bytes};
+
+ paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+
+ paramTextSize = BSG_PackList(paramText, 2,
+ BSG_TPM_COMMAND_CODE, &command,
+ BSG_TPM_SIZE32_DATA, &bound_data32);
+
+ TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
+ usage_auth, auth) );
+
+ // Call TCS
+ TPMTRYRETURN( TCSP_UnBind( hContext,
+ key_handle,
+ buffer_len(bound_data),
+ bound_data->bytes,
+ auth,
+ &clear_data_size,
+ &clear_data_text) );
+
+
+ // Verify Auth
+ clear_data32.size = clear_data_size;
+ clear_data32.data = clear_data_text;
+ paramTextSize = BSG_PackList(paramText, 3,
+ BSG_TPM_RESULT, &status,
+ BSG_TPM_COMMAND_CODE, &command,
+ BSG_TPM_SIZE32_DATA, &clear_data32);
+
+ TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
+ usage_auth, auth,
+ hContext) );
+
+ // Unpack/return key structure
+ TPMTRYRETURN(buffer_init(clear_data, 0, 0));
+ TPMTRYRETURN(buffer_append_raw (clear_data, clear_data_size,
clear_data_text) );
+
+ goto egress;
+
+ abort_egress:
+
+ egress:
+
+ free(paramText);
+ TCS_FreeMemory(hContext, clear_data_text);
+
+ return status;
+}
+
+TPM_RESULT VTSP_Bind( CRYPTO_INFO *cryptoInfo,
+ const buffer_t *inData,
+ buffer_t *outData)
+{
+ vtpmloginfo(VTPM_LOG_VTSP, "Binding %d bytes of data.\n",
buffer_len(inData));
+ TPM_BOUND_DATA boundData;
+ UINT32 i;
+
+ // Fill boundData's accessory information
+ boundData.ver = TPM_STRUCT_VER_1_1;
+ boundData.payload = TPM_PT_BIND;
+ boundData.payloadData = inData->bytes;
+
+ // Pack boundData before encryption
+ BYTE* flatBoundData = (BYTE *)malloc(sizeof(BYTE) *
+ (sizeof(TPM_VERSION) +
+ sizeof(TPM_PAYLOAD_TYPE) +
+ buffer_len(inData)));
+ if (flatBoundData == NULL) {
+ return TPM_NOSPACE;
+ }
+ UINT32 flatBoundDataSize = 0;
+ flatBoundDataSize = BSG_PackList( flatBoundData, 2,
+ BSG_TPM_VERSION, &boundData.ver,
+ BSG_TYPE_BYTE, &boundData.payload);
+
+ memcpy(flatBoundData+flatBoundDataSize, inData->bytes, buffer_len(inData));
+ flatBoundDataSize += buffer_len(inData);
+
+ BYTE out_tmp[RSA_KEY_SIZE/8]; // RSAEnc does not do blocking, So this is
what will come out.
+ UINT32 out_tmp_size;
+
+ // Encrypt flatBoundData
+ Crypto_RSAEnc( cryptoInfo,
+ flatBoundDataSize,
+ flatBoundData,
+ &out_tmp_size,
+ out_tmp);
+
+ if (out_tmp_size > RSA_KEY_SIZE/8) {
+ // The result of RSAEnc should be a fixed size based on key size.
+ vtpmlogerror(VTPM_LOG_VTSP, "Enc buffer just overflowed.\n");
+ }
+
+ buffer_init(outData, 0, NULL);
+ buffer_append_raw(outData, out_tmp_size, out_tmp);
+
+ vtpmloginfo(VTPM_LOG_TXDATA, "Bind Generated[%d] = 0x", out_tmp_size);
+ for(i = 0 ; i < out_tmp_size ; i++) {
+ vtpmloginfomore(VTPM_LOG_TXDATA, "%2.2x ", out_tmp[i]);
+ }
+ vtpmloginfomore(VTPM_LOG_TXDATA, "\n");
+
+ // Free flatBoundData
+ free(flatBoundData);
+
+ return TPM_SUCCESS;
+}
+
+// Function Reaches into unsupported TCS command, beware.
+TPM_RESULT VTSP_RawTransmit(const TCS_CONTEXT_HANDLE hContext,
+ const buffer_t *inbuf,
+ buffer_t *outbuf ) {
+
+ vtpmloginfo(VTPM_LOG_VTSP, "Passthrough in use.\n");
+ TPM_RESULT status = TPM_SUCCESS;
+
+ // Generate Extra TCS Parameters
+ BYTE *resultText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+ UINT32 resultTextSize = TCPA_MAX_BUFFER_LENGTH;
+
+ // Call TCS
+ TPMTRYRETURN( TCSP_RawTransmitData(buffer_len(inbuf), inbuf->bytes,
+ &resultTextSize, resultText) );
+
+ // Unpack/return key structure
+ TPMTRYRETURN(buffer_init (outbuf, resultTextSize, resultText) );
+ goto egress;
+
+ abort_egress:
+
+ egress:
+ TCS_FreeMemory(hContext, resultText);
+ free(resultText);
+ return status;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/manager/vtsp.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/manager/vtsp.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,102 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+//
+// vtsp.h
+//
+// Higher level interface to TCS.
+//
+// ==================================================================
+
+#ifndef __VTSP_H__
+#define __VTSP_H__
+
+#include "tcg.h"
+#include "tcs.h"
+
+#define KEY_BUFFER_SIZE 2048
+
+TPM_RESULT VTSP_RawTransmit(const TCS_CONTEXT_HANDLE hContext,
+ const buffer_t *inbuf,
+ buffer_t *outbuf );
+
+TPM_RESULT VTSP_OIAP( const TCS_CONTEXT_HANDLE hContext,
+ TCS_AUTH *auth);
+
+TPM_RESULT VTSP_OSAP( const TCS_CONTEXT_HANDLE hContext,
+ const TPM_ENTITY_TYPE entityType,
+ const UINT32 entityValue,
+ const TPM_AUTHDATA *usageAuth,
+ TPM_SECRET *sharedsecret,
+ TCS_AUTH *auth);
+
+TPM_RESULT VTSP_ReadPubek( const TCS_CONTEXT_HANDLE hContext,
+ CRYPTO_INFO *cypto_info);
+
+TPM_RESULT VTSP_TakeOwnership( const TCS_CONTEXT_HANDLE hContext,
+ const TPM_AUTHDATA *ownerAuth,
+ const TPM_AUTHDATA *srkAuth,
+ CRYPTO_INFO *ek_cryptoInfo,
+ TCS_AUTH *auth);
+
+TPM_RESULT VTSP_DisablePubekRead( const TCS_CONTEXT_HANDLE hContext,
+ const TPM_AUTHDATA *ownerAuth,
+ TCS_AUTH *auth);
+
+TPM_RESULT VTSP_CreateWrapKey( const TCS_CONTEXT_HANDLE hContext,
+ const TPM_KEY_USAGE usage,
+ const TPM_AUTHDATA *newKeyAuth,
+ const TCS_KEY_HANDLE parentHandle,
+ const TPM_AUTHDATA *osapSharedSecret,
+ buffer_t *pubKeyBuf,
+ TCS_AUTH *auth);
+
+TPM_RESULT VTSP_LoadKey(const TCS_CONTEXT_HANDLE hContext,
+ const TCS_KEY_HANDLE hUnwrappingKey,
+ const buffer_t *rgbWrappedKeyBlob,
+ const TPM_AUTHDATA *parentAuth,
+ TPM_HANDLE *newKeyHandle,
+ TCS_AUTH *pAuth,
+ CRYPTO_INFO *cryptoinfo);
+
+TPM_RESULT VTSP_Unbind( const TCS_CONTEXT_HANDLE hContext,
+ const TPM_KEY_HANDLE key_handle,
+ const buffer_t *bound_data,
+ const TPM_AUTHDATA *usage_auth,
+ buffer_t *clear_data,
+ TCS_AUTH *auth);
+
+TPM_RESULT VTSP_Bind( CRYPTO_INFO *cryptoInfo,
+ const buffer_t *inData,
+ buffer_t *outData);
+
+#endif //_VTSP_H_
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/tcs/Makefile
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/tcs/Makefile Fri Sep 9 16:30:54 2005
@@ -0,0 +1,18 @@
+XEN_ROOT = ../../..
+include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk
+
+BIN = libTCS.a
+
+all: build
+
+build: $(BIN)
+
+install: build
+
+clean:
+ rm -f *.a *.so *.o *.rpm $(DEP_FILES)
+
+mrproper: clean
+
+$(BIN): $(OBJS)
+ $(AR) rcs $(BIN) $(OBJS)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/tcs/contextmgr.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/tcs/contextmgr.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,219 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+//
+// contextmgr.c
+//
+// This file contains the context management functions for TCS.
+//
+// ==================================================================
+
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+#include "tcs.h"
+#include "contextmgr.h"
+#include "log.h"
+
+BYTE* AddMemBlock(CONTEXT_HANDLE* pContextHandle, // in
+ int BlockSize) { // in
+
+ BLOCK* pCurrentBlock = NULL;
+ BLOCK* pBlock = NULL;
+
+ // check incoming params
+ if (pContextHandle == NULL || BlockSize == 0)
+ return NULL;
+
+ // Create New Block
+ pBlock = (BLOCK *)malloc(sizeof(BLOCK));
+ if (pBlock == NULL)
+ return (0);
+
+ pBlock->aMemory = (BYTE *)malloc(sizeof(BYTE) * BlockSize);
+ if (pBlock->aMemory == NULL)
+ return (0);
+
+ memset(pBlock->aMemory, 0, BlockSize);
+ pBlock->nBlockSize = BlockSize;
+ pBlock->pNextBlock = NULL;
+
+ // search for the last block created where to add the
+ // newly created block
+ if(pContextHandle->pTopBlock != NULL) {
+ pCurrentBlock = pContextHandle->pTopBlock;
+ while(pCurrentBlock->pNextBlock != NULL)
+ pCurrentBlock = pCurrentBlock->pNextBlock;
+
+
+ pCurrentBlock->pNextBlock= pBlock;
+ } else
+ pContextHandle->pTopBlock = pBlock;
+
+
+ pContextHandle->nBlockCount++;
+
+ return pBlock->aMemory;
+}
+
+
+BOOL DeleteMemBlock(CONTEXT_HANDLE* pContextHandle, // in
+ BYTE* pTCPA_BYTEs) { // in
+ BLOCK* pCurrentBlock = NULL;
+ BLOCK* pParentBlock = NULL;
+ BOOL bFound = FALSE;
+
+ if (pContextHandle == NULL)
+ return FALSE;
+
+
+ // Search for the Block in the context by aMemory pointer
+ pParentBlock = NULL;
+ pCurrentBlock = pContextHandle->pTopBlock;
+
+ while(pCurrentBlock != NULL) {
+ // If aMemory block is found, delete it
+ if(pCurrentBlock->aMemory == pTCPA_BYTEs || pTCPA_BYTEs == NULL) {
+ // if it is the top Block, remove it from the top,
+ // otherwise remove it from the ParentBlock and stitch
+ // the NextBlock to the ParentBlock
+ if(pParentBlock == NULL)
+ pContextHandle->pTopBlock = pContextHandle->pTopBlock->pNextBlock;
+ else
+ pParentBlock->pNextBlock = pCurrentBlock->pNextBlock;
+
+ // delete memory Block associated with pointer pTCPA_BYTEs
+ free(pCurrentBlock->aMemory);
+ pCurrentBlock->aMemory = NULL;
+
+ free(pCurrentBlock);
+ pCurrentBlock = pParentBlock;
+
+ pContextHandle->nBlockCount--;
+ bFound = TRUE;
+ }
+
+ if(pCurrentBlock != NULL) {
+ pParentBlock = pCurrentBlock;
+ pCurrentBlock = pCurrentBlock->pNextBlock;
+ }
+ }
+
+ return bFound;
+}
+
+BOOL AddHandleToList(CONTEXT_HANDLE* pContextHandle, // in
+ TPM_RESOURCE_TYPE type, // in
+ TPM_HANDLE handle) { // in
+ HANDLE_LIST* pNewHandle = NULL;
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Adding Handle to list\n");
+ if (pContextHandle == NULL)
+ return 0;
+
+ pNewHandle = (HANDLE_LIST *)malloc(sizeof(HANDLE_LIST));
+
+ if (pNewHandle == NULL)
+ return (0);
+
+ pNewHandle->handle = handle;
+ pNewHandle->type = type;
+ pNewHandle->pNextHandle = pContextHandle->pHandleList;
+
+ pContextHandle->pHandleList = pNewHandle;
+
+ return 1;
+}
+
+BOOL DeleteHandleFromList( CONTEXT_HANDLE* pContextHandle, // in
+ TPM_HANDLE handle) { // in
+
+ HANDLE_LIST *pCurrentHandle = pContextHandle->pHandleList,
+ *pLastHandle = pCurrentHandle;
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Deleting Handle from list\n");
+
+ if (pContextHandle == NULL)
+ return 0;
+
+ while (1) {
+
+ if (pCurrentHandle->handle == handle) { // Found element
+ if (pCurrentHandle == pLastHandle) { // First element in list
+ pContextHandle->pHandleList = pCurrentHandle->pNextHandle;
+ free(pCurrentHandle);
+ } else { // Ordinary element
+ pLastHandle->pNextHandle = pCurrentHandle->pNextHandle;
+ free(pCurrentHandle);
+ }
+
+ return 1;
+
+ } else { // Not found yet;
+ pLastHandle = pCurrentHandle;
+ pCurrentHandle = pCurrentHandle->pNextHandle;
+ if (pCurrentHandle == NULL) // Found end of list
+ return 0;
+ }
+
+ }
+}
+
+BOOL FreeHandleList( CONTEXT_HANDLE* pContextHandle) { // in
+ HANDLE_LIST* pCurrentHandle;
+ BOOL returncode = TRUE;
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Freeing all handles for context\n");
+
+ if (pContextHandle == NULL)
+ return 1;
+
+ pCurrentHandle = pContextHandle->pHandleList;
+ while (pCurrentHandle != NULL) {
+
+ switch (pCurrentHandle->type) {
+ case TPM_RT_KEY:
+ returncode = returncode && !TCSP_EvictKey((TCS_CONTEXT_HANDLE)
pContextHandle, pCurrentHandle->handle);
+ break;
+ case TPM_RT_AUTH:
+ returncode = returncode && !TCSP_TerminateHandle((TCS_CONTEXT_HANDLE)
pContextHandle, pCurrentHandle->handle);
+ break;
+ default:
+ returncode = FALSE;
+ }
+
+ pCurrentHandle = pCurrentHandle->pNextHandle;
+
+ }
+
+ return 1;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/tcs/contextmgr.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/tcs/contextmgr.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,81 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+//
+// contextmgr.c
+//
+// This file contains the context management functions for TCS.
+//
+// ==================================================================
+
+#ifndef __CONTEXTMGR_H__
+#define __CONTEXTMGR_H__
+
+#include "tcg.h"
+
+#define BLOCK_SIZE 300
+
+typedef struct block {
+ int nBlockSize;
+ BYTE* aMemory;
+ struct block* pNextBlock;
+} BLOCK;
+
+typedef struct handle_List {
+ TPM_HANDLE handle;
+ TPM_RESOURCE_TYPE type;
+ struct handle_List* pNextHandle;
+} HANDLE_LIST;
+
+typedef struct context_handle {
+ int nBlockCount;
+ BLOCK* pTopBlock;
+ HANDLE_LIST* pHandleList;
+} CONTEXT_HANDLE;
+
+BYTE* AddMemBlock( CONTEXT_HANDLE* pContextHandle, // in
+ int BlockSize); // in
+
+BOOL DeleteMemBlock(CONTEXT_HANDLE* pContextHandle, // in
+ BYTE* pTCPA_BYTEs); // in
+
+
+BOOL AddHandleToList( CONTEXT_HANDLE* pContextHandle, // in
+ TPM_RESOURCE_TYPE type, // in
+ TPM_HANDLE handle); // in
+
+BOOL DeleteHandleFromList( CONTEXT_HANDLE* pContextHandle, // in
+ TPM_HANDLE handle); // in
+
+BOOL FreeHandleList( CONTEXT_HANDLE* pContextHandle); // in
+
+#endif //_CONTEXTMGR_H_
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/tcs/tcs.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/tcs/tcs.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,1102 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+//
+// tcs.c
+//
+// This file contains the functions that implement a TCS.
+//
+// ==================================================================
+
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+
+#include "tcg.h"
+#include "bsg.h"
+#include "tcs.h"
+#include "contextmgr.h"
+#include "tpmddl.h"
+#include "log.h"
+
+// Static Global Vars for the TCS
+static BOOL TCS_m_bConnected;
+static int TCS_m_nCount = 0;
+
+#define TCPA_MAX_BUFFER_LENGTH 0x2000
+
+static BYTE InBuf [TCPA_MAX_BUFFER_LENGTH];
+static BYTE OutBuf[TCPA_MAX_BUFFER_LENGTH];
+
+
+//
---------------------------------------------------------------------------------
+// Initialization/Uninitialization SubComponent API
+//
---------------------------------------------------------------------------------
+TPM_RESULT TCS_create() {
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TPM_RESULT result = TPM_FAIL;
+ TCS_m_bConnected = FALSE;
+
+ if (TCS_m_nCount == 0) {
+ vtpmloginfo(VTPM_LOG_TCS, "Constructing new TCS:\n");
+ hRes = TDDL_Open();
+
+ if (hRes == TDDL_SUCCESS) {
+ TCS_m_bConnected = TRUE;
+ result = TPM_SUCCESS;
+ }
+ } else
+ TCS_m_bConnected = TRUE;
+
+ TCS_m_nCount++;
+
+ return(result);
+}
+
+
+void TCS_destroy()
+{
+ // FIXME: Should iterate through all open contexts and close them.
+ TCS_m_nCount--;
+
+ if (TCS_m_bConnected == TRUE && TCS_m_nCount == 0) {
+ vtpmloginfo(VTPM_LOG_TCS, "Destructing TCS:\n");
+ TDDL_Close();
+ TCS_m_bConnected = FALSE;
+ }
+
+}
+
+TPM_RESULT TCS_Malloc( TCS_CONTEXT_HANDLE hContext, // in
+ UINT32 MemSize, // in
+ BYTE** ppMemPtr) {// out
+
+ TPM_RESULT returnCode = TPM_FAIL;
+ CONTEXT_HANDLE* pContextHandle = (CONTEXT_HANDLE*)hContext;
+
+ if (pContextHandle != NULL && ppMemPtr != NULL) {
+ *ppMemPtr = (BYTE *)AddMemBlock(pContextHandle, MemSize);
+ returnCode = TPM_SUCCESS;
+ }
+
+ return returnCode;
+}
+
+TPM_RESULT TCS_FreeMemory( TCS_CONTEXT_HANDLE hContext, // in
+ BYTE* pMemory) { // in
+ TPM_RESULT returnCode = TPM_FAIL;
+ CONTEXT_HANDLE* pContextHandle = (CONTEXT_HANDLE*)hContext;
+
+ if ( (pContextHandle != NULL && pMemory != NULL) &&
+ (DeleteMemBlock(pContextHandle, pMemory) == TRUE) )
+ returnCode = TPM_SUCCESS;
+
+
+ return returnCode;
+}
+
+TPM_RESULT TCS_OpenContext(TCS_CONTEXT_HANDLE* hContext) { // out
+ TPM_RESULT returnCode = TPM_FAIL;
+
+ vtpmloginfo(VTPM_LOG_TCS, "Calling TCS_OpenContext:\n");
+
+ // hContext must point to a null memory context handle
+ if(*hContext == HANDLE_NULL) {
+ CONTEXT_HANDLE* pContextHandle = (CONTEXT_HANDLE
*)malloc(sizeof(CONTEXT_HANDLE));
+ if (pContextHandle == NULL)
+ return TPM_SIZE;
+
+
+ // initialize to 0
+ pContextHandle->nBlockCount = 0;
+ pContextHandle->pTopBlock = NULL;
+ pContextHandle->pHandleList = NULL;
+
+ // Create New Block
+ AddMemBlock(pContextHandle, BLOCK_SIZE);
+
+ *hContext = (TCS_CONTEXT_HANDLE)pContextHandle;
+ returnCode = TPM_SUCCESS;
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCS_CloseContext(TCS_CONTEXT_HANDLE hContext) {// in
+ //FIXME: TCS SHOULD Track track failed auths and make sure
+ //we don't try and re-free them here.
+ TPM_RESULT returnCode = TPM_FAIL;
+
+ CONTEXT_HANDLE* pContextHandle = (CONTEXT_HANDLE*)hContext;
+
+ if(pContextHandle != NULL) {
+ // Print test info
+ vtpmloginfo(VTPM_LOG_TCS, "Calling TCS_CloseContext.\n");
+
+ // free memory for all the blocks
+ DeleteMemBlock(pContextHandle, NULL );
+ pContextHandle->pTopBlock = NULL;
+
+ FreeHandleList(pContextHandle);
+ if (pContextHandle->pHandleList != NULL)
+ vtpmlogerror(VTPM_LOG_TCS, "Not all handles evicted from TPM.\n");
+
+ // Release the TPM's resources
+ free(pContextHandle);
+ returnCode = TPM_SUCCESS;
+ }
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Finished closing context\n");
+ return(returnCode);
+}
+
+// ------------------------------------------------------------------
+// Internal Functions
+// ------------------------------------------------------------------
+int packAuth(BYTE* dst, TCS_AUTH* auth) {
+ // CHECK: according to the command specs, the outgoing auth params are:
+ // nonceEven
+ // nonceOdd
+ // continueAuthSession
+ // auth digest for return params
+ //
+ // this is a bit different than this code...
+
+ return BSG_PackList(dst, 4,
+ BSG_TYPE_UINT32, &(auth->AuthHandle),
+ BSG_TPM_NONCE, &(auth->NonceOdd),
+ BSG_TYPE_BOOL, &(auth->fContinueAuthSession),
+ BSG_TPM_AUTHDATA, &(auth->HMAC));
+}
+
+int unpackAuth(TCS_AUTH* auth, BYTE* src) {
+ return BSG_UnpackList(src, 3,
+ BSG_TPM_NONCE, &(auth->NonceEven),
+ BSG_TYPE_BOOL, &(auth->fContinueAuthSession),
+ BSG_TPM_AUTHDATA, &(auth->HMAC));
+}
+
+// ------------------------------------------------------------------
+// Authorization Commands
+// ------------------------------------------------------------------
+
+TPM_RESULT TCSP_OIAP(TCS_CONTEXT_HANDLE hContext, // in
+ TCS_AUTHHANDLE* authHandle, // out
+ TPM_NONCE* nonce0) // out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_OIAP;
+ UINT32 paramSize = 0;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (authHandle == NULL || nonce0 == NULL)
+ return TPM_BAD_PARAMETER;
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal);
+
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength))
+ == TDDL_SUCCESS) {
+
+ // unpack to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList( OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) {
+ // Extract the remaining output parameters
+ BSG_UnpackList(OutBuf+i, 2,
+ BSG_TYPE_UINT32, authHandle,
+ BSG_TPM_NONCE, nonce0);
+
+ if (!AddHandleToList((CONTEXT_HANDLE *)hContext, TPM_RT_AUTH,
*authHandle))
+ vtpmlogerror(VTPM_LOG_TCS, "New AuthHandle not recorded\n");
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "Failed with return code %s\n",
tpm_get_error_name(returnCode));
+
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_OSAP(TCS_CONTEXT_HANDLE hContext, // in
+ TPM_ENTITY_TYPE entityType, // in
+ UINT32 entityValue, // in
+ TPM_NONCE nonceOddOSAP, // in
+ TCS_AUTHHANDLE* authHandle, // out
+ TPM_NONCE* nonceEven, // out
+ TPM_NONCE* nonceEvenOSAP) // out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_OSAP;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (authHandle == NULL || nonceEven == NULL || nonceEvenOSAP == NULL)
+ return TPM_BAD_PARAMETER;
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 6,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT16, &entityType,
+ BSG_TYPE_UINT32, &entityValue,
+ BSG_TPM_NONCE, &nonceOddOSAP);
+
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength))
+ == TDDL_SUCCESS) {
+
+ // unpack to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) {
+ // Extract the remaining output parameters
+ BSG_UnpackList(OutBuf+i, 3,
+ BSG_TYPE_UINT32, authHandle,
+ BSG_TPM_NONCE, nonceEven,
+ BSG_TPM_NONCE, nonceEvenOSAP);
+
+ if (!AddHandleToList((CONTEXT_HANDLE *)hContext, TPM_RT_AUTH,
*authHandle)) {
+ vtpmlogerror(VTPM_LOG_TCS, "New AuthHandle not recorded\n");
+ }
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "Failed with return code %s\n",
tpm_get_error_name(returnCode));
+
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_TakeOwnership(TCS_CONTEXT_HANDLE hContext, // in
+ UINT16 protocolID, // in
+ UINT32 encOwnerAuthSize, // in
+ BYTE* encOwnerAuth, // in
+ UINT32 encSrkAuthSize, // in
+ BYTE* encSrkAuth, // in
+ UINT32* SrkSize, // in, out
+ BYTE** Srk, // in, out
+ TCS_AUTH* ownerAuth) // in, out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_AUTH1_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_TakeOwnership;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (encOwnerAuth == NULL || encSrkAuth == NULL || SrkSize == NULL || *Srk ==
NULL)
+ return TPM_BAD_PARAMETER;
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 5,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT16, &protocolID,
+ BSG_TYPE_UINT32, &encOwnerAuthSize);
+
+ memcpy(InBuf+InLength, encOwnerAuth, encOwnerAuthSize);
+ InLength += encOwnerAuthSize;
+ InLength += BSG_Pack( BSG_TYPE_UINT32,
+ &encSrkAuthSize,
+ InBuf+InLength);
+ memcpy(InBuf+InLength, encSrkAuth, encSrkAuthSize);
+ InLength += encSrkAuthSize;
+ memcpy(InBuf+InLength, *Srk, *SrkSize);
+ InLength += *SrkSize;
+ InLength += packAuth(InBuf+InLength, ownerAuth);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32,
+ &InLength,
+ InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength))
+ == TDDL_SUCCESS){
+
+ // unpack to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList( OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH1_COMMAND) {
+ // Extract the remaining output parameters
+ TPM_KEY srkPub;
+ i += BSG_Unpack(BSG_TPM_KEY, OutBuf+i, &srkPub);
+ unpackAuth(ownerAuth, OutBuf+i);
+
+ // fill output params
+ BYTE tempBuf[1024];
+ *SrkSize = BSG_Pack(BSG_TPM_KEY, &srkPub, tempBuf);
+ if (TCS_Malloc(hContext, *SrkSize, Srk) == TPM_FAIL) {
+ return(TPM_SIZE);
+ }
+ memcpy(*Srk, tempBuf, *SrkSize);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_TakeOwnership Failed with return code
%s\n", tpm_get_error_name(returnCode));
+ }
+
+ return(returnCode);
+}
+
+
+TPM_RESULT TCSP_DisablePubekRead ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_AUTH* ownerAuth) { // in, out
+
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_AUTH1_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_DisablePubekRead;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal);
+
+ InLength += packAuth(InBuf+InLength, ownerAuth);
+
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength))
+ == TDDL_SUCCESS){
+
+ // unpack to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList( OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH1_COMMAND) {
+ // Extract the remaining output parameters
+ unpackAuth(ownerAuth, OutBuf+i);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_DisablePubekRead Failed with return
code %s\n", tpm_get_error_name(returnCode));
+ }
+
+ return(returnCode);
+}
+
+
+TPM_RESULT TCSP_TerminateHandle(TCS_CONTEXT_HANDLE hContext, // in
+ TCS_AUTHHANDLE handle) // in
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_Terminate_Handle;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 4,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT32, &handle);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength))
+ == TDDL_SUCCESS) {
+
+ // unpack to get the tag, paramSize, & returnCode
+ BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (!DeleteHandleFromList((CONTEXT_HANDLE *)hContext, handle))
+ vtpmlogerror(VTPM_LOG_TCS, "KeyHandle not removed from list\n");
+
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) {
+ // Print debug info
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_TerminateHandle Failed with return code
%s\n", tpm_get_error_name(returnCode));
+
+ }
+
+ return(returnCode);
+}
+
+// TPM Mandatory
+TPM_RESULT TCSP_Extend( TCS_CONTEXT_HANDLE hContext, // in
+ TPM_PCRINDEX pcrNum, // in
+ TPM_DIGEST inDigest, // in
+ TPM_PCRVALUE* outDigest) // out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_Extend;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 5,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT32, &pcrNum,
+ BSG_TPM_DIGEST, &inDigest);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength))
+ == TDDL_SUCCESS) {
+
+ // unpack to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND){
+ // Extract the remaining output parameters
+ BSG_Unpack(BSG_TPM_PCRVALUE, OutBuf+i, outDigest);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_Extend Failed with return code %s\n",
tpm_get_error_name(returnCode));
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_Seal( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE keyHandle, // in
+ TPM_ENCAUTH encAuth, // in
+ UINT32 pcrInfoSize, // in
+ BYTE* PcrInfo, // in
+ UINT32 inDataSize, // in
+ BYTE* inData, // in
+ TCS_AUTH* pubAuth, // in, out
+ UINT32* SealedDataSize, // out
+ BYTE** SealedData) // out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_AUTH1_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_Seal;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (inData == NULL || pubAuth == NULL || SealedDataSize == NULL ||
*SealedData == NULL)
+ return TPM_BAD_PARAMETER;
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 6,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT32, &keyHandle,
+ BSG_TPM_ENCAUTH, encAuth,
+ BSG_TYPE_UINT32, &pcrInfoSize);
+ memcpy(InBuf+InLength, PcrInfo, pcrInfoSize);
+ InLength += pcrInfoSize;
+ InLength += BSG_Pack(BSG_TYPE_UINT32, &inDataSize, InBuf+InLength);
+ memcpy(InBuf+InLength, inData, inDataSize);
+ InLength += inDataSize;
+ InLength += packAuth(InBuf+InLength, pubAuth);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength))
+ == TDDL_SUCCESS) {
+ // unpack OutBuf to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH1_COMMAND) {
+ // Extract the remaining output parameters
+ TPM_STORED_DATA sealedData;
+
+ i += BSG_Unpack(BSG_TPM_STORED_DATA, OutBuf+i, &sealedData);
+ unpackAuth(pubAuth, OutBuf+i);
+
+ // fill SealedData
+ BYTE tempBuf[1024];
+ *SealedDataSize = BSG_Pack(BSG_TPM_STORED_DATA, &sealedData, tempBuf);
+ if (TCS_Malloc(hContext, *SealedDataSize, SealedData) == TPM_FAIL) {
+ return TPM_SIZE;
+ }
+ memcpy(*SealedData, tempBuf, *SealedDataSize);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_Seal Failed with return code %s\n",
tpm_get_error_name(returnCode));
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_Unseal(TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE parentHandle, // in
+ UINT32 SealedDataSize, // in
+ BYTE* SealedData, // in
+ TCS_AUTH* parentAuth, // in, out
+ TCS_AUTH* dataAuth, // in, out
+ UINT32* DataSize, // out
+ BYTE** Data) // out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_AUTH2_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_Unseal;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (SealedData == NULL || parentAuth == NULL || dataAuth == NULL ||
+ DataSize == NULL || Data == NULL)
+ return TPM_BAD_PARAMETER;
+
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 4,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT32, &parentHandle);
+ memcpy(InBuf+InLength, SealedData, SealedDataSize);
+ InLength += SealedDataSize;
+ InLength += packAuth(InBuf+InLength, parentAuth);
+ InLength += packAuth(InBuf+InLength, dataAuth);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) ==
TDDL_SUCCESS) {
+ // unpack OutBuf to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList( OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH2_COMMAND) {
+ // Extract the remaining output parameters
+ i += BSG_Unpack(BSG_TYPE_UINT32, OutBuf+i, DataSize);
+ if (TCS_Malloc(hContext, *DataSize, Data) == TPM_FAIL) {
+ return TPM_SIZE;
+ }
+ memcpy(*Data, OutBuf+i, *DataSize);
+ i += *DataSize;
+ i += unpackAuth(parentAuth, OutBuf+i);
+ unpackAuth(dataAuth, OutBuf+i);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_Unseal Failed with return code %s\n",
tpm_get_error_name(returnCode));
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_UnBind(TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE keyHandle, // in
+ UINT32 inDataSize, // in
+ BYTE* inData, // in
+ TCS_AUTH* privAuth, // in, out
+ UINT32* outDataSize, // out
+ BYTE** outData) // out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_AUTH1_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_UnBind;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (inData == NULL || privAuth == NULL || outDataSize == NULL || *outData ==
NULL)
+ return TPM_BAD_PARAMETER;
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 5,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT32, &keyHandle,
+ BSG_TYPE_UINT32, &inDataSize);
+ memcpy(InBuf+InLength, inData, inDataSize);
+ InLength += inDataSize;
+ InLength += packAuth(InBuf+InLength, privAuth);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "\n\tSending paramSize = %d", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) ==
TDDL_SUCCESS) {
+ // unpack OutBuf to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH1_COMMAND) {
+ // Extract the remaining output parameters
+ i += BSG_Unpack(BSG_TYPE_UINT32, OutBuf+i, outDataSize);
+ if (TCS_Malloc(hContext, *outDataSize, outData) == TPM_FAIL)
+ return TPM_SIZE;
+
+ memcpy(*outData, OutBuf+i, *outDataSize);
+ i += *outDataSize;
+ unpackAuth(privAuth, OutBuf+i);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_UnBind Failed with return code %s\n",
tpm_get_error_name(returnCode));
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_CreateWrapKey(TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE hWrappingKey, // in
+ TPM_ENCAUTH KeyUsageAuth, // in
+ TPM_ENCAUTH KeyMigrationAuth, // in
+ UINT32* pcKeySize, // in, out
+ BYTE** prgbKey, // in, out
+ TCS_AUTH* pAuth) // in, out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_AUTH1_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_CreateWrapKey;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (pcKeySize == NULL || *prgbKey == NULL || pAuth == NULL)
+ return TPM_BAD_PARAMETER;
+
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 6,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT32, &hWrappingKey,
+ BSG_TPM_ENCAUTH, KeyUsageAuth,
+ BSG_TPM_ENCAUTH, KeyMigrationAuth);
+ memcpy(InBuf+InLength, *prgbKey, *pcKeySize);
+ InLength += *pcKeySize;
+ InLength += packAuth(InBuf+InLength, pAuth);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) ==
TDDL_SUCCESS) {
+ // unpack OutBuf to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_RESULT, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH1_COMMAND) {
+ // Extract the remaining output parameters
+ TPM_KEY wrappedKey;
+
+ i += BSG_Unpack(BSG_TPM_KEY, OutBuf+i, &wrappedKey);
+ unpackAuth(pAuth, OutBuf+i);
+
+ // Fill prgbKey
+ BYTE tempBuf[1024];
+ *pcKeySize = BSG_Pack(BSG_TPM_KEY, &wrappedKey, tempBuf);
+ if (TCS_Malloc(hContext, *pcKeySize, prgbKey) == TPM_FAIL)
+ return TPM_SIZE;
+
+ memcpy(*prgbKey, tempBuf, *pcKeySize);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_CreateWrapKey Failed with return code
%s\n", tpm_get_error_name(returnCode));
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_LoadKeyByBlob(TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE hUnwrappingKey, // in
+ UINT32 cWrappedKeyBlobSize, // in
+ BYTE* rgbWrappedKeyBlob, // in
+ TCS_AUTH* pAuth, // in, out
+ TCS_KEY_HANDLE* phKeyTCSI, // out
+ TCS_KEY_HANDLE* phKeyHMAC) // out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_AUTH1_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_LoadKey;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (rgbWrappedKeyBlob == NULL || pAuth == NULL || phKeyTCSI == NULL ||
phKeyHMAC == NULL)
+ return TPM_BAD_PARAMETER;
+
+ *phKeyHMAC = hUnwrappingKey; // the parent key is the one that the TPM use
to make the HMAC calc
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 4,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT32, &hUnwrappingKey);
+ memcpy(InBuf+InLength, rgbWrappedKeyBlob, cWrappedKeyBlobSize);
+ InLength += cWrappedKeyBlobSize;
+ InLength += packAuth(InBuf+InLength, pAuth);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) ==
TDDL_SUCCESS) {
+ // unpack OutBuf to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH1_COMMAND) {
+ // Extract the remaining output parameters
+ i += BSG_Unpack(BSG_TYPE_UINT32,
+ OutBuf+i,
+ phKeyTCSI);
+ unpackAuth(pAuth, OutBuf+i);
+
+ if (!AddHandleToList((CONTEXT_HANDLE *)hContext, TPM_RT_KEY,
*phKeyTCSI)) {
+ vtpmlogerror(VTPM_LOG_TCS, "New KeyHandle not recorded\n");
+ }
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_LoadKeyByBlob Failed with return code
%s\n", tpm_get_error_name(returnCode));
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_EvictKey(TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE hKey) // in
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_EvictKey;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 4,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT32, &hKey);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) ==
TDDL_SUCCESS) {
+ // unpack OutBuf to get the tag, paramSize, & returnCode
+ BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (!DeleteHandleFromList((CONTEXT_HANDLE *)hContext, hKey)) {
+ vtpmlogerror(VTPM_LOG_TCS, "KeyHandle not removed from list\n");
+ }
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) {
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else {
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_EvictKey Failed with return code %s\n",
tpm_get_error_name(returnCode));
+ }
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_GetRandom(TCS_CONTEXT_HANDLE hContext, // in
+ UINT32* bytesRequested, // in, out
+ BYTE** randomBytes) // out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_GetRandom;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (bytesRequested == NULL || *randomBytes == NULL){
+ return TPM_BAD_PARAMETER;
+ }
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 4,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT32, bytesRequested);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) ==
TDDL_SUCCESS) {
+ // unpack OutBuf to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) {
+ // Extract the remaining output parameters
+ BSG_Unpack(BSG_TYPE_UINT32, OutBuf+i, bytesRequested);
+ if (TCS_Malloc(hContext, *bytesRequested, randomBytes) == TPM_FAIL) {
+ return TPM_SIZE;
+ }
+ memcpy(*randomBytes, OutBuf+i+sizeof(UINT32), *bytesRequested);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else {
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_GetRandom Failed with return code
%s\n", tpm_get_error_name(returnCode));
+ }
+ }
+
+ return(returnCode);
+}
+
+
+TPM_RESULT TCSP_ReadPubek(TCS_CONTEXT_HANDLE hContext, // in
+ TPM_NONCE antiReplay, // in
+ UINT32* pubEndorsementKeySize, // out
+ BYTE** pubEndorsementKey, // out
+ TPM_DIGEST* checksum) // out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_ReadPubek;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (pubEndorsementKeySize == NULL || pubEndorsementKey == NULL || checksum
== NULL) {
+ return TPM_BAD_PARAMETER;
+ }
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 4,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TPM_NONCE, &antiReplay);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) ==
TDDL_SUCCESS) {
+ // unpack OutBuf to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) {
+ // Extract the remaining output parameters
+ TPM_PUBKEY pubEK;
+ i += BSG_UnpackList(OutBuf+i, 2,
+ BSG_TPM_PUBKEY, &pubEK,
+ BSG_TPM_DIGEST, checksum);
+
+ // fill EndorsementKey
+ BYTE tempBuf[1024];
+ *pubEndorsementKeySize = BSG_Pack(BSG_TPM_PUBKEY, &pubEK, tempBuf);
+ if (TCS_Malloc(hContext, *pubEndorsementKeySize, pubEndorsementKey) ==
TPM_FAIL) {
+ return TPM_SIZE;
+ }
+ memcpy(*pubEndorsementKey, tempBuf, *pubEndorsementKeySize);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else {
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_ReadPubek Failed with return code
%s\n", tpm_get_error_name(returnCode));
+ }
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_RawTransmitData( UINT32 inDataSize, // in
+ BYTE *inData, // in
+ UINT32 *outDataSize,// in/out
+ BYTE *outData) { // out
+
+ TDDL_RESULT hRes;
+
+ vtpmloginfo(VTPM_LOG_TCS, "Calling TransmitData directly.\n");
+ //FIXME: Add Context Management
+ hRes = TDDL_TransmitData( inData,
+ inDataSize,
+ outData,
+ outDataSize);
+
+ if (hRes == TDDL_SUCCESS) {
+ return TPM_SUCCESS;
+ } else {
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_RawTransmitData Failed with return code
%s\n", tpm_get_error_name(TPM_IOERROR));
+ return TPM_IOERROR;
+ }
+
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/tcs/tcs.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/tcs/tcs.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,238 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+//
+// tcs.h
+//
+// This file declares the TCS API
+//
+// ==================================================================
+
+#ifndef __TCS_H__
+#define __TCS_H__
+
+#include "tcg.h"
+#include "buffer.h"
+
+#define HANDLE_NULL 0
+
+// ------------------------------------------------------------------
+// Exposed API
+// ------------------------------------------------------------------
+
+TPM_RESULT TCS_create();
+void TCS_destroy();
+
+TPM_RESULT TCS_OpenContext( /* OUT */ TCS_CONTEXT_HANDLE* hContext );
+
+TPM_RESULT TCS_CloseContext ( /* IN */ TCS_CONTEXT_HANDLE hContext );
+
+TPM_RESULT TCS_Malloc ( TCS_CONTEXT_HANDLE hContext, // in
+ UINT32 MemSize, // in
+ BYTE** ppMemPtr ); //out
+
+TPM_RESULT TCS_FreeMemory ( TCS_CONTEXT_HANDLE hContext, // in
+ BYTE* pMemory); // in
+
+// ------------------------------------------------------------------
+// Exposed API
+// ------------------------------------------------------------------
+
+// TPM v1.1B Command Set
+
+// Authorzation
+TPM_RESULT TCSP_OIAP( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_AUTHHANDLE* authHandle, // out
+ TPM_NONCE* nonce0 // out
+ );
+
+TPM_RESULT TCSP_OSAP ( TCS_CONTEXT_HANDLE hContext, // in
+ TPM_ENTITY_TYPE entityType, // in
+ UINT32 entityValue, // in
+ TPM_NONCE nonceOddOSAP, // in
+ TCS_AUTHHANDLE* authHandle, // out
+ TPM_NONCE* nonceEven, // out
+ TPM_NONCE* nonceEvenOSAP // out
+ );
+
+TPM_RESULT TCSP_TakeOwnership ( TCS_CONTEXT_HANDLE hContext, // in
+ UINT16 protocolID, // in
+ UINT32 encOwnerAuthSize, // in
+ BYTE* encOwnerAuth, // in
+ UINT32 encSrkAuthSize, // in
+ BYTE* encSrkAuth, // in
+ UINT32* SrkSize, // in, out
+ BYTE** Srk, // in, out
+ TCS_AUTH* ownerAuth // in, out
+ );
+
+TPM_RESULT TCSP_DisablePubekRead ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_AUTH* ownerAuth // in, out
+ );
+
+TPM_RESULT TCSP_TerminateHandle ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_AUTHHANDLE handle // in
+ );
+
+TPM_RESULT TCSP_FlushSpecific ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_AUTHHANDLE handle, // in
+ TPM_RESOURCE_TYPE resourceType //in
+ );
+
+// TPM Mandatory
+TPM_RESULT TCSP_Extend ( TCS_CONTEXT_HANDLE hContext, // in
+ TPM_PCRINDEX pcrNum, // in
+ TPM_DIGEST inDigest, // in
+ TPM_PCRVALUE* outDigest // out
+ );
+
+TPM_RESULT TCSP_PcrRead ( TCS_CONTEXT_HANDLE hContext, // in
+ TPM_PCRINDEX pcrNum, // in
+ TPM_PCRVALUE* outDigest // out
+ );
+
+TPM_RESULT TCSP_Quote ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE keyHandle, // in
+ TPM_NONCE antiReplay, // in
+ UINT32* PcrDataSize, // in, out
+ BYTE** PcrData, // in, out
+ TCS_AUTH* privAuth, // in, out
+ UINT32* sigSize, // out
+ BYTE** sig // out
+ );
+
+TPM_RESULT TCSP_Seal ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE keyHandle, // in
+ TPM_ENCAUTH encAuth, // in
+ UINT32 pcrInfoSize, // in
+ BYTE* PcrInfo, // in
+ UINT32 inDataSize, // in
+ BYTE* inData, // in
+ TCS_AUTH* pubAuth, // in, out
+ UINT32* SealedDataSize, // out
+ BYTE** SealedData // out
+ );
+
+TPM_RESULT TCSP_Unseal ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE parentHandle, // in
+ UINT32 SealedDataSize, // in
+ BYTE* SealedData, // in
+ TCS_AUTH* parentAuth, // in, out
+ TCS_AUTH* dataAuth, // in, out
+ UINT32* DataSize, // out
+ BYTE** Data // out
+ );
+
+TPM_RESULT TCSP_DirWriteAuth ( TCS_CONTEXT_HANDLE hContext, // in
+ TPM_DIRINDEX dirIndex, // in
+ TPM_DIRVALUE newContents, // in
+ TCS_AUTH* ownerAuth // in, out
+ );
+
+TPM_RESULT TCSP_DirRead ( TCS_CONTEXT_HANDLE hContext, // in
+ TPM_DIRINDEX dirIndex, // in
+ TPM_DIRVALUE* dirValue // out
+ );
+
+TPM_RESULT TCSP_UnBind ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE keyHandle, // in
+ UINT32 inDataSize, // in
+ BYTE* inData, // in
+ TCS_AUTH* privAuth, // in, out
+ UINT32* outDataSize, // out
+ BYTE** outData // out
+ );
+
+TPM_RESULT TCSP_CreateWrapKey ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE hWrappingKey, // in
+ TPM_ENCAUTH KeyUsageAuth, // in
+ TPM_ENCAUTH KeyMigrationAuth, // in
+ UINT32* pcKeySize, // in, out
+ BYTE** prgbKey, // in, out
+ TCS_AUTH* pAuth // in, out
+ );
+
+TPM_RESULT TCSP_LoadKeyByBlob ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE hUnwrappingKey, // in
+ UINT32 cWrappedKeyBlobSize, // in
+ BYTE* rgbWrappedKeyBlob, // in
+ TCS_AUTH* pAuth, // in, out
+ TCS_KEY_HANDLE* phKeyTCSI, // out
+ TCS_KEY_HANDLE* phKeyHMAC // out
+ );
+
+TPM_RESULT TCSP_GetPubKey ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE hKey, // in
+ TCS_AUTH* pAuth, // in, out
+ UINT32* pcPubKeySize, // out
+ BYTE** prgbPubKey // out
+ );
+
+TPM_RESULT TCSP_EvictKey ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE hKey // in
+ );
+
+TPM_RESULT TCSP_Sign ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE keyHandle, // in
+ UINT32 areaToSignSize, // in
+ BYTE* areaToSign, // in
+ TCS_AUTH* privAuth, // in, out
+ UINT32* sigSize, // out
+ BYTE** sig // out
+ );
+
+TPM_RESULT TCSP_GetRandom ( TCS_CONTEXT_HANDLE hContext, // in
+ UINT32* bytesRequested, // in, out
+ BYTE** randomBytes // out
+ );
+
+TPM_RESULT TCSP_StirRandom ( TCS_CONTEXT_HANDLE hContext, // in
+ UINT32 inDataSize, // in
+ BYTE* inData // in
+ );
+
+TPM_RESULT TCSP_ReadPubek ( TCS_CONTEXT_HANDLE hContext, // in
+ TPM_NONCE antiReplay, // in
+ UINT32* pubEndorsementKeySize, // out
+ BYTE** pubEndorsementKey, // out
+ TPM_DIGEST* checksum // out
+ );
+
+
+// Non-Standard TCSP call to give direct access to TransmitData.
+// Key and Auth Management is done before transfering command to TDDL.
+TPM_RESULT TCSP_RawTransmitData(UINT32 inDataSize, // in
+ BYTE *inData, // in
+ UINT32 *outDataSize,// in/out
+ BYTE *outData); // out
+
+#endif //TCS_H
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/tcs/tpmddl.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/tcs/tpmddl.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,69 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+//
+// tpmddl.c
+//
+// This file defines the TDDLI API
+//
+// ==================================================================
+
+#ifndef __TPMDDL_H__
+#define __TPMDDL_H__
+
+#define TDDL_CAP_PROP_MANUFACTURER 0x0001
+
+#define TDDL_E_FAIL 1
+#define TDDL_E_SUCCESS 0
+#define TDDL_SUCCESS 0
+
+typedef unsigned int TDDL_UINT32;
+typedef TDDL_UINT32 TDDL_RESULT;
+typedef unsigned char TDDL_BYTE;
+
+TDDL_RESULT TDDL_Open();
+void TDDL_Close();
+TDDL_RESULT TDDL_TransmitData( TDDL_BYTE* in,
+ TDDL_UINT32 insize,
+ TDDL_BYTE* out,
+ TDDL_UINT32* outsize);
+TDDL_RESULT TDDL_GetStatus();
+TDDL_RESULT TDDL_GetCapability( TDDL_UINT32 cap,
+ TDDL_UINT32 sub,
+ TDDL_BYTE* buffer,
+ TDDL_UINT32* size);
+TDDL_RESULT TDDL_SetCapability( TDDL_UINT32 cap,
+ TDDL_UINT32 sub,
+ TDDL_BYTE* buffer,
+ TDDL_UINT32* size);
+
+#endif // __TPMDDL_H__
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/tcs/transmit.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/tcs/transmit.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,131 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include "tcg.h"
+#include "buffer.h"
+#include "log.h"
+#include "tpmddl.h"
+
+// flag to track whether TDDL has been opened
+static int g_TDDL_open = 0;
+static int g_fd = -1; // the fd to the TPM
+
+TPM_RESULT
+TDDL_TransmitData( TDDL_BYTE* in,
+ TDDL_UINT32 insize,
+ TDDL_BYTE* out,
+ TDDL_UINT32* outsize) {
+ TPM_RESULT status = TPM_SUCCESS;
+ TDDL_UINT32 i;
+
+ vtpmloginfo(VTPM_LOG_TXDATA, "Sending buffer = 0x");
+ for(i = 0 ; i < insize ; i++)
+ vtpmloginfomore(VTPM_LOG_TXDATA, "%2.2x ", in[i]);
+
+ vtpmloginfomore(VTPM_LOG_TXDATA, "\n");
+
+ ssize_t size = 0;
+ int fd = g_fd;
+
+ // send the request
+ size = write (fd, in, insize);
+ if (size < 0) {
+ vtpmlogerror(VTPM_LOG_TXDATA, "write() failed");
+ ERRORDIE (TPM_IOERROR);
+ }
+ else if ((TDDL_UINT32) size < insize) {
+ vtpmlogerror(VTPM_LOG_TXDATA, "Wrote %d instead of %d bytes!\n", size,
insize);
+ // ... ?
+ }
+
+ // read the response
+ size = read (fd, out, TCPA_MAX_BUFFER_LENGTH);
+ if (size < 0) {
+ vtpmlogerror(VTPM_LOG_TXDATA, "read() failed");
+ ERRORDIE (TPM_IOERROR);
+ }
+
+ vtpmloginfo(VTPM_LOG_TXDATA, "Receiving buffer = 0x");
+ for(i = 0 ; i < size ; i++)
+ vtpmloginfomore(VTPM_LOG_TXDATA, "%2.2x ", out[i]);
+
+ vtpmloginfomore(VTPM_LOG_TXDATA, "\n");
+
+ *outsize = size;
+ // close connection
+ goto egress;
+
+ abort_egress:
+ egress:
+ return status;
+}
+
+TPM_RESULT TDDL_Open() {
+
+ TDDL_RESULT status = TDDL_SUCCESS;
+ int fd = -1;
+
+ if (g_TDDL_open)
+ return TPM_FAIL;
+
+ fd = open ("/dev/tpm0", O_RDWR);
+ if (fd < 0) {
+ vtpmlogerror(VTPM_LOG_TXDATA, "TPM open failed");
+ return TPM_IOERROR;
+ }
+
+ g_fd = fd;
+ g_TDDL_open = 1;
+
+ return status;
+}
+
+void TDDL_Close() {
+ if (! g_TDDL_open)
+ return;
+
+ if (g_fd>= 0) {
+ if (close(g_fd) < 0)
+ vtpmlogerror(VTPM_LOG_TXDATA, "closeing tpm failed");
+
+ g_fd = -1;
+ }
+
+ g_TDDL_open = 0;
+
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/Makefile
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/util/Makefile Fri Sep 9 16:30:54 2005
@@ -0,0 +1,18 @@
+XEN_ROOT = ../../..
+include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk
+
+BIN = libTCGUtils.a
+
+all: build
+
+build: $(BIN)
+
+install: build
+
+clean:
+ rm -f *.a *.so *.o *.rpm $(DEP_FILES)
+
+mrproper: clean
+
+$(BIN): $(OBJS)
+ $(AR) rcs $(BIN) $(OBJS)
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/bsg.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/util/bsg.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,830 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+//
+// bsg.cpp
+//
+// This file will handle all the TPM Byte Stream functions
+//
+// ==================================================================
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <malloc.h>
+#include "tcg.h"
+#include "crypto.h"
+#include "bsg.h"
+#include "log.h"
+
+static int g_log_recursion_level = 0;
+
+// a largest buffer size. if we get a buf size bigger than this when unpacking,
+// will complain!
+#define BSG_MAX_BUF_SIZE (1<<18)
+
+#define bsglog(fmt, ...) do { \
+ int __i; \
+ for (__i=0; __i < g_log_recursion_level; __i++) { \
+ vtpmloginfomore (VTPM_LOG_BSG, "%s", " "); \
+ } \
+ vtpmloginfomore (VTPM_LOG_BSG, fmt, __VA_ARGS__); \
+ } while (0)
+
+
+// FIXME: trigger the selfcheck--need to use glibc hook to do this
+//BOOL dummy1 = BSG_static_selfcheck();
+
+
+// Interpretting Types
+// -------------------
+//
+// Incoming Types are composed of two parts {format, info} squished into a
+// BSG_UINT32. The first 4 bits is a format spec indicating what type of
+// data it is. If the first 4 bits are zero the info corresponds to a value in
+// BSG_s_fmt[]. This is a structure whose composition is described in
+// BSG_s_fmt[]. If the value is non-zero, info corresponds to the size of the
+// data (in bytes) being passed in. For example a UINT32 being passed in would
+// have a format of (__FMT_CONST | 4). If both, the format and info are zero,
+// this is interpretted as the end of the structure, and the result is
returned.
+
+// these flags are mutually exclusive, so I'll just make them
+// format values which indicate the semantics of the 'info' part and the source
+// data. The above description has been accordingly adjusted.
+
+// format values for determining what type of data the incoming type is
+// it's a 4 bit value, occupying the high 4 bits
+#define __FMT_CONST (1UL << 28) // Constant sized value
+#define __FMT_DATA (2UL << 28) // Believed to be raw data NOT {size,data}
+#define __FMT_SIZE (3UL << 28) // A size. Used in FMT_SIZE??_DATA.
+#define __FMT_HSIZE (4UL << 28) // A number of handles
+#define __FMT_PACKED (5UL << 28) // 'info' is unused; the source data consists
+ // of {size32, data} but we're to pack only
the
+ // data as that is already packed, and so
+ // can/must be unpacked without
+ // explicitly reading it size
+
+#define __FMT_MASK 0x0FFFFFFFUL // this masks out the 4-bit format
+#define __FMT_MASK_SIZE(type) ((type) & __FMT_MASK)
+#define __FMT_MASK_FORMAT(type) ((type) & (~__FMT_MASK))
+
+// constant (8/16/32-bits)
+#define FMT_U8 (__FMT_CONST | 1UL)
+#define FMT_U16 (__FMT_CONST | 2UL)
+#define FMT_U32 (__FMT_CONST | 4UL)
+
+// const with a compiler-computed size
+#define FMT_SIZEOF(type) (__FMT_CONST | sizeof(type))
+
+// other data (size bytes)
+// Used primarily for DIGESTS -> FMT_DATA(20)
+#define FMT_DATA(size) (__FMT_DATA | ((BSG_UINT32) (size) & __FMT_MASK))
+
+// 16/32-bit size followed by N bytes of data
+#define FMT_SIZE16_DATA (__FMT_SIZE | 2UL)
+#define FMT_SIZE32_DATA (__FMT_SIZE | 4UL)
+
+// 16-bit size followed by N key handles
+#define FMT_SIZE16_HANDLES (__FMT_HSIZE | 2UL)
+
+#define DIGEST_SIZE 20
+typedef BSG_UINT32 BSG_HANDLE;
+
+// TCPA_AUTH has 11 fields!
+#define MAX_FIELDS 11
+typedef struct BSG_Format
+{
+ BSG_Type type;
+ const char* name;
+ BSG_UINT32 fields[MAX_FIELDS + 1];
+} BSG_Format;
+
+/*
+ * TCPA structure data formats
+ */
+// this has to be manually kept in sync with the
+// Type enum!! the static_selfcheck() function should be used regularly!
+static BSG_Format s_fmt[] =
+{
+ {BSG_TYPE_UINT32, "BSG_TYPE_UINT32", {FMT_U32, 0}},
+ {BSG_TYPE_UINT16, "BSG_TYPE_UINT16", {FMT_U16, 0}},
+ {BSG_TYPE_BYTE, "BSG_TYPE_BYTE", {FMT_U8, 0}},
+ {BSG_TYPE_BOOL, "BSG_TYPE_BOOL", {FMT_U8, 0}},
+ {BSG_TPM_SIZE32_DATA, "BSG_TPM_SIZE32_DATA", {FMT_SIZE32_DATA, 0}},
+ {BSG_TPM_TAG, "BSG_TPM_TAG", {FMT_SIZEOF(TPM_TAG), 0}},
+ {BSG_TPM_HANDLE, "BSG_TPM_HANDLE", {FMT_SIZEOF(TPM_HANDLE), 0}},
+ {BSG_TPM_RESULT, "BSG_TPM_RESULT", {FMT_SIZEOF(TPM_RESULT), 0}},
+ {BSG_TPM_RESOURCE_TYPE, "BSG_TPM_RESOURCE_TYPE",
{FMT_SIZEOF(TPM_RESOURCE_TYPE), 0}},
+ {BSG_TPM_COMMAND_CODE, "BSG_TPM_COMMAND_CODE", {FMT_U32, 0}},
+ {BSG_TPM_AUTH_DATA_USAGE, "BSG_TPM_AUTH_DATA_USAGE", {FMT_U8, 0}},
+ {BSG_TPM_ALGORITHM_ID, "BSG_TPM_ALGORITHM_ID", {FMT_U32, 0}},
+ {BSG_TPM_PROTOCOL_ID, "BSG_TPM_PROTOCOL_ID", {FMT_SIZEOF(TPM_PROTOCOL_ID),
0}},
+ {BSG_TPM_KEY_USAGE, "BSG_TPM_KEY_USAGE", {FMT_U16, 0}},
+ {BSG_TPM_ENC_SCHEME, "BSG_TPM_ENC_SCHEME", {FMT_U16, 0}},
+ {BSG_TPM_SIG_SCHEME, "BSG_TPM_SIG_SCHEME", {FMT_U16, 0}},
+ {BSG_TPM_MIGRATE_SCHEME, "BSG_TPM_MIGRATE_SCHEME", {FMT_U16, 0}},
+ {BSG_TPM_KEY_FLAGS, "BSG_TPM_KEY_FLAGS", {FMT_U32, 0}},
+
+ {BSG_TPM_AUTHDATA, "BSG_TPM_AUTHDATA", {FMT_DATA(DIGEST_SIZE), 0}},
+ {BSG_TPM_SECRET, "BSG_TPM_SECRET", {BSG_TPM_AUTHDATA, 0}},
+ {BSG_TPM_ENCAUTH, "BSG_TPM_ENCAUTH", {BSG_TPM_AUTHDATA, 0}},
+ {BSG_TPM_PAYLOAD_TYPE, "BSG_TPM_PAYLOAD_TYPE",
{FMT_SIZEOF(TPM_PAYLOAD_TYPE), 0}},
+
+ {BSG_TPM_VERSION, "BSG_TPM_VERSION", {FMT_DATA(4), 0}}, // vers 1.2
+ {BSG_TPM_DIGEST, "BSG_TPM_DIGEST", {FMT_DATA(DIGEST_SIZE), 0}},
+ {BSG_TPM_COMPOSITE_HASH, "BSG_TPM_COMPOSITE_HASH", {BSG_TPM_DIGEST, 0}},
+ {BSG_TPM_CHOSENID_HASH, "BSG_TPM_CHOSENID_HASH", {BSG_TPM_DIGEST, 0}},
+
+ {BSG_TPM_NONCE, "BSG_TPM_NONCE", {FMT_DATA(DIGEST_SIZE), 0}},
+ {BSG_TPM_KEY_HANDLE, "BSG_TPM_KEY_HANDLE", {FMT_SIZEOF(TPM_KEY_HANDLE), 0}},
+ {BSG_TPM_KEY_HANDLE_LIST, "BSG_TPM_KEY_HANDLE_LIST",
+ {FMT_SIZE16_HANDLES, 0}},
+
+ {BSG_TPM_KEY_PARMS, "BSG_TPM_KEY_PARMS", {
+ BSG_TPM_ALGORITHM_ID,
+ BSG_TPM_ENC_SCHEME,
+ BSG_TPM_SIG_SCHEME,
+ FMT_SIZE32_DATA,
+ 0}},
+ {BSG_TPM_RSA_KEY_PARMS, "BSG_TPM_RSA_KEY_PARMS", {
+ FMT_U32, FMT_U32, FMT_SIZE32_DATA, 0}},
+ {BSG_TPM_STORE_PUBKEY, "BSG_TPM_STORE_PUBKEY", {FMT_SIZE32_DATA, 0}},
+ {BSG_TPM_PUBKEY, "BSG_TPM_PUBKEY", {BSG_TPM_KEY_PARMS, BSG_TPM_STORE_PUBKEY,
0}},
+ {BSG_TPM_KEY, "BSG_TPM_KEY", {
+ BSG_TPM_VERSION,
+ BSG_TPM_KEY_USAGE,
+ BSG_TPM_KEY_FLAGS,
+ BSG_TPM_AUTH_DATA_USAGE,
+ BSG_TPM_KEY_PARMS,
+ FMT_SIZE32_DATA, // the PCR_INFO
+ BSG_TPM_STORE_PUBKEY,
+ FMT_SIZE32_DATA, // the encrypted part
+ 0}},
+
+ {BSG_TPM_MIGRATIONKEYAUTH, "BSG_TPM_MIGRATIONKEYAUTH", {
+ BSG_TPM_PUBKEY,
+ BSG_TPM_MIGRATE_SCHEME,
+ BSG_TPM_DIGEST, 0}},
+
+ {BSG_TCPA_AUDIT_EVENT, "TCPA_AUDIT_EVENT", {
+ BSG_TPM_COMMAND_CODE,
+ BSG_TPM_RESULT, 0 }},
+
+ {BSG_TCPA_EVENT_CERT, "TCPA_EVENT_CERT", {
+ BSG_TPM_DIGEST,
+ BSG_TPM_DIGEST,
+ FMT_DATA(2),
+ FMT_SIZE32_DATA, 0}},
+
+ {BSG_TPM_PCR_SELECTION, "BSG_TPM_PCR_SELECTION", {FMT_SIZE16_DATA, 0} },
+ {BSG_TPM_PCR_COMPOSITE, "BSG_TPM_PCR_COMPOSITE", { BSG_TPM_PCR_SELECTION,
+ FMT_SIZE32_DATA,
+ 0} },
+
+ {BSG_TPM_PCR_INFO, "BSG_TPM_PCR_INFO", { BSG_TPM_PCR_SELECTION,
+ BSG_TPM_COMPOSITE_HASH,
+ BSG_TPM_COMPOSITE_HASH,
+ 0} },
+
+
+ {BSG_TPM_STORED_DATA, "BSG_TPM_STORED_DATA", {
+ BSG_TPM_VERSION,
+ FMT_SIZE32_DATA,
+ FMT_SIZE32_DATA,
+ 0}},
+ {BSG_TPM_SYMMETRIC_KEY, "BSG_TPM_SYMMETRIC_KEY", {
+ BSG_TPM_ALGORITHM_ID,
+ BSG_TPM_ENC_SCHEME,
+ FMT_SIZE16_DATA,
+ 0}},
+ {BSG_TPM_STORE_PRIVKEY, "BSG_TPM_STORE_PRIVKEY", {FMT_SIZE32_DATA, 0}},
+ {BSG_TPM_STORE_ASYMKEY, "BSG_TPM_STORE_ASYMKEY", {
+ BSG_TPM_PAYLOAD_TYPE,
+ BSG_TPM_SECRET,
+ BSG_TPM_SECRET,
+ BSG_TPM_DIGEST,
+ BSG_TPM_STORE_PRIVKEY,
+ 0}},
+ {BSG_TPM_MIGRATE_ASYMKEY, "BSG_TPM_MIGRATE_ASYMKEY", {
+ BSG_TPM_PAYLOAD_TYPE,
+ BSG_TPM_SECRET,
+ BSG_TPM_DIGEST,
+ FMT_U32,
+ BSG_TPM_STORE_PRIVKEY,
+ 0}},
+
+ {BSG_TPM_QUOTE_INFO, "BSG_TPM_QUOTE_INFO", {
+ BSG_TPM_VERSION,
+ FMT_DATA(4),
+ BSG_TPM_COMPOSITE_HASH,
+ BSG_TPM_NONCE,
+ 0}},
+
+ {BSG_TPM_IDENTITY_CONTENTS, "BSG_TPM_IDENTITY_CONTENTS", {
+ BSG_TPM_VERSION,
+ FMT_U32,
+ BSG_TPM_CHOSENID_HASH,
+ BSG_TPM_PUBKEY,
+ 0}},
+
+ {BSG_TPM_PCRVALUE, "BSG_TPM_PCRVALUE", {FMT_DATA(DIGEST_SIZE), 0}},
+
+ {BSG_TCPA_PCR_FLAGS, "TCPA_PCR_FLAGS", {
+ FMT_U8,
+ FMT_U8,
+ 0}},
+
+ {BSG_TCS_AUTH, "TCS_AUTH", {
+ BSG_TYPE_UINT32,
+ BSG_TPM_NONCE,
+ BSG_TPM_NONCE,
+ BSG_TYPE_BOOL,
+ BSG_TPM_AUTHDATA,
+ 0}},
+
+ {BSG_TPM_KEY_NONSENSITIVE, "BSG_TPM_KEY_NONSENSITIVE", {
+ BSG_TPM_VERSION,
+ BSG_TPM_KEY_USAGE,
+ BSG_TPM_KEY_FLAGS,
+ BSG_TPM_AUTH_DATA_USAGE,
+ BSG_TPM_KEY_PARMS,
+ FMT_SIZE32_DATA,
+ BSG_TPM_STORE_PUBKEY,
+ 0}},
+
+ {BSG_PACKED, "BSG_PACKED", {
+ __FMT_PACKED,
+ 0 }},
+
+ {BSG_TYPE_MAX, "", {0}},
+};
+
+
+static const BSG_Format* find_format (BSG_Type t) {
+ BSG_Format * f = s_fmt;
+
+ if (t >= BSG_TYPE_MAX) {
+ return NULL;
+ }
+
+ // WARNING: this depends on the enum and s_fmt[] array being in sync! make
+ // sure to run the static_selfcheck() to make sure
+ f = s_fmt + (t - BSG_TYPE_FIRST);
+
+ return f;
+}
+
+//
+// a consistency-checking routine which can be run at compile time
+// (ie. immediately after compilation)
+//
+// tasks:
+// - verify that s_fmt has one entry per Type t, and that entry is at s_fmt[t]
+//
+// conditions:
+// - need that s_fmt[0] is the first type listed in the Type enum! ie the first
+// Type has value 0, not 1
+//
+// FIXME: should have a function be passed in here which is called if the test
+// fails. Then the caller can decide what to do: abort, notify, whatever
+//
+BOOL BSG_static_selfcheck ()
+{
+ int i;
+
+ for (i=BSG_TYPE_FIRST; i <= BSG_TYPE_MAX; i++) {
+ if (s_fmt[i - BSG_TYPE_FIRST].type != i) {
+ bsglog ("%s\n", "BSG: static_selfcheck failed!\n");
+ bsglog ("failure at %i, allegedly %s\n",
+ i, s_fmt[i - BSG_TYPE_FIRST].name);
+ abort();
+ return FALSE;
+ }
+ }
+
+ bsglog ("%s\n", "BSG: static_selfcheck success!");
+ return TRUE;
+}
+
+
+/**
+ * Flatten a TCPA structure into a buffer in big-endian format
+ * @type: TCPA structure type
+ * @src: (IN) TCPA structure (OUT) end of TCPA structure
+ * @dst: (OUT) flattened data
+ * Returns: Flattened size or -1 for unknown types
+ */
+// make it so that it can just run through the whole process and return
+// the packed size, without packing anything. this will be done if dst is NULL.
+static int BSG_Pack_private(BSG_Type type, const BSG_BYTE** src, BSG_BYTE* dst)
+{
+ // check incoming parameters
+ if (*src == NULL)
+ return 0;
+
+ const BSG_BYTE* s = *src;
+ BSG_BYTE* d = dst;
+
+ BSG_UINT32 size = __FMT_MASK_SIZE(type);
+ BSG_UINT32 format = __FMT_MASK_FORMAT(type);
+
+ if (format == __FMT_CONST) // We are dealing with a fixed length value eg.
UINT32
+ {
+ BSG_UINT32 val = 0;
+ switch (size) {
+ case 1: val = * (BYTE*) s; break;
+ case 2: val = * (unsigned short*) s; break;
+ case 4: val = * (BSG_UINT32*) s; break;
+ }
+ if (dst)
+ BSG_PackConst(val, size, d);
+
+ s += size;
+ d += size;
+ } else if (format == __FMT_DATA) { // We are dealing with raw data. Not
sure when
+ // this is used.
+
+ if (dst) {
+ bsglog ("BSG: __FMT_DATA size %d, src %p, dst %p\n", size, s, d);
+ memcpy(d, s, size);
+ }
+
+ s += size;
+ d += size;
+ } else if (format == __FMT_SIZE || format == __FMT_HSIZE) { // It's a size,
followed by that much data or handles
+
+ BSG_UINT32 psize = 0;
+ switch (size) {
+ case 1: psize = * (BYTE*) s; break;
+ case 2: psize = * (unsigned short*) s; break;
+ case 4: psize = * (BSG_UINT32*) s; break;
+ }
+
+ if (dst)
+ BSG_PackConst(psize, size, d);
+
+ s += size;
+ d += size;
+
+ // now 's' points to an address, so cast it to BSG_BYTE**
+ const BSG_BYTE* pdata = * ((BSG_BYTE**) s);
+ s += sizeof(BSG_BYTE*);
+
+ if (format == __FMT_HSIZE) {// This is a list of psize Handles
+ if (dst) {
+ BSG_HANDLE* d2 = (BSG_HANDLE*) d;
+ BSG_HANDLE* p2 = (BSG_HANDLE*) pdata;
+ BSG_UINT32 i;
+ for (i = 0; i < psize; i++)
+ d2[i] = BSG_UnpackConst((BSG_BYTE*)(p2 + i), 4);
+
+ }
+ d += psize * sizeof(BSG_HANDLE);
+ } else {// If it's not psize handles, it's psize data.
+ if (psize > 0) {
+ if (dst) {
+ bsglog ("BSG: __FMT_SIZE, size=%d, src=%p, dst=%p\n",
+ psize, pdata, d);
+ memcpy(d, pdata, psize);
+ }
+ }
+ d += psize;
+ }
+ } else if (format == __FMT_PACKED) {
+ // the source buffer is a pack_constbuf_t, which has a size and a
+ // pointer. just copy the buffer value, the size is not included in the
+ // output stream.
+ pack_constbuf_t * buf = (pack_constbuf_t*) s;
+
+ if (dst) {
+ bsglog ("BSG: __FMT_PACKED, size=%d, src=%p, dst=%p\n",
+ buf->size, buf->data, d);
+ memcpy(d, buf->data, buf->size);
+ }
+
+ s += buf->size;
+ d += buf->size;
+ } else if (format == 0) {// No flags are set. This is a structure & it should
+ // be looked up in the bsg_s_fmt[]
+
+ const BSG_Format* x = find_format (type);
+ if (x == NULL) {
+ vtpmloginfo(VTPM_LOG_BSG, "BSG_Pack: cannot find type %d\n", type);
+ return -1;
+ }
+
+ if (dst)
+ bsglog ("BSG_Pack type %s\n", x->name);
+
+
+ // iterate through the fields
+ const BSG_UINT32* f = x->fields;
+ for (; *f; f++) {
+ int fsize;
+
+ g_log_recursion_level++;
+ fsize = BSG_Pack_private((BSG_Type) *f, &s, dst ? d : NULL);
+ g_log_recursion_level--;
+
+ if (fsize <= 0)
+ return fsize;
+
+ d += fsize;
+ }
+ } else {
+ vtpmlogerror(VTPM_LOG_BSG, "BSG_Pack(): Unknown format %d\n", format);
+ return -1;
+ }
+
+ *src = s;
+ return (d - dst);
+}
+
+/**
+ * Unflatten a TCPA structure from a buffer in big-endian format
+ * @type: TCPA structure type
+ * @src: flattened data
+ * @dst: (IN) TCPA structure (OUT) end of TCPA structure
+ * Returns: Flattened size
+ * Note: Returns flattened size NOT the unpacked structure size
+ */
+static int BSG_Unpack_private(BSG_Type type, const BSG_BYTE* src, BSG_BYTE**
dst) {
+ // check incoming parameters
+ if (src == NULL)
+ return 0;
+
+
+ const BSG_BYTE* s = src;
+ BSG_BYTE* d = dst ? *dst:NULL;
+ if (dst && !d)
+ dst = NULL;
+
+ BSG_UINT32 size = __FMT_MASK_SIZE(type);
+ BSG_UINT32 format = __FMT_MASK_FORMAT(type);
+
+ if (format == __FMT_CONST) {// We are dealing with a fixed length value ie.
UINT32
+
+ BSG_UINT32 val = BSG_UnpackConst(s, size);
+
+ if (dst) {
+ switch (size) {
+ case 1: *(BYTE *) d = (BSG_BYTE) val; break;
+ case 2: *(unsigned short*) d = (unsigned short) val; break;
+ case 4: *(BSG_UINT32*) d = (BSG_UINT32) val; break;
+ }
+ }
+
+ s += size;
+ d += size;
+ } else if (format == __FMT_DATA) {// We are dealing with raw data. Not sure
when this is used.
+ if (dst)
+ memcpy(d, s, size);
+
+ d += size;
+ s += size;
+ } else if (format == __FMT_SIZE || format == __FMT_HSIZE) {// It's a size,
followed by that much data or handles
+
+ BSG_UINT32 psize = BSG_UnpackConst(s, size);
+
+ if (psize > BSG_MAX_BUF_SIZE) {
+ vtpmlogerror(VTPM_LOG_BSG, "BSG_Unpack runs into var-sized data bigger
than %u bytes!!\n",
+ BSG_MAX_BUF_SIZE);
+ return -1;
+ }
+
+ if (dst) {
+ switch (size) {
+ case 1: *(BYTE *) d = (BSG_BYTE) psize; break;
+ case 2: *(unsigned short*) d = (unsigned short) psize; break;
+ case 4: *(BSG_UINT32*) d = (BSG_UINT32) psize; break;
+ }
+ }
+
+ s += size;
+ d += size;
+
+ BSG_BYTE* pdata = NULL;
+
+ if (psize) {
+ if (format == __FMT_HSIZE) { // This is a list of psize Handles
+ if (dst) {
+ BSG_HANDLE* s2 = (BSG_HANDLE*) s;
+ pdata = (BSG_BYTE *)malloc(psize * sizeof(BSG_HANDLE));
+ if (!pdata)
+ return -1;
+
+ BSG_HANDLE* p2 = (BSG_HANDLE*) pdata;
+ BSG_UINT32 i;
+ for (i = 0; i < psize; i++) {
+ BSG_PackConst(s2[i], 4, (BSG_BYTE*)(p2 + i));
+ }
+ }
+ s += psize * sizeof(BSG_HANDLE);
+ } else { // If it's not psize handles, it's psize data.
+ if (dst) {
+ pdata = (BSG_BYTE *)malloc(sizeof(BSG_BYTE) * psize);
+ if (!pdata)
+ return -1;
+ memcpy(pdata, s, psize);
+ }
+ s += psize;
+ }
+ }
+ if (dst)
+ *(void**) d = pdata;
+
+ d += sizeof(void*);
+ } else if (format == __FMT_PACKED) {
+
+ // this doesn't make sense for unpacking!
+ vtpmlogerror(VTPM_LOG_BSG, "BSG_Unpack() called with format __FMT_PACKED. "
+ "This does not make
sense\n");
+
+ return -1;
+ } else if (format == 0) {// No flags are set. This is a structure & it should
+ // be looked up in the bsg_s_fmt[]
+
+ const BSG_Format* x = find_format (type);
+ if (x == NULL) {
+ vtpmlogerror(VTPM_LOG_BSG, "BSG_Unpack: cannot find type %d\n", type);
+ return -1;
+ }
+
+ const BSG_UINT32* f = x->fields;
+ for (; *f; f++) {
+ int fsize = BSG_Unpack_private((BSG_Type) *f, s, dst ? &d:NULL);
+ if (fsize <= 0)
+ return fsize;
+ s += fsize;
+ }
+ }
+
+ if (dst)
+ *dst = d;
+ return (s - src);
+}
+
+/**
+ * Free memory associated with unpacked TCPA structure
+ * @type: TCPA structure type
+ * @src: (IN) TCPA structure (OUT) end of TCPA structure
+ * Note: Destroy should be called on all structures created with Unpack
+ * to ensure that any allocated memory is freed
+ */
+static void BSG_Destroy_private(BSG_Type type, BSG_BYTE** src) {
+ BSG_BYTE* s = *src;
+
+ BSG_UINT32 size = __FMT_MASK_SIZE(type);
+ BSG_UINT32 format = __FMT_MASK_FORMAT(type);
+
+ if ((src == NULL) || (*src == NULL)) {
+ vtpmlogerror(VTPM_LOG_BSG, "BSG_Destroy() called with NULL src\n");
+ return;
+ }
+
+ if (format == __FMT_CONST || format == __FMT_DATA)
+ s += size;
+ else if (format == __FMT_SIZE || format == __FMT_HSIZE) {
+ s += size;
+ BSG_BYTE* ptr = *(BSG_BYTE**) s;
+ if (ptr)
+ free(ptr);
+ s += sizeof(void*);
+ } else if (format == __FMT_PACKED) {
+
+ // this doesn't make sense for unpacking, hence also for Destroy()
+ vtpmlogerror(VTPM_LOG_BSG, "BSG_Destroy() called with format __FMT_PACKED.
"
+ "This does not make
sense\n");
+
+ return;
+ } else if (format == 0) {
+ const BSG_Format* x = find_format (type);
+ if (x == NULL) {
+ vtpmlogerror(VTPM_LOG_BSG, "BSG_Destroy: cannot find type %d\n", type);
+ return;
+ }
+
+ const BSG_UINT32* f = x->fields;
+ for (; *f; f++)
+ BSG_Destroy_private((BSG_Type) *f, &s);
+ }
+
+ *src = s;
+}
+
+int BSG_Pack(BSG_Type type, const void* src, BSG_BYTE* dst)
+{
+ const BSG_BYTE* src2 = (const BSG_BYTE*) src;
+ return BSG_Pack_private(type, &src2, dst);
+}
+
+int BSG_Unpack(BSG_Type type, const BSG_BYTE* src, void* dst)
+{
+ BSG_BYTE* dst2 = (BSG_BYTE*) dst;
+ return BSG_Unpack_private(type, src, dst ? &dst2:NULL);
+}
+
+void BSG_Destroy(BSG_Type type, void* src)
+{
+ BSG_BYTE* src2 = (BSG_BYTE*) src;
+ BSG_Destroy_private(type, &src2);
+}
+
+/**
+ * Pack a 8/16/32-bit constant into a buffer in big-endian format
+ * @val: constant value
+ * @size: constant size in bytes (1, 2, or 4)
+ * @dst: (OUT) buffer
+ */
+void BSG_PackConst(BSG_UINT32 val, int size, BSG_BYTE* dst) {
+ bsglog ("BSG: PackConst on %d of size %i into address %p\n", val, size, dst);
+
+ switch (size) {
+ case 4:
+ dst[0] = (BSG_BYTE)((val >> 24) & 0xff);
+ dst[1] = (BSG_BYTE)((val >> 16) & 0xff);
+ dst[2] = (BSG_BYTE)((val >> 8) & 0xff);
+ dst[3] = (BSG_BYTE)(val & 0xff);
+ break;
+ case 2:
+ dst[0] = (BSG_BYTE)((val >> 8) & 0xff);
+ dst[1] = (BSG_BYTE)(val & 0xff);
+ break;
+ case 1:
+ dst[0] = (BSG_BYTE)(val & 0xff);
+ break;
+ }
+}
+
+/**
+ * Unpack a 8/16/32-bit constant from a buffer in big-endian format
+ * @src: buffer
+ * @size: constant size in bytes (1, 2, or 4)
+ */
+BSG_UINT32 BSG_UnpackConst(const BSG_BYTE* src, int size) {
+ BSG_UINT32 val = 0;
+
+ if (src == NULL)
+ return 0;
+
+ switch (size) {
+ case 4:
+ val = (((BSG_UINT32) src[0]) << 24
+ | ((BSG_UINT32) src[1]) << 16
+ | ((BSG_UINT32) src[2]) << 8
+ | (BSG_UINT32) src[3]);
+ break;
+ case 2:
+ val = (((BSG_UINT32) src[0]) << 8 | (BSG_UINT32) src[1]);
+ break;
+ case 1:
+ val = (BSG_UINT32) src[0];
+ break;
+ }
+ return val;
+}
+
+// Pack a list of parameters. Beware not to send values, but rather you must
+// send a pointer to your values Instead. This includes UINT32's.
+int BSG_PackList( BSG_BYTE* dst, int ParamCount, ... ) {
+ int ParamNumber;
+ BSG_Type format;
+ BSG_BYTE* val = NULL;
+ int size=0;
+
+ va_list paramList;
+ va_start( paramList, ParamCount );
+
+ for( ParamNumber = 1; ParamNumber <= ParamCount; ParamNumber++) {
+ //Strangeness with int is because gcc wanted an int rather than a enum of
ints.
+ format = (BSG_Type) va_arg( paramList, int );
+ val = va_arg( paramList, BSG_BYTE* );
+ size += BSG_Pack(format, val, dst == NULL ? NULL : dst + size);
+ }
+
+ va_end (paramList);
+
+ return size;
+}
+
+// Unpack a list of parameters.
+int BSG_UnpackList( const BSG_BYTE* src, int ParamCount, ... ) {
+ int ParamNumber = 0;
+ BSG_Type format;
+ BSG_BYTE* val = NULL;
+ int size = 0;
+
+ va_list paramList;
+ va_start( paramList, ParamCount );
+
+ for( ParamNumber = 1; ParamNumber <= ParamCount; ParamNumber++) {
+ format = (BSG_Type) va_arg( paramList, int );
+ val = va_arg( paramList, BSG_BYTE* );
+
+ size += BSG_Unpack(format, src + size, val);
+ }
+
+ va_end( paramList );
+
+ return size;
+}
+
+// Destroy any memory allocated by calls to unpack
+void BSG_DestroyList(int ParamCount, ... ) {
+ int ParamNumber = 0;
+ BSG_Type argType;
+ BSG_BYTE* paramValue = NULL;
+
+ va_list paramList;
+ va_start( paramList, ParamCount );
+
+ for( ParamNumber = 1; ParamNumber <= ParamCount; ParamNumber++) {
+ argType = (BSG_Type) va_arg( paramList, int );
+ paramValue = va_arg( paramList, BSG_BYTE* );
+
+ BSG_Destroy(argType, paramValue);
+ }
+
+ va_end( paramList );
+
+ return;
+}
+
+
+// and a tuple version
+TPM_RESULT BSG_DestroyTuple (int numParams, pack_tuple_t params[]) {
+ int i;
+
+ for (i = 0; i < numParams; i++)
+ BSG_Destroy (params[i].type, params[i].addr);
+
+ return TPM_SUCCESS;
+}
+
+
+//
+// wrappers of Pack and PackList which malloc the ouput buffer. to be freed
+// by the caller later
+//
+
+int BSG_PackMalloc (BSG_Type type, const void* src, BSG_BYTE** o_dst) {
+ int size = BSG_Pack (type, src, NULL);
+ BSG_BYTE * dest = (BSG_BYTE*) malloc (size);
+ if (dest == NULL)
+ return -1;
+
+ size = BSG_Pack(type, src, dest);
+ *o_dst = dest;
+ return size;
+}
+
+
+
+int BSG_PackListMalloc(BSG_BYTE** outBuffer, int ParamCount, ... ) {
+ va_list args;
+ int size;
+
+ va_start (args, ParamCount);
+ size = BSG_PackList (NULL, ParamCount, args);
+ va_end (args);
+
+ BSG_BYTE * dest = (BSG_BYTE*) malloc (size);
+ if (dest == NULL)
+ return -1;
+
+ va_start (args, ParamCount);
+ size = BSG_PackList (dest, ParamCount, args);
+ va_end (args);
+
+ *outBuffer = dest;
+ return size;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/bsg.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/util/bsg.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,166 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+//
+// bsg.h
+//
+// This file contains API's for the TPM Byte Stream functions
+//
+// ==================================================================
+
+#ifndef __BSG_H__
+#define __BSG_H__
+
+#include <stdarg.h>
+#include "buffer.h"
+
+typedef unsigned int BSG_UINT32;
+typedef unsigned char BSG_BYTE;
+
+// forward decl
+struct pack_const_tuple_t;
+
+struct pack_tuple_t;
+
+
+/**
+ * Byte stream generator
+ */
+// this has to be manually kept in sync with the
+// s_fmt array!!
+// but now we have a self-check function which can make sure things are well
+// (if used!)
+typedef enum BSG_Type
+{
+ BSG_TYPE_FIRST = 1,
+ BSG_TYPE_UINT32 = 1, // start at 1 so that Type 0 only serves as an
+ // unused/special value
+ BSG_TYPE_UINT16,
+ BSG_TYPE_BYTE,
+ BSG_TYPE_BOOL,
+ BSG_TPM_SIZE32_DATA, // a 32 bit unsigned size, followed by
+ // a pointer to that much data. can pass a
+ // struct pack_buf_t as the param
+ BSG_TPM_TAG,
+ BSG_TPM_HANDLE,
+ BSG_TPM_RESULT,
+ BSG_TPM_RESOURCE_TYPE,
+ BSG_TPM_COMMAND_CODE,
+ BSG_TPM_AUTH_DATA_USAGE,
+ BSG_TPM_ALGORITHM_ID,
+ BSG_TPM_PROTOCOL_ID,
+ BSG_TPM_KEY_USAGE,
+ BSG_TPM_ENC_SCHEME,
+ BSG_TPM_SIG_SCHEME,
+ BSG_TPM_MIGRATE_SCHEME,
+ BSG_TPM_KEY_FLAGS,
+ BSG_TPM_AUTHDATA,
+ BSG_TPM_SECRET,
+ BSG_TPM_ENCAUTH,
+ BSG_TPM_PAYLOAD_TYPE,
+
+ BSG_TPM_VERSION,
+ BSG_TPM_DIGEST,
+ BSG_TPM_COMPOSITE_HASH,
+ BSG_TPM_CHOSENID_HASH,
+ BSG_TPM_NONCE,
+ BSG_TPM_KEY_HANDLE,
+ BSG_TPM_KEY_HANDLE_LIST,
+ BSG_TPM_KEY_PARMS,
+ BSG_TPM_RSA_KEY_PARMS,
+ BSG_TPM_STORE_PUBKEY,
+ BSG_TPM_PUBKEY,
+ BSG_TPM_KEY,
+
+ BSG_TPM_MIGRATIONKEYAUTH,
+ BSG_TCPA_AUDIT_EVENT,
+ BSG_TCPA_EVENT_CERT,
+ BSG_TPM_PCR_SELECTION,
+ BSG_TPM_PCR_COMPOSITE,
+ BSG_TPM_PCR_INFO,
+ BSG_TPM_STORED_DATA,
+ BSG_TPM_SYMMETRIC_KEY,
+ BSG_TPM_STORE_PRIVKEY,
+ BSG_TPM_STORE_ASYMKEY,
+ BSG_TPM_MIGRATE_ASYMKEY,
+ BSG_TPM_QUOTE_INFO,
+ BSG_TPM_IDENTITY_CONTENTS,
+ BSG_TPM_PCRVALUE,
+ BSG_TCPA_PCR_FLAGS,
+ BSG_TCS_AUTH,
+
+ // this is the BSG_TPM_KEY struct without the encData field
+ BSG_TPM_KEY_NONSENSITIVE,
+
+ BSG_PACKED,
+
+ BSG_TYPE_MAX
+} BSG_Type;
+
+struct pack_const_tuple_t {
+ BSG_Type type;
+ const void * addr;
+};
+
+
+typedef struct pack_tuple_t {
+ BSG_Type type;
+ void * addr;
+} pack_tuple_t;
+
+int BSG_Pack(BSG_Type type, const void* src, BSG_BYTE* dst);
+int BSG_Unpack(BSG_Type type, const BSG_BYTE* src, void* dst);
+void BSG_Destroy(BSG_Type type, void* src);
+
+// wrappers of Pack and PackList which malloc the ouput buffer. to be freed
+// by the caller later. returns size of allocated buffer, or -1 in case
+// allocation failed
+int BSG_PackMalloc (BSG_Type type, const void* src, BSG_BYTE** o_dst);
+int BSG_PackListMalloc (BSG_BYTE** outBuffer, int ParamCount, ... );
+
+// a va_list version of PackList
+int BSG_PackList(BSG_BYTE* outBuffer, int ParamCount, ... );
+int BSG_UnpackList(const BSG_BYTE* inBuffer, int ParamCount, ... );
+void BSG_DestroyList(int ParamCount, ... );
+
+// wrapper of PackList which uses a buffer_t
+TPM_RESULT BSG_PackListBuf (buffer_t * o_buf, int ParamCount, ...);
+
+// and a tuple version
+TPM_RESULT BSG_DestroyTuple (int numParams, pack_tuple_t params[]);
+
+void BSG_PackConst(BSG_UINT32 val, int size, BSG_BYTE* dst);
+BSG_UINT32 BSG_UnpackConst(const BSG_BYTE* src, int size);
+
+BOOL BSG_static_selfcheck ();
+
+#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/buffer.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/util/buffer.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,213 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/param.h>
+
+#include "tcg.h"
+#include "bsg.h"
+#include "buffer.h"
+
+static TPM_RESULT buffer_priv_realloc (buffer_t * buf, tpm_size_t newsize);
+
+//
+// buffer functions!
+//
+
+TPM_RESULT buffer_init (buffer_t * buf, tpm_size_t initsize, const BYTE*
initval) {
+ if (initsize == 0) {
+ memset(buf, 0, sizeof(*buf));
+ return TPM_SUCCESS;
+ }
+
+
+ buf->bytes = (BYTE*) malloc (initsize);
+ if (buf->bytes == NULL)
+ return TPM_RESOURCES;
+
+ buf->size = initsize;
+ buf->alloc_size = initsize;
+
+ if (initval)
+ memcpy (buf->bytes, initval, initsize);
+
+ buf->is_owner = TRUE;
+
+ return TPM_SUCCESS;
+}
+
+TPM_RESULT buffer_init_convert (buffer_t * buf, tpm_size_t initsize, BYTE*
initval) {
+
+ buf->size = initsize;
+ buf->alloc_size = initsize;
+ buf->bytes = initval;
+
+ buf->is_owner = TRUE;
+
+ return TPM_SUCCESS;
+}
+
+TPM_RESULT buffer_init_copy (buffer_t * buf, const buffer_t * src) {
+ TPM_RESULT status = buffer_init (buf, src->size, src->bytes);
+ buf->is_owner = TRUE;
+
+ return status;
+}
+
+
+
+// make an alias to a constant array
+TPM_RESULT buffer_init_const (buffer_t * buf, tpm_size_t size, const BYTE*
val) {
+ // TODO: try to enforce the const things somehow!
+ buf->bytes = (BYTE*) val;
+ buf->size = size;
+ buf->alloc_size = 0; // this field is now unneeded
+
+ buf->is_owner = FALSE;
+
+ return TPM_SUCCESS;
+}
+
+// make an alias into buf, with given offset and length
+// if len = 0, make the alias go to the end of buf
+TPM_RESULT buffer_init_alias (buffer_t * buf, const buffer_t * b,
+ tpm_size_t offset, tpm_size_t len) {
+ if (offset + len > b->size) {
+ return TPM_NOSPACE;
+ }
+
+ buf->bytes = b->bytes + offset;
+ buf->size = len > 0 ? len : b->size - offset;
+
+ //VS/ buf->alloc_size = 0;
+ if (len ==0)
+ buf->alloc_size = b->alloc_size - offset;
+ else
+ buf->alloc_size = MIN(b->alloc_size - offset, len);
+
+
+ buf->is_owner = FALSE;
+
+ return TPM_SUCCESS;
+}
+
+
+// copy into the start of dest
+TPM_RESULT buffer_copy (buffer_t * dest, const buffer_t* src)
+{
+ TPM_RESULT status = TPM_SUCCESS;
+
+ if (dest->alloc_size < src->size) {
+ status = buffer_priv_realloc (dest, src->size);
+ STATUSCHECK (status);
+ }
+
+ memcpy (dest->bytes, src->bytes, src->size);
+ dest->size = src->size;
+
+ //VS/ dest->is_owner = TRUE;
+
+ abort_egress:
+
+ return status;
+}
+
+
+
+BOOL buffer_eq (const buffer_t * a, const buffer_t * b) {
+ return (a->size == b->size && memcmp (a->bytes, b->bytes, a->size) == 0);
+}
+
+
+void buffer_memset (buffer_t * buf, BYTE b) {
+ memset (buf->bytes, b, buf->size);
+}
+
+
+TPM_RESULT buffer_append_raw (buffer_t * buf, tpm_size_t len, const BYTE*
bytes) {
+ TPM_RESULT status = TPM_SUCCESS;
+
+ if (buf->alloc_size < buf->size + len) {
+ status = buffer_priv_realloc (buf, buf->size + len);
+ STATUSCHECK (status);
+ }
+
+ memcpy (buf->bytes + buf->size, bytes, len);
+
+ buf->size += len;
+
+ goto egress;
+
+ abort_egress:
+
+ egress:
+
+ return status;
+}
+
+tpm_size_t buffer_len (const buffer_t* buf) {
+ return buf->size;
+}
+
+TPM_RESULT buffer_free (buffer_t * buf) {
+ if (buf && buf->is_owner && buf->bytes != NULL) {
+ free (buf->bytes);
+ buf->bytes = NULL;
+ }
+
+ return TPM_SUCCESS;
+}
+
+TPM_RESULT buffer_priv_realloc (buffer_t * buf, tpm_size_t newsize) {
+
+ // we want to realloc to twice the size, or the new size, whichever
+ // bigger
+
+ BYTE * tmpbuf = NULL;
+
+ newsize = MAX (buf->alloc_size * 2, newsize);
+
+ tmpbuf = (BYTE*) realloc (buf->bytes, newsize);
+ if (tmpbuf == NULL)
+ return TPM_SIZE;
+
+
+ buf->bytes = tmpbuf;
+ buf->alloc_size = newsize;
+
+ return TPM_SUCCESS;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/buffer.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/util/buffer.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,103 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+
+#ifndef __VTPM_BUFFER_H__
+#define __VTPM_BUFFER_H__
+
+#include <stddef.h> // for pointer NULL
+#include "tcg.h"
+
+// structure to enable use of FMT_SIZE32_DATA in BSG_Unpack
+typedef struct pack_buf_t {
+ UINT32 size;
+ BYTE * data;
+} pack_buf_t;
+
+// and a const version for Pack
+typedef struct pack_constbuf_t {
+ UINT32 size;
+ const BYTE* data;
+} pack_constbuf_t;
+
+typedef UINT32 tpm_size_t;
+
+// first version, probably will be expanded...
+
+#define NULL_BUF {0,0,0,0}
+
+typedef struct {
+ // private!!
+ tpm_size_t size, alloc_size;
+ BYTE * bytes;
+
+ BOOL is_owner; // do we own this buffer, and need to free it?
+} buffer_t;
+
+// allocate the buffer if initsize > 0, copying over initval if provided
+TPM_RESULT buffer_init (buffer_t * buf,
+ tpm_size_t initsize,
+ const BYTE* initval);
+
+// Create a new buffer from a BYTE *. Use buffer_free to destroy original BYTE
*
+TPM_RESULT buffer_init_convert (buffer_t * buf,
+ tpm_size_t initsize,
+ BYTE* initval);
+
+// make an alias to a constant array, no copying
+TPM_RESULT buffer_init_const (buffer_t * buf, tpm_size_t size, const BYTE*
val);
+
+// make an alias into buf, with given offset and length
+// if len = 0, make the alias go to the end of buf
+TPM_RESULT buffer_init_alias (buffer_t * buf, const buffer_t * b,
+ tpm_size_t offset, tpm_size_t);
+
+// "copy constructor"
+TPM_RESULT buffer_init_copy (buffer_t * buf, const buffer_t * src);
+
+
+// copy into the start of a
+TPM_RESULT buffer_copy (buffer_t * dest, const buffer_t* src);
+
+// are they equal?
+BOOL buffer_eq (const buffer_t * a, const buffer_t * b);
+
+// set the buffer to a constant byte
+void buffer_memset (buffer_t * buf, BYTE b);
+
+tpm_size_t buffer_len (const buffer_t* buf);
+
+TPM_RESULT buffer_free (buffer_t * buf);
+
+TPM_RESULT buffer_append_raw (buffer_t * buf, tpm_size_t len, const BYTE*
bytes);
+
+#endif // _TOOLS_H_
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/depend
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/util/depend Fri Sep 9 16:30:54 2005
@@ -0,0 +1,7 @@
+hashtable.o: hashtable.c hashtable.h hashtable_private.h
+hashtable_itr.o: hashtable_itr.c hashtable.h hashtable_private.h \
+ hashtable_itr.h
+bsg.o: bsg.c tcg.h ../crypto/crypto.h ../crypto/sym_crypto.h buffer.h \
+ bsg.h log.h
+log.o: log.c buffer.h tcg.h
+buffer.o: buffer.c tcg.h bsg.h buffer.h
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/hashtable.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/util/hashtable.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2005, Intel Corp
+ * Copyright (c) 2002, Christopher Clark <firstname.lastname@xxxxxxxxxxxx>
+ * 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.
+*/
+
+#include "hashtable.h"
+#include "hashtable_private.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.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 float max_load_factor = 0.65;
+
+/*****************************************************************************/
+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) ceil(size * max_load_factor);
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_init(&h->mutex, NULL);
+#endif
+ return h;
+}
+
+/*****************************************************************************/
+unsigned int
+hash(struct hashtable *h, void *k)
+{
+ 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) ceil(newsize * max_load_factor);
+ return -1;
+}
+
+/*****************************************************************************/
+unsigned int
+hashtable_count(struct hashtable *h)
+{
+ unsigned int count;
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&h->mutex);
+#endif
+ count = h->entrycount;
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_unlock(&h->mutex);
+#endif
+ return count;
+}
+
+/*****************************************************************************/
+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;
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&h->mutex);
+#endif
+ 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;
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_unlock(&h->mutex);
+#endif
+ return -1;
+}
+
+/*****************************************************************************/
+void * /* returns value associated with key */
+hashtable_search(struct hashtable *h, void *k)
+{
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&h->mutex);
+#endif
+ 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))) {
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_unlock(&h->mutex);
+#endif
+ return e->v;
+ }
+ e = e->next;
+ }
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_unlock(&h->mutex);
+#endif
+ 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. */
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&h->mutex);
+#endif
+ 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;
+ }
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_unlock(&h->mutex);
+#endif
+ return NULL;
+}
+
+/*****************************************************************************/
+/* destroy */
+void
+hashtable_destroy(struct hashtable *h, int free_values)
+{
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&h->mutex);
+#endif
+ 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);
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_destroy(&h->mutex);
+#endif
+ free(h);
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/hashtable.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/util/hashtable.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2005, Intel Corp
+ * Copyright (c) 2002, Christopher Clark <firstname.lastname@xxxxxxxxxxxx>
+ * 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.
+*/
+
+
+#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__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/hashtable_itr.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/util/hashtable_itr.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2005, Intel Corp
+ * Copyright (c) 2002, Christopher Clark <firstname.lastname@xxxxxxxxxxxx>
+ * 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.
+*/
+
+#include "hashtable.h"
+#include "hashtable_private.h"
+#include "hashtable_itr.h"
+#include <stdlib.h> /* defines NULL */
+
+/*****************************************************************************/
+/* hashtable_iterator - iterator constructor */
+
+struct hashtable_itr *
+hashtable_iterator(struct hashtable *h)
+{
+ unsigned int i, tablelength;
+ struct hashtable_itr *itr = (struct hashtable_itr *)
+ malloc(sizeof(struct hashtable_itr));
+ if (NULL == itr) return NULL;
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&h->mutex);
+#endif
+ itr->h = h;
+ itr->e = NULL;
+ itr->parent = NULL;
+ tablelength = h->tablelength;
+ itr->index = tablelength;
+ if (0 == h->entrycount) {
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_unlock(&h->mutex);
+#endif
+ return itr;
+ }
+
+ for (i = 0; i < tablelength; i++)
+ {
+ if (NULL != h->table[i])
+ {
+ itr->e = h->table[i];
+ itr->index = i;
+ break;
+ }
+ }
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_unlock(&h->mutex);
+#endif
+ return itr;
+}
+
+/*****************************************************************************/
+/* key - return the key of the (key,value) pair at the current position */
+/* value - return the value of the (key,value) pair at the current position
*/
+
+void *
+hashtable_iterator_key(struct hashtable_itr *i)
+{ return i->e->k; }
+
+void *
+hashtable_iterator_value(struct hashtable_itr *i)
+{ return i->e->v; }
+
+/*****************************************************************************/
+/* advance - advance the iterator to the next element
+ * returns zero if advanced to end of table */
+
+int
+hashtable_iterator_advance(struct hashtable_itr *itr)
+{
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&itr->h->mutex);
+#endif
+ unsigned int j,tablelength;
+ struct entry **table;
+ struct entry *next;
+ int ret;
+ if (NULL == itr->e) { /* stupidity check */
+ ret = 0;
+ goto egress;
+ }
+
+ next = itr->e->next;
+ if (NULL != next)
+ {
+ itr->parent = itr->e;
+ itr->e = next;
+ ret = -1;
+ goto egress;
+ }
+
+ tablelength = itr->h->tablelength;
+ itr->parent = NULL;
+ if (tablelength <= (j = ++(itr->index)))
+ {
+ itr->e = NULL;
+ ret = 0;
+ goto egress;
+ }
+ table = itr->h->table;
+ while (NULL == (next = table[j]))
+ {
+ if (++j >= tablelength)
+ {
+ itr->index = tablelength;
+ itr->e = NULL;
+ ret = 0;
+ goto egress;
+ }
+ }
+ itr->index = j;
+ itr->e = next;
+ ret = -1;
+
+ egress:
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_unlock(&itr->h->mutex);
+#endif
+ return ret;
+}
+
+/*****************************************************************************/
+/* remove - remove the entry at the current iterator position
+ * and advance the iterator, if there is a successive
+ * element.
+ * If you want the value, read it before you remove:
+ * beware memory leaks if you don't.
+ * Returns zero if end of iteration. */
+
+int
+hashtable_iterator_remove(struct hashtable_itr *itr)
+{
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&itr->h->mutex);
+#endif
+ struct entry *remember_e, *remember_parent;
+ int ret;
+
+ /* Do the removal */
+ if (NULL == (itr->parent))
+ {
+ /* element is head of a chain */
+ itr->h->table[itr->index] = itr->e->next;
+ } else {
+ /* element is mid-chain */
+ itr->parent->next = itr->e->next;
+ }
+ /* itr->e is now outside the hashtable */
+ remember_e = itr->e;
+ itr->h->entrycount--;
+ freekey(remember_e->k);
+
+ /* Advance the iterator, correcting the parent */
+ remember_parent = itr->parent;
+ ret = hashtable_iterator_advance(itr);
+ if (itr->parent == remember_e) { itr->parent = remember_parent; }
+ free(remember_e);
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_unlock(&itr->h->mutex);
+#endif
+ return ret;
+}
+
+/*****************************************************************************/
+int /* returns zero if not found */
+hashtable_iterator_search(struct hashtable_itr *itr,
+ struct hashtable *h, void *k)
+{
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&h->mutex);
+#endif
+ struct entry *e, *parent;
+ unsigned int hashvalue, index;
+ int ret;
+
+ hashvalue = hash(h,k);
+ index = indexFor(h->tablelength,hashvalue);
+
+ e = h->table[index];
+ parent = NULL;
+ while (NULL != e)
+ {
+ /* Check hash value to short circuit heavier comparison */
+ if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
+ {
+ itr->index = index;
+ itr->e = e;
+ itr->parent = parent;
+ itr->h = h;
+ ret= -1;
+ goto egress;
+ }
+ parent = e;
+ e = e->next;
+ }
+ ret = 0;
+
+egress:
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&h->mutex);
+#endif
+ return ret;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/hashtable_itr.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/util/hashtable_itr.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2005, Intel Corp
+ * Copyright (c) 2002, Christopher Clark <firstname.lastname@xxxxxxxxxxxx>
+ * 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.
+*/
+
+
+#ifndef __HASHTABLE_ITR_CWC22__
+#define __HASHTABLE_ITR_CWC22__
+#include "hashtable.h"
+#include "hashtable_private.h" /* needed to enable inlining */
+
+/*****************************************************************************/
+/* This struct is only concrete here to allow the inlining of two of the
+ * accessor functions. */
+struct hashtable_itr
+{
+ struct hashtable *h;
+ struct entry *e;
+ struct entry *parent;
+ unsigned int index;
+};
+
+
+/*****************************************************************************/
+/* hashtable_iterator
+ */
+
+struct hashtable_itr *
+hashtable_iterator(struct hashtable *h);
+
+/*****************************************************************************/
+/* hashtable_iterator_key
+ * - return the value of the (key,value) pair at the current position */
+
+void *hashtable_iterator_key(struct hashtable_itr *i);
+
+/*****************************************************************************/
+/* value - return the value of the (key,value) pair at the current position */
+
+void *hashtable_iterator_value(struct hashtable_itr *i);
+
+/*****************************************************************************/
+/* advance - advance the iterator to the next element
+ * returns zero if advanced to end of table */
+
+int
+hashtable_iterator_advance(struct hashtable_itr *itr);
+
+/*****************************************************************************/
+/* remove - remove current element and advance the iterator to the next element
+ * NB: if you need the value to free it, read it before
+ * removing. ie: beware memory leaks!
+ * returns zero if advanced to end of table */
+
+int
+hashtable_iterator_remove(struct hashtable_itr *itr);
+
+/*****************************************************************************/
+/* search - overwrite the supplied iterator, to point to the entry
+ * matching the supplied key.
+ h points to the hashtable to be searched.
+ * returns zero if not found. */
+int
+hashtable_iterator_search(struct hashtable_itr *itr,
+ struct hashtable *h, void *k);
+
+#define DEFINE_HASHTABLE_ITERATOR_SEARCH(fnname, keytype) \
+int fnname (struct hashtable_itr *i, struct hashtable *h, keytype *k) \
+{ \
+ return (hashtable_iterator_search(i,h,k)); \
+}
+
+
+
+#endif /* __HASHTABLE_ITR_CWC22__*/
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/hashtable_private.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/util/hashtable_private.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2005, Intel Corp
+ * Copyright (c) 2002, Christopher Clark <firstname.lastname@xxxxxxxxxxxx>
+ * 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.
+*/
+
+#ifndef __HASHTABLE_PRIVATE_CWC22_H__
+#define __HASHTABLE_PRIVATE_CWC22_H__
+
+#include "hashtable.h"
+#ifdef HASHTABLE_THREADED
+#include <pthread.h>
+#endif
+
+/*****************************************************************************/
+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);
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_t mutex;
+#endif
+};
+
+/*****************************************************************************/
+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__*/
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/log.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/util/log.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,142 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "buffer.h"
+#include "tcg.h"
+
+// Helper code for the consts, eg. to produce messages for error codes.
+
+typedef struct error_code_entry_t {
+ TPM_RESULT code;
+ char * code_name;
+ char * msg;
+} error_code_entry_t;
+
+static const error_code_entry_t error_msgs [] = {
+ { TPM_SUCCESS, "TPM_SUCCESS", "Successful completion of the operation" },
+ { TPM_AUTHFAIL, "TPM_AUTHFAIL", "Authentication failed" },
+ { TPM_BADINDEX, "TPM_BADINDEX", "The index to a PCR, DIR or other register
is incorrect" },
+ { TPM_BAD_PARAMETER, "TPM_BAD_PARAMETER", "One or more parameter is bad" },
+ { TPM_AUDITFAILURE, "TPM_AUDITFAILURE", "An operation completed successfully
but the auditing of that operation failed." },
+ { TPM_CLEAR_DISABLED, "TPM_CLEAR_DISABLED", "The clear disable flag is set
and all clear operations now require physical access" },
+ { TPM_DEACTIVATED, "TPM_DEACTIVATED", "The TPM is deactivated" },
+ { TPM_DISABLED, "TPM_DISABLED", "The TPM is disabled" },
+ { TPM_DISABLED_CMD, "TPM_DISABLED_CMD", "The target command has been
disabled" },
+ { TPM_FAIL, "TPM_FAIL", "The operation failed" },
+ { TPM_BAD_ORDINAL, "TPM_BAD_ORDINAL", "The ordinal was unknown or
inconsistent" },
+ { TPM_INSTALL_DISABLED, "TPM_INSTALL_DISABLED", "The ability to install an
owner is disabled" },
+ { TPM_INVALID_KEYHANDLE, "TPM_INVALID_KEYHANDLE", "The key handle presented
was invalid" },
+ { TPM_KEYNOTFOUND, "TPM_KEYNOTFOUND", "The target key was not found" },
+ { TPM_INAPPROPRIATE_ENC, "TPM_INAPPROPRIATE_ENC", "Unacceptable encryption
scheme" },
+ { TPM_MIGRATEFAIL, "TPM_MIGRATEFAIL", "Migration authorization failed" },
+ { TPM_INVALID_PCR_INFO, "TPM_INVALID_PCR_INFO", "PCR information could not
be interpreted" },
+ { TPM_NOSPACE, "TPM_NOSPACE", "No room to load key." },
+ { TPM_NOSRK, "TPM_NOSRK", "There is no SRK set" },
+ { TPM_NOTSEALED_BLOB, "TPM_NOTSEALED_BLOB", "An encrypted blob is invalid or
was not created by this TPM" },
+ { TPM_OWNER_SET, "TPM_OWNER_SET", "There is already an Owner" },
+ { TPM_RESOURCES, "TPM_RESOURCES", "The TPM has insufficient internal
resources to perform the requested action." },
+ { TPM_SHORTRANDOM, "TPM_SHORTRANDOM", "A random string was too short" },
+ { TPM_SIZE, "TPM_SIZE", "The TPM does not have the space to perform the
operation." },
+ { TPM_WRONGPCRVAL, "TPM_WRONGPCRVAL", "The named PCR value does not match
the current PCR value." },
+ { TPM_BAD_PARAM_SIZE, "TPM_BAD_PARAM_SIZE", "The paramSize argument to the
command has the incorrect value" },
+ { TPM_SHA_THREAD, "TPM_SHA_THREAD", "There is no existing SHA-1 thread." },
+ { TPM_SHA_ERROR, "TPM_SHA_ERROR", "The calculation is unable to proceed
because the existing SHA-1 thread has already encountered an error." },
+ { TPM_FAILEDSELFTEST, "TPM_FAILEDSELFTEST", "Self-test has failed and the
TPM has shutdown." },
+ { TPM_AUTH2FAIL, "TPM_AUTH2FAIL", "The authorization for the second key in a
2 key function failed authorization" },
+ { TPM_BADTAG, "TPM_BADTAG", "The tag value sent to for a command is invalid"
},
+ { TPM_IOERROR, "TPM_IOERROR", "An IO error occurred transmitting information
to the TPM" },
+ { TPM_ENCRYPT_ERROR, "TPM_ENCRYPT_ERROR", "The encryption process had a
problem." },
+ { TPM_DECRYPT_ERROR, "TPM_DECRYPT_ERROR", "The decryption process did not
complete." },
+ { TPM_INVALID_AUTHHANDLE, "TPM_INVALID_AUTHHANDLE", "An invalid handle was
used." },
+ { TPM_NO_ENDORSEMENT, "TPM_NO_ENDORSEMENT", "The TPM does not a EK
installed" },
+ { TPM_INVALID_KEYUSAGE, "TPM_INVALID_KEYUSAGE", "The usage of a key is not
allowed" },
+ { TPM_WRONG_ENTITYTYPE, "TPM_WRONG_ENTITYTYPE", "The submitted entity type
is not allowed" },
+ { TPM_INVALID_POSTINIT, "TPM_INVALID_POSTINIT", "The command was received in
the wrong sequence relative to TPM_Init and a subsequent TPM_Startup" },
+ { TPM_INAPPROPRIATE_SIG, "TPM_INAPPROPRIATE_SIG", "Signed data cannot
include additional DER information" },
+ { TPM_BAD_KEY_PROPERTY, "TPM_BAD_KEY_PROPERTY", "The key properties in
TPM_KEY_PARMs are not supported by this TPM" },
+
+ { TPM_BAD_MIGRATION, "TPM_BAD_MIGRATION", "The migration properties of this
key are incorrect." },
+ { TPM_BAD_SCHEME, "TPM_BAD_SCHEME", "The signature or encryption scheme for
this key is incorrect or not permitted in this situation." },
+ { TPM_BAD_DATASIZE, "TPM_BAD_DATASIZE", "The size of the data (or blob)
parameter is bad or inconsistent with the referenced key" },
+ { TPM_BAD_MODE, "TPM_BAD_MODE", "A mode parameter is bad, such as capArea or
subCapArea for TPM_GetCapability, phsicalPresence parameter for
TPM_PhysicalPresence, or migrationType for TPM_CreateMigrationBlob." },
+ { TPM_BAD_PRESENCE, "TPM_BAD_PRESENCE", "Either the physicalPresence or
physicalPresenceLock bits have the wrong value" },
+ { TPM_BAD_VERSION, "TPM_BAD_VERSION", "The TPM cannot perform this version
of the capability" },
+ { TPM_NO_WRAP_TRANSPORT, "TPM_NO_WRAP_TRANSPORT", "The TPM does not allow
for wrapped transport sessions" },
+ { TPM_AUDITFAIL_UNSUCCESSFUL, "TPM_AUDITFAIL_UNSUCCESSFUL", "TPM audit
construction failed and the underlying command was returning a failure code
also" },
+ { TPM_AUDITFAIL_SUCCESSFUL, "TPM_AUDITFAIL_SUCCESSFUL", "TPM audit
construction failed and the underlying command was returning success" },
+ { TPM_NOTRESETABLE, "TPM_NOTRESETABLE", "Attempt to reset a PCR register
that does not have the resettable attribute" },
+ { TPM_NOTLOCAL, "TPM_NOTLOCAL", "Attempt to reset a PCR register that
requires locality and locality modifier not part of command transport" },
+ { TPM_BAD_TYPE, "TPM_BAD_TYPE", "Make identity blob not properly typed" },
+ { TPM_INVALID_RESOURCE, "TPM_INVALID_RESOURCE", "When saving context
identified resource type does not match actual resource" },
+ { TPM_NOTFIPS, "TPM_NOTFIPS", "The TPM is attempting to execute a command
only available when in FIPS mode" },
+ { TPM_INVALID_FAMILY, "TPM_INVALID_FAMILY", "The command is attempting to
use an invalid family ID" },
+ { TPM_NO_NV_PERMISSION, "TPM_NO_NV_PERMISSION", "The permission to
manipulate the NV storage is not available" },
+ { TPM_REQUIRES_SIGN, "TPM_REQUIRES_SIGN", "The operation requires a signed
command" },
+ { TPM_KEY_NOTSUPPORTED, "TPM_KEY_NOTSUPPORTED", "Wrong operation to load an
NV key" },
+ { TPM_AUTH_CONFLICT, "TPM_AUTH_CONFLICT", "NV_LoadKey blob requires both
owner and blob authorization" },
+ { TPM_AREA_LOCKED, "TPM_AREA_LOCKED", "The NV area is locked and not
writtable" },
+ { TPM_BAD_LOCALITY, "TPM_BAD_LOCALITY", "The locality is incorrect for the
attempted operation" },
+ { TPM_READ_ONLY, "TPM_READ_ONLY", "The NV area is read only and can't be
written to" },
+ { TPM_PER_NOWRITE, "TPM_PER_NOWRITE", "There is no protection on the write
to the NV area" },
+ { TPM_FAMILYCOUNT, "TPM_FAMILYCOUNT", "The family count value does not
match" },
+ { TPM_WRITE_LOCKED, "TPM_WRITE_LOCKED", "The NV area has already been
written to" },
+ { TPM_BAD_ATTRIBUTES, "TPM_BAD_ATTRIBUTES", "The NV area attributes
conflict" },
+ { TPM_INVALID_STRUCTURE, "TPM_INVALID_STRUCTURE", "The structure tag and
version are invalid or inconsistent" },
+ { TPM_KEY_OWNER_CONTROL, "TPM_KEY_OWNER_CONTROL", "The key is under control
of the TPM Owner and can only be evicted by the TPM Owner." },
+ { TPM_BAD_COUNTER, "TPM_BAD_COUNTER", "The counter handle is incorrect" },
+ { TPM_NOT_FULLWRITE, "TPM_NOT_FULLWRITE", "The write is not a complete write
of the area" },
+ { TPM_CONTEXT_GAP, "TPM_CONTEXT_GAP", "The gap between saved context counts
is too large" },
+ { TPM_MAXNVWRITES, "TPM_MAXNVWRITES", "The maximum number of NV writes
without an owner has been exceeded" },
+ { TPM_NOOPERATOR, "TPM_NOOPERATOR", "No operator authorization value is set"
},
+ { TPM_RESOURCEMISSING, "TPM_RESOURCEMISSING", "The resource pointed to by
context is not loaded" },
+ { TPM_DELEGATE_LOCK, "TPM_DELEGATE_LOCK", "The delegate administration is
locked" },
+ { TPM_DELEGATE_FAMILY, "TPM_DELEGATE_FAMILY", "Attempt to manage a family
other then the delegated family" },
+ { TPM_DELEGATE_ADMIN, "TPM_DELEGATE_ADMIN", "Delegation table management not
enabled" },
+ { TPM_TRANSPORT_EXCLUSIVE, "TPM_TRANSPORT_EXCLUSIVE", "There was a command
executed outside of an exclusive transport session" },
+};
+
+
+// helper function for the error codes:
+const char* tpm_get_error_name (TPM_RESULT code) {
+ // just do a linear scan for now
+ unsigned i;
+ for (i = 0; i < sizeof(error_msgs)/sizeof(error_msgs[0]); i++)
+ if (code == error_msgs[i].code)
+ return error_msgs[i].code_name;
+
+ return "Failed to find code name for given code";
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/log.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/util/log.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,92 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+
+#ifndef __VTPM_LOG_H__
+#define __VTPM_LOG_H__
+
+#include <stdint.h> // for uint32_t
+#include <stddef.h> // for pointer NULL
+
+// =========================== LOGGING ==============================
+
+// the logging module numbers
+#define VTPM_LOG_CRYPTO 1
+#define VTPM_LOG_BSG 2
+#define VTPM_LOG_TXDATA 3
+#define VTPM_LOG_TCS 4
+#define VTPM_LOG_TCS_DEEP 5
+#define VTPM_LOG_VTSP 6
+#define VTPM_LOG_VTPM 7
+#define VTPM_LOG_VTPM_DEEP 8
+
+static char *module_names[] = { "",
+ "CRYPTO",
+ "BSG",
+ "TXDATA",
+ "TCS",
+ "TCS",
+ "VTSP",
+ "VTPM",
+ "VTPM"
+ };
+
+// Default to standard logging
+#ifndef LOGGING_MODULES
+#define LOGGING_MODULES (BITMASK(VTPM_LOG_VTPM))
+#endif
+
+// bit-access macros
+#define BITMASK(idx) ( 1U << (idx) )
+#define GETBIT(num,idx) ( ((num) & BITMASK(idx)) >> idx )
+#define SETBIT(num,idx) (num) |= BITMASK(idx)
+#define CLEARBIT(num,idx) (num) &= ( ~ BITMASK(idx) )
+
+#define vtpmloginfo(module, fmt, args...) \
+ if (GETBIT (LOGGING_MODULES, module) == 1) { \
+ fprintf (stdout, "INFO[%s]: " fmt, module_names[module], ##args); \
+ }
+
+#define vtpmloginfomore(module, fmt, args...) \
+ if (GETBIT (LOGGING_MODULES, module) == 1) { \
+ fprintf (stdout, fmt,##args); \
+ }
+
+#define vtpmlogerror(module, fmt, args...) \
+ fprintf (stderr, "ERROR[%s]: " fmt, module_names[module], ##args);
+
+//typedef UINT32 tpm_size_t;
+
+// helper function for the error codes:
+const char* tpm_get_error_name (TPM_RESULT code);
+
+#endif // _VTPM_LOG_H_
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/vtpm_manager/util/tcg.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/vtpm_manager/util/tcg.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,486 @@
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// 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 Intel Corporation nor the names of its
+// 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.
+// ===================================================================
+//
+// tcg.h
+//
+// This file contains all the structure and type definitions
+//
+// ==================================================================
+
+#ifndef __TCG_H__
+#define __TCG_H__
+
+// This pragma is used to disallow structure padding
+#pragma pack(push, 1)
+
+// *************************** TYPEDEFS *********************************
+typedef unsigned char BYTE;
+typedef unsigned char BOOL;
+typedef unsigned short UINT16;
+typedef unsigned int UINT32;
+typedef unsigned long long UINT64;
+
+typedef UINT32 TPM_RESULT;
+typedef UINT32 TPM_PCRINDEX;
+typedef UINT32 TPM_DIRINDEX;
+typedef UINT32 TPM_HANDLE;
+typedef TPM_HANDLE TPM_AUTHHANDLE;
+typedef TPM_HANDLE TCPA_HASHHANDLE;
+typedef TPM_HANDLE TCPA_HMACHANDLE;
+typedef TPM_HANDLE TCPA_ENCHANDLE;
+typedef TPM_HANDLE TPM_KEY_HANDLE;
+typedef TPM_HANDLE TCPA_ENTITYHANDLE;
+typedef UINT32 TPM_RESOURCE_TYPE;
+typedef UINT32 TPM_COMMAND_CODE;
+typedef UINT16 TPM_PROTOCOL_ID;
+typedef BYTE TPM_AUTH_DATA_USAGE;
+typedef UINT16 TPM_ENTITY_TYPE;
+typedef UINT32 TPM_ALGORITHM_ID;
+typedef UINT16 TPM_KEY_USAGE;
+typedef UINT16 TPM_STARTUP_TYPE;
+typedef UINT32 TPM_CAPABILITY_AREA;
+typedef UINT16 TPM_ENC_SCHEME;
+typedef UINT16 TPM_SIG_SCHEME;
+typedef UINT16 TPM_MIGRATE_SCHEME;
+typedef UINT16 TPM_PHYSICAL_PRESENCE;
+typedef UINT32 TPM_KEY_FLAGS;
+
+#define TPM_DIGEST_SIZE 20 // Don't change this
+typedef BYTE TPM_AUTHDATA[TPM_DIGEST_SIZE];
+typedef TPM_AUTHDATA TPM_SECRET;
+typedef TPM_AUTHDATA TPM_ENCAUTH;
+typedef BYTE TPM_PAYLOAD_TYPE;
+typedef UINT16 TPM_TAG;
+
+// Data Types of the TCS
+typedef UINT32 TCS_AUTHHANDLE; // Handle addressing a authorization session
+typedef UINT32 TCS_CONTEXT_HANDLE; // Basic context handle
+typedef UINT32 TCS_KEY_HANDLE; // Basic key handle
+
+// ************************* STRUCTURES **********************************
+
+typedef struct TPM_VERSION {
+ BYTE major;
+ BYTE minor;
+ BYTE revMajor;
+ BYTE revMinor;
+} TPM_VERSION;
+
+static const TPM_VERSION TPM_STRUCT_VER_1_1 = { 1,1,0,0 };
+
+typedef struct TPM_DIGEST {
+ BYTE digest[TPM_DIGEST_SIZE];
+} TPM_DIGEST;
+
+typedef TPM_DIGEST TPM_PCRVALUE;
+typedef TPM_DIGEST TPM_COMPOSITE_HASH;
+typedef TPM_DIGEST TPM_DIRVALUE;
+typedef TPM_DIGEST TPM_HMAC;
+typedef TPM_DIGEST TPM_CHOSENID_HASH;
+
+typedef struct TPM_NONCE {
+ BYTE nonce[TPM_DIGEST_SIZE];
+} TPM_NONCE;
+
+typedef struct TPM_KEY_PARMS {
+ TPM_ALGORITHM_ID algorithmID;
+ TPM_ENC_SCHEME encScheme;
+ TPM_SIG_SCHEME sigScheme;
+ UINT32 parmSize;
+ BYTE* parms;
+} TPM_KEY_PARMS;
+
+typedef struct TPM_RSA_KEY_PARMS {
+ UINT32 keyLength;
+ UINT32 numPrimes;
+ UINT32 exponentSize;
+ BYTE* exponent;
+} TPM_RSA_KEY_PARMS;
+
+typedef struct TPM_STORE_PUBKEY {
+ UINT32 keyLength;
+ BYTE* key;
+} TPM_STORE_PUBKEY;
+
+typedef struct TPM_PUBKEY {
+ TPM_KEY_PARMS algorithmParms;
+ TPM_STORE_PUBKEY pubKey;
+} TPM_PUBKEY;
+
+typedef struct TPM_KEY {
+ TPM_VERSION ver;
+ TPM_KEY_USAGE keyUsage;
+ TPM_KEY_FLAGS keyFlags;
+ TPM_AUTH_DATA_USAGE authDataUsage;
+ TPM_KEY_PARMS algorithmParms;
+ UINT32 PCRInfoSize;
+ BYTE* PCRInfo; // this should be a TPM_PCR_INFO, or NULL
+ TPM_STORE_PUBKEY pubKey;
+ UINT32 encDataSize;
+ BYTE* encData;
+} TPM_KEY;
+
+typedef struct TPM_PCR_SELECTION {
+ UINT16 sizeOfSelect; /// in bytes
+ BYTE* pcrSelect;
+} TPM_PCR_SELECTION;
+
+typedef struct TPM_PCR_COMPOSITE {
+ TPM_PCR_SELECTION select;
+ UINT32 valueSize;
+ TPM_PCRVALUE* pcrValue;
+} TPM_PCR_COMPOSITE;
+
+
+typedef struct TPM_PCR_INFO {
+ TPM_PCR_SELECTION pcrSelection;
+ TPM_COMPOSITE_HASH digestAtRelease;
+ TPM_COMPOSITE_HASH digestAtCreation;
+} TPM_PCR_INFO;
+
+
+typedef struct TPM_BOUND_DATA {
+ TPM_VERSION ver;
+ TPM_PAYLOAD_TYPE payload;
+ BYTE* payloadData;
+} TPM_BOUND_DATA;
+
+typedef struct TPM_STORED_DATA {
+ TPM_VERSION ver;
+ UINT32 sealInfoSize;
+ BYTE* sealInfo;
+ UINT32 encDataSize;
+ BYTE* encData;
+} TPM_STORED_DATA;
+
+typedef struct TCS_AUTH {
+ TCS_AUTHHANDLE AuthHandle;
+ TPM_NONCE NonceOdd; // system
+ TPM_NONCE NonceEven; // TPM
+ BOOL fContinueAuthSession;
+ TPM_AUTHDATA HMAC;
+} TCS_AUTH;
+
+// **************************** CONSTANTS *********************************
+
+// BOOL values
+#define TRUE 0x01
+#define FALSE 0x00
+
+#define TCPA_MAX_BUFFER_LENGTH 0x2000
+
+//
+// TPM_COMMAND_CODE values
+#define TPM_PROTECTED_ORDINAL 0x00000000UL
+#define TPM_UNPROTECTED_ORDINAL 0x80000000UL
+#define TPM_CONNECTION_ORDINAL 0x40000000UL
+#define TPM_VENDOR_ORDINAL 0x20000000UL
+
+#define TPM_ORD_OIAP (10UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_OSAP (11UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ChangeAuth (12UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_TakeOwnership (13UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ChangeAuthAsymStart (14UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ChangeAuthAsymFinish (15UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ChangeAuthOwner (16UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Extend (20UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_PcrRead (21UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Quote (22UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Seal (23UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Unseal (24UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_DirWriteAuth (25UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_DirRead (26UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_UnBind (30UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_CreateWrapKey (31UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_LoadKey (32UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetPubKey (33UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_EvictKey (34UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_CreateMigrationBlob (40UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ReWrapKey (41UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ConvertMigrationBlob (42UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_AuthorizeMigrationKey (43UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_CreateMaintenanceArchive (44UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_LoadMaintenanceArchive (45UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_KillMaintenanceFeature (46UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_LoadManuMaintPub (47UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ReadManuMaintPub (48UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_CertifyKey (50UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Sign (60UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetRandom (70UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_StirRandom (71UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SelfTestFull (80UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SelfTestStartup (81UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_CertifySelfTest (82UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ContinueSelfTest (83UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetTestResult (84UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Reset (90UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_OwnerClear (91UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_DisableOwnerClear (92UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ForceClear (93UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_DisableForceClear (94UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetCapabilitySigned (100UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetCapability (101UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetCapabilityOwner (102UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_OwnerSetDisable (110UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_PhysicalEnable (111UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_PhysicalDisable (112UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SetOwnerInstall (113UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_PhysicalSetDeactivated (114UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SetTempDeactivated (115UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_CreateEndorsementKeyPair (120UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_MakeIdentity (121UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ActivateIdentity (122UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ReadPubek (124UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_OwnerReadPubek (125UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_DisablePubekRead (126UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetAuditEvent (130UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetAuditEventSigned (131UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetOrdinalAuditStatus (140UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SetOrdinalAuditStatus (141UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Terminate_Handle (150UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Init (151UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SaveState (152UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Startup (153UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SetRedirection (154UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SHA1Start (160UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SHA1Update (161UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SHA1Complete (162UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SHA1CompleteExtend (163UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_FieldUpgrade (170UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SaveKeyContext (180UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_LoadKeyContext (181UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SaveAuthContext (182UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_LoadAuthContext (183UL + TPM_PROTECTED_ORDINAL)
+#define TSC_ORD_PhysicalPresence (10UL + TPM_CONNECTION_ORDINAL)
+
+
+
+//
+// TPM_RESULT values
+//
+// just put in the whole table from spec 1.2
+
+#define TPM_BASE 0x0 // The start of TPM return codes
+#define TPM_VENDOR_ERROR 0x00000400 // Mask to indicate that the error code is
vendor specific for vendor specific commands
+#define TPM_NON_FATAL 0x00000800 // Mask to indicate that the error code is a
non-fatal failure.
+
+#define TPM_SUCCESS TPM_BASE // Successful completion of the operation
+#define TPM_AUTHFAIL TPM_BASE + 1 // Authentication failed
+#define TPM_BADINDEX TPM_BASE + 2 // The index to a PCR, DIR or other
register is incorrect
+#define TPM_BAD_PARAMETER TPM_BASE + 3 // One or more parameter is bad
+#define TPM_AUDITFAILURE TPM_BASE + 4 // An operation completed
successfully but the auditing of that operation failed.
+#define TPM_CLEAR_DISABLED TPM_BASE + 5 // The clear disable flag is set
and all clear operations now require physical access
+#define TPM_DEACTIVATED TPM_BASE + 6 // The TPM is deactivated
+#define TPM_DISABLED TPM_BASE + 7 // The TPM is disabled
+#define TPM_DISABLED_CMD TPM_BASE + 8 // The target command has been
disabled
+#define TPM_FAIL TPM_BASE + 9 // The operation failed
+#define TPM_BAD_ORDINAL TPM_BASE + 10 // The ordinal was unknown or
inconsistent
+#define TPM_INSTALL_DISABLED TPM_BASE + 11 // The ability to install an
owner is disabled
+#define TPM_INVALID_KEYHANDLE TPM_BASE + 12 // The key handle presented was
invalid
+#define TPM_KEYNOTFOUND TPM_BASE + 13 // The target key was not found
+#define TPM_INAPPROPRIATE_ENC TPM_BASE + 14 // Unacceptable encryption scheme
+#define TPM_MIGRATEFAIL TPM_BASE + 15 // Migration authorization failed
+#define TPM_INVALID_PCR_INFO TPM_BASE + 16 // PCR information could not be
interpreted
+#define TPM_NOSPACE TPM_BASE + 17 // No room to load key.
+#define TPM_NOSRK TPM_BASE + 18 // There is no SRK set
+#define TPM_NOTSEALED_BLOB TPM_BASE + 19 // An encrypted blob is invalid
or was not created by this TPM
+#define TPM_OWNER_SET TPM_BASE + 20 // There is already an Owner
+#define TPM_RESOURCES TPM_BASE + 21 // The TPM has insufficient internal
resources to perform the requested action.
+#define TPM_SHORTRANDOM TPM_BASE + 22 // A random string was too short
+#define TPM_SIZE TPM_BASE + 23 // The TPM does not have the space to
perform the operation.
+#define TPM_WRONGPCRVAL TPM_BASE + 24 // The named PCR value does not
match the current PCR value.
+#define TPM_BAD_PARAM_SIZE TPM_BASE + 25 // The paramSize argument to the
command has the incorrect value
+#define TPM_SHA_THREAD TPM_BASE + 26 // There is no existing SHA-1 thread.
+#define TPM_SHA_ERROR TPM_BASE + 27 // The calculation is unable to
proceed because the existing SHA-1 thread has already encountered an error.
+#define TPM_FAILEDSELFTEST TPM_BASE + 28 // Self-test has failed and the
TPM has shutdown.
+#define TPM_AUTH2FAIL TPM_BASE + 29 // The authorization for the second
key in a 2 key function failed authorization
+#define TPM_BADTAG TPM_BASE + 30 // The tag value sent to for a command
is invalid
+#define TPM_IOERROR TPM_BASE + 31 // An IO error occurred transmitting
information to the TPM
+#define TPM_ENCRYPT_ERROR TPM_BASE + 32 // The encryption process had a
problem.
+#define TPM_DECRYPT_ERROR TPM_BASE + 33 // The decryption process did not
complete.
+#define TPM_INVALID_AUTHHANDLE TPM_BASE + 34 // An invalid handle was used.
+#define TPM_NO_ENDORSEMENT TPM_BASE + 35 // The TPM does not a EK installed
+#define TPM_INVALID_KEYUSAGE TPM_BASE + 36 // The usage of a key is not
allowed
+#define TPM_WRONG_ENTITYTYPE TPM_BASE + 37 // The submitted entity type is
not allowed
+#define TPM_INVALID_POSTINIT TPM_BASE + 38 // The command was received in
the wrong sequence relative to TPM_Init and a subsequent TPM_Startup
+#define TPM_INAPPROPRIATE_SIG TPM_BASE + 39 // Signed data cannot include
additional DER information
+#define TPM_BAD_KEY_PROPERTY TPM_BASE + 40 // The key properties in
TPM_KEY_PARMs are not supported by this TPM
+
+#define TPM_BAD_MIGRATION TPM_BASE + 41 // The migration properties of
this key are incorrect.
+#define TPM_BAD_SCHEME TPM_BASE + 42 // The signature or encryption
scheme for this key is incorrect or not permitted in this situation.
+#define TPM_BAD_DATASIZE TPM_BASE + 43 // The size of the data (or blob)
parameter is bad or inconsistent with the referenced key
+#define TPM_BAD_MODE TPM_BASE + 44 // A mode parameter is bad, such as
capArea or subCapArea for TPM_GetCapability, phsicalPresence parameter for
TPM_PhysicalPresence, or migrationType for TPM_CreateMigrationBlob.
+#define TPM_BAD_PRESENCE TPM_BASE + 45 // Either the physicalPresence or
physicalPresenceLock bits have the wrong value
+#define TPM_BAD_VERSION TPM_BASE + 46 // The TPM cannot perform this
version of the capability
+#define TPM_NO_WRAP_TRANSPORT TPM_BASE + 47 // The TPM does not allow for
wrapped transport sessions
+#define TPM_AUDITFAIL_UNSUCCESSFUL TPM_BASE + 48 // TPM audit construction
failed and the underlying command was returning a failure code also
+#define TPM_AUDITFAIL_SUCCESSFUL TPM_BASE + 49 // TPM audit construction
failed and the underlying command was returning success
+#define TPM_NOTRESETABLE TPM_BASE + 50 // Attempt to reset a PCR register
that does not have the resettable attribute
+#define TPM_NOTLOCAL TPM_BASE + 51 // Attempt to reset a PCR register
that requires locality and locality modifier not part of command transport
+#define TPM_BAD_TYPE TPM_BASE + 52 // Make identity blob not properly
typed
+#define TPM_INVALID_RESOURCE TPM_BASE + 53 // When saving context
identified resource type does not match actual resource
+#define TPM_NOTFIPS TPM_BASE + 54 // The TPM is attempting to execute a
command only available when in FIPS mode
+#define TPM_INVALID_FAMILY TPM_BASE + 55 // The command is attempting to
use an invalid family ID
+#define TPM_NO_NV_PERMISSION TPM_BASE + 56 // The permission to manipulate
the NV storage is not available
+#define TPM_REQUIRES_SIGN TPM_BASE + 57 // The operation requires a
signed command
+#define TPM_KEY_NOTSUPPORTED TPM_BASE + 58 // Wrong operation to load an
NV key
+#define TPM_AUTH_CONFLICT TPM_BASE + 59 // NV_LoadKey blob requires both
owner and blob authorization
+#define TPM_AREA_LOCKED TPM_BASE + 60 // The NV area is locked and not
writtable
+#define TPM_BAD_LOCALITY TPM_BASE + 61 // The locality is incorrect for
the attempted operation
+#define TPM_READ_ONLY TPM_BASE + 62 // The NV area is read only and
can't be written to
+#define TPM_PER_NOWRITE TPM_BASE + 63 // There is no protection on the
write to the NV area
+#define TPM_FAMILYCOUNT TPM_BASE + 64 // The family count value does not
match
+#define TPM_WRITE_LOCKED TPM_BASE + 65 // The NV area has already been
written to
+#define TPM_BAD_ATTRIBUTES TPM_BASE + 66 // The NV area attributes
conflict
+#define TPM_INVALID_STRUCTURE TPM_BASE + 67 // The structure tag and
version are invalid or inconsistent
+#define TPM_KEY_OWNER_CONTROL TPM_BASE + 68 // The key is under control of
the TPM Owner and can only be evicted by the TPM Owner.
+#define TPM_BAD_COUNTER TPM_BASE + 69 // The counter handle is incorrect
+#define TPM_NOT_FULLWRITE TPM_BASE + 70 // The write is not a complete
write of the area
+#define TPM_CONTEXT_GAP TPM_BASE + 71 // The gap between saved context
counts is too large
+#define TPM_MAXNVWRITES TPM_BASE + 72 // The maximum number of NV writes
without an owner has been exceeded
+#define TPM_NOOPERATOR TPM_BASE + 73 // No operator authorization value
is set
+#define TPM_RESOURCEMISSING TPM_BASE + 74 // The resource pointed to by
context is not loaded
+#define TPM_DELEGATE_LOCK TPM_BASE + 75 // The delegate administration is
locked
+#define TPM_DELEGATE_FAMILY TPM_BASE + 76 // Attempt to manage a family
other then the delegated family
+#define TPM_DELEGATE_ADMIN TPM_BASE + 77 // Delegation table management
not enabled
+#define TPM_TRANSPORT_EXCLUSIVE TPM_BASE + 78 // There was a command
executed outside of an exclusive transport session
+
+// TPM_TAG values
+#define TPM_TAG_RQU_COMMAND 0x00c1
+#define TPM_TAG_RQU_AUTH1_COMMAND 0x00c2
+#define TPM_TAG_RQU_AUTH2_COMMAND 0x00c3
+#define TPM_TAG_RSP_COMMAND 0x00c4
+#define TPM_TAG_RSP_AUTH1_COMMAND 0x00c5
+#define TPM_TAG_RSP_AUTH2_COMMAND 0x00c6
+
+// TPM_PAYLOAD_TYPE values
+#define TPM_PT_ASYM 0x01
+#define TPM_PT_BIND 0x02
+#define TPM_PT_MIGRATE 0x03
+#define TPM_PT_MAINT 0x04
+#define TPM_PT_SEAL 0x05
+
+// TPM_ENTITY_TYPE values
+#define TPM_ET_KEYHANDLE 0x0001
+#define TPM_ET_OWNER 0x0002
+#define TPM_ET_DATA 0x0003
+#define TPM_ET_SRK 0x0004
+#define TPM_ET_KEY 0x0005
+
+/// TPM_ResourceTypes
+#define TPM_RT_KEY 0x00000001
+#define TPM_RT_AUTH 0x00000002
+#define TPM_RT_TRANS 0x00000004
+#define TPM_RT_CONTEXT 0x00000005
+
+// TPM_PROTOCOL_ID values
+#define TPM_PID_OIAP 0x0001
+#define TPM_PID_OSAP 0x0002
+#define TPM_PID_ADIP 0x0003
+#define TPM_PID_ADCP 0x0004
+#define TPM_PID_OWNER 0x0005
+
+// TPM_ALGORITHM_ID values
+#define TPM_ALG_RSA 0x00000001
+#define TPM_ALG_DES 0x00000002
+#define TPM_ALG_3DES 0X00000003
+#define TPM_ALG_SHA 0x00000004
+#define TPM_ALG_HMAC 0x00000005
+#define TCPA_ALG_AES 0x00000006
+
+// TPM_ENC_SCHEME values
+#define TPM_ES_NONE 0x0001
+#define TPM_ES_RSAESPKCSv15 0x0002
+#define TPM_ES_RSAESOAEP_SHA1_MGF1 0x0003
+
+// TPM_SIG_SCHEME values
+#define TPM_SS_NONE 0x0001
+#define TPM_SS_RSASSAPKCS1v15_SHA1 0x0002
+#define TPM_SS_RSASSAPKCS1v15_DER 0x0003
+
+// TPM_KEY_USAGE values
+#define TPM_KEY_EK 0x0000
+#define TPM_KEY_SIGNING 0x0010
+#define TPM_KEY_STORAGE 0x0011
+#define TPM_KEY_IDENTITY 0x0012
+#define TPM_KEY_AUTHCHANGE 0X0013
+#define TPM_KEY_BIND 0x0014
+#define TPM_KEY_LEGACY 0x0015
+
+// TPM_AUTH_DATA_USAGE values
+#define TPM_AUTH_NEVER 0x00
+#define TPM_AUTH_ALWAYS 0x01
+
+// Key Handle of owner and srk
+#define TPM_OWNER_KEYHANDLE 0x40000001
+#define TPM_SRK_KEYHANDLE 0x40000000
+
+// ---------------------- Functions for checking TPM_RESULTs -----------------
+
+// FIXME: Review use of these and delete unneeded ones.
+
+// these are really badly dependent on local structure:
+// DEPENDS: local var 'status' of type TPM_RESULT
+// DEPENDS: label 'abort_egress' which cleans up and returns the status
+#define ERRORDIE(s) do { status = s; \
+ fprintf (stderr, "*** ERRORDIE in %s, line %i\n",
__func__, __LINE__); \
+ goto abort_egress; } \
+ while (0)
+
+// ASSUME: the return value used after the abort_egress label has been set
+// already (eg. the 'status' local var)
+#define STATUSCHECK(s) if (s != TPM_SUCCESS) { \
+ fprintf (stderr, "*** ERR in %s, line %i\n",
__func__, __LINE__); \
+ goto abort_egress; \
+ }
+
+// DEPENDS: local var 'status' of type TPM_RESULT
+// DEPENDS: label 'abort_egress' which cleans up and returns the status
+// Try command c. If it fails, set status to s and goto shame.
+#define TPMTRY(s,c) if (c != TPM_SUCCESS) { \
+ status = s; \
+ goto abort_egress; \
+ }
+
+// Try command c. If it fails, print error message, set status to actual
return code. Goto shame
+#define TPMTRYRETURN(c) do { status = c; \
+ if (status != TPM_SUCCESS) { \
+ printf("ERROR in %s:%i code: %s.\n", __func__,
__LINE__, tpm_get_error_name(status)); \
+ goto abort_egress; \
+ } \
+ } while(0)
+
+
+#pragma pack(pop)
+
+#endif //__TCPA_H__
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xenstore/xenstore_client.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/tools/xenstore/xenstore_client.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,130 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of
+ * this archive for more details.
+ *
+ * Copyright (C) 2005 by Christian Limpach
+ *
+ */
+
+#include <err.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <xs.h>
+
+static void
+usage(const char *progname)
+{
+#if defined(CLIENT_read)
+ errx(1, "Usage: %s [-h] [-p] key [...]", progname);
+#elif defined(CLIENT_write)
+ errx(1, "Usage: %s [-h] key value [...]", progname);
+#elif defined(CLIENT_rm)
+ errx(1, "Usage: %s [-h] key [...]", progname);
+#endif
+}
+
+int
+main(int argc, char **argv)
+{
+ struct xs_handle *xsh;
+ bool success;
+ int ret = 0;
+#if defined(CLIENT_read)
+ char *val;
+ int prefix = 0;
+#endif
+
+ xsh = xs_domain_open();
+ if (xsh == NULL)
+ err(1, "xs_domain_open");
+
+ while (1) {
+ int c, index = 0;
+ static struct option long_options[] = {
+ {"help", 0, 0, 'h'},
+#if defined(CLIENT_read)
+ {"prefix", 0, 0, 'p'},
+#endif
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long(argc, argv, "h"
+#if defined(CLIENT_read)
+ "p"
+#endif
+ , long_options, &index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ usage(argv[0]);
+ /* NOTREACHED */
+#if defined(CLIENT_read)
+ case 'p':
+ prefix = 1;
+ break;
+#endif
+ }
+ }
+
+ if (optind == argc) {
+ usage(argv[0]);
+ /* NOTREACHED */
+ }
+#if defined(CLIENT_write)
+ if ((argc - optind) % 1) {
+ usage(argv[0]);
+ /* NOTREACHED */
+ }
+#endif
+
+ /* XXX maybe find longest common prefix */
+ success = xs_transaction_start(xsh, "/");
+ if (!success)
+ errx(1, "couldn't start transaction");
+
+ while (optind < argc) {
+#if defined(CLIENT_read)
+ val = xs_read(xsh, argv[optind], NULL);
+ if (val == NULL) {
+ warnx("couldn't read path %s", argv[optind]);
+ ret = 1;
+ goto out;
+ }
+ if (prefix)
+ printf("%s: ", argv[optind]);
+ printf("%s\n", val);
+ free(val);
+ optind++;
+#elif defined(CLIENT_write)
+ success = xs_write(xsh, argv[optind], argv[optind + 1],
+ strlen(argv[optind + 1]), O_CREAT);
+ if (!success) {
+ warnx("could not write path %s", argv[optind]);
+ ret = 1;
+ goto out;
+ }
+ optind += 2;
+#elif defined(CLIENT_rm)
+ success = xs_rm(xsh, argv[optind]);
+ if (!success) {
+ warnx("could not remove path %s", argv[optind]);
+ ret = 1;
+ goto out;
+ }
+ optind++;
+#endif
+ }
+
+ out:
+ success = xs_transaction_end(xsh, ret ? true : false);
+ if (!success)
+ errx(1, "couldn't end transaction");
+
+ return ret;
+}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/arch/x86/shadow_guest32.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/xen/arch/x86/shadow_guest32.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,18 @@
+#define GUEST_PGENTRY_32
+#if defined (__x86_64__)
+
+#include "shadow.c"
+struct shadow_ops MODE_D_HANDLER = {
+ .guest_paging_levels = 2,
+ .invlpg = shadow_invlpg_64,
+ .fault = shadow_fault_64,
+ .update_pagetables = shadow_update_pagetables,
+ .sync_all = sync_all,
+ .remove_all_write_access = remove_all_write_access,
+ .do_update_va_mapping = do_update_va_mapping,
+ .mark_mfn_out_of_sync = mark_mfn_out_of_sync,
+ .is_out_of_sync = is_out_of_sync,
+ .gva_to_gpa = gva_to_gpa_64,
+};
+
+#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/common/memory.c
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/xen/common/memory.c Fri Sep 9 16:30:54 2005
@@ -0,0 +1,214 @@
+/******************************************************************************
+ * memory.c
+ *
+ * Code to handle memory-related requests.
+ *
+ * Copyright (c) 2003-2004, B Dragovic
+ * Copyright (c) 2003-2005, K A Fraser
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/lib.h>
+#include <xen/mm.h>
+#include <xen/perfc.h>
+#include <xen/sched.h>
+#include <xen/event.h>
+#include <xen/shadow.h>
+#include <asm/current.h>
+#include <asm/hardirq.h>
+#include <public/memory.h>
+
+static long
+increase_reservation(
+ struct domain *d,
+ unsigned long *extent_list,
+ unsigned int nr_extents,
+ unsigned int extent_order,
+ unsigned int flags,
+ int *preempted)
+{
+ struct pfn_info *page;
+ unsigned long i;
+
+ if ( (extent_list != NULL) &&
+ !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
+ return 0;
+
+ if ( (extent_order != 0) && !IS_CAPABLE_PHYSDEV(current->domain) )
+ {
+ DPRINTK("Only I/O-capable domains may allocate > order-0 memory.\n");
+ return 0;
+ }
+
+ for ( i = 0; i < nr_extents; i++ )
+ {
+ if ( hypercall_preempt_check() )
+ {
+ *preempted = 1;
+ return i;
+ }
+
+ if ( unlikely((page = alloc_domheap_pages(
+ d, extent_order, flags)) == NULL) )
+ {
+ DPRINTK("Could not allocate order=%d extent: id=%d flags=%x\n",
+ extent_order, d->domain_id, flags);
+ return i;
+ }
+
+ /* Inform the domain of the new page's machine address. */
+ if ( (extent_list != NULL) &&
+ (__put_user(page_to_pfn(page), &extent_list[i]) != 0) )
+ return i;
+ }
+
+ return nr_extents;
+}
+
+static long
+decrease_reservation(
+ struct domain *d,
+ unsigned long *extent_list,
+ unsigned int nr_extents,
+ unsigned int extent_order,
+ unsigned int flags,
+ int *preempted)
+{
+ struct pfn_info *page;
+ unsigned long i, j, mpfn;
+
+ if ( !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
+ return 0;
+
+ for ( i = 0; i < nr_extents; i++ )
+ {
+ if ( hypercall_preempt_check() )
+ {
+ *preempted = 1;
+ return i;
+ }
+
+ if ( unlikely(__get_user(mpfn, &extent_list[i]) != 0) )
+ return i;
+
+ for ( j = 0; j < (1 << extent_order); j++ )
+ {
+ if ( unlikely((mpfn + j) >= max_page) )
+ {
+ DPRINTK("Domain %u page number out of range (%lx >= %lx)\n",
+ d->domain_id, mpfn + j, max_page);
+ return i;
+ }
+
+ page = &frame_table[mpfn + j];
+ if ( unlikely(!get_page(page, d)) )
+ {
+ DPRINTK("Bad page free for domain %u\n", d->domain_id);
+ return i;
+ }
+
+ if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
+ put_page_and_type(page);
+
+ if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
+ put_page(page);
+
+ shadow_sync_and_drop_references(d, page);
+
+ put_page(page);
+ }
+ }
+
+ return nr_extents;
+}
+
+/*
+ * To allow safe resume of do_memory_op() after preemption, we need to know
+ * at what point in the page list to resume. For this purpose I steal the
+ * high-order bits of the @cmd parameter, which are otherwise unused and zero.
+ */
+#define START_EXTENT_SHIFT 4 /* cmd[:4] == start_extent */
+
+long do_memory_op(int cmd, void *arg)
+{
+ struct domain *d;
+ int rc, start_extent, op, flags = 0, preempted = 0;
+ struct xen_memory_reservation reservation;
+
+ op = cmd & ((1 << START_EXTENT_SHIFT) - 1);
+
+ switch ( op )
+ {
+ case XENMEM_increase_reservation:
+ case XENMEM_decrease_reservation:
+ if ( copy_from_user(&reservation, arg, sizeof(reservation)) )
+ return -EFAULT;
+
+ start_extent = cmd >> START_EXTENT_SHIFT;
+ if ( unlikely(start_extent > reservation.nr_extents) )
+ return -EINVAL;
+
+ if ( reservation.extent_start != NULL )
+ reservation.extent_start += start_extent;
+ reservation.nr_extents -= start_extent;
+
+ if ( (reservation.address_bits != 0) &&
+ (reservation.address_bits <
+ (get_order_from_pages(max_page) + PAGE_SHIFT)) )
+ {
+ if ( reservation.address_bits < 31 )
+ return -ENOMEM;
+ flags = ALLOC_DOM_DMA;
+ }
+
+ if ( likely(reservation.domid == DOMID_SELF) )
+ d = current->domain;
+ else if ( !IS_PRIV(current->domain) )
+ return -EPERM;
+ else if ( (d = find_domain_by_id(reservation.domid)) == NULL )
+ return -ESRCH;
+
+ rc = ((op == XENMEM_increase_reservation) ?
+ increase_reservation : decrease_reservation)(
+ d,
+ reservation.extent_start,
+ reservation.nr_extents,
+ reservation.extent_order,
+ flags,
+ &preempted);
+
+ if ( unlikely(reservation.domid != DOMID_SELF) )
+ put_domain(d);
+
+ rc += start_extent;
+
+ if ( preempted )
+ return hypercall2_create_continuation(
+ __HYPERVISOR_memory_op, op | (rc << START_EXTENT_SHIFT), arg);
+
+ break;
+
+ case XENMEM_maximum_ram_page:
+ if ( put_user(max_page, (unsigned long *)arg) )
+ return -EFAULT;
+ rc = 0;
+ break;
+
+ default:
+ rc = -ENOSYS;
+ break;
+ }
+
+ return rc;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/asm-x86/shadow_ops.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/xen/include/asm-x86/shadow_ops.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,130 @@
+/******************************************************************************
+ * include/asm-x86/shadow_ops.h
+ *
+ * Copyright (c) 2005 Michael A Fetterman
+ * Based on an earlier implementation by Ian Pratt et al
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _XEN_SHADOW_OPS_H
+#define _XEN_SHADOW_OPS_H
+
+#if defined( GUEST_PGENTRY_32 )
+
+#define GUEST_L1_PAGETABLE_ENTRIES L1_PAGETABLE_ENTRIES_32
+#define GUEST_L2_PAGETABLE_ENTRIES L2_PAGETABLE_ENTRIES_32
+#define GUEST_ROOT_PAGETABLE_ENTRIES ROOT_PAGETABLE_ENTRIES_32
+#define GUEST_L2_PAGETABLE_SHIFT L2_PAGETABLE_SHIFT_32
+
+#define guest_l1_pgentry_t l1_pgentry_32_t
+#define guest_l2_pgentry_t l2_pgentry_32_t
+#define guest_root_pgentry_t l2_pgentry_32_t
+
+#define guest_l1e_get_paddr l1e_get_paddr_32
+#define guest_l2e_get_paddr l2e_get_paddr_32
+
+#define guest_get_pte_flags get_pte_flags_32
+#define guest_put_pte_flags put_pte_flags_32
+
+#define guest_l1e_get_flags l1e_get_flags_32
+#define guest_l2e_get_flags l2e_get_flags_32
+#define guest_root_get_flags l2e_get_flags_32
+#define guest_root_get_intpte l2e_get_intpte
+
+#define guest_l1e_empty l1e_empty_32
+#define guest_l2e_empty l2e_empty_32
+
+#define guest_l1e_from_pfn l1e_from_pfn_32
+#define guest_l2e_from_pfn l2e_from_pfn_32
+
+#define guest_l1e_from_paddr l1e_from_paddr_32
+#define guest_l2e_from_paddr l2e_from_paddr_32
+
+#define guest_l1e_from_page l1e_from_page_32
+#define guest_l2e_from_page l2e_from_page_32
+
+#define guest_l1e_add_flags l1e_add_flags_32
+#define guest_l2e_add_flags l2e_add_flags_32
+
+#define guest_l1e_remove_flag l1e_remove_flags_32
+#define guest_l2e_remove_flag l2e_remove_flags_32
+
+#define guest_l1e_has_changed l1e_has_changed_32
+#define guest_l2e_has_changed l2e_has_changed_32
+#define root_entry_has_changed l2e_has_changed_32
+
+#define guest_l1_table_offset l1_table_offset_32
+#define guest_l2_table_offset l2_table_offset_32
+
+#define guest_linear_l1_table linear_pg_table_32
+#define guest_linear_l2_table linear_l2_table_32
+
+#define guest_va_to_l1mfn va_to_l1mfn_32
+
+#else
+
+#define GUEST_L1_PAGETABLE_ENTRIES L1_PAGETABLE_ENTRIES
+#define GUEST_L2_PAGETABLE_ENTRIES L2_PAGETABLE_ENTRIES
+#define GUEST_ROOT_PAGETABLE_ENTRIES ROOT_PAGETABLE_ENTRIES
+#define GUEST_L2_PAGETABLE_SHIFT L2_PAGETABLE_SHIFT
+
+#define guest_l1_pgentry_t l1_pgentry_t
+#define guest_l2_pgentry_t l2_pgentry_t
+#define guest_root_pgentry_t l4_pgentry_t
+
+#define guest_l1e_get_paddr l1e_get_paddr
+#define guest_l2e_get_paddr l2e_get_paddr
+
+#define guest_get_pte_flags get_pte_flags
+#define guest_put_pte_flags put_pte_flags
+
+#define guest_l1e_get_flags l1e_get_flags
+#define guest_l2e_get_flags l2e_get_flags
+#define guest_root_get_flags l4e_get_flags
+#define guest_root_get_intpte l4e_get_intpte
+
+#define guest_l1e_empty l1e_empty
+#define guest_l2e_empty l2e_empty
+
+#define guest_l1e_from_pfn l1e_from_pfn
+#define guest_l2e_from_pfn l2e_from_pfn
+
+#define guest_l1e_from_paddr l1e_from_paddr
+#define guest_l2e_from_paddr l2e_from_paddr
+
+#define guest_l1e_from_page l1e_from_page
+#define guest_l2e_from_page l2e_from_page
+
+#define guest_l1e_add_flags l1e_add_flags
+#define guest_l2e_add_flags l2e_add_flags
+
+#define guest_l1e_remove_flag l1e_remove_flags
+#define guest_l2e_remove_flag l2e_remove_flags
+
+#define guest_l1e_has_changed l1e_has_changed
+#define guest_l2e_has_changed l2e_has_changed
+#define root_entry_has_changed l4e_has_changed
+
+#define guest_l1_table_offset l1_table_offset
+#define guest_l2_table_offset l2_table_offset
+
+#define guest_linear_l1_table linear_pg_table
+#define guest_linear_l2_table linear_l2_table
+
+#define guest_va_to_l1mfn va_to_l1mfn
+#endif
+
+#endif /* _XEN_SHADOW_OPS_H */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/public/io/tpmif.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/xen/include/public/io/tpmif.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,42 @@
+/******************************************************************************
+ * tpmif.h
+ *
+ * TPM I/O interface for Xen guest OSes.
+ *
+ * Copyright (c) 2005, IBM Corporation
+ *
+ * Author: Stefan Berger, stefanb@xxxxxxxxxx
+ * Grant table support: Mahadevan Gomathisankaran
+ *
+ * This code has been derived from tools/libxc/xen/io/netif.h
+ *
+ * Copyright (c) 2003-2004, Keir Fraser
+ */
+
+#ifndef __XEN_PUBLIC_IO_TPMIF_H__
+#define __XEN_PUBLIC_IO_TPMIF_H__
+
+typedef struct {
+ unsigned long addr; /* Machine address of packet. */
+ int ref; /* grant table access reference */
+ u16 id; /* Echoed in response message. */
+ u16 size:15; /* Packet size in bytes. */
+ u16 mapped:1;
+} tpmif_tx_request_t;
+
+/*
+ * The TPMIF_TX_RING_SIZE defines the number of pages the
+ * front-end and backend can exchange (= size of array).
+ */
+typedef u32 TPMIF_RING_IDX;
+
+#define TPMIF_TX_RING_SIZE 16
+
+/* This structure must fit in a memory page. */
+typedef struct {
+ union {
+ tpmif_tx_request_t req;
+ } ring[TPMIF_TX_RING_SIZE];
+} tpmif_tx_interface_t;
+
+#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/include/public/memory.h
--- /dev/null Thu Sep 8 15:18:40 2005
+++ b/xen/include/public/memory.h Fri Sep 9 16:30:54 2005
@@ -0,0 +1,50 @@
+/******************************************************************************
+ * memory.h
+ *
+ * Memory reservation and information.
+ *
+ * Copyright (c) 2005, Keir Fraser <keir@xxxxxxxxxxxxx>
+ */
+
+#ifndef __XEN_PUBLIC_MEMORY_H__
+#define __XEN_PUBLIC_MEMORY_H__
+
+/* arg == addr of struct xen_memory_reservation. */
+#define XENMEM_increase_reservation 0
+
+/* arg == addr of struct xen_memory_reservation. */
+#define XENMEM_decrease_reservation 1
+
+/* arg == addr of unsigned long. */
+#define XENMEM_maximum_ram_page 2
+
+typedef struct xen_memory_reservation {
+
+ /*
+ * MFN bases of extents to free (XENMEM_decrease_reservation).
+ * MFN bases of extents that were allocated (XENMEM_increase_reservation).
+ */
+ unsigned long *extent_start;
+
+ /* Number of extents, and size/alignment of each (2^extent_order pages). */
+ unsigned long nr_extents;
+ unsigned int extent_order;
+
+ /*
+ * XENMEM_increase_reservation: maximum # bits addressable by the user
+ * of the allocated region (e.g., I/O devices often have a 32-bit
+ * limitation even in 64-bit systems). If zero then the user has no
+ * addressing restriction.
+ * XENMEM_decrease_reservation: unused.
+ */
+ unsigned int address_bits;
+
+ /*
+ * Domain whose reservation is being changed.
+ * Unprivileged domains can specify only DOMID_SELF.
+ */
+ domid_t domid;
+
+} xen_memory_reservation_t;
+
+#endif /* __XEN_PUBLIC_MEMORY_H__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/arch/xen/kernel/ctrl_if.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/ctrl_if.c Thu Sep 8 15:18:40 2005
+++ /dev/null Fri Sep 9 16:30:54 2005
@@ -1,569 +0,0 @@
-/******************************************************************************
- * ctrl_if.c
- *
- * Management functions for special interface to the domain controller.
- *
- * Copyright (c) 2004, K A Fraser
- *
- * This file may be distributed separately from the Linux kernel, or
- * incorporated into other software packages, subject to the following license:
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this source file (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy, modify,
- * merge, publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <asm-xen/ctrl_if.h>
-#include <asm-xen/evtchn.h>
-
-#if 0
-#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \
- __FILE__ , __LINE__ , ## _a )
-#else
-#define DPRINTK(_f, _a...) ((void)0)
-#endif
-
-/*
- * Extra ring macros to sync a consumer index up to the public producer index.
- * Generally UNSAFE, but we use it for recovery and shutdown in some cases.
- */
-#define RING_DROP_PENDING_REQUESTS(_r) \
- do { \
- (_r)->req_cons = (_r)->sring->req_prod; \
- } while (0)
-#define RING_DROP_PENDING_RESPONSES(_r) \
- do { \
- (_r)->rsp_cons = (_r)->sring->rsp_prod; \
- } while (0)
-
-/*
- * Only used by initial domain which must create its own control-interface
- * event channel. This value is picked up by the user-space domain controller
- * via an ioctl.
- */
-int initdom_ctrlif_domcontroller_port = -1;
-
-static int ctrl_if_evtchn;
-static int ctrl_if_irq;
-static spinlock_t ctrl_if_lock;
-
-static struct irqaction ctrl_if_irq_action;
-
-static ctrl_front_ring_t ctrl_if_tx_ring;
-static ctrl_back_ring_t ctrl_if_rx_ring;
-
-/* Incoming message requests. */
- /* Primary message type -> message handler. */
-static ctrl_msg_handler_t ctrl_if_rxmsg_handler[256];
- /* Primary message type -> callback in process context? */
-static unsigned long ctrl_if_rxmsg_blocking_context[256/sizeof(unsigned long)];
- /* Is it late enough during bootstrap to use schedule_task()? */
-static int safe_to_schedule_task;
- /* Queue up messages to be handled in process context. */
-static ctrl_msg_t ctrl_if_rxmsg_deferred[CONTROL_RING_SIZE];
-static CONTROL_RING_IDX ctrl_if_rxmsg_deferred_prod;
-static CONTROL_RING_IDX ctrl_if_rxmsg_deferred_cons;
-
-/* Incoming message responses: message identifier -> message handler/id. */
-static struct {
- ctrl_msg_handler_t fn;
- unsigned long id;
-} ctrl_if_txmsg_id_mapping[CONTROL_RING_SIZE];
-
-/* For received messages that must be deferred to process context. */
-static void __ctrl_if_rxmsg_deferred(void *unused);
-static DECLARE_WORK(ctrl_if_rxmsg_deferred_work,
- __ctrl_if_rxmsg_deferred,
- NULL);
-
-/* Deferred callbacks for people waiting for space in the transmit ring. */
-static DECLARE_TASK_QUEUE(ctrl_if_tx_tq);
-
-static DECLARE_WAIT_QUEUE_HEAD(ctrl_if_tx_wait);
-static void __ctrl_if_tx_tasklet(unsigned long data);
-static DECLARE_TASKLET(ctrl_if_tx_tasklet, __ctrl_if_tx_tasklet, 0);
-
-static void __ctrl_if_rx_tasklet(unsigned long data);
-static DECLARE_TASKLET(ctrl_if_rx_tasklet, __ctrl_if_rx_tasklet, 0);
-
-#define get_ctrl_if() ((control_if_t *)((char *)HYPERVISOR_shared_info + 2048))
-
-static void ctrl_if_notify_controller(void)
-{
- notify_via_evtchn(ctrl_if_evtchn);
-}
-
-static void ctrl_if_rxmsg_default_handler(ctrl_msg_t *msg, unsigned long id)
-{
- msg->length = 0;
- ctrl_if_send_response(msg);
-}
-
-static void __ctrl_if_tx_tasklet(unsigned long data)
-{
- ctrl_msg_t *msg;
- int was_full = RING_FULL(&ctrl_if_tx_ring);
- RING_IDX i, rp;
-
- i = ctrl_if_tx_ring.rsp_cons;
- rp = ctrl_if_tx_ring.sring->rsp_prod;
- rmb(); /* Ensure we see all requests up to 'rp'. */
-
- for ( ; i != rp; i++ )
- {
- msg = RING_GET_RESPONSE(&ctrl_if_tx_ring, i);
-
- DPRINTK("Rx-Rsp %u/%u :: %d/%d\n", i-1,
- ctrl_if_tx_ring.sring->rsp_prod,
- msg->type, msg->subtype);
-
- /* Execute the callback handler, if one was specified. */
- if ( msg->id != 0xFF )
- {
- (*ctrl_if_txmsg_id_mapping[msg->id].fn)(
- msg, ctrl_if_txmsg_id_mapping[msg->id].id);
- smp_mb(); /* Execute, /then/ free. */
- ctrl_if_txmsg_id_mapping[msg->id].fn = NULL;
- }
- }
-
- /*
- * Step over messages in the ring /after/ finishing reading them. As soon
- * as the index is updated then the message may get blown away.
- */
- smp_mb();
- ctrl_if_tx_ring.rsp_cons = i;
-
- if ( was_full && !RING_FULL(&ctrl_if_tx_ring) )
- {
- wake_up(&ctrl_if_tx_wait);
- run_task_queue(&ctrl_if_tx_tq);
- }
-}
-
-static void __ctrl_if_rxmsg_deferred(void *unused)
-{
- ctrl_msg_t *msg;
- CONTROL_RING_IDX dp;
-
- dp = ctrl_if_rxmsg_deferred_prod;
- rmb(); /* Ensure we see all deferred requests up to 'dp'. */
-
- while ( ctrl_if_rxmsg_deferred_cons != dp )
- {
- msg = &ctrl_if_rxmsg_deferred[MASK_CONTROL_IDX(
- ctrl_if_rxmsg_deferred_cons++)];
- (*ctrl_if_rxmsg_handler[msg->type])(msg, 0);
- }
-}
-
-static void __ctrl_if_rx_tasklet(unsigned long data)
-{
- ctrl_msg_t msg, *pmsg;
- CONTROL_RING_IDX dp;
- RING_IDX rp, i;
-
- i = ctrl_if_rx_ring.req_cons;
- rp = ctrl_if_rx_ring.sring->req_prod;
- dp = ctrl_if_rxmsg_deferred_prod;
- rmb(); /* Ensure we see all requests up to 'rp'. */
-
- for ( ; i != rp; i++)
- {
- pmsg = RING_GET_REQUEST(&ctrl_if_rx_ring, i);
- memcpy(&msg, pmsg, offsetof(ctrl_msg_t, msg));
-
- DPRINTK("Rx-Req %u/%u :: %d/%d\n", i-1,
- ctrl_if_rx_ring.sring->req_prod,
- msg.type, msg.subtype);
-
- if ( msg.length > sizeof(msg.msg) )
- msg.length = sizeof(msg.msg);
-
- if ( msg.length != 0 )
- memcpy(msg.msg, pmsg->msg, msg.length);
-
- if ( test_bit(msg.type,
- (unsigned long *)&ctrl_if_rxmsg_blocking_context) )
- memcpy(&ctrl_if_rxmsg_deferred[MASK_CONTROL_IDX(dp++)],
- &msg, offsetof(ctrl_msg_t, msg) + msg.length);
- else
- (*ctrl_if_rxmsg_handler[msg.type])(&msg, 0);
- }
-
- ctrl_if_rx_ring.req_cons = i;
-
- if ( dp != ctrl_if_rxmsg_deferred_prod )
- {
- wmb();
- ctrl_if_rxmsg_deferred_prod = dp;
- schedule_work(&ctrl_if_rxmsg_deferred_work);
- }
-}
-
-static irqreturn_t ctrl_if_interrupt(int irq, void *dev_id,
- struct pt_regs *regs)
-{
- if ( RING_HAS_UNCONSUMED_RESPONSES(&ctrl_if_tx_ring) )
- tasklet_schedule(&ctrl_if_tx_tasklet);
-
- if ( RING_HAS_UNCONSUMED_REQUESTS(&ctrl_if_rx_ring) )
- tasklet_schedule(&ctrl_if_rx_tasklet);
-
- return IRQ_HANDLED;
-}
-
-int
-ctrl_if_send_message_noblock(
- ctrl_msg_t *msg,
- ctrl_msg_handler_t hnd,
- unsigned long id)
-{
- unsigned long flags;
- ctrl_msg_t *dmsg;
- int i;
-
- spin_lock_irqsave(&ctrl_if_lock, flags);
-
- if ( RING_FULL(&ctrl_if_tx_ring) )
- {
- spin_unlock_irqrestore(&ctrl_if_lock, flags);
- return -EAGAIN;
- }
-
- msg->id = 0xFF;
- if ( hnd != NULL )
- {
- for ( i = 0; ctrl_if_txmsg_id_mapping[i].fn != NULL; i++ )
- continue;
- ctrl_if_txmsg_id_mapping[i].fn = hnd;
- ctrl_if_txmsg_id_mapping[i].id = id;
- msg->id = i;
- }
-
- DPRINTK("Tx-Req %u/%u :: %d/%d\n",
- ctrl_if_tx_ring.req_prod_pvt,
- ctrl_if_tx_ring.rsp_cons,
- msg->type, msg->subtype);
-
- dmsg = RING_GET_REQUEST(&ctrl_if_tx_ring,
- ctrl_if_tx_ring.req_prod_pvt);
- memcpy(dmsg, msg, sizeof(*msg));
- ctrl_if_tx_ring.req_prod_pvt++;
- RING_PUSH_REQUESTS(&ctrl_if_tx_ring);
-
- spin_unlock_irqrestore(&ctrl_if_lock, flags);
-
- ctrl_if_notify_controller();
-
- return 0;
-}
-
-int
-ctrl_if_send_message_block(
- ctrl_msg_t *msg,
- ctrl_msg_handler_t hnd,
- unsigned long id,
- long wait_state)
-{
- DECLARE_WAITQUEUE(wait, current);
- int rc;
-
- /* Fast path. */
- if ( (rc = ctrl_if_send_message_noblock(msg, hnd, id)) != -EAGAIN )
- return rc;
-
- add_wait_queue(&ctrl_if_tx_wait, &wait);
-
- for ( ; ; )
- {
- set_current_state(wait_state);
-
- if ( (rc = ctrl_if_send_message_noblock(msg, hnd, id)) != -EAGAIN )
- break;
-
- rc = -ERESTARTSYS;
- if ( signal_pending(current) && (wait_state == TASK_INTERRUPTIBLE) )
- break;
-
- schedule();
- }
-
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&ctrl_if_tx_wait, &wait);
-
- return rc;
-}
-
-/* Allow a reponse-callback handler to find context of a blocked requester. */
-struct rsp_wait {
- ctrl_msg_t *msg; /* Buffer for the response message. */
- struct task_struct *task; /* The task that is blocked on the response. */
- int done; /* Indicate to 'task' that response is rcv'ed. */
-};
-
-static void __ctrl_if_get_response(ctrl_msg_t *msg, unsigned long id)
-{
- struct rsp_wait *wait = (struct rsp_wait *)id;
- struct task_struct *task = wait->task;
-
- memcpy(wait->msg, msg, sizeof(*msg));
- wmb();
- wait->done = 1;
-
- wake_up_process(task);
-}
-
-int
-ctrl_if_send_message_and_get_response(
- ctrl_msg_t *msg,
- ctrl_msg_t *rmsg,
- long wait_state)
-{
- struct rsp_wait wait;
- int rc;
-
- wait.msg = rmsg;
- wait.done = 0;
- wait.task = current;
-
- if ( (rc = ctrl_if_send_message_block(msg, __ctrl_if_get_response,
- (unsigned long)&wait,
- wait_state)) != 0 )
- return rc;
-
- for ( ; ; )
- {
- /* NB. Can't easily support TASK_INTERRUPTIBLE here. */
- set_current_state(TASK_UNINTERRUPTIBLE);
- if ( wait.done )
- break;
- schedule();
- }
-
- set_current_state(TASK_RUNNING);
- return 0;
-}
-
-int
-ctrl_if_enqueue_space_callback(
- struct tq_struct *task)
-{
- /* Fast path. */
- if ( !RING_FULL(&ctrl_if_tx_ring) )
- return 0;
-
- (void)queue_task(task, &ctrl_if_tx_tq);
-
- /*
- * We may race execution of the task queue, so return re-checked status. If
- * the task is not executed despite the ring being non-full then we will
- * certainly return 'not full'.
- */
- smp_mb();
- return RING_FULL(&ctrl_if_tx_ring);
-}
-
-void
-ctrl_if_send_response(
- ctrl_msg_t *msg)
-{
- unsigned long flags;
- ctrl_msg_t *dmsg;
-
- /*
- * NB. The response may the original request message, modified in-place.
- * In this situation we may have src==dst, so no copying is required.
- */
- spin_lock_irqsave(&ctrl_if_lock, flags);
-
- DPRINTK("Tx-Rsp %u :: %d/%d\n",
- ctrl_if_rx_ring.rsp_prod_pvt,
- msg->type, msg->subtype);
-
- dmsg = RING_GET_RESPONSE(&ctrl_if_rx_ring,
- ctrl_if_rx_ring.rsp_prod_pvt);
- if ( dmsg != msg )
- memcpy(dmsg, msg, sizeof(*msg));
-
- ctrl_if_rx_ring.rsp_prod_pvt++;
- RING_PUSH_RESPONSES(&ctrl_if_rx_ring);
-
- spin_unlock_irqrestore(&ctrl_if_lock, flags);
-
- ctrl_if_notify_controller();
-}
-
-int
-ctrl_if_register_receiver(
- u8 type,
- ctrl_msg_handler_t hnd,
- unsigned int flags)
-{
- unsigned long _flags;
- int inuse;
-
- spin_lock_irqsave(&ctrl_if_lock, _flags);
-
- inuse = (ctrl_if_rxmsg_handler[type] != ctrl_if_rxmsg_default_handler);
-
- if ( inuse )
- {
- printk(KERN_INFO "Receiver %p already established for control "
- "messages of type %d.\n", ctrl_if_rxmsg_handler[type], type);
- }
- else
- {
- ctrl_if_rxmsg_handler[type] = hnd;
- clear_bit(type, (unsigned long *)&ctrl_if_rxmsg_blocking_context);
- if ( flags == CALLBACK_IN_BLOCKING_CONTEXT )
- {
- set_bit(type, (unsigned long *)&ctrl_if_rxmsg_blocking_context);
- if ( !safe_to_schedule_task )
- BUG();
- }
- }
-
- spin_unlock_irqrestore(&ctrl_if_lock, _flags);
-
- return !inuse;
-}
-
-void
-ctrl_if_unregister_receiver(
- u8 type,
- ctrl_msg_handler_t hnd)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&ctrl_if_lock, flags);
-
- if ( ctrl_if_rxmsg_handler[type] != hnd )
- printk(KERN_INFO "Receiver %p is not registered for control "
- "messages of type %d.\n", hnd, type);
- else
- ctrl_if_rxmsg_handler[type] = ctrl_if_rxmsg_default_handler;
-
- spin_unlock_irqrestore(&ctrl_if_lock, flags);
-
- /* Ensure that @hnd will not be executed after this function returns. */
- tasklet_unlock_wait(&ctrl_if_rx_tasklet);
-}
-
-void ctrl_if_suspend(void)
-{
- teardown_irq(ctrl_if_irq, &ctrl_if_irq_action);
- unbind_evtchn_from_irq(ctrl_if_evtchn);
-}
-
-void ctrl_if_resume(void)
-{
- control_if_t *ctrl_if = get_ctrl_if();
-
- if ( xen_start_info.flags & SIF_INITDOMAIN )
- {
- /*
- * The initial domain must create its own domain-controller link.
- * The controller is probably not running at this point, but will
- * pick up its end of the event channel from
- */
- evtchn_op_t op;
- extern void bind_evtchn_to_cpu(unsigned port, unsigned cpu);
-
- op.cmd = EVTCHNOP_bind_interdomain;
- op.u.bind_interdomain.dom1 = DOMID_SELF;
- op.u.bind_interdomain.dom2 = DOMID_SELF;
- op.u.bind_interdomain.port1 = 0;
- op.u.bind_interdomain.port2 = 0;
- if ( HYPERVISOR_event_channel_op(&op) != 0 )
- BUG();
- xen_start_info.domain_controller_evtchn = op.u.bind_interdomain.port1;
- initdom_ctrlif_domcontroller_port = op.u.bind_interdomain.port2;
- bind_evtchn_to_cpu(op.u.bind_interdomain.port1, 0);
- }
-
- /* Sync up with shared indexes. */
- FRONT_RING_ATTACH(&ctrl_if_tx_ring, &ctrl_if->tx_ring, CONTROL_RING_MEM);
- BACK_RING_ATTACH(&ctrl_if_rx_ring, &ctrl_if->rx_ring, CONTROL_RING_MEM);
-
- ctrl_if_evtchn = xen_start_info.domain_controller_evtchn;
- ctrl_if_irq = bind_evtchn_to_irq(ctrl_if_evtchn);
-
- memset(&ctrl_if_irq_action, 0, sizeof(ctrl_if_irq_action));
- ctrl_if_irq_action.handler = ctrl_if_interrupt;
- ctrl_if_irq_action.name = "ctrl-if";
- (void)setup_irq(ctrl_if_irq, &ctrl_if_irq_action);
-}
-
-void __init ctrl_if_init(void)
-{
- control_if_t *ctrl_if = get_ctrl_if();
- int i;
-
- for ( i = 0; i < 256; i++ )
- ctrl_if_rxmsg_handler[i] = ctrl_if_rxmsg_default_handler;
-
- FRONT_RING_ATTACH(&ctrl_if_tx_ring, &ctrl_if->tx_ring, CONTROL_RING_MEM);
- BACK_RING_ATTACH(&ctrl_if_rx_ring, &ctrl_if->rx_ring, CONTROL_RING_MEM);
-
- spin_lock_init(&ctrl_if_lock);
-
- ctrl_if_resume();
-}
-
-
-/* This is called after it is safe to call schedule_task(). */
-static int __init ctrl_if_late_setup(void)
-{
- safe_to_schedule_task = 1;
- return 0;
-}
-__initcall(ctrl_if_late_setup);
-
-
-/*
- * !! The following are DANGEROUS FUNCTIONS !!
- * Use with care [for example, see xencons_force_flush()].
- */
-
-int ctrl_if_transmitter_empty(void)
-{
- return (ctrl_if_tx_ring.sring->req_prod == ctrl_if_tx_ring.rsp_cons);
-
-}
-
-void ctrl_if_discard_responses(void)
-{
- RING_DROP_PENDING_RESPONSES(&ctrl_if_tx_ring);
-}
-
-EXPORT_SYMBOL(ctrl_if_send_message_noblock);
-EXPORT_SYMBOL(ctrl_if_send_message_block);
-EXPORT_SYMBOL(ctrl_if_send_message_and_get_response);
-EXPORT_SYMBOL(ctrl_if_enqueue_space_callback);
-EXPORT_SYMBOL(ctrl_if_send_response);
-EXPORT_SYMBOL(ctrl_if_register_receiver);
-EXPORT_SYMBOL(ctrl_if_unregister_receiver);
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/blktap/blktap_controlmsg.c
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap_controlmsg.c Thu Sep
8 15:18:40 2005
+++ /dev/null Fri Sep 9 16:30:54 2005
@@ -1,573 +0,0 @@
-/******************************************************************************
- * blktap_controlmsg.c
- *
- * XenLinux virtual block-device tap.
- * Control interfaces to the frontend and backend drivers.
- *
- * Copyright (c) 2004, Andrew Warfield
- *
- */
-
-#include "blktap.h"
-#include <asm-xen/evtchn.h>
-
-static char *blkif_state_name[] = {
- [BLKIF_STATE_CLOSED] = "closed",
- [BLKIF_STATE_DISCONNECTED] = "disconnected",
- [BLKIF_STATE_CONNECTED] = "connected",
-};
-
-static char *blkif_status_name[] = {
- [BLKIF_INTERFACE_STATUS_CLOSED] = "closed",
- [BLKIF_INTERFACE_STATUS_DISCONNECTED] = "disconnected",
- [BLKIF_INTERFACE_STATUS_CONNECTED] = "connected",
- [BLKIF_INTERFACE_STATUS_CHANGED] = "changed",
-};
-
-unsigned int blktap_be_state = BLKIF_STATE_CLOSED;
-unsigned int blktap_be_evtchn;
-
-/*-----[ Control Messages to/from Frontend VMs ]--------------------------*/
-
-#define BLKIF_HASHSZ 1024
-#define BLKIF_HASH(_d,_h) (((int)(_d)^(int)(_h))&(BLKIF_HASHSZ-1))
-
-static kmem_cache_t *blkif_cachep;
-static blkif_t *blkif_hash[BLKIF_HASHSZ];
-
-blkif_t *blkif_find_by_handle(domid_t domid, unsigned int handle)
-{
- blkif_t *blkif = blkif_hash[BLKIF_HASH(domid, handle)];
- while ( (blkif != NULL) &&
- ((blkif->domid != domid) || (blkif->handle != handle)) )
- blkif = blkif->hash_next;
- return blkif;
-}
-
-static void __blkif_disconnect_complete(void *arg)
-{
- blkif_t *blkif = (blkif_t *)arg;
- ctrl_msg_t cmsg;
- blkif_be_disconnect_t disc;
-#ifdef CONFIG_XEN_BLKDEV_GRANT
- struct gnttab_unmap_grant_ref op;
-#endif
-
- /*
- * These can't be done in blkif_disconnect() because at that point there
- * may be outstanding requests at the disc whose asynchronous responses
- * must still be notified to the remote driver.
- */
-#ifdef CONFIG_XEN_BLKDEV_GRANT
- op.host_addr = blkif->shmem_vaddr;
- op.handle = blkif->shmem_handle;
- op.dev_bus_addr = 0;
- BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
-#endif
- vfree(blkif->blk_ring.sring);
-
- /* Construct the deferred response message. */
- cmsg.type = CMSG_BLKIF_BE;
- cmsg.subtype = CMSG_BLKIF_BE_DISCONNECT;
- cmsg.id = blkif->disconnect_rspid;
- cmsg.length = sizeof(blkif_be_disconnect_t);
- disc.domid = blkif->domid;
- disc.blkif_handle = blkif->handle;
- disc.status = BLKIF_BE_STATUS_OKAY;
- memcpy(cmsg.msg, &disc, sizeof(disc));
-
- /*
- * Make sure message is constructed /before/ status change, because
- * after the status change the 'blkif' structure could be deallocated at
- * any time. Also make sure we send the response /after/ status change,
- * as otherwise a subsequent CONNECT request could spuriously fail if
- * another CPU doesn't see the status change yet.
- */
- mb();
- if ( blkif->status != DISCONNECTING )
- BUG();
- blkif->status = DISCONNECTED;
- mb();
-
- /* Send the successful response. */
- ctrl_if_send_response(&cmsg);
-}
-
-void blkif_disconnect_complete(blkif_t *blkif)
-{
- INIT_WORK(&blkif->work, __blkif_disconnect_complete, (void *)blkif);
- schedule_work(&blkif->work);
-}
-
-void blkif_ptfe_create(blkif_be_create_t *create)
-{
- blkif_t *blkif, **pblkif;
- domid_t domid = create->domid;
- unsigned int handle = create->blkif_handle;
-
-
- /* May want to store info on the connecting domain here. */
-
- DPRINTK("PT got BE_CREATE\n");
-
- if ( (blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL)) == NULL )
- {
- WPRINTK("Could not create blkif: out of memory\n");
- create->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
- return;
- }
-
- /* blkif struct init code from blkback.c */
- memset(blkif, 0, sizeof(*blkif));
- blkif->domid = domid;
- blkif->handle = handle;
- blkif->status = DISCONNECTED;
- spin_lock_init(&blkif->blk_ring_lock);
- atomic_set(&blkif->refcnt, 0);
-
- pblkif = &blkif_hash[BLKIF_HASH(domid, handle)];
- while ( *pblkif != NULL )
- {
- if ( ((*pblkif)->domid == domid) && ((*pblkif)->handle == handle) )
- {
- WPRINTK("Could not create blkif: already exists\n");
- create->status = BLKIF_BE_STATUS_INTERFACE_EXISTS;
- kmem_cache_free(blkif_cachep, blkif);
- return;
- }
- pblkif = &(*pblkif)->hash_next;
- }
-
- blkif->hash_next = *pblkif;
- *pblkif = blkif;
-
- create->status = BLKIF_BE_STATUS_OKAY;
-}
-
-
-void blkif_ptfe_destroy(blkif_be_destroy_t *destroy)
-{
- /* Clear anything that we initialized above. */
-
- domid_t domid = destroy->domid;
- unsigned int handle = destroy->blkif_handle;
- blkif_t **pblkif, *blkif;
-
- DPRINTK("PT got BE_DESTROY\n");
-
- pblkif = &blkif_hash[BLKIF_HASH(domid, handle)];
- while ( (blkif = *pblkif) != NULL )
- {
- if ( (blkif->domid == domid) && (blkif->handle == handle) )
- {
- if ( blkif->status != DISCONNECTED )
- goto still_connected;
- goto destroy;
- }
- pblkif = &blkif->hash_next;
- }
-
- destroy->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
- return;
-
- still_connected:
- destroy->status = BLKIF_BE_STATUS_INTERFACE_CONNECTED;
- return;
-
- destroy:
- *pblkif = blkif->hash_next;
- kmem_cache_free(blkif_cachep, blkif);
- destroy->status = BLKIF_BE_STATUS_OKAY;
-}
-
-void blkif_ptfe_connect(blkif_be_connect_t *connect)
-{
- domid_t domid = connect->domid;
- unsigned int handle = connect->blkif_handle;
- unsigned int evtchn = connect->evtchn;
- unsigned long shmem_frame = connect->shmem_frame;
- struct vm_struct *vma;
-#ifdef CONFIG_XEN_BLKDEV_GRANT
- int ref = connect->shmem_ref;
-#else
- pgprot_t prot;
- int error;
-#endif
- blkif_t *blkif;
- blkif_sring_t *sring;
-
- DPRINTK("PT got BE_CONNECT\n");
-
- blkif = blkif_find_by_handle(domid, handle);
- if ( unlikely(blkif == NULL) )
- {
- WPRINTK("blkif_connect attempted for non-existent blkif (%u,%u)\n",
- connect->domid, connect->blkif_handle);
- connect->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
- return;
- }
-
- if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL )
- {
- connect->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
- return;
- }
-
-#ifndef CONFIG_XEN_BLKDEV_GRANT
- prot = __pgprot(_KERNPG_TABLE);
- error = direct_remap_area_pages(&init_mm, VMALLOC_VMADDR(vma->addr),
- shmem_frame<<PAGE_SHIFT, PAGE_SIZE,
- prot, domid);
- if ( error != 0 )
- {
- if ( error == -ENOMEM )
- connect->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
- else if ( error == -EFAULT )
- connect->status = BLKIF_BE_STATUS_MAPPING_ERROR;
- else
- connect->status = BLKIF_BE_STATUS_ERROR;
- vfree(vma->addr);
- return;
- }
-#else
- { /* Map: Use the Grant table reference */
- struct gnttab_map_grant_ref op;
- op.host_addr = VMALLOC_VMADDR(vma->addr);
- op.flags = GNTMAP_host_map;
- op.ref = ref;
- op.dom = domid;
-
- BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) );
-
- handle = op.handle;
-
- if (op.handle < 0) {
- DPRINTK(" Grant table operation failure !\n");
- connect->status = BLKIF_BE_STATUS_MAPPING_ERROR;
- vfree(vma->addr);
- return;
- }
-
- blkif->shmem_ref = ref;
- blkif->shmem_handle = handle;
- blkif->shmem_vaddr = VMALLOC_VMADDR(vma->addr);
- }
-#endif
-
- if ( blkif->status != DISCONNECTED )
- {
- connect->status = BLKIF_BE_STATUS_INTERFACE_CONNECTED;
- vfree(vma->addr);
- return;
- }
-
- sring = (blkif_sring_t *)vma->addr;
- SHARED_RING_INIT(sring);
- BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE);
-
- blkif->evtchn = evtchn;
- blkif->shmem_frame = shmem_frame;
- blkif->status = CONNECTED;
- blkif_get(blkif);
-
- bind_evtchn_to_irqhandler(
- evtchn, blkif_ptfe_int, 0, "blkif-pt-backend", blkif);
-
- connect->status = BLKIF_BE_STATUS_OKAY;
-}
-
-int blkif_ptfe_disconnect(blkif_be_disconnect_t *disconnect, u8 rsp_id)
-{
- domid_t domid = disconnect->domid;
- unsigned int handle = disconnect->blkif_handle;
- blkif_t *blkif;
-
- DPRINTK("PT got BE_DISCONNECT\n");
-
- blkif = blkif_find_by_handle(domid, handle);
- if ( unlikely(blkif == NULL) )
- {
- WPRINTK("blkif_disconnect attempted for non-existent blkif"
- " (%u,%u)\n", disconnect->domid, disconnect->blkif_handle);
- disconnect->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
- return 1; /* Caller will send response error message. */
- }
-
- if ( blkif->status == CONNECTED )
- {
- blkif->status = DISCONNECTING;
- blkif->disconnect_rspid = rsp_id;
- wmb(); /* Let other CPUs see the status change. */
- unbind_evtchn_from_irqhandler(blkif->evtchn, blkif);
- blkif_deschedule(blkif);
- blkif_put(blkif);
- return 0; /* Caller should not send response message. */
- }
-
- disconnect->status = BLKIF_BE_STATUS_OKAY;
- return 1;
-}
-
-/*-----[ Control Messages to/from Backend VM ]----------------------------*/
-
-/* Tell the controller to bring up the interface. */
-static void blkif_ptbe_send_interface_connect(void)
-{
- ctrl_msg_t cmsg = {
- .type = CMSG_BLKIF_FE,
- .subtype = CMSG_BLKIF_FE_INTERFACE_CONNECT,
- .length = sizeof(blkif_fe_interface_connect_t),
- };
- blkif_fe_interface_connect_t *msg = (void*)cmsg.msg;
- msg->handle = 0;
- msg->shmem_frame = virt_to_mfn(blktap_be_ring.sring);
-
- ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
-}
-
-static void blkif_ptbe_close(void)
-{
-}
-
-/* Move from CLOSED to DISCONNECTED state. */
-static void blkif_ptbe_disconnect(void)
-{
- blkif_sring_t *sring;
-
- sring = (blkif_sring_t *)__get_free_page(GFP_KERNEL);
- SHARED_RING_INIT(sring);
- FRONT_RING_INIT(&blktap_be_ring, sring, PAGE_SIZE);
- blktap_be_state = BLKIF_STATE_DISCONNECTED;
- DPRINTK("Blkif-Passthrough-BE is now DISCONNECTED.\n");
- blkif_ptbe_send_interface_connect();
-}
-
-static void blkif_ptbe_connect(blkif_fe_interface_status_t *status)
-{
- int err = 0;
-
- blktap_be_evtchn = status->evtchn;
-
- err = bind_evtchn_to_irqhandler(
- blktap_be_evtchn, blkif_ptbe_int, SA_SAMPLE_RANDOM, "blkif", NULL);
- if ( err ) {
- WPRINTK("blkfront bind_evtchn_to_irqhandler failed (%d)\n", err);
- return;
- } else {
- /* transtion to connected in case we need to do a
- a partion probe on a whole disk */
- blktap_be_state = BLKIF_STATE_CONNECTED;
- }
-}
-
-static void unexpected(blkif_fe_interface_status_t *status)
-{
- WPRINTK(" TAP: Unexpected blkif status %s in state %s\n",
- blkif_status_name[status->status],
- blkif_state_name[blktap_be_state]);
-}
-
-static void blkif_ptbe_status(
- blkif_fe_interface_status_t *status)
-{
- if ( status->handle != 0 )
- {
- DPRINTK("Status change on unsupported blkif %d\n",
- status->handle);
- return;
- }
-
- DPRINTK("ptbe_status: got %s\n", blkif_status_name[status->status]);
-
- switch ( status->status )
- {
- case BLKIF_INTERFACE_STATUS_CLOSED:
- switch ( blktap_be_state )
- {
- case BLKIF_STATE_CLOSED:
- unexpected(status);
- break;
- case BLKIF_STATE_DISCONNECTED:
- case BLKIF_STATE_CONNECTED:
- unexpected(status);
- blkif_ptbe_close();
- break;
- }
- break;
-
- case BLKIF_INTERFACE_STATUS_DISCONNECTED:
- switch ( blktap_be_state )
- {
- case BLKIF_STATE_CLOSED:
- blkif_ptbe_disconnect();
- break;
- case BLKIF_STATE_DISCONNECTED:
- case BLKIF_STATE_CONNECTED:
- printk(KERN_ALERT "*** add recovery code to the tap driver.
***\n");
- unexpected(status);
- break;
- }
- break;
-
- case BLKIF_INTERFACE_STATUS_CONNECTED:
- switch ( blktap_be_state )
- {
- case BLKIF_STATE_CLOSED:
- unexpected(status);
- blkif_ptbe_disconnect();
- blkif_ptbe_connect(status);
- break;
- case BLKIF_STATE_DISCONNECTED:
- blkif_ptbe_connect(status);
- break;
- case BLKIF_STATE_CONNECTED:
- unexpected(status);
- blkif_ptbe_connect(status);
- break;
- }
- break;
-
- case BLKIF_INTERFACE_STATUS_CHANGED:
- switch ( blktap_be_state )
- {
- case BLKIF_STATE_CLOSED:
- case BLKIF_STATE_DISCONNECTED:
- unexpected(status);
- break;
- case BLKIF_STATE_CONNECTED:
- /* vbd_update(); */
- /* tap doesn't really get state changes... */
- unexpected(status);
- break;
- }
- break;
-
- default:
- DPRINTK("Status change to unknown value %d\n", status->status);
- break;
- }
-}
-
-/*-----[ All control messages enter here: ]-------------------------------*/
-
-void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
-{
- switch ( msg->type )
- {
- case CMSG_BLKIF_FE:
-
- switch ( msg->subtype )
- {
- case CMSG_BLKIF_FE_INTERFACE_STATUS:
- blkif_ptbe_status((blkif_fe_interface_status_t *) &msg->msg[0]);
- break;
-
- default:
- goto parse_error;
- }
-
- break;
-
- case CMSG_BLKIF_BE:
-
- /* send a copy of the message to user if wanted */
-
- if ( (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) ||
- (blktap_mode & BLKTAP_MODE_COPY_FE) ) {
-
- blktap_write_ctrl_ring(msg);
- blktap_kick_user();
- }
-
- switch ( msg->subtype )
- {
- case CMSG_BLKIF_BE_CREATE:
- blkif_ptfe_create((blkif_be_create_t *)&msg->msg[0]);
- break;
- case CMSG_BLKIF_BE_DESTROY:
- blkif_ptfe_destroy((blkif_be_destroy_t *)&msg->msg[0]);
- break;
- case CMSG_BLKIF_BE_CONNECT:
- blkif_ptfe_connect((blkif_be_connect_t *)&msg->msg[0]);
- break;
- case CMSG_BLKIF_BE_DISCONNECT:
- if ( !blkif_ptfe_disconnect((blkif_be_disconnect_t *)&msg->msg[0],
- msg->id) )
- return;
- break;
-
- /* We just ignore anything to do with vbds for now. */
-
- case CMSG_BLKIF_BE_VBD_CREATE:
- DPRINTK("PT got VBD_CREATE\n");
- ((blkif_be_vbd_create_t *)&msg->msg[0])->status
- = BLKIF_BE_STATUS_OKAY;
- break;
- case CMSG_BLKIF_BE_VBD_DESTROY:
- DPRINTK("PT got VBD_DESTROY\n");
- ((blkif_be_vbd_destroy_t *)&msg->msg[0])->status
- = BLKIF_BE_STATUS_OKAY;
- break;
- default:
- goto parse_error;
- }
-
- break;
- }
-
- ctrl_if_send_response(msg);
- return;
-
- parse_error:
- msg->length = 0;
- ctrl_if_send_response(msg);
-}
-
-/*-----[ Initialization ]-------------------------------------------------*/
-
-void __init blkif_interface_init(void)
-{
- blkif_cachep = kmem_cache_create("blkif_cache", sizeof(blkif_t),
- 0, 0, NULL, NULL);
- memset(blkif_hash, 0, sizeof(blkif_hash));
-
- blktap_be_ring.sring = NULL;
-}
-
-
-
-/* Debug : print the current ring indices. */
-
-void print_fe_ring_idxs(void)
-{
- int i;
- blkif_t *blkif;
-
- WPRINTK("FE Rings: \n---------\n");
- for ( i = 0; i < BLKIF_HASHSZ; i++) {
- blkif = blkif_hash[i];
- while (blkif != NULL) {
- if (blkif->status == DISCONNECTED) {
- WPRINTK("(%2d,%2d) DISCONNECTED\n",
- blkif->domid, blkif->handle);
- } else if (blkif->status == DISCONNECTING) {
- WPRINTK("(%2d,%2d) DISCONNECTING\n",
- blkif->domid, blkif->handle);
- } else if (blkif->blk_ring.sring == NULL) {
- WPRINTK("(%2d,%2d) CONNECTED, but null sring!\n",
- blkif->domid, blkif->handle);
- } else {
- blkif_get(blkif);
- WPRINTK("(%2d,%2d): req_cons: %2d, rsp_prod_prv: %2d "
- "| req_prod: %2d, rsp_prod: %2d\n",
- blkif->domid, blkif->handle,
- blkif->blk_ring.req_cons,
- blkif->blk_ring.rsp_prod_pvt,
- blkif->blk_ring.sring->req_prod,
- blkif->blk_ring.sring->rsp_prod);
- blkif_put(blkif);
- }
- blkif = blkif->hash_next;
- }
- }
-}
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/blktap/blktap_datapath.c
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap_datapath.c Thu Sep 8
15:18:40 2005
+++ /dev/null Fri Sep 9 16:30:54 2005
@@ -1,449 +0,0 @@
-/******************************************************************************
- * blktap_datapath.c
- *
- * XenLinux virtual block-device tap.
- * Block request routing data path.
- *
- * Copyright (c) 2004, Andrew Warfield
- * -- see full header in blktap.c
- */
-
-#include "blktap.h"
-#include <asm-xen/evtchn.h>
-
-/*-----[ The data paths ]-------------------------------------------------*/
-
-/* Connection to a single backend domain. */
-blkif_front_ring_t blktap_be_ring;
-
-/*-----[ Tracking active requests ]---------------------------------------*/
-
-/* this must be the same as MAX_PENDING_REQS in blkback.c */
-#define MAX_ACTIVE_REQS ((ACTIVE_RING_IDX)64U)
-
-active_req_t active_reqs[MAX_ACTIVE_REQS];
-ACTIVE_RING_IDX active_req_ring[MAX_ACTIVE_REQS];
-spinlock_t active_req_lock = SPIN_LOCK_UNLOCKED;
-ACTIVE_RING_IDX active_prod, active_cons;
-#define MASK_ACTIVE_IDX(_i) ((_i)&(MAX_ACTIVE_REQS-1))
-#define ACTIVE_IDX(_ar) (_ar - active_reqs)
-#define NR_ACTIVE_REQS (MAX_ACTIVE_REQS - active_prod + active_cons)
-
-inline active_req_t *get_active_req(void)
-{
- ACTIVE_RING_IDX idx;
- active_req_t *ar;
- unsigned long flags;
-
- ASSERT(active_cons != active_prod);
-
- spin_lock_irqsave(&active_req_lock, flags);
- idx = active_req_ring[MASK_ACTIVE_IDX(active_cons++)];
- ar = &active_reqs[idx];
- spin_unlock_irqrestore(&active_req_lock, flags);
-
- return ar;
-}
-
-inline void free_active_req(active_req_t *ar)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&active_req_lock, flags);
- active_req_ring[MASK_ACTIVE_IDX(active_prod++)] = ACTIVE_IDX(ar);
- spin_unlock_irqrestore(&active_req_lock, flags);
-}
-
-active_req_t *lookup_active_req(ACTIVE_RING_IDX idx)
-{
- return &active_reqs[idx];
-}
-
-void active_reqs_init(void)
-{
- ACTIVE_RING_IDX i;
-
- active_cons = 0;
- active_prod = MAX_ACTIVE_REQS;
- memset(active_reqs, 0, sizeof(active_reqs));
- for ( i = 0; i < MAX_ACTIVE_REQS; i++ )
- active_req_ring[i] = i;
-}
-
-/* Requests passing through the tap to the backend hijack the id field
- * in the request message. In it we put the AR index _AND_ the fe domid.
- * the domid is used by the backend to map the pages properly.
- */
-
-static inline unsigned long MAKE_ID(domid_t fe_dom, ACTIVE_RING_IDX idx)
-{
- return ( (fe_dom << 16) | MASK_ACTIVE_IDX(idx) );
-}
-
-/*-----[ Ring helpers ]---------------------------------------------------*/
-
-static void maybe_trigger_blktap_schedule(void);
-
-inline int write_resp_to_fe_ring(blkif_t *blkif, blkif_response_t *rsp)
-{
- blkif_response_t *resp_d;
- active_req_t *ar;
-
- ar = &active_reqs[ID_TO_IDX(rsp->id)];
- rsp->id = ar->id;
-
- resp_d = RING_GET_RESPONSE(&blkif->blk_ring,
- blkif->blk_ring.rsp_prod_pvt);
- memcpy(resp_d, rsp, sizeof(blkif_response_t));
- wmb();
- blkif->blk_ring.rsp_prod_pvt++;
-
- blkif_put(ar->blkif);
- free_active_req(ar);
-
- return 0;
-}
-
-inline int write_req_to_be_ring(blkif_request_t *req)
-{
- blkif_request_t *req_d;
-
- if ( blktap_be_state != BLKIF_STATE_CONNECTED ) {
- WPRINTK("Tap trying to access an unconnected backend!\n");
- return 0;
- }
-
- req_d = RING_GET_REQUEST(&blktap_be_ring,
- blktap_be_ring.req_prod_pvt);
- memcpy(req_d, req, sizeof(blkif_request_t));
- wmb();
- blktap_be_ring.req_prod_pvt++;
-
- return 0;
-}
-
-void kick_fe_domain(blkif_t *blkif)
-{
- RING_PUSH_RESPONSES(&blkif->blk_ring);
- notify_via_evtchn(blkif->evtchn);
- DPRINTK("notified FE(dom %u)\n", blkif->domid);
-
- /* We just feed up a batch of request slots... */
- maybe_trigger_blktap_schedule();
-
-}
-
-void kick_be_domain(void)
-{
- if ( blktap_be_state != BLKIF_STATE_CONNECTED )
- return;
-
- wmb(); /* Ensure that the frontend can see the requests. */
- RING_PUSH_REQUESTS(&blktap_be_ring);
- notify_via_evtchn(blktap_be_evtchn);
- DPRINTK("notified BE\n");
-}
-
-/*-----[ Data to/from Frontend (client) VMs ]-----------------------------*/
-
-/*-----[ Scheduler list maint -from blkback ]--- */
-
-static struct list_head blkio_schedule_list;
-static spinlock_t blkio_schedule_list_lock;
-
-static int __on_blkdev_list(blkif_t *blkif)
-{
- return blkif->blkdev_list.next != NULL;
-}
-
-static void remove_from_blkdev_list(blkif_t *blkif)
-{
- unsigned long flags;
- if ( !__on_blkdev_list(blkif) ) return;
- spin_lock_irqsave(&blkio_schedule_list_lock, flags);
- if ( __on_blkdev_list(blkif) )
- {
- list_del(&blkif->blkdev_list);
- blkif->blkdev_list.next = NULL;
- blkif_put(blkif);
- }
- spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
-}
-
-static void add_to_blkdev_list_tail(blkif_t *blkif)
-{
- unsigned long flags;
- if ( __on_blkdev_list(blkif) ) return;
- spin_lock_irqsave(&blkio_schedule_list_lock, flags);
- if ( !__on_blkdev_list(blkif) && (blkif->status == CONNECTED) )
- {
- list_add_tail(&blkif->blkdev_list, &blkio_schedule_list);
- blkif_get(blkif);
- }
- spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
-}
-
-
-/*-----[ Scheduler functions - from blkback ]--- */
-
-static DECLARE_WAIT_QUEUE_HEAD(blkio_schedule_wait);
-
-static int do_block_io_op(blkif_t *blkif, int max_to_do);
-
-static int blkio_schedule(void *arg)
-{
- DECLARE_WAITQUEUE(wq, current);
-
- blkif_t *blkif;
- struct list_head *ent;
-
- daemonize(
- "xentapd"
- );
-
- for ( ; ; )
- {
- /* Wait for work to do. */
- add_wait_queue(&blkio_schedule_wait, &wq);
- set_current_state(TASK_INTERRUPTIBLE);
- if ( (NR_ACTIVE_REQS == MAX_ACTIVE_REQS) ||
- list_empty(&blkio_schedule_list) )
- schedule();
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&blkio_schedule_wait, &wq);
-
- /* Queue up a batch of requests. */
- while ( (NR_ACTIVE_REQS < MAX_ACTIVE_REQS) &&
- !list_empty(&blkio_schedule_list) )
- {
- ent = blkio_schedule_list.next;
- blkif = list_entry(ent, blkif_t, blkdev_list);
- blkif_get(blkif);
- remove_from_blkdev_list(blkif);
- if ( do_block_io_op(blkif, BATCH_PER_DOMAIN) )
- add_to_blkdev_list_tail(blkif);
- blkif_put(blkif);
- }
- }
-}
-
-static void maybe_trigger_blktap_schedule(void)
-{
- /*
- * Needed so that two processes, who together make the following predicate
- * true, don't both read stale values and evaluate the predicate
- * incorrectly. Incredibly unlikely to stall the scheduler on x86, but...
- */
- smp_mb();
-
- if ( (NR_ACTIVE_REQS < (MAX_ACTIVE_REQS/2)) &&
- !list_empty(&blkio_schedule_list) )
- wake_up(&blkio_schedule_wait);
-}
-
-void blkif_deschedule(blkif_t *blkif)
-{
- remove_from_blkdev_list(blkif);
-}
-
-void __init blkdev_schedule_init(void)
-{
- spin_lock_init(&blkio_schedule_list_lock);
- INIT_LIST_HEAD(&blkio_schedule_list);
-
- if ( kernel_thread(blkio_schedule, 0, CLONE_FS | CLONE_FILES) < 0 )
- BUG();
-}
-
-/*-----[ Interrupt entry from a frontend ]------ */
-
-irqreturn_t blkif_ptfe_int(int irq, void *dev_id, struct pt_regs *regs)
-{
- blkif_t *blkif = dev_id;
-
- add_to_blkdev_list_tail(blkif);
- maybe_trigger_blktap_schedule();
- return IRQ_HANDLED;
-}
-
-/*-----[ Other Frontend Ring functions ]-------- */
-
-/* irqreturn_t blkif_ptfe_int(int irq, void *dev_id, struct pt_regs *regs)*/
-static int do_block_io_op(blkif_t *blkif, int max_to_do)
-{
- /* we have pending messages from the real frontend. */
-
- blkif_request_t *req_s;
- RING_IDX i, rp;
- unsigned long flags;
- active_req_t *ar;
- int more_to_do = 0;
- int notify_be = 0, notify_user = 0;
-
- /* lock both rings */
- spin_lock_irqsave(&blkif_io_lock, flags);
-
- rp = blkif->blk_ring.sring->req_prod;
- rmb();
-
- for ( i = blkif->blk_ring.req_cons;
- (i != rp) &&
- !RING_REQUEST_CONS_OVERFLOW(&blkif->blk_ring, i);
- i++ )
- {
-
- if ((--max_to_do == 0) || (NR_ACTIVE_REQS == MAX_ACTIVE_REQS))
- {
- more_to_do = 1;
- break;
- }
-
- req_s = RING_GET_REQUEST(&blkif->blk_ring, i);
- /* This is a new request:
- * Assign an active request record, and remap the id.
- */
- ar = get_active_req();
- ar->id = req_s->id;
- ar->nr_pages = req_s->nr_segments;
- blkif_get(blkif);
- ar->blkif = blkif;
- req_s->id = MAKE_ID(blkif->domid, ACTIVE_IDX(ar));
- /* WPRINTK("%3u < %3lu\n", ID_TO_IDX(req_s->id), ar->id); */
-
- /* FE -> BE interposition point is here. */
-
- /* ------------------------------------------------------------- */
- /* BLKIF_OP_PROBE_HACK: */
- /* Signal to the backend that we are a tap domain. */
-
- if (req_s->operation == BLKIF_OP_PROBE) {
- DPRINTK("Adding BLKTAP_COOKIE to PROBE request.\n");
- req_s->frame_and_sects[1] = BLKTAP_COOKIE;
- }
-
- /* ------------------------------------------------------------- */
-
- /* If we are in MODE_INTERCEPT_FE or MODE_COPY_FE: */
- if ( (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) ||
- (blktap_mode & BLKTAP_MODE_COPY_FE) ) {
-
- /* Copy the response message to UFERing */
- /* In MODE_INTERCEPT_FE, map attached pages into the app vma */
- /* In MODE_COPY_FE_PAGES, copy attached pages into the app vma */
-
- DPRINTK("req->UFERing\n");
- blktap_write_fe_ring(req_s);
- notify_user = 1;
- }
-
- /* If we are not in MODE_INTERCEPT_FE or MODE_INTERCEPT_BE: */
- if ( !((blktap_mode & BLKTAP_MODE_INTERCEPT_FE) ||
- (blktap_mode & BLKTAP_MODE_INTERCEPT_BE)) ) {
-
- /* be included to prevent noise from the fe when its off */
- /* copy the request message to the BERing */
-
- DPRINTK("blktap: FERing[%u] -> BERing[%u]\n",
- (unsigned)i & (RING_SIZE(&blktap_be_ring)-1),
- (unsigned)blktap_be_ring.req_prod_pvt &
- (RING_SIZE((&blktap_be_ring)-1)));
-
- write_req_to_be_ring(req_s);
- notify_be = 1;
- }
- }
-
- blkif->blk_ring.req_cons = i;
-
- /* unlock rings */
- spin_unlock_irqrestore(&blkif_io_lock, flags);
-
- if (notify_user)
- blktap_kick_user();
- if (notify_be)
- kick_be_domain();
-
- return more_to_do;
-}
-
-/*-----[ Data to/from Backend (server) VM ]------------------------------*/
-
-
-irqreturn_t blkif_ptbe_int(int irq, void *dev_id,
- struct pt_regs *ptregs)
-{
- blkif_response_t *resp_s;
- blkif_t *blkif;
- RING_IDX rp, i;
- unsigned long flags;
-
- DPRINTK("PT got BE interrupt.\n");
-
- /* lock both rings */
- spin_lock_irqsave(&blkif_io_lock, flags);
-
- rp = blktap_be_ring.sring->rsp_prod;
- rmb();
-
- for ( i = blktap_be_ring.rsp_cons; i != rp; i++)
- {
- resp_s = RING_GET_RESPONSE(&blktap_be_ring, i);
-
- /* BE -> FE interposition point is here. */
-
- blkif = active_reqs[ID_TO_IDX(resp_s->id)].blkif;
-
- /* If we are in MODE_INTERCEPT_BE or MODE_COPY_BE: */
- if ( (blktap_mode & BLKTAP_MODE_INTERCEPT_BE) ||
- (blktap_mode & BLKTAP_MODE_COPY_BE) ) {
-
- /* Copy the response message to UBERing */
- /* In MODE_INTERCEPT_BE, map attached pages into the app vma */
- /* In MODE_COPY_BE_PAGES, copy attached pages into the app vma */
-
- DPRINTK("rsp->UBERing\n");
- blktap_write_be_ring(resp_s);
- blktap_kick_user();
-
- }
-
- /* If we are NOT in MODE_INTERCEPT_BE or MODE_INTERCEPT_FE: */
- if ( !((blktap_mode & BLKTAP_MODE_INTERCEPT_BE) ||
- (blktap_mode & BLKTAP_MODE_INTERCEPT_FE)) ) {
-
- /* (fe included to prevent random interference from the BE) */
- /* Copy the response message to FERing */
-
- DPRINTK("blktap: BERing[%u] -> FERing[%u]\n",
- (unsigned)i & (RING_SIZE(&blkif->blk_ring)-1),
- (unsigned)blkif->blk_ring.rsp_prod_pvt &
- (RING_SIZE((&blkif->blk_ring)-1)));
-
- write_resp_to_fe_ring(blkif, resp_s);
- kick_fe_domain(blkif);
-
- }
- }
-
- blktap_be_ring.rsp_cons = i;
-
-
- spin_unlock_irqrestore(&blkif_io_lock, flags);
-
- return IRQ_HANDLED;
-}
-
-/* Debug : print the current ring indices. */
-
-void print_be_ring_idxs(void)
-{
- if (blktap_be_ring.sring != NULL) {
- WPRINTK("BE Ring: \n--------\n");
- WPRINTK("BE: rsp_cons: %2d, req_prod_prv: %2d "
- "| req_prod: %2d, rsp_prod: %2d\n",
- blktap_be_ring.rsp_cons,
- blktap_be_ring.req_prod_pvt,
- blktap_be_ring.sring->req_prod,
- blktap_be_ring.sring->rsp_prod);
- }
-}
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/drivers/xen/blktap/blktap_userdev.c
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap_userdev.c Thu Sep 8
15:18:40 2005
+++ /dev/null Fri Sep 9 16:30:54 2005
@@ -1,801 +0,0 @@
-/******************************************************************************
- * blktap_userdev.c
- *
- * XenLinux virtual block-device tap.
- * Control interface between the driver and a character device.
- *
- * Copyright (c) 2004, Andrew Warfield
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/miscdevice.h>
-#include <linux/errno.h>
-#include <linux/major.h>
-#include <linux/gfp.h>
-#include <linux/poll.h>
-#include <asm/pgalloc.h>
-#include <asm/tlbflush.h>
-#include <asm-xen/xen-public/io/blkif.h> /* for control ring. */
-#ifdef CONFIG_XEN_BLKDEV_GRANT
-#include <asm-xen/xen-public/grant_table.h>
-#endif
-
-#include "blktap.h"
-
-
-unsigned long blktap_mode = BLKTAP_MODE_PASSTHROUGH;
-
-/* Only one process may open /dev/xen/blktap at any time. */
-static unsigned long blktap_dev_inuse;
-unsigned long blktap_ring_ok; /* make this ring->state */
-
-/* for poll: */
-static wait_queue_head_t blktap_wait;
-
-/* Rings up to user space. */
-static blkif_front_ring_t blktap_ufe_ring;
-static blkif_back_ring_t blktap_ube_ring;
-static ctrl_front_ring_t blktap_uctrl_ring;
-
-/* local prototypes */
-static int blktap_read_fe_ring(void);
-static int blktap_read_be_ring(void);
-
-
-/* -------[ mmap region ]--------------------------------------------- */
-/*
- * We use a big chunk of address space to map in-flight requests into,
- * and export this region up to user-space. See the comments in blkback
- * about this -- the two must be kept in sync if the tap is used as a
- * passthrough.
- */
-
-#define MAX_PENDING_REQS 64
-
-/* immediately before the mmap area, we have a bunch of pages reserved
- * for shared memory rings.
- */
-#define RING_PAGES 3 /* Ctrl, Front, and Back */
-
-/* Where things are inside the device mapping. */
-struct vm_area_struct *blktap_vma = NULL;
-unsigned long mmap_vstart; /* Kernel pages for mapping in data. */
-unsigned long rings_vstart; /* start of mmaped vma */
-unsigned long user_vstart; /* start of user mappings */
-
-#define MMAP_PAGES_PER_REQUEST \
- (BLKIF_MAX_SEGMENTS_PER_REQUEST + 1)
-#define MMAP_PAGES \
- (MAX_PENDING_REQS * MMAP_PAGES_PER_REQUEST)
-#define MMAP_VADDR(_start, _req,_seg) \
- ( _start + \
- ((_req) * MMAP_PAGES_PER_REQUEST * PAGE_SIZE) + \
- ((_seg) * PAGE_SIZE))
-
-/* -------[ grant handles ]------------------------------------------- */
-
-#ifdef CONFIG_XEN_BLKDEV_GRANT
-/* When using grant tables to map a frame for device access then the
- * handle returned must be used to unmap the frame. This is needed to
- * drop the ref count on the frame.
- */
-struct grant_handle_pair
-{
- u16 kernel;
- u16 user;
-};
-static struct grant_handle_pair pending_grant_handles[MMAP_PAGES];
-#define pending_handle(_idx, _i) \
- (pending_grant_handles[((_idx) * BLKIF_MAX_SEGMENTS_PER_REQUEST) + (_i)])
-#define BLKTAP_INVALID_HANDLE(_g) \
- (((_g->kernel) == 0xFFFF) && ((_g->user) == 0xFFFF))
-#define BLKTAP_INVALIDATE_HANDLE(_g) do { \
- (_g)->kernel = 0xFFFF; (_g)->user = 0xFFFF; \
- } while(0)
-
-#endif
-
-
-/* -------[ blktap vm ops ]------------------------------------------- */
-
-static struct page *blktap_nopage(struct vm_area_struct *vma,
- unsigned long address,
- int *type)
-{
- /*
- * if the page has not been mapped in by the driver then generate
- * a SIGBUS to the domain.
- */
-
- force_sig(SIGBUS, current);
-
- return 0;
-}
-
-struct vm_operations_struct blktap_vm_ops = {
- nopage: blktap_nopage,
-};
-
-/* -------[ blktap file ops ]----------------------------------------- */
-
-static int blktap_open(struct inode *inode, struct file *filp)
-{
- blkif_sring_t *sring;
- ctrl_sring_t *csring;
-
- if ( test_and_set_bit(0, &blktap_dev_inuse) )
- return -EBUSY;
-
- /* Allocate the ctrl ring. */
- csring = (ctrl_sring_t *)get_zeroed_page(GFP_KERNEL);
- if (csring == NULL)
- goto fail_nomem;
-
- SetPageReserved(virt_to_page(csring));
-
- SHARED_RING_INIT(csring);
- FRONT_RING_INIT(&blktap_uctrl_ring, csring, PAGE_SIZE);
-
- /* Allocate the fe ring. */
- sring = (blkif_sring_t *)get_zeroed_page(GFP_KERNEL);
- if (sring == NULL)
- goto fail_free_ctrl;
-
- SetPageReserved(virt_to_page(sring));
-
- SHARED_RING_INIT(sring);
- FRONT_RING_INIT(&blktap_ufe_ring, sring, PAGE_SIZE);
-
- /* Allocate the be ring. */
- sring = (blkif_sring_t *)get_zeroed_page(GFP_KERNEL);
- if (sring == NULL)
- goto fail_free_fe;
-
- SetPageReserved(virt_to_page(sring));
-
- SHARED_RING_INIT(sring);
- BACK_RING_INIT(&blktap_ube_ring, sring, PAGE_SIZE);
-
- DPRINTK(KERN_ALERT "blktap open.\n");
-
- return 0;
-
- fail_free_ctrl:
- free_page( (unsigned long) blktap_uctrl_ring.sring);
-
- fail_free_fe:
- free_page( (unsigned long) blktap_ufe_ring.sring);
-
- fail_nomem:
- return -ENOMEM;
-}
-
-static int blktap_release(struct inode *inode, struct file *filp)
-{
- blktap_dev_inuse = 0;
- blktap_ring_ok = 0;
-
- DPRINTK(KERN_ALERT "blktap closed.\n");
-
- /* Free the ring page. */
- ClearPageReserved(virt_to_page(blktap_uctrl_ring.sring));
- free_page((unsigned long) blktap_uctrl_ring.sring);
-
- ClearPageReserved(virt_to_page(blktap_ufe_ring.sring));
- free_page((unsigned long) blktap_ufe_ring.sring);
-
- ClearPageReserved(virt_to_page(blktap_ube_ring.sring));
- free_page((unsigned long) blktap_ube_ring.sring);
-
- /* Clear any active mappings and free foreign map table */
- if (blktap_vma != NULL) {
- zap_page_range(blktap_vma, blktap_vma->vm_start,
- blktap_vma->vm_end - blktap_vma->vm_start, NULL);
- blktap_vma = NULL;
- }
-
- return 0;
-}
-
-/* Note on mmap:
- * We need to map pages to user space in a way that will allow the block
- * subsystem set up direct IO to them. This couldn't be done before, because
- * there isn't really a sane way to make a user virtual address down to a
- * physical address when the page belongs to another domain.
- *
- * My first approach was to map the page in to kernel memory, add an entry
- * for it in the physical frame list (using alloc_lomem_region as in blkback)
- * and then attempt to map that page up to user space. This is disallowed
- * by xen though, which realizes that we don't really own the machine frame
- * underlying the physical page.
- *
- * The new approach is to provide explicit support for this in xen linux.
- * The VMA now has a flag, VM_FOREIGN, to indicate that it contains pages
- * mapped from other vms. vma->vm_private_data is set up as a mapping
- * from pages to actual page structs. There is a new clause in get_user_pages
- * that does the right thing for this sort of mapping.
- *
- * blktap_mmap sets up this mapping. Most of the real work is done in
- * blktap_write_fe_ring below.
- */
-static int blktap_mmap(struct file *filp, struct vm_area_struct *vma)
-{
- int size;
- struct page **map;
- int i;
-
- DPRINTK(KERN_ALERT "blktap mmap (%lx, %lx)\n",
- vma->vm_start, vma->vm_end);
-
- vma->vm_flags |= VM_RESERVED;
- vma->vm_ops = &blktap_vm_ops;
-
- size = vma->vm_end - vma->vm_start;
- if ( size != ( (MMAP_PAGES + RING_PAGES) << PAGE_SHIFT ) ) {
- printk(KERN_INFO
- "blktap: you _must_ map exactly %d pages!\n",
- MMAP_PAGES + RING_PAGES);
- return -EAGAIN;
- }
-
- size >>= PAGE_SHIFT;
- DPRINTK(KERN_INFO "blktap: 2 rings + %d pages.\n", size-1);
-
- rings_vstart = vma->vm_start;
- user_vstart = rings_vstart + (RING_PAGES << PAGE_SHIFT);
-
- /* Map the ring pages to the start of the region and reserve it. */
-
- /* not sure if I really need to do this... */
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
- DPRINTK("Mapping ctrl_ring page %lx.\n", __pa(blktap_uctrl_ring.sring));
- if (remap_pfn_range(vma, vma->vm_start,
- __pa(blktap_uctrl_ring.sring) >> PAGE_SHIFT,
- PAGE_SIZE, vma->vm_page_prot))
- goto fail;
-
-
- DPRINTK("Mapping be_ring page %lx.\n", __pa(blktap_ube_ring.sring));
- if (remap_pfn_range(vma, vma->vm_start + PAGE_SIZE,
- __pa(blktap_ube_ring.sring) >> PAGE_SHIFT,
- PAGE_SIZE, vma->vm_page_prot))
- goto fail;
-
- DPRINTK("Mapping fe_ring page %lx.\n", __pa(blktap_ufe_ring.sring));
- if (remap_pfn_range(vma, vma->vm_start + ( 2 * PAGE_SIZE ),
- __pa(blktap_ufe_ring.sring) >> PAGE_SHIFT,
- PAGE_SIZE, vma->vm_page_prot))
- goto fail;
-
- /* Mark this VM as containing foreign pages, and set up mappings. */
- map = kmalloc(((vma->vm_end - vma->vm_start) >> PAGE_SHIFT)
- * sizeof(struct page_struct*),
- GFP_KERNEL);
- if (map == NULL) goto fail;
-
- for (i=0; i<((vma->vm_end - vma->vm_start) >> PAGE_SHIFT); i++)
- map[i] = NULL;
-
- vma->vm_private_data = map;
- vma->vm_flags |= VM_FOREIGN;
-
- blktap_vma = vma;
- blktap_ring_ok = 1;
-
- return 0;
- fail:
- /* Clear any active mappings. */
- zap_page_range(vma, vma->vm_start,
- vma->vm_end - vma->vm_start, NULL);
-
- return -ENOMEM;
-}
-
-static int blktap_ioctl(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- switch(cmd) {
- case BLKTAP_IOCTL_KICK_FE: /* There are fe messages to process. */
- return blktap_read_fe_ring();
-
- case BLKTAP_IOCTL_KICK_BE: /* There are be messages to process. */
- return blktap_read_be_ring();
-
- case BLKTAP_IOCTL_SETMODE:
- if (BLKTAP_MODE_VALID(arg)) {
- blktap_mode = arg;
- /* XXX: may need to flush rings here. */
- printk(KERN_INFO "blktap: set mode to %lx\n", arg);
- return 0;
- }
- case BLKTAP_IOCTL_PRINT_IDXS:
- {
- print_be_ring_idxs();
- print_fe_ring_idxs();
- WPRINTK("User Rings: \n-----------\n");
- WPRINTK("UF: rsp_cons: %2d, req_prod_prv: %2d "
- "| req_prod: %2d, rsp_prod: %2d\n",
- blktap_ufe_ring.rsp_cons,
- blktap_ufe_ring.req_prod_pvt,
- blktap_ufe_ring.sring->req_prod,
- blktap_ufe_ring.sring->rsp_prod);
- WPRINTK("UB: req_cons: %2d, rsp_prod_prv: %2d "
- "| req_prod: %2d, rsp_prod: %2d\n",
- blktap_ube_ring.req_cons,
- blktap_ube_ring.rsp_prod_pvt,
- blktap_ube_ring.sring->req_prod,
- blktap_ube_ring.sring->rsp_prod);
-
- }
- }
- return -ENOIOCTLCMD;
-}
-
-static unsigned int blktap_poll(struct file *file, poll_table *wait)
-{
- poll_wait(file, &blktap_wait, wait);
-
- if ( RING_HAS_UNPUSHED_REQUESTS(&blktap_uctrl_ring) ||
- RING_HAS_UNPUSHED_REQUESTS(&blktap_ufe_ring) ||
- RING_HAS_UNPUSHED_RESPONSES(&blktap_ube_ring) ) {
-
- flush_tlb_all();
-
- RING_PUSH_REQUESTS(&blktap_uctrl_ring);
- RING_PUSH_REQUESTS(&blktap_ufe_ring);
- RING_PUSH_RESPONSES(&blktap_ube_ring);
- return POLLIN | POLLRDNORM;
- }
-
- return 0;
-}
-
-void blktap_kick_user(void)
-{
- /* blktap_ring->req_prod = blktap_req_prod; */
- wake_up_interruptible(&blktap_wait);
-}
-
-static struct file_operations blktap_fops = {
- owner: THIS_MODULE,
- poll: blktap_poll,
- ioctl: blktap_ioctl,
- open: blktap_open,
- release: blktap_release,
- mmap: blktap_mmap,
-};
-
-/*-----[ Data to/from user space ]----------------------------------------*/
-
-static void fast_flush_area(int idx, int nr_pages)
-{
-#ifdef CONFIG_XEN_BLKDEV_GRANT
- struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
- unsigned int i, op = 0;
- struct grant_handle_pair *handle;
- unsigned long ptep;
-
- for (i=0; i<nr_pages; i++)
- {
- handle = &pending_handle(idx, i);
- if (!BLKTAP_INVALID_HANDLE(handle))
- {
-
- unmap[op].host_addr = MMAP_VADDR(mmap_vstart, idx, i);
- unmap[op].dev_bus_addr = 0;
- unmap[op].handle = handle->kernel;
- op++;
-
- if (create_lookup_pte_addr(blktap_vma->vm_mm,
- MMAP_VADDR(user_vstart, idx, i),
- &ptep) !=0) {
- DPRINTK("Couldn't get a pte addr!\n");
- return;
- }
- unmap[op].host_addr = ptep;
- unmap[op].dev_bus_addr = 0;
- unmap[op].handle = handle->user;
- op++;
-
- BLKTAP_INVALIDATE_HANDLE(handle);
- }
- }
- if ( unlikely(HYPERVISOR_grant_table_op(
- GNTTABOP_unmap_grant_ref, unmap, op)))
- BUG();
-#else
- multicall_entry_t mcl[BLKIF_MAX_SEGMENTS_PER_REQUEST];
- int i;
-
- for ( i = 0; i < nr_pages; i++ )
- {
- MULTI_update_va_mapping(mcl+i, MMAP_VADDR(mmap_vstart, idx, i),
- __pte(0), 0);
- }
-
- mcl[nr_pages-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
- if ( unlikely(HYPERVISOR_multicall(mcl, nr_pages) != 0) )
- BUG();
-#endif
-}
-
-
-int blktap_write_fe_ring(blkif_request_t *req)
-{
- blkif_request_t *target;
- int i, ret = 0;
-#ifdef CONFIG_XEN_BLKDEV_GRANT
- struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
- int op;
-#else
- unsigned long remap_prot;
- multicall_entry_t mcl[BLKIF_MAX_SEGMENTS_PER_REQUEST+1];
- mmu_update_t mmu[BLKIF_MAX_SEGMENTS_PER_REQUEST];
-#endif
-
- /*
- * This is called to pass a request from the real frontend domain's
- * blkif ring to the character device.
- */
-
- if ( ! blktap_ring_ok ) {
- DPRINTK("blktap: ufe_ring not ready for a request!\n");
- return 0;
- }
-
- if ( RING_FULL(&blktap_ufe_ring) ) {
- PRINTK("blktap: fe_ring is full, can't add.\n");
- return 0;
- }
-
- flush_cache_all(); /* a noop on intel... */
-
- target = RING_GET_REQUEST(&blktap_ufe_ring, blktap_ufe_ring.req_prod_pvt);
- memcpy(target, req, sizeof(*req));
-
- /* Map the foreign pages directly in to the application */
-#ifdef CONFIG_XEN_BLKDEV_GRANT
- op = 0;
- for (i=0; i<target->nr_segments; i++) {
-
- unsigned long uvaddr;
- unsigned long kvaddr;
- unsigned long ptep;
-
- uvaddr = MMAP_VADDR(user_vstart, ID_TO_IDX(req->id), i);
- kvaddr = MMAP_VADDR(mmap_vstart, ID_TO_IDX(req->id), i);
-
- /* Map the remote page to kernel. */
- map[op].host_addr = kvaddr;
- map[op].dom = ID_TO_DOM(req->id);
- map[op].ref = blkif_gref_from_fas(target->frame_and_sects[i]);
- map[op].flags = GNTMAP_host_map;
- /* This needs a bit more thought in terms of interposition:
- * If we want to be able to modify pages during write using
- * grant table mappings, the guest will either need to allow
- * it, or we'll need to incur a copy. */
- if (req->operation == BLKIF_OP_WRITE)
- map[op].flags |= GNTMAP_readonly;
- op++;
-
- /* Now map it to user. */
- ret = create_lookup_pte_addr(blktap_vma->vm_mm, uvaddr, &ptep);
- if (ret)
- {
- DPRINTK("Couldn't get a pte addr!\n");
- goto fail;
- }
-
- map[op].host_addr = ptep;
- map[op].dom = ID_TO_DOM(req->id);
- map[op].ref = blkif_gref_from_fas(target->frame_and_sects[i]);
- map[op].flags = GNTMAP_host_map | GNTMAP_application_map
- | GNTMAP_contains_pte;
- /* Above interposition comment applies here as well. */
- if (req->operation == BLKIF_OP_WRITE)
- map[op].flags |= GNTMAP_readonly;
- op++;
- }
-
- if ( unlikely(HYPERVISOR_grant_table_op(
- GNTTABOP_map_grant_ref, map, op)))
- BUG();
-
- op = 0;
- for (i=0; i<(target->nr_segments*2); i+=2) {
- unsigned long uvaddr;
- unsigned long kvaddr;
- unsigned long offset;
- int cancel = 0;
-
- uvaddr = MMAP_VADDR(user_vstart, ID_TO_IDX(req->id), i/2);
- kvaddr = MMAP_VADDR(mmap_vstart, ID_TO_IDX(req->id), i/2);
-
- if ( unlikely(map[i].handle < 0) ) {
- DPRINTK("Error on kernel grant mapping (%d)\n", map[i].handle);
- ret = map[i].handle;
- cancel = 1;
- }
-
- if ( unlikely(map[i+1].handle < 0) ) {
- DPRINTK("Error on user grant mapping (%d)\n", map[i+1].handle);
- ret = map[i+1].handle;
- cancel = 1;
- }
-
- if (cancel)
- goto fail;
-
- /* Set the necessary mappings in p2m and in the VM_FOREIGN
- * vm_area_struct to allow user vaddr -> struct page lookups
- * to work. This is needed for direct IO to foreign pages. */
- phys_to_machine_mapping[__pa(kvaddr) >> PAGE_SHIFT] =
- FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT);
-
- offset = (uvaddr - blktap_vma->vm_start) >> PAGE_SHIFT;
- ((struct page **)blktap_vma->vm_private_data)[offset] =
- pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT);
-
- /* Save handles for unmapping later. */
- pending_handle(ID_TO_IDX(req->id), i/2).kernel = map[i].handle;
- pending_handle(ID_TO_IDX(req->id), i/2).user = map[i+1].handle;
- }
-
-#else
-
- remap_prot = _PAGE_PRESENT|_PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_RW;
-
- for (i=0; i<target->nr_segments; i++) {
- unsigned long buf;
- unsigned long uvaddr;
- unsigned long kvaddr;
- unsigned long offset;
- unsigned long ptep;
-
- buf = target->frame_and_sects[i] & PAGE_MASK;
- uvaddr = MMAP_VADDR(user_vstart, ID_TO_IDX(req->id), i);
- kvaddr = MMAP_VADDR(mmap_vstart, ID_TO_IDX(req->id), i);
-
- MULTI_update_va_mapping_otherdomain(
- mcl+i,
- kvaddr,
- pfn_pte_ma(buf >> PAGE_SHIFT, __pgprot(remap_prot)),
- 0,
- ID_TO_DOM(req->id));
-
- phys_to_machine_mapping[__pa(kvaddr)>>PAGE_SHIFT] =
- FOREIGN_FRAME(buf >> PAGE_SHIFT);
-
- ret = create_lookup_pte_addr(blktap_vma->vm_mm, uvaddr, &ptep);
- if (ret)
- {
- DPRINTK("error getting pte\n");
- goto fail;
- }
-
- mmu[i].ptr = ptep;
- mmu[i].val = (target->frame_and_sects[i] & PAGE_MASK)
- | pgprot_val(blktap_vma->vm_page_prot);
-
- offset = (uvaddr - blktap_vma->vm_start) >> PAGE_SHIFT;
- ((struct page **)blktap_vma->vm_private_data)[offset] =
- pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT);
- }
-
- /* Add the mmu_update call. */
- mcl[i].op = __HYPERVISOR_mmu_update;
- mcl[i].args[0] = (unsigned long)mmu;
- mcl[i].args[1] = target->nr_segments;
- mcl[i].args[2] = 0;
- mcl[i].args[3] = ID_TO_DOM(req->id);
-
- BUG_ON(HYPERVISOR_multicall(mcl, target->nr_segments+1) != 0);
-
- /* Make sure it all worked. */
- for ( i = 0; i < target->nr_segments; i++ )
- {
- if ( unlikely(mcl[i].result != 0) )
- {
- DPRINTK("invalid buffer -- could not remap it\n");
- ret = mcl[i].result;
- goto fail;
- }
- }
- if ( unlikely(mcl[i].result != 0) )
- {
- DPRINTK("direct remapping of pages to /dev/blktap failed.\n");
- ret = mcl[i].result;
- goto fail;
- }
-#endif /* CONFIG_XEN_BLKDEV_GRANT */
-
- /* Mark mapped pages as reserved: */
- for ( i = 0; i < target->nr_segments; i++ )
- {
- unsigned long kvaddr;
-
- kvaddr = MMAP_VADDR(mmap_vstart, ID_TO_IDX(req->id), i);
- SetPageReserved(pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT));
- }
-
-
- blktap_ufe_ring.req_prod_pvt++;
-
- return 0;
-
- fail:
- fast_flush_area(ID_TO_IDX(req->id), target->nr_segments);
- return ret;
-}
-
-int blktap_write_be_ring(blkif_response_t *rsp)
-{
- blkif_response_t *target;
-
- /*
- * This is called to pass a request from the real backend domain's
- * blkif ring to the character device.
- */
-
- if ( ! blktap_ring_ok ) {
- DPRINTK("blktap: be_ring not ready for a request!\n");
- return 0;
- }
-
- /* No test for fullness in the response direction. */
-
- target = RING_GET_RESPONSE(&blktap_ube_ring,
- blktap_ube_ring.rsp_prod_pvt);
- memcpy(target, rsp, sizeof(*rsp));
-
- /* no mapping -- pages were mapped in blktap_write_fe_ring() */
-
- blktap_ube_ring.rsp_prod_pvt++;
-
- return 0;
-}
-
-static int blktap_read_fe_ring(void)
-{
- /* This is called to read responses from the UFE ring. */
-
- RING_IDX i, j, rp;
- blkif_response_t *resp_s;
- blkif_t *blkif;
- active_req_t *ar;
-
- DPRINTK("blktap_read_fe_ring()\n");
-
- /* if we are forwarding from UFERring to FERing */
- if (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) {
-
- /* for each outstanding message on the UFEring */
- rp = blktap_ufe_ring.sring->rsp_prod;
- rmb();
-
- for ( i = blktap_ufe_ring.rsp_cons; i != rp; i++ )
- {
- resp_s = RING_GET_RESPONSE(&blktap_ufe_ring, i);
-
- DPRINTK("resp->fe_ring\n");
- ar = lookup_active_req(ID_TO_IDX(resp_s->id));
- blkif = ar->blkif;
- for (j = 0; j < ar->nr_pages; j++) {
- unsigned long vaddr;
- struct page **map = blktap_vma->vm_private_data;
- int offset;
-
- vaddr = MMAP_VADDR(user_vstart, ID_TO_IDX(resp_s->id), j);
- offset = (vaddr - blktap_vma->vm_start) >> PAGE_SHIFT;
-
- ClearPageReserved(virt_to_page(vaddr));
- map[offset] = NULL;
- }
-
- fast_flush_area(ID_TO_IDX(resp_s->id), ar->nr_pages);
- zap_page_range(blktap_vma,
- MMAP_VADDR(user_vstart, ID_TO_IDX(resp_s->id), 0),
- ar->nr_pages << PAGE_SHIFT, NULL);
- write_resp_to_fe_ring(blkif, resp_s);
- blktap_ufe_ring.rsp_cons = i + 1;
- kick_fe_domain(blkif);
- }
- }
- return 0;
-}
-
-static int blktap_read_be_ring(void)
-{
- /* This is called to read requests from the UBE ring. */
-
- RING_IDX i, rp;
- blkif_request_t *req_s;
-
- DPRINTK("blktap_read_be_ring()\n");
-
- /* if we are forwarding from UFERring to FERing */
- if (blktap_mode & BLKTAP_MODE_INTERCEPT_BE) {
-
- /* for each outstanding message on the UFEring */
- rp = blktap_ube_ring.sring->req_prod;
- rmb();
- for ( i = blktap_ube_ring.req_cons; i != rp; i++ )
- {
- req_s = RING_GET_REQUEST(&blktap_ube_ring, i);
-
- DPRINTK("req->be_ring\n");
- write_req_to_be_ring(req_s);
- kick_be_domain();
- }
-
- blktap_ube_ring.req_cons = i;
- }
-
- return 0;
-}
-
-int blktap_write_ctrl_ring(ctrl_msg_t *msg)
-{
- ctrl_msg_t *target;
-
- if ( ! blktap_ring_ok ) {
- DPRINTK("blktap: be_ring not ready for a request!\n");
- return 0;
- }
-
- /* No test for fullness in the response direction. */
-
- target = RING_GET_REQUEST(&blktap_uctrl_ring,
- blktap_uctrl_ring.req_prod_pvt);
- memcpy(target, msg, sizeof(*msg));
-
- blktap_uctrl_ring.req_prod_pvt++;
-
- /* currently treat the ring as unidirectional. */
- blktap_uctrl_ring.rsp_cons = blktap_uctrl_ring.sring->rsp_prod;
-
- return 0;
-
-}
-
-/* -------[ blktap module setup ]------------------------------------- */
-
-static struct miscdevice blktap_miscdev = {
- .minor = BLKTAP_MINOR,
- .name = "blktap",
- .fops = &blktap_fops,
- .devfs_name = "misc/blktap",
-};
-
-int blktap_init(void)
-{
- int err, i, j;
- struct page *page;
-
- page = balloon_alloc_empty_page_range(MMAP_PAGES);
- BUG_ON(page == NULL);
- mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
-
-#ifdef CONFIG_XEN_BLKDEV_GRANT
- for (i=0; i<MAX_PENDING_REQS ; i++)
- for (j=0; j<BLKIF_MAX_SEGMENTS_PER_REQUEST; j++)
- BLKTAP_INVALIDATE_HANDLE(&pending_handle(i, j));
-#endif
-
- err = misc_register(&blktap_miscdev);
- if ( err != 0 )
- {
- printk(KERN_ALERT "Couldn't register /dev/misc/blktap (%d)\n", err);
- return err;
- }
-
- init_waitqueue_head(&blktap_wait);
-
-
- return 0;
-}
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/include/asm-xen/ctrl_if.h
--- a/linux-2.6-xen-sparse/include/asm-xen/ctrl_if.h Thu Sep 8 15:18:40 2005
+++ /dev/null Fri Sep 9 16:30:54 2005
@@ -1,160 +0,0 @@
-/******************************************************************************
- * ctrl_if.h
- *
- * Management functions for special interface to the domain controller.
- *
- * Copyright (c) 2004, K A Fraser
- *
- * This file may be distributed separately from the Linux kernel, or
- * incorporated into other software packages, subject to the following license:
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this source file (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy, modify,
- * merge, publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef __ASM_XEN__CTRL_IF_H__
-#define __ASM_XEN__CTRL_IF_H__
-
-#include <asm-xen/hypervisor.h>
-#include <asm-xen/queues.h>
-
-typedef control_msg_t ctrl_msg_t;
-
-/*
- * Callback function type. Called for asynchronous processing of received
- * request messages, and responses to previously-transmitted request messages.
- * The parameters are (@msg, @id).
- * @msg: Original request/response message (not a copy). The message can be
- * modified in-place by the handler (e.g., a response callback can
- * turn a request message into a response message in place). The message
- * is no longer accessible after the callback handler returns -- if the
- * message is required to persist for longer then it must be copied.
- * @id: (Response callbacks only) The 'id' that was specified when the
- * original request message was queued for transmission.
- */
-typedef void (*ctrl_msg_handler_t)(ctrl_msg_t *, unsigned long);
-
-/*
- * Send @msg to the domain controller. Execute @hnd when a response is
- * received, passing the response message and the specified @id. This
- * operation will not block: it will return -EAGAIN if there is no space.
- * Notes:
- * 1. The @msg is copied if it is transmitted and so can be freed after this
- * function returns.
- * 2. If @hnd is NULL then no callback is executed.
- */
-int
-ctrl_if_send_message_noblock(
- ctrl_msg_t *msg,
- ctrl_msg_handler_t hnd,
- unsigned long id);
-
-/*
- * Send @msg to the domain controller. Execute @hnd when a response is
- * received, passing the response message and the specified @id. This
- * operation will block until the message is sent, or a signal is received
- * for the calling process (unless @wait_state is TASK_UNINTERRUPTIBLE).
- * Notes:
- * 1. The @msg is copied if it is transmitted and so can be freed after this
- * function returns.
- * 2. If @hnd is NULL then no callback is executed.
- */
-int
-ctrl_if_send_message_block(
- ctrl_msg_t *msg,
- ctrl_msg_handler_t hnd,
- unsigned long id,
- long wait_state);
-
-/*
- * Send @msg to the domain controller. Block until the response is received,
- * and then copy it into the provided buffer, @rmsg.
- */
-int
-ctrl_if_send_message_and_get_response(
- ctrl_msg_t *msg,
- ctrl_msg_t *rmsg,
- long wait_state);
-
-/*
- * Request a callback when there is /possibly/ space to immediately send a
- * message to the domain controller. This function returns 0 if there is
- * already space to trasnmit a message --- in this case the callback task /may/
- * still be executed. If this function returns 1 then the callback /will/ be
- * executed when space becomes available.
- */
-int
-ctrl_if_enqueue_space_callback(
- struct tq_struct *task);
-
-/*
- * Send a response (@msg) to a message from the domain controller. This will
- * never block.
- * Notes:
- * 1. The @msg is copied and so can be freed after this function returns.
- * 2. The @msg may be the original request message, modified in-place.
- */
-void
-ctrl_if_send_response(
- ctrl_msg_t *msg);
-
-/*
- * Register a receiver for typed messages from the domain controller. The
- * handler (@hnd) is called for every received message of specified @type.
- * Returns TRUE (non-zero) if the handler was successfully registered.
- * If CALLBACK_IN_BLOCKING CONTEXT is specified in @flags then callbacks will
- * occur in a context in which it is safe to yield (i.e., process context).
- */
-#define CALLBACK_IN_BLOCKING_CONTEXT 1
-int ctrl_if_register_receiver(
- u8 type,
- ctrl_msg_handler_t hnd,
- unsigned int flags);
-
-/*
- * Unregister a receiver for typed messages from the domain controller. The
- * handler (@hnd) will not be executed after this function returns.
- */
-void
-ctrl_if_unregister_receiver(
- u8 type, ctrl_msg_handler_t hnd);
-
-/* Suspend/resume notifications. */
-void ctrl_if_suspend(void);
-void ctrl_if_resume(void);
-
-/* Start-of-day setup. */
-void ctrl_if_init(void);
-
-/*
- * Returns TRUE if there are no outstanding message requests at the domain
- * controller. This can be used to ensure that messages have really flushed
- * through when it is not possible to use the response-callback interface.
- * WARNING: If other subsystems are using the control interface then this
- * function might never return TRUE!
- */
-int ctrl_if_transmitter_empty(void); /* !! DANGEROUS FUNCTION !! */
-
-/*
- * Manually discard response messages from the domain controller.
- * WARNING: This is usually done automatically -- this function should only
- * be called when normal interrupt mechanisms are disabled!
- */
-void ctrl_if_discard_responses(void); /* !! DANGEROUS FUNCTION !! */
-
-#endif /* __ASM_XEN__CONTROL_IF_H__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0
linux-2.6-xen-sparse/include/asm-xen/linux-public/suspend.h
--- a/linux-2.6-xen-sparse/include/asm-xen/linux-public/suspend.h Thu Sep
8 15:18:40 2005
+++ /dev/null Fri Sep 9 16:30:54 2005
@@ -1,43 +0,0 @@
-/******************************************************************************
- * suspend.h
- *
- * Copyright (c) 2003-2004, K A Fraser
- *
- * This file may be distributed separately from the Linux kernel, or
- * incorporated into other software packages, subject to the following license:
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this source file (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy, modify,
- * merge, publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef __ASM_XEN_SUSPEND_H__
-#define __ASM_XEN_SUSPEND_H__
-
-typedef struct suspend_record_st {
- /* To be filled in before resume. */
- start_info_t resume_info;
- /*
- * The number of a machine frame containing, in sequence, the number of
- * each machine frame that contains PFN -> MFN translation table data.
- */
- unsigned long pfn_to_mfn_frame_list;
- /* Number of entries in the PFN -> MFN translation table. */
- unsigned long nr_pfns;
-} suspend_record_t;
-
-#endif /* __ASM_XEN_SUSPEND_H__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/check/check_curl_devel
--- a/tools/check/check_curl_devel Thu Sep 8 15:18:40 2005
+++ /dev/null Fri Sep 9 16:30:54 2005
@@ -1,11 +0,0 @@
-#!/bin/bash
-# CHECK-BUILD
-
-function error {
- echo 'Check for libcurl includes failed.'
- exit 1
-}
-
-set -e
-[ -e /usr/include/curl ] || error
-[ -e /usr/include/curl/curl.h ] || error
\ No newline at end of file
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/check/check_curl_lib
--- a/tools/check/check_curl_lib Thu Sep 8 15:18:40 2005
+++ /dev/null Fri Sep 9 16:30:54 2005
@@ -1,10 +0,0 @@
-#!/bin/bash
-# CHECK-BUILD CHECK-INSTALL
-
-function error {
- echo 'Check for CURL library failed.'
- exit 1
-}
-
-set -e
-ldconfig -p | grep libcurl.so || error
\ No newline at end of file
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/examples/backend.hotplug
--- a/tools/examples/backend.hotplug Thu Sep 8 15:18:40 2005
+++ /dev/null Fri Sep 9 16:30:54 2005
@@ -1,21 +0,0 @@
-#! /bin/sh
-
-#DEVPATH=/devices/xen-backend/vif-1-0
-#ACTION=add
-
-PATH=/etc/xen/scripts:$PATH
-
-DEV=$(basename "$DEVPATH")
-case "$ACTION" in
- add)
- case "$DEV" in
- vif-*)
- vif=$(echo "$DEV" | sed 's/-\([0-9]*\)-\([0-9]*\)/\1.\2/')
- vif-bridge up domain=unknown vif="$vif" mac=fe:ff:ff:ff:ff:ff
bridge=xen-br0 >/dev/null 2>&1
- ;;
- esac
- ;;
- remove)
- ;;
-esac
-
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/firmware/vmxassist/TODO
--- a/tools/firmware/vmxassist/TODO Thu Sep 8 15:18:40 2005
+++ /dev/null Fri Sep 9 16:30:54 2005
@@ -1,8 +0,0 @@
-
-- Use the VME extensions (interrupt handling)
-
-- Use E820 map in vmxassist instead of cmos hack
-
-- Add ACPI support (Nitin's patch)
-
-
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/lowlevel/xu/xu.c
--- a/tools/python/xen/lowlevel/xu/xu.c Thu Sep 8 15:18:40 2005
+++ /dev/null Fri Sep 9 16:30:54 2005
@@ -1,1781 +0,0 @@
-/******************************************************************************
- * utils.c
- *
- * Copyright (c) 2004, K A Fraser
- */
-
-#include <Python.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/mman.h>
-#include <sys/poll.h>
-#include <sys/sysmacros.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <signal.h>
-#include <xenctrl.h>
-
-#include <xen/xen.h>
-#include <xen/io/domain_controller.h>
-#include <xen/linux/privcmd.h>
-
-#define XENPKG "xen.lowlevel.xu"
-
-/* Needed for Python versions earlier than 2.3. */
-#ifndef PyMODINIT_FUNC
-#define PyMODINIT_FUNC DL_EXPORT(void)
-#endif
-
-/* NB. The following should be kept in sync with the kernel's evtchn driver. */
-#define EVTCHN_DEV_NAME "/dev/xen/evtchn"
-#define EVTCHN_DEV_MAJOR 10
-#define EVTCHN_DEV_MINOR 201
-/* /dev/xen/evtchn ioctls: */
-/* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
-#define EVTCHN_RESET _IO('E', 1)
-/* EVTCHN_BIND: Bind to teh specified event-channel port. */
-#define EVTCHN_BIND _IO('E', 2)
-/* EVTCHN_UNBIND: Unbind from the specified event-channel port. */
-#define EVTCHN_UNBIND _IO('E', 3)
-
-/* Set the close-on-exec flag on a file descriptor. Doesn't currently bother
- * to check for errors. */
-/*
-static void set_cloexec(int fd)
-{
- int flags = fcntl(fd, F_GETFD, 0);
-
- if ( flags < 0 )
- return;
-
- flags |= FD_CLOEXEC;
- fcntl(fd, F_SETFD, flags);
-}
-*/
-/*
- * *********************** XCS INTERFACE ***********************
- */
-
-#include <arpa/inet.h>
-#include <xcs_proto.h>
-
-static int xcs_ctrl_fd = -1; /* control connection to the xcs server. */
-static int xcs_data_fd = -1; /* data connection to the xcs server. */
-static unsigned long xcs_session_id = 0;
-
-static int xcs_ctrl_send(xcs_msg_t *msg);
-static int xcs_ctrl_read(xcs_msg_t *msg);
-static int xcs_data_send(xcs_msg_t *msg);
-static int xcs_data_read(xcs_msg_t *msg);
-
-static int xcs_connect(char *path)
-{
- struct sockaddr_un addr;
- int ret, len, flags;
- xcs_msg_t msg;
-
- if (xcs_data_fd != -1) /* already connected */
- return 0;
-
- xcs_ctrl_fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (xcs_ctrl_fd < 0)
- {
- printf("error creating xcs socket!\n");
- goto fail;
- }
-
- addr.sun_family = AF_UNIX;
- strcpy(addr.sun_path, path);
- len = sizeof(addr.sun_family) + strlen(addr.sun_path) + 1;
-
- ret = connect(xcs_ctrl_fd, (struct sockaddr *)&addr, len);
- if (ret < 0)
- {
- printf("error connecting to xcs(ctrl)! (%d)\n", errno);
- goto ctrl_fd_fail;
- }
-
- /*set_cloexec(xcs_ctrl_fd);*/
-
- msg.type = XCS_CONNECT_CTRL;
- msg.u.connect.session_id = xcs_session_id;
- xcs_ctrl_send(&msg);
- xcs_ctrl_read(&msg); /* TODO: timeout + error! */
-
- if (msg.result != XCS_RSLT_OK)
- {
- printf("error connecting xcs control channel!\n");
- goto ctrl_fd_fail;
- }
- xcs_session_id = msg.u.connect.session_id;
-
- /* now the data connection. */
- xcs_data_fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (xcs_data_fd < 0)
- {
- printf("error creating xcs data socket!\n");
- goto ctrl_fd_fail;
- }
-
- addr.sun_family = AF_UNIX;
- strcpy(addr.sun_path, path);
- len = sizeof(addr.sun_family) + strlen(addr.sun_path) + 1;
-
- ret = connect(xcs_data_fd, (struct sockaddr *)&addr, len);
- if (ret < 0)
- {
- printf("error connecting to xcs(data)! (%d)\n", errno);
- goto data_fd_fail;
- }
-
- //set_cloexec(xcs_data_fd);
- msg.type = XCS_CONNECT_DATA;
- msg.u.connect.session_id = xcs_session_id;
- xcs_data_send(&msg);
- xcs_data_read(&msg); /* TODO: timeout + error! */
-
- if (msg.result != XCS_RSLT_OK)
- {
- printf("error connecting xcs control channel!\n");
- goto ctrl_fd_fail;
- }
-
- if ( ((flags = fcntl(xcs_data_fd, F_GETFL, 0)) < 0) ||
- (fcntl(xcs_data_fd, F_SETFL, flags | O_NONBLOCK) < 0) )
- {
- printf("Unable to set non-blocking status on data socket.");
- goto data_fd_fail;
- }
-
- return 0;
-
-data_fd_fail:
- close(xcs_data_fd);
- xcs_data_fd = -1;
-
-ctrl_fd_fail:
- close(xcs_ctrl_fd);
- xcs_ctrl_fd = -1;
-
-fail:
- return -1;
-
-}
-
-static void xcs_disconnect(void)
-{
- close(xcs_data_fd);
- xcs_data_fd = -1;
- close(xcs_ctrl_fd);
- xcs_ctrl_fd = -1;
-}
-
-static int xcs_ctrl_read(xcs_msg_t *msg)
-{
- int ret;
-
- ret = read(xcs_ctrl_fd, msg, sizeof(xcs_msg_t));
- return ret;
-}
-
-static int xcs_ctrl_send(xcs_msg_t *msg)
-{
- int ret;
-
- ret = send(xcs_ctrl_fd, msg, sizeof(xcs_msg_t), 0);
- return ret;
-}
-
-static int xcs_data_read(xcs_msg_t *msg)
-{
- int ret;
-
- ret = read(xcs_data_fd, msg, sizeof(xcs_msg_t));
- return ret;
-}
-
-static int xcs_data_send(xcs_msg_t *msg)
-{
- int ret;
-
- ret = send(xcs_data_fd, msg, sizeof(xcs_msg_t), 0);
- return ret;
-}
-
-
-typedef struct kme_st {
- xcs_msg_t msg;
- struct kme_st *next;
-} xcs_msg_ent_t;
-
-
-#define XCS_RING_SIZE 64
-static xcs_msg_ent_t *req_ring[64];
-static unsigned req_prod = 0;
-static unsigned req_cons = 0;
-
-static xcs_msg_ent_t *rsp_ring[64];
-static unsigned rsp_prod = 0;
-static unsigned rsp_cons = 0;
-
-#define REQ_RING_ENT(_idx) (req_ring[(_idx) % XCS_RING_SIZE])
-#define RSP_RING_ENT(_idx) (rsp_ring[(_idx) % XCS_RING_SIZE])
-#define REQ_RING_FULL ( req_prod - req_cons == XCS_RING_SIZE )
-#define RSP_RING_FULL ( rsp_prod - rsp_cons == XCS_RING_SIZE )
-#define REQ_RING_EMPTY ( req_prod == req_cons )
-#define RSP_RING_EMPTY ( rsp_prod == rsp_cons )
-/*
- * *********************** NOTIFIER ***********************
- */
-
-typedef struct {
- PyObject_HEAD;
- int evtchn_fd;
-} xu_notifier_object;
-
-static PyObject *xu_notifier_read(PyObject *self, PyObject *args)
-{
- xcs_msg_ent_t *ent;
- int ret;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- while ((!REQ_RING_FULL) && (!RSP_RING_FULL))
- {
- ent = (xcs_msg_ent_t *)malloc(sizeof(xcs_msg_ent_t));
- ret = xcs_data_read(&ent->msg);
-
- if (ret == -1)
- {
- free(ent);
- if ( errno == EINTR )
- continue;
- if ( errno == EAGAIN )
- break;
- return PyErr_SetFromErrno(PyExc_IOError);
- }
-
- switch (ent->msg.type)
- {
- case XCS_REQUEST:
- REQ_RING_ENT(req_prod) = ent;
- req_prod++;
- continue;
-
- case XCS_RESPONSE:
- RSP_RING_ENT(rsp_prod) = ent;
- rsp_prod++;
- continue;
-
- case XCS_VIRQ:
- ret = ent->msg.u.control.local_port;
- free(ent);
- return PyInt_FromLong(ret);
-
- default:
- /*printf("Throwing away xcs msg type: %u\n", ent->msg.type);*/
- free(ent);
- }
- }
-
- if (!REQ_RING_EMPTY)
- {
- return
PyInt_FromLong(REQ_RING_ENT(req_cons)->msg.u.control.local_port);
- }
-
- if (!RSP_RING_EMPTY)
- {
- return
PyInt_FromLong(RSP_RING_ENT(rsp_cons)->msg.u.control.local_port);
- }
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *xu_notifier_bind_virq(PyObject *self,
- PyObject *args, PyObject *kwds)
-{
- int virq;
- xcs_msg_t kmsg;
-
- static char *kwd_list[] = { "virq", NULL };
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &virq) )
- return NULL;
-
- kmsg.type = XCS_VIRQ_BIND;
- kmsg.u.virq.virq = virq;
- xcs_ctrl_send(&kmsg);
- xcs_ctrl_read(&kmsg);
-
- if ( kmsg.result != XCS_RSLT_OK )
- {
- Py_INCREF(Py_None);
- return Py_None;
- }
-
- return PyInt_FromLong(kmsg.u.virq.port);
-}
-
-static PyObject *xu_notifier_virq_send(PyObject *self,
- PyObject *args, PyObject *kwds)
-{
- int port;
- xcs_msg_t kmsg;
-
- static char *kwd_list[] = { "port", NULL };
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &port) )
- return NULL;
-
- kmsg.type = XCS_VIRQ;
- kmsg.u.control.local_port = port;
- xcs_ctrl_send(&kmsg);
- xcs_ctrl_read(&kmsg);
-
- if ( kmsg.result != XCS_RSLT_OK )
- {
- Py_INCREF(Py_None);
- return Py_None;
- }
-
- return PyInt_FromLong(kmsg.u.virq.port);
-}
-
-static PyObject *xu_notifier_fileno(PyObject *self, PyObject *args)
-{
- return PyInt_FromLong(xcs_data_fd);
-}
-
-static PyMethodDef xu_notifier_methods[] = {
- { "read",
- (PyCFunction)xu_notifier_read,
- METH_VARARGS,
- "Read a @port with pending notifications.\n" },
-
- { "bind_virq",
- (PyCFunction)xu_notifier_bind_virq,
- METH_VARARGS | METH_KEYWORDS,
- "Get notifications for a virq.\n"
- " virq [int]: VIRQ to bind.\n\n" },
-
- { "virq_send",
- (PyCFunction)xu_notifier_virq_send,
- METH_VARARGS | METH_KEYWORDS,
- "Fire a virq notification.\n"
- " port [int]: port that VIRQ is bound to.\n\n" },
-
- { "fileno",
- (PyCFunction)xu_notifier_fileno,
- METH_VARARGS,
- "Return the file descriptor for the notification channel.\n" },
-
- { NULL, NULL, 0, NULL }
-};
-
-staticforward PyTypeObject xu_notifier_type;
-
-/* connect to xcs if we aren't already, and return a dummy object. */
-static PyObject *xu_notifier_new(PyObject *self, PyObject *args)
-{
- xu_notifier_object *xun;
- int i;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- xun = PyObject_New(xu_notifier_object, &xu_notifier_type);
-
- for (i = 0; i < XCS_RING_SIZE; i++)
- REQ_RING_ENT(i) = RSP_RING_ENT(i) = NULL;
-
- (void)xcs_connect(XCS_SUN_PATH);
-
-
- return (PyObject *)xun;
-}
-
-static PyObject *xu_notifier_getattr(PyObject *obj, char *name)
-{
- return Py_FindMethod(xu_notifier_methods, obj, name);
-}
-
-static void xu_notifier_dealloc(PyObject *self)
-{
- xcs_disconnect();
- PyObject_Del(self);
-}
-
-static PyTypeObject xu_notifier_type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "notifier",
- sizeof(xu_notifier_object),
- 0,
- xu_notifier_dealloc, /* tp_dealloc */
- NULL, /* tp_print */
- xu_notifier_getattr, /* tp_getattr */
- NULL, /* tp_setattr */
- NULL, /* tp_compare */
- NULL, /* tp_repr */
- NULL, /* tp_as_number */
- NULL, /* tp_as_sequence */
- NULL, /* tp_as_mapping */
- NULL /* tp_hash */
-};
-
-
-
-/*
- * *********************** MESSAGE ***********************
- */
-
-#define TYPE(_x,_y) (((_x)<<8)|(_y))
-
-#define P2C(_struct, _field, _ctype) \
- do { \
- PyObject *obj; \
- if ( (obj = PyDict_GetItemString(payload, #_field)) != NULL ) \
- { \
- if ( PyInt_Check(obj) ) \
- { \
- ((_struct *)&xum->msg.msg[0])->_field = \
- (_ctype)PyInt_AsLong(obj); \
- dict_items_parsed++; \
- } \
- else if ( PyLong_Check(obj) ) \
- { \
- ((_struct *)&xum->msg.msg[0])->_field = \
- (_ctype)PyLong_AsUnsignedLongLong(obj); \
- dict_items_parsed++; \
- } \
- } \
- xum->msg.length = sizeof(_struct); \
- } while ( 0 )
-
-/** Set a char[] field in a struct from a Python string.
- * Can't do this in P2C because of the typing.
- */
-#define P2CSTRING(_struct, _field) \
- do { \
- PyObject *obj; \
- if ( (obj = PyDict_GetItemString(payload, #_field)) != NULL ) \
- { \
- if ( PyString_Check(obj) ) \
- { \
- _struct * _cobj = (_struct *)&xum->msg.msg[0]; \
- int _field_n = sizeof(_cobj->_field); \
- memset(_cobj->_field, 0, _field_n); \
- strncpy(_cobj->_field, \
- PyString_AsString(obj), \
- _field_n - 1); \
- dict_items_parsed++; \
- } \
- } \
- xum->msg.length = sizeof(_struct); \
- } while ( 0 )
-
-#define C2P(_struct, _field, _pytype, _ctype) \
- do { \
- PyObject *obj = Py ## _pytype ## _From ## _ctype \
- (((_struct *)&xum->msg.msg[0])->_field); \
- if ( dict == NULL ) dict = PyDict_New(); \
- PyDict_SetItemString(dict, #_field, obj); \
- } while ( 0 )
-
-#define PSTR2CHAR(_struct, _field) \
- do { \
- PyObject *obj; \
- if ( (obj = PyDict_GetItemString(payload, #_field)) != NULL ) \
- { \
- if ( PyString_Check(obj) ) \
- { \
- char *buffer = PyString_AsString(obj); \
- \
- strcpy(((_struct *)&xum->msg.msg[0])->_field, \
- buffer); \
- /* Should complain about length - think later */ \
- dict_items_parsed++; \
- } \
- } \
- xum->msg.length = sizeof(_struct); \
- } while ( 0 )
-
-typedef struct {
- PyObject_HEAD;
- control_msg_t msg;
-} xu_message_object;
-
-static PyObject *xu_message_append_payload(PyObject *self, PyObject *args)
-{
- xu_message_object *xum = (xu_message_object *)self;
- char *str;
- int len;
-
- if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
- return NULL;
-
- if ( (len + xum->msg.length) > sizeof(xum->msg.msg) )
- {
- PyErr_SetString(PyExc_RuntimeError, "out of space in control message");
- return NULL;
- }
-
- memcpy(&xum->msg.msg[xum->msg.length], str, len);
- xum->msg.length += len;
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *xu_message_set_response_fields(PyObject *self, PyObject *args)
-{
- xu_message_object *xum = (xu_message_object *)self;
- PyObject *payload;
- int dict_items_parsed = 0;
-
- if ( !PyArg_ParseTuple(args, "O", &payload) )
- return NULL;
-
- if ( !PyDict_Check(payload) )
- {
- PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
- return NULL;
- }
-
- switch ( TYPE(xum->msg.type, xum->msg.subtype) )
- {
- case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS):
- P2C(blkif_fe_driver_status_t, max_handle, u32);
- break;
- case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS):
- P2C(netif_fe_driver_status_t, max_handle, u32);
- break;
- }
-
- if ( dict_items_parsed != PyDict_Size(payload) )
- {
- PyErr_SetString(PyExc_TypeError, "payload contains bad items");
- return NULL;
- }
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *xu_message_get_payload(PyObject *self, PyObject *args)
-{
- xu_message_object *xum = (xu_message_object *)self;
- PyObject *dict = NULL;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- switch ( TYPE(xum->msg.type, xum->msg.subtype) )
- {
- case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS):
- C2P(blkif_fe_interface_status_t, handle, Int, Long);
- C2P(blkif_fe_interface_status_t, status, Int, Long);
- C2P(blkif_fe_interface_status_t, evtchn, Int, Long);
- return dict;
- case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS):
- C2P(blkif_fe_driver_status_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT):
- C2P(blkif_fe_interface_connect_t, handle, Int, Long);
- C2P(blkif_fe_interface_connect_t, shmem_frame, Int, Long);
- C2P(blkif_fe_interface_connect_t, shmem_ref , Int, Long);
- return dict;
- case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_DISCONNECT):
- C2P(blkif_fe_interface_disconnect_t, handle, Int, Long);
- return dict;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
- C2P(blkif_be_create_t, domid, Int, Long);
- C2P(blkif_be_create_t, blkif_handle, Int, Long);
- C2P(blkif_be_create_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
- C2P(blkif_be_destroy_t, domid, Int, Long);
- C2P(blkif_be_destroy_t, blkif_handle, Int, Long);
- C2P(blkif_be_destroy_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
- C2P(blkif_be_connect_t, domid, Int, Long);
- C2P(blkif_be_connect_t, blkif_handle, Int, Long);
- C2P(blkif_be_connect_t, shmem_frame, Int, Long);
- C2P(blkif_be_connect_t, shmem_ref, Int, Long);
- C2P(blkif_be_connect_t, evtchn, Int, Long);
- C2P(blkif_be_connect_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
- C2P(blkif_be_disconnect_t, domid, Int, Long);
- C2P(blkif_be_disconnect_t, blkif_handle, Int, Long);
- C2P(blkif_be_disconnect_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
- C2P(blkif_be_vbd_create_t, domid, Int, Long);
- C2P(blkif_be_vbd_create_t, blkif_handle, Int, Long);
- C2P(blkif_be_vbd_create_t, pdevice, Int, Long);
- C2P(blkif_be_vbd_create_t, dev_handle, Int, Long);
- C2P(blkif_be_vbd_create_t, vdevice, Int, Long);
- C2P(blkif_be_vbd_create_t, readonly, Int, Long);
- C2P(blkif_be_vbd_create_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
- C2P(blkif_be_vbd_destroy_t, domid, Int, Long);
- C2P(blkif_be_vbd_destroy_t, blkif_handle, Int, Long);
- C2P(blkif_be_vbd_destroy_t, vdevice, Int, Long);
- C2P(blkif_be_vbd_destroy_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DRIVER_STATUS):
- C2P(blkif_be_driver_status_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS):
- C2P(netif_fe_interface_status_t, handle, Int, Long);
- C2P(netif_fe_interface_status_t, status, Int, Long);
- C2P(netif_fe_interface_status_t, evtchn, Int, Long);
- C2P(netif_fe_interface_status_t, mac[0], Int, Long);
- C2P(netif_fe_interface_status_t, mac[1], Int, Long);
- C2P(netif_fe_interface_status_t, mac[2], Int, Long);
- C2P(netif_fe_interface_status_t, mac[3], Int, Long);
- C2P(netif_fe_interface_status_t, mac[4], Int, Long);
- C2P(netif_fe_interface_status_t, mac[5], Int, Long);
- return dict;
- case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS):
- C2P(netif_fe_driver_status_t, status, Int, Long);
- C2P(netif_fe_driver_status_t, max_handle, Int, Long);
- return dict;
- case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT):
- C2P(netif_fe_interface_connect_t, handle, Int, Long);
- C2P(netif_fe_interface_connect_t, tx_shmem_frame, Int, Long);
- C2P(netif_fe_interface_connect_t, tx_shmem_ref, Int, Long);
- C2P(netif_fe_interface_connect_t, rx_shmem_frame, Int, Long);
- C2P(netif_fe_interface_connect_t, rx_shmem_ref, Int, Long);
- return dict;
- case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_DISCONNECT):
- C2P(netif_fe_interface_disconnect_t, handle, Int, Long);
- return dict;
- case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
- C2P(netif_be_create_t, domid, Int, Long);
- C2P(netif_be_create_t, netif_handle, Int, Long);
- C2P(netif_be_create_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
- C2P(netif_be_destroy_t, domid, Int, Long);
- C2P(netif_be_destroy_t, netif_handle, Int, Long);
- C2P(netif_be_destroy_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREDITLIMIT):
- C2P(netif_be_creditlimit_t, domid, Int, Long);
- C2P(netif_be_creditlimit_t, netif_handle, Int, Long);
- C2P(netif_be_creditlimit_t, credit_bytes, Int, Long);
- C2P(netif_be_creditlimit_t, period_usec, Int, Long);
- C2P(netif_be_creditlimit_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
- C2P(netif_be_connect_t, domid, Int, Long);
- C2P(netif_be_connect_t, netif_handle, Int, Long);
- C2P(netif_be_connect_t, tx_shmem_frame, Int, Long);
- C2P(netif_be_connect_t, tx_shmem_ref, Int, Long);
- C2P(netif_be_connect_t, rx_shmem_frame, Int, Long);
- C2P(netif_be_connect_t, rx_shmem_ref, Int, Long);
- C2P(netif_be_connect_t, evtchn, Int, Long);
- C2P(netif_be_connect_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
- C2P(netif_be_disconnect_t, domid, Int, Long);
- C2P(netif_be_disconnect_t, netif_handle, Int, Long);
- C2P(netif_be_disconnect_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS):
- C2P(netif_be_driver_status_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED):
- C2P(usbif_fe_interface_status_changed_t, status, Int, Long);
- C2P(usbif_fe_interface_status_changed_t, evtchn, Int, Long);
- C2P(usbif_fe_interface_status_changed_t, domid, Int, Long);
- C2P(usbif_fe_interface_status_changed_t, bandwidth, Int, Long);
- C2P(usbif_fe_interface_status_changed_t, num_ports, Int, Long);
- return dict;
- case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_DRIVER_STATUS_CHANGED):
- C2P(usbif_fe_driver_status_changed_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_CONNECT):
- C2P(usbif_fe_interface_connect_t, shmem_frame, Int, Long);
- return dict;
- case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_DISCONNECT):
- return dict;
- case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CREATE):
- C2P(usbif_be_create_t, domid, Int, Long);
- C2P(usbif_be_create_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DESTROY):
- C2P(usbif_be_destroy_t, domid, Int, Long);
- C2P(usbif_be_destroy_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CONNECT):
- C2P(usbif_be_connect_t, domid, Int, Long);
- C2P(usbif_be_connect_t, shmem_frame, Int, Long);
- C2P(usbif_be_connect_t, evtchn, Int, Long);
- C2P(usbif_be_connect_t, bandwidth, Int, Long);
- C2P(usbif_be_connect_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DISCONNECT):
- C2P(usbif_be_disconnect_t, domid, Int, Long);
- C2P(usbif_be_disconnect_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DRIVER_STATUS_CHANGED):
- C2P(usbif_be_driver_status_changed_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CLAIM_PORT):
- C2P(usbif_be_claim_port_t, domid, Int, Long);
- C2P(usbif_be_claim_port_t, usbif_port, Int, Long);
- C2P(usbif_be_claim_port_t, status, Int, Long);
- C2P(usbif_be_claim_port_t, path, String, String);
- return dict;
- case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_RELEASE_PORT):
- C2P(usbif_be_release_port_t, path, String, String);
- return dict;
- case TYPE(CMSG_MEM_REQUEST, CMSG_MEM_REQUEST_SET):
- C2P(mem_request_t, target, Int, Long);
- C2P(mem_request_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_VCPU_HOTPLUG, CMSG_VCPU_HOTPLUG_OFF):
- C2P(vcpu_hotplug_t, vcpu, Int, Long);
- C2P(vcpu_hotplug_t, status, Int, Long);
- return dict;
- case TYPE(CMSG_VCPU_HOTPLUG, CMSG_VCPU_HOTPLUG_ON):
- C2P(vcpu_hotplug_t, vcpu, Int, Long);
- C2P(vcpu_hotplug_t, status, Int, Long);
- return dict;
- }
-
- return PyString_FromStringAndSize((char *)xum->msg.msg, xum->msg.length);
-}
-
-static PyObject *xu_message_get_header(PyObject *self, PyObject *args)
-{
- xu_message_object *xum = (xu_message_object *)self;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- return Py_BuildValue("{s:i,s:i,s:i}",
- "type", xum->msg.type,
- "subtype", xum->msg.subtype,
- "id", xum->msg.id);
-}
-
-static PyMethodDef xu_message_methods[] = {
- { "append_payload",
- (PyCFunction)xu_message_append_payload,
- METH_VARARGS,
- "Append @str to the message payload.\n" },
-
- { "set_response_fields",
- (PyCFunction)xu_message_set_response_fields,
- METH_VARARGS,
- "Fill in the response fields in a message that was passed to us.\n" },
-
- { "get_payload",
- (PyCFunction)xu_message_get_payload,
- METH_VARARGS,
- "Return the message payload in string form.\n" },
-
- { "get_header",
- (PyCFunction)xu_message_get_header,
- METH_VARARGS,
- "Returns a dictionary of values for @type, @subtype, and @id.\n" },
-
- { NULL, NULL, 0, NULL }
-};
-
-staticforward PyTypeObject xu_message_type;
-
-static PyObject *xu_message_new(PyObject *self, PyObject *args)
-{
- xu_message_object *xum;
- int type, subtype, id, dict_items_parsed = 0;
- PyObject *payload = NULL;
-
- if ( !PyArg_ParseTuple(args, "iii|O", &type, &subtype, &id, &payload) )
- return NULL;
-
- xum = PyObject_New(xu_message_object, &xu_message_type);
-
- xum->msg.type = type;
- xum->msg.subtype = subtype;
- xum->msg.id = id;
- xum->msg.length = 0;
-
- if ( payload == NULL )
- return (PyObject *)xum;
-
- if ( !PyDict_Check(payload) )
- {
- PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
- PyObject_Del((PyObject *)xum);
- return NULL;
- }
-
- switch ( TYPE(type, subtype) )
- {
- case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS):
- P2C(blkif_fe_interface_status_t, handle, u32);
- P2C(blkif_fe_interface_status_t, status, u32);
- P2C(blkif_fe_interface_status_t, evtchn, u16);
- P2C(blkif_fe_interface_status_t, domid, u16);
- break;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
- P2C(blkif_be_create_t, domid, u32);
- P2C(blkif_be_create_t, blkif_handle, u32);
- break;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
- P2C(blkif_be_destroy_t, domid, u32);
- P2C(blkif_be_destroy_t, blkif_handle, u32);
- break;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
- P2C(blkif_be_connect_t, domid, u32);
- P2C(blkif_be_connect_t, blkif_handle, u32);
- P2C(blkif_be_connect_t, shmem_frame, unsigned long);
- P2C(blkif_be_connect_t, shmem_ref, u32);
- P2C(blkif_be_connect_t, evtchn, u16);
- break;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
- P2C(blkif_be_disconnect_t, domid, u32);
- P2C(blkif_be_disconnect_t, blkif_handle, u32);
- break;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
- P2C(blkif_be_vbd_create_t, domid, u32);
- P2C(blkif_be_vbd_create_t, blkif_handle, u32);
- P2C(blkif_be_vbd_create_t, pdevice, blkif_pdev_t);
- P2C(blkif_be_vbd_create_t, dev_handle, u32);
- P2C(blkif_be_vbd_create_t, vdevice, blkif_vdev_t);
- P2C(blkif_be_vbd_create_t, readonly, u16);
- break;
- case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
- P2C(blkif_be_vbd_destroy_t, domid, u32);
- P2C(blkif_be_vbd_destroy_t, blkif_handle, u32);
- P2C(blkif_be_vbd_destroy_t, vdevice, blkif_vdev_t);
- break;
- case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS):
- P2C(netif_fe_interface_status_t, handle, u32);
- P2C(netif_fe_interface_status_t, status, u32);
- P2C(netif_fe_interface_status_t, evtchn, u16);
- P2C(netif_fe_interface_status_t, domid, u16);
- P2C(netif_fe_interface_status_t, mac[0], u8);
- P2C(netif_fe_interface_status_t, mac[1], u8);
- P2C(netif_fe_interface_status_t, mac[2], u8);
- P2C(netif_fe_interface_status_t, mac[3], u8);
- P2C(netif_fe_interface_status_t, mac[4], u8);
- P2C(netif_fe_interface_status_t, mac[5], u8);
- break;
- case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
- P2C(netif_be_create_t, domid, u32);
- P2C(netif_be_create_t, netif_handle, u32);
- P2C(netif_be_create_t, mac[0], u8);
- P2C(netif_be_create_t, mac[1], u8);
- P2C(netif_be_create_t, mac[2], u8);
- P2C(netif_be_create_t, mac[3], u8);
- P2C(netif_be_create_t, mac[4], u8);
- P2C(netif_be_create_t, mac[5], u8);
- P2C(netif_be_create_t, be_mac[0], u8);
- P2C(netif_be_create_t, be_mac[1], u8);
- P2C(netif_be_create_t, be_mac[2], u8);
- P2C(netif_be_create_t, be_mac[3], u8);
- P2C(netif_be_create_t, be_mac[4], u8);
- P2C(netif_be_create_t, be_mac[5], u8);
- break;
- case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
- P2C(netif_be_destroy_t, domid, u32);
- P2C(netif_be_destroy_t, netif_handle, u32);
- break;
- case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREDITLIMIT):
- P2C(netif_be_creditlimit_t, domid, u32);
- P2C(netif_be_creditlimit_t, netif_handle, u32);
- P2C(netif_be_creditlimit_t, credit_bytes, u32);
- P2C(netif_be_creditlimit_t, period_usec, u32);
- break;
- case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
- P2C(netif_be_connect_t, domid, u32);
- P2C(netif_be_connect_t, netif_handle, u32);
- P2C(netif_be_connect_t, tx_shmem_frame, unsigned long);
- P2C(netif_be_connect_t, tx_shmem_ref, u32);
- P2C(netif_be_connect_t, rx_shmem_frame, unsigned long);
- P2C(netif_be_connect_t, rx_shmem_ref, u32);
- P2C(netif_be_connect_t, evtchn, u16);
- break;
- case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
- P2C(netif_be_disconnect_t, domid, u32);
- P2C(netif_be_disconnect_t, netif_handle, u32);
- break;
- case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS):
- P2C(netif_fe_driver_status_t, status, u32);
- P2C(netif_fe_driver_status_t, max_handle, u32);
- break;
- case TYPE(CMSG_MEM_REQUEST, CMSG_MEM_REQUEST_SET):
- P2C(mem_request_t, target, u32);
- break;
- case TYPE(CMSG_VCPU_HOTPLUG, CMSG_VCPU_HOTPLUG_OFF):
- P2C(vcpu_hotplug_t, vcpu, u32);
- P2C(vcpu_hotplug_t, status, u32);
- break;
- case TYPE(CMSG_VCPU_HOTPLUG, CMSG_VCPU_HOTPLUG_ON):
- P2C(vcpu_hotplug_t, vcpu, u32);
- P2C(vcpu_hotplug_t, status, u32);
- break;
- case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED):
- P2C(usbif_fe_interface_status_changed_t, status, u32);
- P2C(usbif_fe_interface_status_changed_t, evtchn, u16);
- P2C(usbif_fe_interface_status_changed_t, domid, domid_t);
- P2C(usbif_fe_interface_status_changed_t, bandwidth, u32);
- P2C(usbif_fe_interface_status_changed_t, num_ports, u32);
- break;
- case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_DRIVER_STATUS_CHANGED):
- P2C(usbif_fe_driver_status_changed_t, status, u32);
- break;
- case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_CONNECT):
- P2C(usbif_fe_interface_connect_t, shmem_frame, unsigned long);
- break;
- case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_DISCONNECT):
- break;
- case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CREATE):
- P2C(usbif_be_create_t, domid, domid_t);
- P2C(usbif_be_create_t, status, u32);
- break;
- case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DESTROY):
- P2C(usbif_be_destroy_t, domid, domid_t);
- P2C(usbif_be_destroy_t, status, u32);
- break;
- case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CONNECT):
- P2C(usbif_be_connect_t, domid, domid_t);
- P2C(usbif_be_connect_t, shmem_frame, unsigned long);
- P2C(usbif_be_connect_t, evtchn, u32);
- P2C(usbif_be_connect_t, bandwidth, u32);
- P2C(usbif_be_connect_t, status, u32);
- break;
- case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DISCONNECT):
- P2C(usbif_be_disconnect_t, domid, domid_t);
- P2C(usbif_be_disconnect_t, status, u32);
- break;
- case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DRIVER_STATUS_CHANGED):
- P2C(usbif_be_driver_status_changed_t, status, u32);
- break;
- case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CLAIM_PORT):
- P2C(usbif_be_claim_port_t, domid, domid_t);
- P2C(usbif_be_claim_port_t, usbif_port, u32);
- P2C(usbif_be_claim_port_t, status, u32);
- PSTR2CHAR(usbif_be_claim_port_t, path);
- printf("dict items parsed = %d", dict_items_parsed);
- break;
- case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_RELEASE_PORT):
- PSTR2CHAR(usbif_be_release_port_t, path);
- break;
- case TYPE(CMSG_SHUTDOWN, CMSG_SHUTDOWN_SYSRQ):
- P2C(shutdown_sysrq_t, key, char);
- break;
- }
-
- if ( dict_items_parsed != PyDict_Size(payload) )
- {
- PyErr_SetString(PyExc_TypeError, "payload contains bad items");
- PyObject_Del((PyObject *)xum);
- return NULL;
- }
-
- return (PyObject *)xum;
-}
-
-static PyObject *xu_message_getattr(PyObject *obj, char *name)
-{
- xu_message_object *xum;
- if ( strcmp(name, "MAX_PAYLOAD") == 0 )
- return PyInt_FromLong(sizeof(xum->msg.msg));
- return Py_FindMethod(xu_message_methods, obj, name);
-}
-
-static void xu_message_dealloc(PyObject *self)
-{
- PyObject_Del(self);
-}
-
-static PyTypeObject xu_message_type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "message",
- sizeof(xu_message_object),
- 0,
- xu_message_dealloc, /* tp_dealloc */
- NULL, /* tp_print */
- xu_message_getattr, /* tp_getattr */
- NULL, /* tp_setattr */
- NULL, /* tp_compare */
- NULL, /* tp_repr */
- NULL, /* tp_as_number */
- NULL, /* tp_as_sequence */
- NULL, /* tp_as_mapping */
- NULL /* tp_hash */
-};
-
-
-
-/*
- * *********************** PORT ***********************
- */
-
-typedef struct xu_port_object {
- PyObject_HEAD;
- int xc_handle;
- int connected;
- u32 remote_dom;
- int local_port, remote_port;
- struct xu_port_object *fix_next;
-} xu_port_object;
-
-static PyObject *port_error;
-
-static PyObject *xu_port_read_request(PyObject *self, PyObject *args)
-{
- xu_port_object *xup = (xu_port_object *)self;
- xu_message_object *xum;
- control_msg_t *cmsg;
- unsigned i;
- xcs_msg_ent_t *ent = NULL;
-
- for ( i = req_cons; (i != req_prod); i++ ) {
- ent = REQ_RING_ENT(i);
- if (ent == NULL)
- continue;
- if (ent->msg.u.control.remote_dom == xup->remote_dom)
- break;
- }
-
- if ((ent == NULL) ||
- (ent->msg.u.control.remote_dom != xup->remote_dom))
- goto none;
-
- cmsg = &ent->msg.u.control.msg;
- xum = PyObject_New(xu_message_object, &xu_message_type);
- memcpy(&xum->msg, cmsg, sizeof(*cmsg));
- if ( xum->msg.length > sizeof(xum->msg.msg) )
- xum->msg.length = sizeof(xum->msg.msg);
- free(ent);
-
- /* remove the entry from the ring and advance the consumer if possible */
- REQ_RING_ENT(i) = NULL;
- while ( (REQ_RING_ENT(req_cons) == NULL) && (!REQ_RING_EMPTY) )
- req_cons++;
-
- return (PyObject *)xum;
-
-none:
- Py_INCREF(Py_None);
- return Py_None;
-
-}
-
-static PyObject *xu_port_write_request(PyObject *self, PyObject *args)
-{
- xu_port_object *xup = (xu_port_object *)self;
- xu_message_object *xum;
- xcs_msg_t kmsg;
-
- if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
- return NULL;
-
- if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
- {
- PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
- return NULL;
- }
-
- kmsg.type = XCS_REQUEST;
- kmsg.u.control.remote_dom = xup->remote_dom;
- memcpy(&kmsg.u.control.msg, &xum->msg, sizeof(control_msg_t));
- xcs_data_send(&kmsg);
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *xu_port_read_response(PyObject *self, PyObject *args)
-{
- xu_port_object *xup = (xu_port_object *)self;
- xu_message_object *xum;
- control_msg_t *cmsg;
- unsigned i;
- xcs_msg_ent_t *ent = NULL;
-
- for ( i = rsp_cons; (i != rsp_prod); i++ ) {
- ent = RSP_RING_ENT(i);
- if (ent == NULL)
- continue;
- if (ent->msg.u.control.remote_dom == xup->remote_dom)
- break;
- }
-
- if ((ent == NULL) ||
- (ent->msg.u.control.remote_dom != xup->remote_dom))
- goto none;
-
- cmsg = &ent->msg.u.control.msg;
- xum = PyObject_New(xu_message_object, &xu_message_type);
- memcpy(&xum->msg, cmsg, sizeof(*cmsg));
- if ( xum->msg.length > sizeof(xum->msg.msg) )
- xum->msg.length = sizeof(xum->msg.msg);
- free(ent);
-
- /* remove the entry from the ring and advance the consumer if possible */
- RSP_RING_ENT(i) = NULL;
- while ( (RSP_RING_ENT(rsp_cons) == NULL) && (!RSP_RING_EMPTY) )
- rsp_cons++;
-
- return (PyObject *)xum;
-
-none:
- Py_INCREF(Py_None);
- return Py_None;
-
-}
-
-static PyObject *xu_port_write_response(PyObject *self, PyObject *args)
-{
- xu_port_object *xup = (xu_port_object *)self;
- xu_message_object *xum;
- xcs_msg_t kmsg;
-
- if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
- return NULL;
-
- if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
- {
- PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
- return NULL;
- }
-
- kmsg.type = XCS_RESPONSE;
- kmsg.u.control.remote_dom = xup->remote_dom;
- memcpy(&kmsg.u.control.msg, &xum->msg, sizeof(control_msg_t));
- xcs_data_send(&kmsg);
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *xu_port_request_to_read(PyObject *self, PyObject *args)
-{
- xu_port_object *xup = (xu_port_object *)self;
- xcs_msg_ent_t *ent;
- int found = 0;
- unsigned i;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- for ( i = req_cons; (i != req_prod); i++ ) {
- ent = REQ_RING_ENT(i);
- if (ent == NULL)
- continue;
- if (ent->msg.u.control.remote_dom == xup->remote_dom) {
- found = 1;
- break;
- }
- }
-
- return PyInt_FromLong(found);
-}
-
-static PyObject *xu_port_response_to_read(PyObject *self, PyObject *args)
-{
- xu_port_object *xup = (xu_port_object *)self;
- xcs_msg_ent_t *ent;
- int found = 0;
- unsigned i;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- for ( i = rsp_cons; (i != rsp_prod); i++ ) {
- ent = RSP_RING_ENT(i);
- if (ent == NULL)
- continue;
- if (ent->msg.u.control.remote_dom == xup->remote_dom) {
- found = 1;
- break;
- }
- }
-
- return PyInt_FromLong(found);
-}
-
-static void _xu_port_close(xu_port_object *xup )
-{
- if ( xup->connected && xup->remote_dom != 0 )
- {
- xcs_msg_t kmsg;
- kmsg.type = XCS_CIF_FREE_CC;
- kmsg.u.interface.dom = xup->remote_dom;
- kmsg.u.interface.local_port = xup->local_port;
- kmsg.u.interface.remote_port = xup->remote_port;
- xcs_ctrl_send(&kmsg);
- xcs_ctrl_read(&kmsg);
- xup->connected = 0;
- }
-}
-
-static PyObject *xu_port_close(PyObject *self, PyObject *args)
-{
- xu_port_object *xup = (xu_port_object *)self;
-
- _xu_port_close(xup);
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *xu_port_register(PyObject *self, PyObject *args,
- PyObject *kwds)
-{
- int type;
- xcs_msg_t msg;
- xu_port_object *xup = (xu_port_object *)self;
- static char *kwd_list[] = { "type", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list,
- &type) )
- return NULL;
-
- if (!xup->connected)
- {
- return PyInt_FromLong(0);
- }
-
- msg.type = XCS_MSG_BIND;
- msg.u.bind.port = xup->local_port;
- msg.u.bind.type = type;
- xcs_ctrl_send(&msg);
- xcs_ctrl_read(&msg);
-
- if (msg.result != XCS_RSLT_OK)
- {
- return PyInt_FromLong(0);
- }
-
- return PyInt_FromLong(1);
-}
-
-static PyObject *xu_port_deregister(PyObject *self, PyObject *args,
- PyObject *kwds)
-{
- int type;
- xcs_msg_t msg;
- xu_port_object *xup = (xu_port_object *)self;
- static char *kwd_list[] = { "type", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list,
- &type) )
- return NULL;
-
- if (!xup->connected)
- {
- return PyInt_FromLong(0);
- }
-
- msg.type = XCS_MSG_UNBIND;
- msg.u.bind.port = xup->local_port;
- msg.u.bind.type = type;
- xcs_ctrl_send(&msg);
- xcs_ctrl_read(&msg);
-
- if (msg.result != XCS_RSLT_OK)
- {
- return PyInt_FromLong(0);
- }
-
- return PyInt_FromLong(1);
-}
-
-static PyMethodDef xu_port_methods[] = {
-
- { "read_request",
- (PyCFunction)xu_port_read_request,
- METH_VARARGS,
- "Read a request message from the control interface.\n" },
-
- { "write_request",
- (PyCFunction)xu_port_write_request,
- METH_VARARGS,
- "Write a request message to the control interface.\n" },
-
- { "read_response",
- (PyCFunction)xu_port_read_response,
- METH_VARARGS,
- "Read a response message from the control interface.\n" },
-
- { "write_response",
- (PyCFunction)xu_port_write_response,
- METH_VARARGS,
- "Write a response message to the control interface.\n" },
-
- { "request_to_read",
- (PyCFunction)xu_port_request_to_read,
- METH_VARARGS,
- "Returns TRUE if there is a request message to read.\n" },
-
-
- { "response_to_read",
- (PyCFunction)xu_port_response_to_read,
- METH_VARARGS,
- "Returns TRUE if there is a response message to read.\n" },
-
- { "register",
- (PyCFunction)xu_port_register,
- METH_VARARGS | METH_KEYWORDS,
- "Register to receive a type of message on this channel.\n" },
-
- { "deregister",
- (PyCFunction)xu_port_deregister,
- METH_VARARGS | METH_KEYWORDS,
- "Stop receiving a type of message on this port.\n" },
-
- { "close",
- (PyCFunction)xu_port_close,
- METH_VARARGS,
- "Close the port.\n" },
-
- { NULL, NULL, 0, NULL }
-};
-
-staticforward PyTypeObject xu_port_type;
-
-static PyObject *xu_port_new(PyObject *self, PyObject *args, PyObject *kwds)
-{
- xu_port_object *xup;
- u32 dom;
- int port1 = 0, port2 = 0;
- xcs_msg_t kmsg;
-
- static char *kwd_list[] = { "dom", "local_port", "remote_port", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|ii", kwd_list,
- &dom, &port1, &port2) )
- return NULL;
-
- xup = PyObject_New(xu_port_object, &xu_port_type);
-
- xup->connected = 0;
- xup->remote_dom = dom;
-
- kmsg.type = XCS_CIF_NEW_CC;
- kmsg.u.interface.dom = xup->remote_dom;
- kmsg.u.interface.local_port = port1;
- kmsg.u.interface.remote_port = port2;
- xcs_ctrl_send(&kmsg);
- xcs_ctrl_read(&kmsg);
-
- if ( kmsg.result != XCS_RSLT_OK )
- goto fail1;
-
- xup->local_port = kmsg.u.interface.local_port;
- xup->remote_port = kmsg.u.interface.remote_port;
- xup->connected = 1;
-
- return (PyObject *)xup;
-
- fail1:
- PyObject_Del((PyObject *)xup);
- PyErr_SetString(PyExc_ValueError, "cannot create port");
- return NULL;
-}
-
-static PyObject *xu_port_getattr(PyObject *obj, char *name)
-{
- xu_port_object *xup = (xu_port_object *)obj;
-
- if ( strcmp(name, "local_port") == 0 )
- {
- return PyInt_FromLong(xup->connected ? xup->local_port : -1);
- }
- if ( strcmp(name, "remote_port") == 0 )
- {
- return PyInt_FromLong(xup->connected ? xup->remote_port : -1);
- }
- if ( strcmp(name, "remote_dom") == 0 )
- {
- return PyInt_FromLong(xup->remote_dom);
- }
- if ( strcmp(name, "connected") == 0 )
- {
- return PyInt_FromLong(xup->connected);
- }
- return Py_FindMethod(xu_port_methods, obj, name);
-}
-
-static void xu_port_dealloc(PyObject *self)
-{
- xu_port_object *xup = (xu_port_object *)self;
-
- _xu_port_close(xup);
-
- PyObject_Del(self);
-}
-
-static PyTypeObject xu_port_type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "port",
- sizeof(xu_port_object),
- 0,
- xu_port_dealloc, /* tp_dealloc */
- NULL, /* tp_print */
- xu_port_getattr, /* tp_getattr */
- NULL, /* tp_setattr */
- NULL, /* tp_compare */
- NULL, /* tp_repr */
- NULL, /* tp_as_number */
- NULL, /* tp_as_sequence */
- NULL, /* tp_as_mapping */
- NULL /* tp_hash */
-};
-
-
-
-/*
- * *********************** BUFFER ***********************
- */
-
-#define BUFSZ 65536
-#define MASK_BUF_IDX(_i) ((_i)&(BUFSZ-1))
-typedef unsigned int BUF_IDX;
-
-typedef struct {
- PyObject_HEAD;
- char *buf;
- unsigned int prod, cons;
-} xu_buffer_object;
-
-static PyObject *__xu_buffer_peek(xu_buffer_object *xub, int max)
-{
- PyObject *str1, *str2;
- int len1, len2, c = MASK_BUF_IDX(xub->cons);
-
- len1 = xub->prod - xub->cons;
- if ( len1 > (BUFSZ - c) ) /* clip to ring wrap */
- len1 = BUFSZ - c;
- if ( len1 > max ) /* clip to specified maximum */
- len1 = max;
- if ( len1 < 0 ) /* sanity */
- len1 = 0;
-
- if ( (str1 = PyString_FromStringAndSize(&xub->buf[c], len1)) == NULL )
- return NULL;
-
- if ( (len1 < (xub->prod - xub->cons)) && (len1 < max) )
- {
- len2 = max - len1;
- if ( len2 > MASK_BUF_IDX(xub->prod) )
- len2 = MASK_BUF_IDX(xub->prod);
- if ( len2 > 0 )
- {
- str2 = PyString_FromStringAndSize(&xub->buf[0], len2);
- if ( str2 == NULL )
- return NULL;
- PyString_ConcatAndDel(&str1, str2);
- if ( str1 == NULL )
- return NULL;
- }
- }
-
- return str1;
-}
-
-static PyObject *xu_buffer_peek(PyObject *self, PyObject *args)
-{
- xu_buffer_object *xub = (xu_buffer_object *)self;
- int max = 1024;
-
- if ( !PyArg_ParseTuple(args, "|i", &max) )
- return NULL;
-
- return __xu_buffer_peek(xub, max);
-}
-
-static PyObject *xu_buffer_read(PyObject *self, PyObject *args)
-{
- xu_buffer_object *xub = (xu_buffer_object *)self;
- PyObject *str;
- int max = 1024;
-
- if ( !PyArg_ParseTuple(args, "|i", &max) )
- return NULL;
-
- if ( (str = __xu_buffer_peek(xub, max)) != NULL )
- xub->cons += PyString_Size(str);
-
- return str;
-}
-
-static PyObject *xu_buffer_discard(PyObject *self, PyObject *args)
-{
- xu_buffer_object *xub = (xu_buffer_object *)self;
- int max, len;
-
- if ( !PyArg_ParseTuple(args, "i", &max) )
- return NULL;
-
- len = xub->prod - xub->cons;
- if ( len > max )
- len = max;
- if ( len < 0 )
- len = 0;
-
- xub->cons += len;
-
- return PyInt_FromLong(len);
-}
-
-static PyObject *xu_buffer_write(PyObject *self, PyObject *args)
-{
- xu_buffer_object *xub = (xu_buffer_object *)self;
- char *str;
- int len, len1, len2;
-
- if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
- return NULL;
-
- len1 = len;
- if ( len1 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
- len1 = BUFSZ - MASK_BUF_IDX(xub->prod);
- if ( len1 > (BUFSZ - (xub->prod - xub->cons)) )
- len1 = BUFSZ - (xub->prod - xub->cons);
-
- if ( len1 == 0 )
- return PyInt_FromLong(0);
-
- memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[0], len1);
- xub->prod += len1;
-
- if ( len1 < len )
- {
- len2 = len - len1;
- if ( len2 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
- len2 = BUFSZ - MASK_BUF_IDX(xub->prod);
- if ( len2 > (BUFSZ - (xub->prod - xub->cons)) )
- len2 = BUFSZ - (xub->prod - xub->cons);
- if ( len2 != 0 )
- {
- memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[len1], len2);
- xub->prod += len2;
- return PyInt_FromLong(len1 + len2);
- }
- }
-
- return PyInt_FromLong(len1);
-}
-
-static PyObject *xu_buffer_empty(PyObject *self, PyObject *args)
-{
- xu_buffer_object *xub = (xu_buffer_object *)self;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- if ( xub->cons == xub->prod )
- return PyInt_FromLong(1);
-
- return PyInt_FromLong(0);
-}
-
-static PyObject *xu_buffer_full(PyObject *self, PyObject *args)
-{
- xu_buffer_object *xub = (xu_buffer_object *)self;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- if ( (xub->prod - xub->cons) == BUFSZ )
- return PyInt_FromLong(1);
-
- return PyInt_FromLong(0);
-}
-
-static PyObject *xu_buffer_size(PyObject *self, PyObject *args)
-{
- xu_buffer_object *xub = (xu_buffer_object *)self;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- return PyInt_FromLong(xub->prod - xub->cons);
-}
-
-static PyObject *xu_buffer_space(PyObject *self, PyObject *args)
-{
- xu_buffer_object *xub = (xu_buffer_object *)self;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- return PyInt_FromLong(BUFSZ - (xub->prod - xub->cons));
-}
-
-static PyMethodDef xu_buffer_methods[] = {
- { "peek",
- (PyCFunction)xu_buffer_peek,
- METH_VARARGS,
- "Peek up to @max bytes from the buffer. Returns a string.\n" },
-
- { "read",
- (PyCFunction)xu_buffer_read,
- METH_VARARGS,
- "Read up to @max bytes from the buffer. Returns a string.\n" },
-
- { "discard",
- (PyCFunction)xu_buffer_discard,
- METH_VARARGS,
- "Discard up to @max bytes from the buffer. Returns number of bytes.\n" },
-
- { "write",
- (PyCFunction)xu_buffer_write,
- METH_VARARGS,
- "Write @string into buffer. Return number of bytes written.\n" },
-
- { "empty",
- (PyCFunction)xu_buffer_empty,
- METH_VARARGS,
- "Return TRUE if the buffer is empty.\n" },
-
- { "full",
- (PyCFunction)xu_buffer_full,
- METH_VARARGS,
- "Return TRUE if the buffer is full.\n" },
-
- { "size",
- (PyCFunction)xu_buffer_size,
- METH_VARARGS,
- "Return number of bytes in the buffer.\n" },
-
- { "space",
- (PyCFunction)xu_buffer_space,
- METH_VARARGS,
- "Return space left in the buffer.\n" },
-
- { NULL, NULL, 0, NULL }
-};
-
-staticforward PyTypeObject xu_buffer_type;
-
-static PyObject *xu_buffer_new(PyObject *self, PyObject *args)
-{
- xu_buffer_object *xub;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- xub = PyObject_New(xu_buffer_object, &xu_buffer_type);
-
- if ( (xub->buf = malloc(BUFSZ)) == NULL )
- {
- PyObject_Del((PyObject *)xub);
- return NULL;
- }
-
- xub->prod = xub->cons = 0;
-
- return (PyObject *)xub;
-}
-
-static PyObject *xu_buffer_getattr(PyObject *obj, char *name)
-{
- return Py_FindMethod(xu_buffer_methods, obj, name);
-}
-
-static void xu_buffer_dealloc(PyObject *self)
-{
- xu_buffer_object *xub = (xu_buffer_object *)self;
- free(xub->buf);
- PyObject_Del(self);
-}
-
-static PyTypeObject xu_buffer_type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "buffer",
- sizeof(xu_buffer_object),
- 0,
- xu_buffer_dealloc, /* tp_dealloc */
- NULL, /* tp_print */
- xu_buffer_getattr, /* tp_getattr */
- NULL, /* tp_setattr */
- NULL, /* tp_compare */
- NULL, /* tp_repr */
- NULL, /* tp_as_number */
- NULL, /* tp_as_sequence */
- NULL, /* tp_as_mapping */
- NULL /* tp_hash */
-};
-
-
-
-/*
- * *********************** MODULE WRAPPER ***********************
- */
-
-static void handle_child_death(int dummy)
-{
- while ( waitpid(-1, NULL, WNOHANG) > 0 )
- continue;
-}
-
-static PyObject *xu_autoreap(PyObject *self, PyObject *args)
-{
- struct sigaction sa;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- memset(&sa, 0, sizeof(sa));
- sa.sa_handler = handle_child_death;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
- (void)sigaction(SIGCHLD, &sa, NULL);
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyMethodDef xu_methods[] = {
- { "notifier", xu_notifier_new, METH_VARARGS,
- "Create a new notifier." },
- { "message", xu_message_new, METH_VARARGS,
- "Create a new communications message." },
- { "port", (PyCFunction)xu_port_new, METH_VARARGS | METH_KEYWORDS,
- "Create a new communications port." },
- { "buffer", xu_buffer_new, METH_VARARGS,
- "Create a new ring buffer." },
- { "autoreap", xu_autoreap, METH_VARARGS,
- "Ensure that zombie children are automatically reaped by the OS." },
- { NULL, NULL, 0, NULL }
-};
-
-PyMODINIT_FUNC initxu(void)
-{
- PyObject *m, *d;
-
- m = Py_InitModule(XENPKG, xu_methods);
-
- d = PyModule_GetDict(m);
- port_error = PyErr_NewException(XENPKG ".PortError", NULL, NULL);
- PyDict_SetItemString(d, "PortError", port_error);
-
- /* KAF: This ensures that we get debug output in a timely manner. */
- setbuf(stdout, NULL);
- setbuf(stderr, NULL);
-}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/python/xen/xend/server/messages.py
--- a/tools/python/xen/xend/server/messages.py Thu Sep 8 15:18:40 2005
+++ /dev/null Fri Sep 9 16:30:54 2005
@@ -1,462 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx>
-#============================================================================
-
-import sys
-import struct
-import types
-
-from xen.lowlevel import xu
-
-DEBUG = False
-
-#PORT_WILDCARD = 0xefffffff
-
-"""Wildcard for the control message types."""
-TYPE_WILDCARD = 0xffff
-
-""" All message formats.
-Added to incrementally for the various message types.
-See below.
-"""
-msg_formats = {}
-
-#============================================================================
-# Block interface message types.
-#============================================================================
-
-CMSG_BLKIF_BE = 1
-CMSG_BLKIF_FE = 2
-
-CMSG_BLKIF_FE_INTERFACE_STATUS = 0
-CMSG_BLKIF_FE_DRIVER_STATUS = 32
-CMSG_BLKIF_FE_INTERFACE_CONNECT = 33
-CMSG_BLKIF_FE_INTERFACE_DISCONNECT = 34
-CMSG_BLKIF_FE_INTERFACE_QUERY = 35
-
-CMSG_BLKIF_BE_CREATE = 0
-CMSG_BLKIF_BE_DESTROY = 1
-CMSG_BLKIF_BE_CONNECT = 2
-CMSG_BLKIF_BE_DISCONNECT = 3
-CMSG_BLKIF_BE_VBD_CREATE = 4
-CMSG_BLKIF_BE_VBD_DESTROY = 5
-CMSG_BLKIF_BE_DRIVER_STATUS = 32
-
-BLKIF_DRIVER_STATUS_DOWN = 0
-BLKIF_DRIVER_STATUS_UP = 1
-
-BLKIF_INTERFACE_STATUS_CLOSED = 0 #/* Interface doesn't exist. */
-BLKIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */
-BLKIF_INTERFACE_STATUS_CONNECTED = 2 #/* Exists and is connected. */
-BLKIF_INTERFACE_STATUS_CHANGED = 3 #/* A device has been added or
removed. */
-
-BLKIF_BE_STATUS_OKAY = 0
-BLKIF_BE_STATUS_ERROR = 1
-BLKIF_BE_STATUS_INTERFACE_EXISTS = 2
-BLKIF_BE_STATUS_INTERFACE_NOT_FOUND = 3
-BLKIF_BE_STATUS_INTERFACE_CONNECTED = 4
-BLKIF_BE_STATUS_VBD_EXISTS = 5
-BLKIF_BE_STATUS_VBD_NOT_FOUND = 6
-BLKIF_BE_STATUS_OUT_OF_MEMORY = 7
-BLKIF_BE_STATUS_PHYSDEV_NOT_FOUND = 8
-BLKIF_BE_STATUS_MAPPING_ERROR = 9
-
-blkif_formats = {
- 'blkif_be_connect_t':
- (CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT),
- # Connect be to fe (in response to blkif_fe_interface_connect_t).
-
- 'blkif_be_create_t':
- (CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE),
- # Create be.
-
- 'blkif_be_disconnect_t':
- (CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT),
- # Disconnect be from fe.
-
- 'blkif_be_destroy_t':
- (CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY),
- # Destroy be (after disconnect).
- # Make be do this even if no disconnect (and destroy all vbd too).
-
- 'blkif_be_vbd_create_t':
- (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE),
- # Create a vbd device.
-
- 'blkif_be_vbd_destroy_t':
- (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY),
- # Destroy a vbd.
-
- # Add message to query be for state and vbds.
-
- 'blkif_fe_interface_status_t':
- (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS),
- # Notify device status to fe.
- # Also used to notify 'any' device change with status
BLKIF_INTERFACE_STATUS_CHANGED.
-
- 'blkif_fe_driver_status_t':
- (CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS),
- # Comes from fe, treated as notifying that fe has come up/changed.
- # Xend sets be(s) to BLKIF_INTERFACE_STATUS_DISCONNECTED,
- # sends blkif_fe_interface_status_t to fe (from each be).
- #
- # Reply with i/f count.
- # The i/f sends probes (using -ve trick), we reply with the info.
-
- 'blkif_fe_interface_connect_t':
- (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT),
- # Comes from fe, passing shmem frame to use for be.
- # fe sends when gets blkif_fe_interface_status_t with state
NETIF_INTERFACE_STATUS_DISCONNECTED.
- # Xend creates event channel and notifies be.
- # Then notifies fe of event channel with blkif_fe_interface_status_t.
-
- # Add message to kick fe to probe for devices.
- # Just report new devices to fe?
-
- #
- # Add message for fe to probe a device.
- # And probing with id -1 should return first.
- # And probing with id -n should return first device with id > n.
-
- # Add message to query fe for state and vbds.
-}
-
-msg_formats.update(blkif_formats)
-
-#============================================================================
-# Network interface message types.
-#============================================================================
-
-CMSG_NETIF_BE = 3
-CMSG_NETIF_FE = 4
-
-CMSG_NETIF_FE_INTERFACE_STATUS = 0
-CMSG_NETIF_FE_DRIVER_STATUS = 32
-CMSG_NETIF_FE_INTERFACE_CONNECT = 33
-CMSG_NETIF_FE_INTERFACE_DISCONNECT = 34
-CMSG_NETIF_FE_INTERFACE_QUERY = 35
-
-CMSG_NETIF_BE_CREATE = 0
-CMSG_NETIF_BE_DESTROY = 1
-CMSG_NETIF_BE_CONNECT = 2
-CMSG_NETIF_BE_DISCONNECT = 3
-CMSG_NETIF_BE_CREDITLIMIT = 4
-CMSG_NETIF_BE_DRIVER_STATUS = 32
-
-NETIF_INTERFACE_STATUS_CLOSED = 0 #/* Interface doesn't exist. */
-NETIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */
-NETIF_INTERFACE_STATUS_CONNECTED = 2 #/* Exists and is connected. */
-NETIF_INTERFACE_STATUS_CHANGED = 3 #/* A device has been added or
removed. */
-
-NETIF_DRIVER_STATUS_DOWN = 0
-NETIF_DRIVER_STATUS_UP = 1
-
-netif_formats = {
- 'netif_be_connect_t':
- (CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT),
-
- 'netif_be_create_t':
- (CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE),
-
- 'netif_be_disconnect_t':
- (CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT),
-
- 'netif_be_destroy_t':
- (CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY),
-
- 'netif_be_creditlimit_t':
- (CMSG_NETIF_BE, CMSG_NETIF_BE_CREDITLIMIT),
-
- 'netif_be_driver_status_t':
- (CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS),
-
- 'netif_fe_driver_status_t':
- (CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS),
-
- 'netif_fe_interface_connect_t':
- (CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT),
-
- 'netif_fe_interface_status_t':
- (CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS),
- }
-
-msg_formats.update(netif_formats)
-
-#============================================================================
-# USB interface message types.
-#============================================================================
-
-CMSG_USBIF_BE = 8
-CMSG_USBIF_FE = 9
-
-CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED = 0
-
-CMSG_USBIF_FE_DRIVER_STATUS_CHANGED = 32
-CMSG_USBIF_FE_INTERFACE_CONNECT = 33
-CMSG_USBIF_FE_INTERFACE_DISCONNECT = 34
-
-USBIF_DRIVER_STATUS_DOWN = 0
-USBIF_DRIVER_STATUS_UP = 1
-
-USBIF_INTERFACE_STATUS_DESTROYED = 0 #/* Interface doesn't exist. */
-USBIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */
-USBIF_INTERFACE_STATUS_CONNECTED = 2 #/* Exists and is connected. */
-
-CMSG_USBIF_BE_CREATE = 0
-CMSG_USBIF_BE_DESTROY = 1
-CMSG_USBIF_BE_CONNECT = 2
-
-CMSG_USBIF_BE_DISCONNECT = 3
-CMSG_USBIF_BE_CLAIM_PORT = 4
-CMSG_USBIF_BE_RELEASE_PORT = 5
-
-CMSG_USBIF_BE_DRIVER_STATUS_CHANGED = 32
-
-USBIF_BE_STATUS_OKAY = 0
-USBIF_BE_STATUS_ERROR = 1
-
-USBIF_BE_STATUS_INTERFACE_EXISTS = 2
-USBIF_BE_STATUS_INTERFACE_NOT_FOUND = 3
-USBIF_BE_STATUS_INTERFACE_CONNECTED = 4
-USBIF_BE_STATUS_OUT_OF_MEMORY = 7
-USBIF_BE_STATUS_MAPPING_ERROR = 9
-
-usbif_formats = {
- 'usbif_be_create_t':
- (CMSG_USBIF_BE, CMSG_USBIF_BE_CREATE),
-
- 'usbif_be_destroy_t':
- (CMSG_USBIF_BE, CMSG_USBIF_BE_DESTROY),
-
- 'usbif_be_connect_t':
- (CMSG_USBIF_BE, CMSG_USBIF_BE_CONNECT),
-
- 'usbif_be_disconnect_t':
- (CMSG_USBIF_BE, CMSG_USBIF_BE_DISCONNECT),
-
- 'usbif_be_claim_port_t':
- (CMSG_USBIF_BE, CMSG_USBIF_BE_CLAIM_PORT),
-
- 'usbif_be_release_port_t':
- (CMSG_USBIF_BE, CMSG_USBIF_BE_RELEASE_PORT),
-
- 'usbif_fe_interface_status_changed_t':
- (CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED),
-
- 'usbif_fe_driver_status_changed_t':
- (CMSG_USBIF_FE, CMSG_USBIF_FE_DRIVER_STATUS_CHANGED),
-
- 'usbif_fe_interface_connect_t':
- (CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_CONNECT),
-
- 'usbif_fe_interface_disconnect_t':
- (CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_DISCONNECT),
-
- }
-
-msg_formats.update(usbif_formats)
-
-#============================================================================
-# Domain shutdown message types.
-#============================================================================
-
-CMSG_SHUTDOWN = 6
-
-CMSG_SHUTDOWN_POWEROFF = 0
-CMSG_SHUTDOWN_REBOOT = 1
-CMSG_SHUTDOWN_SUSPEND = 2
-CMSG_SHUTDOWN_SYSRQ = 3
-
-STOPCODE_shutdown = 0
-STOPCODE_reboot = 1
-STOPCODE_suspend = 2
-STOPCODE_sysrq = 3
-
-shutdown_formats = {
- 'shutdown_poweroff_t':
- (CMSG_SHUTDOWN, CMSG_SHUTDOWN_POWEROFF),
-
- 'shutdown_reboot_t':
- (CMSG_SHUTDOWN, CMSG_SHUTDOWN_REBOOT),
-
- 'shutdown_suspend_t':
- (CMSG_SHUTDOWN, CMSG_SHUTDOWN_SUSPEND),
-
- 'shutdown_sysrq_t':
- (CMSG_SHUTDOWN, CMSG_SHUTDOWN_SYSRQ)
- }
-
-msg_formats.update(shutdown_formats)
-
-#============================================================================
-# Domain memory reservation message.
-#============================================================================
-
-CMSG_MEM_REQUEST = 7
-CMSG_MEM_REQUEST_SET = 0
-
-mem_request_formats = {
- 'mem_request_t':
- (CMSG_MEM_REQUEST, CMSG_MEM_REQUEST_SET)
- }
-
-msg_formats.update(mem_request_formats)
-
-#============================================================================
-# Domain vcpu hotplug message.
-#============================================================================
-
-CMSG_VCPU_HOTPLUG = 10
-CMSG_VCPU_HOTPLUG_OFF = 0
-CMSG_VCPU_HOTPLUG_ON = 1
-
-vcpu_hotplug_formats = {
- 'vcpu_hotplug_off_t':
- (CMSG_VCPU_HOTPLUG, CMSG_VCPU_HOTPLUG_OFF),
-
- 'vcpu_hotplug_on_t':
- (CMSG_VCPU_HOTPLUG, CMSG_VCPU_HOTPLUG_ON)
- }
-
-msg_formats.update(vcpu_hotplug_formats)
-
-#============================================================================
-class Msg:
- pass
-
-_next_msgid = 0
-
-def nextid():
- """Generate the next message id.
-
- @return: message id
- @rtype: int
- """
- global _next_msgid
- _next_msgid += 1
- return _next_msgid
-
-def packMsg(ty, params):
- """Pack a message.
- Any I{mac} parameter is passed in as an int[6] array and converted.
-
- @param ty: message type name
- @type ty: string
- @param params: message parameters
- @type params: dicy
- @return: message
- @rtype: xu message
- """
- msgid = nextid()
- if DEBUG: print '>packMsg', msgid, ty, params
- (major, minor) = msg_formats[ty]
- args = {}
- for (k, v) in params.items():
- if k in ['mac', 'be_mac']:
- for i in range(0, 6):
- args['%s[%d]' % (k, i)] = v[i]
- else:
- args[k] = v
- msg = xu.message(major, minor, msgid, args)
- if DEBUG: print '<packMsg', msg.get_header()['id'], ty, args
- return msg
-
-def unpackMsg(ty, msg):
- """Unpack a message.
- Any mac addresses in the message are converted to int[6] array
- in the return dict.
-
- @param ty: message type
- @type ty: string
- @param msg: message
- @type msg: xu message
- @return: parameters
- @rtype: dict
- """
- args = msg.get_payload()
- if DEBUG: print '>unpackMsg', args
- if isinstance(args, types.StringType):
- args = {'value': args}
- else:
- mac = [0, 0, 0, 0, 0, 0]
- macs = []
- for (k, v) in args.items():
- if k.startswith('mac['):
- macs.append(k)
- i = int(k[4:5])
- mac[i] = v
- else:
- pass
- if macs:
- args['mac'] = mac
- #print 'macs=', macs
- #print 'args=', args
- for k in macs:
- del args[k]
- if DEBUG:
- msgid = msg.get_header()['id']
- print '<unpackMsg', msgid, ty, args
- return args
-
-def msgTypeName(ty, subty):
- """Convert a message type, subtype pair to a message type name.
-
- @param ty: message type
- @type ty: int
- @param subty: message subtype
- @type ty: int
- @return: message type name (or None)
- @rtype: string or None
- """
- for (name, info) in msg_formats.items():
- if info[0] == ty and info[1] == subty:
- return name
- return None
-
-def printMsg(msg, out=sys.stdout, all=False):
- """Print a message.
-
- @param msg: message
- @type msg: xu message
- @param out: where to print to
- @type out: stream
- @param all: print payload if true
- @type all: bool
- """
- hdr = msg.get_header()
- major = hdr['type']
- minor = hdr['subtype']
- msgid = hdr['id']
- ty = msgTypeName(major, minor)
- print >>out, 'message:', 'type=', ty, '%d:%d' % (major, minor), 'id=%d' %
msgid
- if all:
- print >>out, 'payload=', msg.get_payload()
-
-
-def getMessageType(msg):
- """Get a 2-tuple of the message type and subtype.
-
- @param msg: message
- @type msg: xu message
- @return: type info
- @rtype: (int, int)
- """
- hdr = msg.get_header()
- return (hdr['type'], hdr.get('subtype'))
-
-def getMessageId(msg):
- hdr = msg.get_header()
- return hdr['id']
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcs/Makefile
--- a/tools/xcs/Makefile Thu Sep 8 15:18:40 2005
+++ /dev/null Fri Sep 9 16:30:54 2005
@@ -1,49 +0,0 @@
-# Makefile for XCS
-# Andrew Warfield, 2004
-
-XEN_ROOT=../..
-include $(XEN_ROOT)/tools/Rules.mk
-
-XCS_INSTALL_DIR = /usr/sbin
-
-INSTALL = install
-INSTALL_PROG = $(INSTALL) -m0755
-INSTALL_DIR = $(INSTALL) -d -m0755
-
-CC = gcc
-CFLAGS = -Wall -Werror -g3 -D _XOPEN_SOURCE=600
-
-CFLAGS += -I $(XEN_XC)
-CFLAGS += -I $(XEN_LIBXC)
-
-SRCS :=
-SRCS += ctrl_interface.c
-SRCS += bindings.c
-SRCS += connection.c
-SRCS += evtchn.c
-SRCS += xcs.c
-
-HDRS = $(wildcard *.h)
-OBJS = $(patsubst %.c,%.o,$(SRCS))
-BIN = xcs
-
-all: $(BIN) xcsdump
-
-clean:
- $(RM) *.a *.so *.o *.rpm $(BIN) xcsdump
-
-xcsdump: xcsdump.c dump.c
- $(CC) $(CFLAGS) -o xcsdump xcsdump.c -L$(XEN_LIBXC) \
- ctrl_interface.c evtchn.c dump.c -lxenctrl
-
-$(BIN): $(OBJS)
- $(CC) $(CFLAGS) $^ -o $@ -L$(XEN_LIBXC) -lxenctrl
-
-$(OBJS): $(HDRS)
-
-install: xcs xcsdump
- $(INSTALL_DIR) -p $(DESTDIR)/$(XCS_INSTALL_DIR)
- $(INSTALL_DIR) -p $(DESTDIR)/usr/include
- $(INSTALL_PROG) xcs $(DESTDIR)/$(XCS_INSTALL_DIR)
- $(INSTALL_PROG) xcsdump $(DESTDIR)/$(XCS_INSTALL_DIR)
- $(INSTALL_PROG) xcs_proto.h $(DESTDIR)/usr/include
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcs/bindings.c
--- a/tools/xcs/bindings.c Thu Sep 8 15:18:40 2005
+++ /dev/null Fri Sep 9 16:30:54 2005
@@ -1,179 +0,0 @@
-/* bindings.c
- *
- * Manage subscriptions for the control interface switch.
- *
- * (c) 2004, Andrew Warfield
- *
- */
-
-/* Interfaces:
- *
- * xcs_bind (port, type, connection)
- * - Register connection to receive messages of this type.
- * xcs_unbind (port, type, connection)
- * - Remove an existing registration. (Must be an exact match)
- * xcs_lookup (port, type)
- * - Return a list of connections matching a registration.
- *
- * - All connections have a connection.bindings list of current bindings.
- * - (port, type) pairs may be wildcarded with -1.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include "xcs.h"
-
-
-typedef struct binding_ent_st {
- connection_t *con;
- struct binding_ent_st *next;
-} binding_ent_t;
-
-#define BINDING_TABLE_SIZE 1024
-
-static binding_ent_t *binding_table[BINDING_TABLE_SIZE];
-
-#define PORT_WILD(_ent) ((_ent)->port == PORT_WILDCARD)
-#define TYPE_WILD(_ent) ((_ent)->type == TYPE_WILDCARD)
-#define FULLY_WILD(_ent) (PORT_WILD(_ent) && TYPE_WILD(_ent))
-
-#define BINDING_HASH(_key) \
- ((((_key)->port * 11) ^ (_key)->type) % BINDING_TABLE_SIZE)
-
-
-void init_bindings(void)
-{
- memset(binding_table, 0, sizeof(binding_table));
-}
-
-static int table_add(binding_ent_t *table[],
- connection_t *con,
- binding_key_t *key)
-{
- binding_ent_t **curs, *ent;
-
- curs = &table[BINDING_HASH(key)];
-
- while (*curs != NULL) {
- if ((*curs)->con == con) {
- DPRINTF("Tried to add an ent that already existed.\n");
- goto done;
- }
- curs = &(*curs)->next;
- }
-
- if (connection_add_binding(con, key) != 0)
- {
- DPRINTF("couldn't add binding on connection (%lu)\n", con->id);
- goto fail;
- }
- ent = (binding_ent_t *)malloc(sizeof(binding_ent_t));
- if (ent == 0) {
- DPRINTF("couldn't alloc binding ent!\n");
- goto fail;
- }
- ent->con = con;
- ent->next = NULL;
- *curs = ent;
-
-done:
- return 0;
-
-fail:
- return -1;
-}
-
-
-static inline int binding_has_colliding_hashes(connection_t *con,
- binding_key_t *key)
-{
- int hash, count = 0;
- binding_key_ent_t *ent;
-
- ent = con->bindings;
- hash = BINDING_HASH(key);
-
- while (ent != NULL) {
- if (BINDING_HASH(&ent->key) == hash) count ++;
- ent = ent->next;
- }
-
- return (count > 1);
-}
-static int table_remove(binding_ent_t *table[],
- connection_t *con,
- binding_key_t *key)
-{
- binding_ent_t **curs, *ent;
-
- if (!binding_has_colliding_hashes(con, key))
- {
-
- curs = &table[BINDING_HASH(key)];
-
- while ((*curs != NULL) && ((*curs)->con != con))
- curs = &(*curs)->next;
-
- if (*curs != NULL) {
- ent = *curs;
- *curs = (*curs)->next;
- free(ent);
- }
- }
-
- connection_remove_binding(con, key);
-
- return 0;
-}
-
-int xcs_bind(connection_t *con, int port, u16 type)
-{
- binding_key_t key;
-
- key.port = port;
- key.type = type;
-
- return table_add(binding_table, con, &key);
-}
-
-int xcs_unbind(connection_t *con, int port, u16 type)
-{
- binding_key_t key;
-
- key.port = port;
- key.type = type;
-
- return table_remove(binding_table, con, &key);
-}
-
-
-static void for_each_binding(binding_ent_t *list, binding_key_t *key,
- void (*f)(connection_t *, void *), void *arg)
-{
- while (list != NULL)
- {
- if (connection_has_binding(list->con, key))
- f(list->con, arg);
- list = list->next;
- }
-}
-
-void xcs_lookup(int port, u16 type, void (*f)(connection_t *, void *),
- void *arg)
-{
- binding_key_t key;
-
- key.port = port; key.type = type;
- for_each_binding(binding_table[BINDING_HASH(&key)], &key, f, arg);
-
- key.port = port; key.type = TYPE_WILDCARD;
- for_each_binding(binding_table[BINDING_HASH(&key)], &key, f, arg);
-
- key.port = PORT_WILDCARD; key.type = type;
- for_each_binding(binding_table[BINDING_HASH(&key)], &key, f, arg);
-
- key.port = PORT_WILDCARD; key.type = TYPE_WILDCARD;
- for_each_binding(binding_table[BINDING_HASH(&key)], &key, f, arg);
-}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcs/connection.c
--- a/tools/xcs/connection.c Thu Sep 8 15:18:40 2005
+++ /dev/null Fri Sep 9 16:30:54 2005
@@ -1,157 +0,0 @@
-/*
- * connection.c
- *
- * State associated with a client connection to xcs.
- *
- * Copyright (c) 2004, Andrew Warfield
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "xcs.h"
-
-connection_t *connection_list = NULL;
-
-#define CONNECTED(_c) (((_c)->ctrl_fd != -1) || ((_c)->data_fd != -1))
-
-connection_t *get_con_by_session(unsigned long session_id)
-{
- connection_t **c, *ent = NULL;
-
- c = &connection_list;
-
- DPRINTF("looking for id: %lu : %lu\n", session_id, (*c)->id);
-
- while (*c != NULL)
- {
- if ((*c)->id == session_id)
- return (*c);
- c = &(*c)->next;
- }
-
- return ent;
-}
-
-connection_t *connection_new()
-{
- connection_t *con;
-
- con = (connection_t *)malloc(sizeof(connection_t));
- if (con == NULL)
- {
- DPRINTF("couldn't allocate a new connection\n");
- return NULL;
- }
-
- con->bindings = NULL;
- con->data_fd = -1;
- con->ctrl_fd = -1;
-
- /* connections need a unique session id.
- * - this approach probably gets fixed later, but for the moment
- * is unique, and clearly identifies a connection.
- */
- con->id = (unsigned long)con;
-
- /* add it to the connection list */
- con->next = connection_list;
- connection_list = con;
-
- return (con);
-}
-
-void connection_free(connection_t *con)
-{
- /* first free all subscribed bindings: */
-
- while (con->bindings != NULL)
- xcs_unbind(con, con->bindings->key.port, con->bindings->key.type);
-
- /* now free the connection. */
- free(con);
-}
-
-int connection_add_binding(connection_t *con, binding_key_t *key)
-{
- binding_key_ent_t *key_ent;
-
- key_ent = (binding_key_ent_t *)malloc(sizeof(binding_key_ent_t));
- if (key_ent == NULL)
- {
- DPRINTF("couldn't alloc key in connection_add_binding\n");
- return -1;
- }
-
- key_ent->key = *key;
- key_ent->next = con->bindings;
- con->bindings = key_ent;
-
- return 0;
-}
-
-int connection_remove_binding(connection_t *con, binding_key_t *key)
-{
- binding_key_ent_t *key_ent;
- binding_key_ent_t **curs = &con->bindings;
-
- while ((*curs != NULL) && (!BINDING_KEYS_EQUAL(&(*curs)->key, key)))
- curs = &(*curs)->next;
-
- if (*curs != NULL) {
- key_ent = *curs;
- *curs = (*curs)->next;
- free(key_ent);
- }
-
- return 0;
-}
-
-
-int connection_has_binding(connection_t *con, binding_key_t *key)
-{
- binding_key_ent_t *ent;
- int ret = 0;
-
- ent = con->bindings;
-
- while (ent != NULL)
- {
- if (BINDING_KEYS_EQUAL(key, &ent->key))
- {
- ret = 1;
- break;
- }
- ent = ent->next;
- }
-
- return ret;
-}
-
-
-void gc_connection_list(void)
-{
- connection_t **c, *ent = NULL;
- struct timeval now, delta;
-
- c = &connection_list;
- gettimeofday(&now, NULL);
-
- while ( *c != NULL )
- {
- if ( !CONNECTED(*c) )
- {
- timersub(&now, &(*c)->disconnect_time, &delta);
- if ( delta.tv_sec >= XCS_SESSION_TIMEOUT )
- {
- DPRINTF(" : Freeing connection %lu after %lds\n",
- (*c)->id, delta.tv_sec);
- ent = *c;
- *c = (*c)->next;
- connection_free(ent);
- continue;
- }
- }
- c = &(*c)->next;
- }
-}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcs/ctrl_interface.c
--- a/tools/xcs/ctrl_interface.c Thu Sep 8 15:18:40 2005
+++ /dev/null Fri Sep 9 16:30:54 2005
@@ -1,269 +0,0 @@
-/* control_interface.c
- *
- * Interfaces to control message rings to VMs.
- *
- * Most of this is directly based on the original xu interface to python
- * written by Keir Fraser.
- *
- * (c) 2004, Andrew Warfield
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <errno.h>
-#include "xcs.h"
-
-static int xc_handle = -1;
-
-/* Called at start-of-day when using the control channel interface. */
-int ctrl_chan_init(void)
-{
- if ( (xc_handle = xc_interface_open()) == -1 )
- {
- DPRINTF("Could not open Xen control interface");
- return -1;
- }
-
- return 0;
-}
-
-static control_if_t *map_control_interface(int fd, unsigned long pfn,
- u32 dom)
-{
- char *vaddr = xc_map_foreign_range( fd, dom, PAGE_SIZE,
- PROT_READ|PROT_WRITE, pfn );
- if ( vaddr == NULL )
- return NULL;
- return (control_if_t *)(vaddr + 2048);
-}
-
-static void unmap_control_interface(int fd, control_if_t *c)
-{
- char *vaddr = (char *)c - 2048;
- (void)munmap(vaddr, PAGE_SIZE);
-}
-
-int ctrl_chan_notify(control_channel_t *cc)
-{
- return xc_evtchn_send(xc_handle, cc->local_port);
-}
-
-int ctrl_chan_read_request(control_channel_t *cc, xcs_control_msg_t *dmsg)
-{
- control_msg_t *smsg;
- RING_IDX c = cc->tx_ring.req_cons;
-
- if ( !RING_HAS_UNCONSUMED_REQUESTS(&cc->tx_ring) )
- {
- DPRINTF("no request to read\n");
- return -1;
- }
-
- rmb(); /* make sure we see the data associated with the request */
- smsg = RING_GET_REQUEST(&cc->tx_ring, c);
- memcpy(&dmsg->msg, smsg, sizeof(*smsg));
- if ( dmsg->msg.length > sizeof(dmsg->msg.msg) )
- dmsg->msg.length = sizeof(dmsg->msg.msg);
- cc->tx_ring.req_cons++;
- return 0;
-}
-
-int ctrl_chan_write_request(control_channel_t *cc,
- xcs_control_msg_t *smsg)
-{
- control_msg_t *dmsg;
- RING_IDX p = cc->rx_ring.req_prod_pvt;
-
- if ( RING_FULL(&cc->rx_ring) )
- {
- DPRINTF("no space to write request");
- return -ENOSPC;
- }
-
- dmsg = RING_GET_REQUEST(&cc->rx_ring, p);
- memcpy(dmsg, &smsg->msg, sizeof(*dmsg));
-
- wmb();
- cc->rx_ring.req_prod_pvt++;
- RING_PUSH_REQUESTS(&cc->rx_ring);
-
- return 0;
-}
-
-int ctrl_chan_read_response(control_channel_t *cc, xcs_control_msg_t *dmsg)
-{
- control_msg_t *smsg;
- RING_IDX c = cc->rx_ring.rsp_cons;
-
- if ( !RING_HAS_UNCONSUMED_RESPONSES(&cc->rx_ring) )
- {
- DPRINTF("no response to read");
- return -1;
- }
-
- rmb(); /* make sure we see the data associated with the request */
- smsg = RING_GET_RESPONSE(&cc->rx_ring, c);
- memcpy(&dmsg->msg, smsg, sizeof(*smsg));
- if ( dmsg->msg.length > sizeof(dmsg->msg.msg) )
- dmsg->msg.length = sizeof(dmsg->msg.msg);
- cc->rx_ring.rsp_cons++;
- return 0;
-}
-
-int ctrl_chan_write_response(control_channel_t *cc,
- xcs_control_msg_t *smsg)
-{
- control_msg_t *dmsg;
- RING_IDX p = cc->tx_ring.rsp_prod_pvt;
-
- /* akw: if the ring is synchronous, you should never need this test! */
- /* (but it was in the original code... ) */
- if ( cc->tx_ring.req_cons == cc->tx_ring.rsp_prod_pvt )
- {
- DPRINTF("no space to write response");
- return -ENOSPC;
- }
-
- dmsg = RING_GET_RESPONSE(&cc->tx_ring, p);
- memcpy(dmsg, &smsg->msg, sizeof(*dmsg));
-
- wmb();
- cc->tx_ring.rsp_prod_pvt++;
- RING_PUSH_RESPONSES(&cc->tx_ring);
-
- return 0;
-}
-
-int ctrl_chan_request_to_read(control_channel_t *cc)
-{
- return (RING_HAS_UNCONSUMED_REQUESTS(&cc->tx_ring));
-}
-
-int ctrl_chan_space_to_write_request(control_channel_t *cc)
-{
- return (!(RING_FULL(&cc->rx_ring)));
-}
-
-int ctrl_chan_response_to_read(control_channel_t *cc)
-{
- return (RING_HAS_UNCONSUMED_RESPONSES(&cc->rx_ring));
-}
-
-int ctrl_chan_space_to_write_response(control_channel_t *cc)
-{
- /* again, there is something fishy here. */
- return ( cc->tx_ring.req_cons != cc->tx_ring.rsp_prod_pvt );
-}
-
-int ctrl_chan_connect(control_channel_t *cc)
-{
- xc_dominfo_t info;
-
- if ( cc->connected )
- {
- return 0;
- }
-
- if ( (xc_domain_getinfo(xc_handle, cc->remote_dom, 1, &info) != 1) ||
- (info.domid != cc->remote_dom) )
- {
- DPRINTF("Failed to obtain domain status");
- return -1;
- }
-
- cc->interface =
- map_control_interface(xc_handle, info.shared_info_frame,
- cc->remote_dom);
-
- if ( cc->interface == NULL )
- {
- DPRINTF("Failed to map domain control interface");
- return -1;
- }
-
- /* Synchronise ring indexes. */
- BACK_RING_ATTACH(&cc->tx_ring, &cc->interface->tx_ring, CONTROL_RING_MEM);
- FRONT_RING_ATTACH(&cc->rx_ring, &cc->interface->rx_ring, CONTROL_RING_MEM);
-
- cc->connected = 1;
-
- return 0;
-}
-
-void ctrl_chan_disconnect(control_channel_t *cc)
-{
- if ( cc->connected )
- unmap_control_interface(xc_handle, cc->interface);
- cc->connected = 0;
-}
-
-
-control_channel_t *ctrl_chan_new(u32 dom, int local_port, int remote_port)
-{
- control_channel_t *cc;
-
- cc = (control_channel_t *)malloc(sizeof(control_channel_t));
- if ( cc == NULL ) return NULL;
-
- cc->connected = 0;
- cc->remote_dom = dom;
-
- if ( dom == 0 )
- {
- /*
- * The control-interface event channel for DOM0 is already set up.
- * We use an ioctl to discover the port at our end of the channel.
- */
- local_port = ioctl(xc_handle, IOCTL_PRIVCMD_INITDOMAIN_EVTCHN,
- NULL);
- remote_port = -1; /* We don't need the remote end of the DOM0 link. */
- if ( local_port < 0 )
- {
- DPRINTF("Could not open channel to DOM0");
- goto fail;
- }
- }
- else if ( xc_evtchn_bind_interdomain(xc_handle,
- DOMID_SELF, dom,
- &local_port, &remote_port) != 0 )
- {
- DPRINTF("Could not open channel to domain");
- goto fail;
- }
-
- cc->local_port = local_port;
- cc->remote_port = remote_port;
-
- if ( ctrl_chan_connect(cc) != 0 )
- goto fail;
-
- return cc;
-
- fail:
- if ( dom != 0 )
- (void)xc_evtchn_close(xc_handle, DOMID_SELF, local_port);
-
- free(cc);
-
- return NULL;
-}
-
-void ctrl_chan_free(control_channel_t *cc)
-{
- ctrl_chan_disconnect(cc);
- if ( cc->remote_dom != 0 )
- (void)xc_evtchn_close(xc_handle, DOMID_SELF, cc->local_port);
- free(cc);
-}
-
-
-/* other libxc commands: */
-
-int ctrl_chan_bind_virq(int virq, int *port)
-{
- return xc_evtchn_bind_virq(xc_handle, virq, port);
-}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcs/dump.c
--- a/tools/xcs/dump.c Thu Sep 8 15:18:40 2005
+++ /dev/null Fri Sep 9 16:30:54 2005
@@ -1,506 +0,0 @@
-/*\
- * Copyright (C) International Business Machines Corp., 2005
- * Author(s): Anthony Liguori <aliguori@xxxxxxxxxx>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; under version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-\*/
-
-#include <stdio.h>
-#include <stdarg.h>
-
-#include "dump.h"
-
-#define str(a) # a
-#define error(a, ...) do { \
- _error("%s:%s():L%d: " a, __FILE__, __FUNCTION__, __LINE__, ## __VA_ARGS__);\
- exit(1); \
-} while (0)
-#define warn(a, ...) do { \
- _error("%s:%s():L%d: " a, __FILE__, __FUNCTION__, __LINE__, ## __VA_ARGS__);\
-} while (0)
-#define debug(a, ...) do { \
- _error(a, ## __VA_ARGS__);\
-} while (0)
-
-void _error(const char *fmt, ...);
-
-#define debug_begin(a, b) debug("CMSG_" a "_" b " {")
-#define debug_end(a, b) debug("}")
-#define debug_field(a, b, c) debug("\t." str(b) " = " c, a->b)
-#define debug_field_mac(a, b) \
- debug("\t." str(b) " = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x", \
- a->b[0], a->b[1], a->b[2], a->b[3], a->b[4], a->b[5])
-
-#define debug_dump(a, b, c) debug_hex("\t." str(b) " = ", a->b, a->c)
-
-#include <stdint.h>
-#include <string.h>
-#include <stdio.h>
-#include <ctype.h>
-
-static int strcount(const char *str, char ch)
-{
- int i;
- int count = 0;
-
- for (i = 0; str[i]; i++) {
- if (str[i] == ch) {
- count++;
- }
- }
-
- return count;
-}
-
-void debug_hex(const char *info, const uint8_t *data, size_t length)
-{
- int indent = strlen(info) + (strcount(info, '\t') * 8 - 1);
- int words_per_row = (2 * (80 - indent - 2) / 7) & ~1;
- size_t i;
-
- for (i = 0; i < length; i += words_per_row) {
- size_t ind;
-
- if (i == 0) {
- fprintf(stderr, "%s", info);
- } else {
- int j;
- for (j = 0; j < indent; j++) {
- fprintf(stderr, " ");
- }
- }
-
- for (ind = 0; ind < words_per_row; ind++) {
- if (ind % 2 == 0) {
- fprintf(stderr, " ");
- }
-
- if (i + ind < length) {
- fprintf(stderr, "%.2X", data[i + ind]);
- } else {
- fprintf(stderr, " ");
- }
- }
-
- fprintf(stderr, " ");
-
- for (ind = 0; ind < words_per_row; ind++) {
- if (i + ind < length) {
- if (isprint(data[i + ind])) {
- fprintf(stderr, "%c", data[i + ind]);
- } else {
- fprintf(stderr, ".");
- }
- } else {
- fprintf(stderr, " ");
- }
- }
- fprintf(stderr, "\n");
- }
-}
-
-void dump_msg(const control_msg_t *msg, uint64_t flags)
-{
- if ((flags & (1 << msg->type)) == 0) {
- return;
- }
-
- switch (msg->type) {
- case CMSG_CONSOLE:
- if (msg->subtype == CMSG_CONSOLE_DATA) {
- debug_begin("CONSOLE", "DATA");
- debug_field(msg, length, "%u");
- debug_dump(msg, msg, length);
- debug_end("CONSOLE", "DATA");
- } else {
- debug_begin("CONSOLE", "UNKNOWN");
- debug_field(msg, subtype, "%u");
- debug_field(msg, length, "%u");
- debug_dump(msg, msg, length);
- debug_end("CONSOLE", "UNKNOWN");
- }
- break;
- case CMSG_BLKIF_BE:
- if (msg->subtype == CMSG_BLKIF_BE_CREATE) {
- blkif_be_create_t *load;
- load = (blkif_be_create_t *)msg->msg;
- debug_begin("BLKIF_BE", "CREATE");
- debug_field(load, domid, "%u");
- debug_field(load, blkif_handle, "%u");
- debug_field(load, status, "%u");
- debug_end("BLKIF_BE", "CREATE");
- } else if (msg->subtype == CMSG_BLKIF_BE_DESTROY) {
- blkif_be_destroy_t *load;
- load = (blkif_be_destroy_t *)msg->msg;
- debug_begin("BLKIF_BE", "DESTROY");
- debug_field(load, domid, "%u");
- debug_field(load, blkif_handle, "%u");
- debug_field(load, status, "%u");
- debug_end("BLKIF_BE", "DESTROY");
- } else if (msg->subtype == CMSG_BLKIF_BE_CONNECT) {
- blkif_be_connect_t *load;
- load = (blkif_be_connect_t *)msg->msg;
- debug_begin("BLKIF_BE", "CONNECT");
- debug_field(load, domid, "%u");
- debug_field(load, blkif_handle, "%u");
- debug_field(load, shmem_frame, "%lu");
- debug_field(load, evtchn, "%u");
- debug_field(load, status, "%u");
- debug_end("BLKIF_BE", "CONNECT");
- } else if (msg->subtype == CMSG_BLKIF_BE_DISCONNECT) {
- blkif_be_disconnect_t *load;
- load = (blkif_be_disconnect_t *)msg->msg;
- debug_begin("BLKIF_BE", "DISCONNECT");
- debug_field(load, domid, "%u");
- debug_field(load, blkif_handle, "%u");
- debug_field(load, status, "%u");
- debug_end("BLKIF_BE", "DISCONNECT");
- } else if (msg->subtype == CMSG_BLKIF_BE_VBD_CREATE) {
- blkif_be_vbd_create_t *load;
- load = (blkif_be_vbd_create_t *)msg->msg;
- debug_begin("BLKIF_BE", "VBD_CREATE");
- debug_field(load, domid, "%u");
- debug_field(load, blkif_handle, "%u");
- debug_field(load, pdevice, "%u");
- debug_field(load, vdevice, "%u");
- debug_field(load, readonly, "%u");
- debug_field(load, status, "%u");
- debug_end("BLKIF_BE", "VBD_CREATE");
- } else if (msg->subtype == CMSG_BLKIF_BE_VBD_DESTROY) {
- blkif_be_vbd_destroy_t *load;
- load = (blkif_be_vbd_destroy_t *)msg->msg;
- debug_begin("BLKIF_BE", "VBD_DESTROY");
- debug_field(load, domid, "%u");
- debug_field(load, blkif_handle, "%u");
- debug_field(load, vdevice, "%u");
- debug_field(load, status, "%u");
- debug_end("BLKIF_BE", "VBD_DESTROY");
- } else if (msg->subtype == CMSG_BLKIF_BE_DRIVER_STATUS) {
- blkif_be_driver_status_t *load;
- load = (blkif_be_driver_status_t *)msg->msg;
- debug_begin("BLKIF_BE", "DRIVER_STATUS");
- debug_field(load, status, "%u");
- debug_end("BLKIF_BE", "DRIVER_STATUS");
- } else {
- debug_begin("BLKIF_BE", "UNKNOWN");
- debug_field(msg, subtype, "%u");
- debug_field(msg, length, "%u");
- debug_dump(msg, msg, length);
- debug_end("BLKIF_BE", "UNKNOWN");
- }
- break;
- case CMSG_BLKIF_FE:
- if (msg->subtype == CMSG_BLKIF_FE_INTERFACE_STATUS) {
- blkif_fe_interface_status_t *load;
- load = (blkif_fe_interface_status_t *)msg->msg;
- debug_begin("BLKIF_FE", "INTERFACE_STATUS");
- debug_field(load, handle, "%u");
- debug_field(load, status, "%u");
- debug_field(load, evtchn, "%u");
- debug_field(load, domid, "%u");
- debug_end("BLKIF_FE", "INTERFACE_STATUS");
- } else if (msg->subtype == CMSG_BLKIF_FE_DRIVER_STATUS) {
- blkif_fe_driver_status_t *load;
- load = (blkif_fe_driver_status_t *)msg->msg;
- debug_begin("BLKIF_FE", "DRIVER_STATUS");
- debug_field(load, status, "%u");
- debug_field(load, max_handle, "%u");
- debug_end("BLKIF_FE", "DRIVER_STATUS");
- } else if (msg->subtype == CMSG_BLKIF_FE_INTERFACE_CONNECT) {
- blkif_fe_interface_connect_t *load;
- load = (blkif_fe_interface_connect_t *)msg->msg;
- debug_begin("BLKIF_FE", "INTERFACE_CONNECT");
- debug_field(load, handle, "%u");
- debug_field(load, shmem_frame, "%lu");
- debug_end("BLKIF_FE", "INTERFACE_CONNECT");
- } else if (msg->subtype == CMSG_BLKIF_FE_INTERFACE_DISCONNECT) {
- blkif_fe_interface_disconnect_t *load;
- load = (blkif_fe_interface_disconnect_t *)msg->msg;
- debug_begin("BLKIF_FE", "INTERFACE_DISCONNECT");
- debug_field(load, handle, "%u");
- debug_end("BLKIF_FE", "INTERFACE_DISCONNECT");
- } else if (msg->subtype == CMSG_BLKIF_FE_INTERFACE_QUERY) {
- blkif_fe_interface_query_t *load;
- load = (blkif_fe_interface_query_t *)msg->msg;
- debug_begin("BLKIF_FE", "INTERFACE_QUERY");
- debug_field(load, handle, "%u");
- debug_field(load, status, "%u");
- debug_field(load, evtchn, "%u");
- debug_field(load, domid, "%u");
- debug_end("BLKIF_FE", "INTERFACE_QUERY");
- } else {
- debug_begin("BLKIF_FE", "UNKNOWN");
- debug_field(msg, subtype, "%u");
- debug_field(msg, length, "%u");
- debug_dump(msg, msg, length);
- debug_end("BLKIF_FE", "UNKNOWN");
- }
- break;
- case CMSG_NETIF_BE:
- if (msg->subtype == CMSG_NETIF_BE_CREATE) {
- netif_be_create_t *load;
- load = (netif_be_create_t *)msg->msg;
- debug_begin("NETIF_BE", "CREATE");
- debug_field(load, domid, "%u");
- debug_field(load, netif_handle, "%u");
- debug_field_mac(load, mac);
- debug_field_mac(load, be_mac);
- debug_field(load, status, "%u");
- debug_end("NETIF_BE", "CREATE");
- } else if (msg->subtype == CMSG_NETIF_BE_DESTROY) {
- netif_be_destroy_t *load;
- load = (netif_be_destroy_t *)msg->msg;
- debug_begin("NETIF_BE", "DESTROY");
- debug_field(load, domid, "%u");
- debug_field(load, netif_handle, "%u");
- debug_field(load, status, "%u");
- debug_end("NETIF_BE", "DESTROY");
- } else if (msg->subtype == CMSG_NETIF_BE_CONNECT) {
- netif_be_connect_t *load;
- load = (netif_be_connect_t *)msg->msg;
- debug_begin("NETIF_BE", "CONNECT");
- debug_field(load, domid, "%u");
- debug_field(load, netif_handle, "%u");
- debug_field(load, tx_shmem_frame, "%lu");
- debug_field(load, rx_shmem_frame, "%lu");
- debug_field(load, evtchn, "%u");
- debug_field(load, status, "%u");
- debug_end("NETIF_BE", "CONNECT");
- } else if (msg->subtype == CMSG_NETIF_BE_DISCONNECT) {
- netif_be_disconnect_t *load;
- load = (netif_be_disconnect_t *)msg->msg;
- debug_begin("NETIF_BE", "DISCONNECT");
- debug_field(load, domid, "%u");
- debug_field(load, netif_handle, "%u");
- debug_field(load, status, "%u");
- debug_end("NETIF_BE", "DISCONNECT");
- } else if (msg->subtype == CMSG_NETIF_BE_DRIVER_STATUS) {
- netif_be_driver_status_t *load;
- load = (netif_be_driver_status_t *)msg->msg;
- debug_begin("NETIF_BE", "DRIVER_STATUS");
- debug_field(load, status, "%u");
- debug_end("NETIF_BE", "DRIVER_STATUS");
- } else {
- debug_begin("NETIF_BE", "UNKNOWN");
- debug_field(msg, subtype, "%u");
- debug_field(msg, length, "%u");
- debug_dump(msg, msg, length);
- debug_end("NETIF_BE", "UNKNOWN");
- }
- break;
- case CMSG_NETIF_FE:
- if (msg->subtype == CMSG_NETIF_FE_INTERFACE_STATUS) {
- netif_fe_interface_status_t *load;
- load = (netif_fe_interface_status_t *)msg->msg;
- debug_begin("NETIF_FE", "INTERFACE_STATUS");
- debug_field(load, handle, "%u");
- debug_field(load, status, "%u");
- debug_field(load, evtchn, "%u");
- debug_field_mac(load, mac);
- debug_field(load, domid, "%u");
- debug_end("NETIF_FE", "INTERFACE_STATUS");
- } else if (msg->subtype == CMSG_NETIF_FE_DRIVER_STATUS) {
- netif_fe_driver_status_t *load;
- load = (netif_fe_driver_status_t *)msg->msg;
- debug_begin("NETIF_FE", "DRIVER_STATUS");
- debug_field(load, status, "%u");
- debug_field(load, max_handle, "%u");
- debug_end("NETIF_FE", "DRIVER_STATUS");
- } else if (msg->subtype == CMSG_NETIF_FE_INTERFACE_CONNECT) {
- netif_fe_interface_connect_t *load;
- load = (netif_fe_interface_connect_t *)msg->msg;
- debug_begin("NETIF_FE", "INTERFACE_CONNECT");
- debug_field(load, handle, "%u");
- debug_field(load, tx_shmem_frame, "%lu");
- debug_field(load, rx_shmem_frame, "%lu");
- debug_end("NETIF_FE", "INTERFACE_CONNECT");
- } else if (msg->subtype == CMSG_NETIF_FE_INTERFACE_DISCONNECT) {
- netif_fe_interface_disconnect_t *load;
- load = (netif_fe_interface_disconnect_t *)msg->msg;
- debug_begin("NETIF_FE", "INTERFACE_DISCONNECT");
- debug_field(load, handle, "%u");
- debug_end("NETIF_FE", "INTERFACE_DISCONNECT");
- } else if (msg->subtype == CMSG_NETIF_FE_INTERFACE_QUERY) {
- netif_fe_interface_query_t *load;
- load = (netif_fe_interface_query_t *)msg->msg;
- debug_begin("NETIF_FE", "INTERFACE_QUERY");
- debug_field(load, handle, "%u");
- debug_field(load, status, "%u");
- debug_field(load, evtchn, "%u");
- debug_field_mac(load, mac);
- debug_field(load, domid, "%u");
- debug_end("NETIF_FE", "INTERFACE_QUERY");
- } else {
- debug_begin("NETIF_FE", "UNKNOWN");
- debug_field(msg, subtype, "%u");
- debug_field(msg, length, "%u");
- debug_dump(msg, msg, length);
- debug_end("NETIF_FE", "UNKNOWN");
- }
- break;
- case CMSG_SHUTDOWN:
- if (msg->subtype == CMSG_SHUTDOWN_POWEROFF) {
- debug_begin("SHUTDOWN", "POWEROFF");
- debug_end("SHUTDOWN", "POWEROFF");
- } else if (msg->subtype == CMSG_SHUTDOWN_REBOOT) {
- debug_begin("SHUTDOWN", "REBOOT");
- debug_end("SHUTDOWN", "REBOOT");
- } else if (msg->subtype == CMSG_SHUTDOWN_SUSPEND) {
- debug_begin("SHUTDOWN", "SUSPEND");
- debug_end("SHUTDOWN", "SUSPEND");
- } else if (msg->subtype == CMSG_SHUTDOWN_SYSRQ) {
- debug_begin("SHUTDOWN", "SYSRQ");
- debug_end("SHUTDOWN", "SYSRQ");
- } else {
- debug_begin("SHUTDOWN", "UNKNOWN");
- debug_field(msg, subtype, "%u");
- debug_field(msg, length, "%u");
- debug_dump(msg, msg, length);
- debug_end("SHUTDOWN", "UNKNOWN");
- }
- break;
- case CMSG_MEM_REQUEST:
- if (msg->subtype == CMSG_MEM_REQUEST_SET) {
- mem_request_t *load;
- load = (mem_request_t *)msg->msg;
- debug_begin("MEM_REQUEST", "SET");
- debug_field(load, target, "%u");
- debug_field(load, status, "%u");
- debug_end("MEM_REQUEST", "SET");
- } else {
- debug_begin("MEM_REQUEST", "UNKNOWN");
- debug_field(msg, subtype, "%u");
- debug_field(msg, length, "%u");
- debug_dump(msg, msg, length);
- debug_end("MEM_REQUEST", "UNKNOWN");
- }
- break;
- case CMSG_USBIF_BE:
- if (msg->subtype == CMSG_USBIF_BE_CREATE) {
- usbif_be_create_t *load;
- load = (usbif_be_create_t *)msg->msg;
- debug_begin("USBIF_BE", "CREATE");
- debug_field(load, domid, "%u");
- debug_field(load, status, "%u");
- debug_end("USBIF_BE", "CREATE");
- } else if (msg->subtype == CMSG_USBIF_BE_DESTROY) {
- usbif_be_destroy_t *load;
- load = (usbif_be_destroy_t *)msg->msg;
- debug_begin("USBIF_BE", "DESTROY");
- debug_field(load, domid, "%u");
- debug_field(load, status, "%u");
- debug_end("USBIF_BE", "DESTROY");
- } else if (msg->subtype == CMSG_USBIF_BE_CONNECT) {
- usbif_be_connect_t *load;
- load = (usbif_be_connect_t *)msg->msg;
- debug_begin("USBIF_BE", "CONNECT");
- debug_field(load, domid, "%u");
- debug_field(load, shmem_frame, "%lu");
- debug_field(load, evtchn, "%u");
- debug_field(load, bandwidth, "%u");
- debug_field(load, status, "%u");
- debug_end("USBIF_BE", "CONNECT");
- } else if (msg->subtype == CMSG_USBIF_BE_DISCONNECT) {
- usbif_be_disconnect_t *load;
- load = (usbif_be_disconnect_t *)msg->msg;
- debug_begin("USBIF_BE", "DISCONNECT");
- debug_field(load, domid, "%u");
- debug_field(load, status, "%u");
- debug_end("USBIF_BE", "DISCONNECT");
- } else if (msg->subtype == CMSG_USBIF_BE_CLAIM_PORT) {
- usbif_be_claim_port_t *load;
- load = (usbif_be_claim_port_t *)msg->msg;
- debug_begin("USBIF_BE", "CLAIM_PORT");
- debug_field(load, domid, "%u");
- debug_field(load, usbif_port, "%u");
- debug_field(load, status, "%u");
- debug_field(load, path, "%s");
- debug_end("USBIF_BE", "CLAIM_PORT");
- } else if (msg->subtype == CMSG_USBIF_BE_RELEASE_PORT) {
- usbif_be_release_port_t *load;
- load = (usbif_be_release_port_t *)msg->msg;
- debug_begin("USBIF_BE", "RELEASE_PORT");
- debug_field(load, path, "%s");
- debug_end("USBIF_BE", "RELEASE_PORT");
- } else if (msg->subtype == CMSG_USBIF_BE_DRIVER_STATUS_CHANGED)
{
- usbif_be_driver_status_changed_t *load;
- load = (usbif_be_driver_status_changed_t *)msg->msg;
- debug_begin("USBIF_BE", "DRIVER_STATUS_CHANGED");
- debug_field(load, status, "%u");
- debug_end("USBIF_BE", "DRIVER_STATUS_CHANGED");
- } else {
- debug_begin("USBIF_BE", "UNKNOWN");
- debug_field(msg, subtype, "%u");
- debug_field(msg, length, "%u");
- debug_dump(msg, msg, length);
- debug_end("USBIF_BE", "UNKNOWN");
- }
- break;
- case CMSG_USBIF_FE:
- if (msg->subtype == CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED) {
- usbif_fe_interface_status_changed_t *load;
- load = (usbif_fe_interface_status_changed_t *)msg->msg;
- debug_begin("USBIF_FE", "INTERFACE_STATUS_CHANGED");
- debug_field(load, status, "%u");
- debug_field(load, evtchn, "%u");
- debug_field(load, domid, "%u");
- debug_field(load, bandwidth, "%u");
- debug_field(load, num_ports, "%u");
- debug_end("USBIF_FE", "INTERFACE_STATUS_CHANGED");
- } else if (msg->subtype == CMSG_USBIF_FE_DRIVER_STATUS_CHANGED)
{
- usbif_fe_driver_status_changed_t *load;
- load = (usbif_fe_driver_status_changed_t *)msg->msg;
- debug_begin("USBIF_FE", "DRIVER_STATUS_CHANGED");
- debug_field(load, status, "%u");
- debug_end("USBIF_FE", "DRIVER_STATUS_CHANGED");
- } else if (msg->subtype == CMSG_USBIF_FE_INTERFACE_CONNECT) {
- usbif_fe_interface_connect_t *load;
- load = (usbif_fe_interface_connect_t *)msg->msg;
- debug_begin("USBIF_FE", "INTERFACE_CONNECT");
- debug_field(load, shmem_frame, "%lu");
- debug_end("USBIF_FE", "INTERFACE_CONNECT");
- } else if (msg->subtype == CMSG_USBIF_FE_INTERFACE_DISCONNECT) {
- debug_begin("USBIF_FE", "INTERFACE_DISCONNECT");
- debug_end("USBIF_FE", "INTERFACE_DISCONNECT");
- } else {
- debug_begin("USBIF_FE", "UNKNOWN");
- debug_field(msg, subtype, "%u");
- debug_field(msg, length, "%u");
- debug_dump(msg, msg, length);
- debug_end("USBIF_FE", "UNKNOWN");
- }
- break;
- default:
- debug_begin("UNKNOWN", "UNKNOWN");
- debug_field(msg, type, "%u");
- debug_field(msg, subtype, "%u");
- debug_field(msg, length, "%u");
- debug_dump(msg, msg, length);
- debug_end("UNKNOWN", "UNKNOWN");
- break;
- }
-}
-
-void _error(const char *fmt, ...)
-{
- va_list ap;
- char buffer[4096];
-
- va_start(ap, fmt);
- vsnprintf(buffer, sizeof(buffer), fmt, ap);
- va_end(ap);
-
- fprintf(stderr, "%s\n", buffer);
-}
-
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcs/dump.h
--- a/tools/xcs/dump.h Thu Sep 8 15:18:40 2005
+++ /dev/null Fri Sep 9 16:30:54 2005
@@ -1,28 +0,0 @@
-/*\
- * Copyright (C) International Business Machines Corp., 2005
- * Author(s): Anthony Liguori <aliguori@xxxxxxxxxx>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; under version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-\*/
-
-#ifndef XENCTLD_ERROR_H
-#define XENCTLD_ERROR_H
-
-#include <stdint.h>
-#include <xenctrl.h>
-#include <xen/io/domain_controller.h>
-
-void dump_msg(const control_msg_t *msg, uint64_t flags);
-
-#endif
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcs/evtchn.c
--- a/tools/xcs/evtchn.c Thu Sep 8 15:18:40 2005
+++ /dev/null Fri Sep 9 16:30:54 2005
@@ -1,106 +0,0 @@
-/* evtchn.c
- *
- * Interfaces to event channel driver.
- *
- * Most of this is directly based on the original xu interface to python
- * written by Keir Fraser.
- *
- * (c) 2004, Andrew Warfield
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/sysmacros.h> /* XOPEN drops makedev, this gets it back. */
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include "xcs.h"
-
-static int evtchn_fd = -1;
-
-/* NB. The following should be kept in sync with the kernel's evtchn driver. */
-#define EVTCHN_DEV_NAME "/dev/xen/evtchn"
-#define EVTCHN_DEV_MAJOR 10
-#define EVTCHN_DEV_MINOR 201
-/* /dev/xen/evtchn ioctls: */
-/* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
-#define EVTCHN_RESET _IO('E', 1)
-/* EVTCHN_BIND: Bind to teh specified event-channel port. */
-#define EVTCHN_BIND _IO('E', 2)
-/* EVTCHN_UNBIND: Unbind from the specified event-channel port. */
-#define EVTCHN_UNBIND _IO('E', 3)
-
-int evtchn_read()
-{
- u16 v;
- int bytes;
-
- while ( (bytes = read(evtchn_fd, &v, sizeof(v))) == -1 )
- {
- if ( errno == EINTR )
- continue;
- /* EAGAIN was cased to return 'None' in the python version... */
- return -errno;
- }
-
- if ( bytes == sizeof(v) )
- return v;
-
- /* bad return */
- return -1;
-}
-
-void evtchn_unmask(u16 idx)
-{
- (void)write(evtchn_fd, &idx, sizeof(idx));
-}
-
-int evtchn_bind(int idx)
-{
- if ( ioctl(evtchn_fd, EVTCHN_BIND, idx) != 0 )
- return -errno;
-
- return 0;
-}
-
-int evtchn_unbind(int idx)
-{
- if ( ioctl(evtchn_fd, EVTCHN_UNBIND, idx) != 0 )
- return -errno;
-
- return 0;
-}
-
-int evtchn_open(void)
-{
- struct stat st;
-
- /* Make sure any existing device file links to correct device. */
- if ( (lstat(EVTCHN_DEV_NAME, &st) != 0) ||
- !S_ISCHR(st.st_mode) ||
- (st.st_rdev != makedev(EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR)) )
- (void)unlink(EVTCHN_DEV_NAME);
-
- reopen:
- evtchn_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR);
- if ( evtchn_fd == -1 )
- {
- if ( (errno == ENOENT) &&
- ((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) &&
- (mknod(EVTCHN_DEV_NAME, S_IFCHR|0600,
- makedev(EVTCHN_DEV_MAJOR,EVTCHN_DEV_MINOR)) == 0) )
- goto reopen;
- return -errno;
- }
- return evtchn_fd;
-}
-
-void evtchn_close()
-{
- (void)close(evtchn_fd);
- evtchn_fd = -1;
-}
-
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcs/xcs.c
--- a/tools/xcs/xcs.c Thu Sep 8 15:18:40 2005
+++ /dev/null Fri Sep 9 16:30:54 2005
@@ -1,973 +0,0 @@
-/* xcs.c
- *
- * xcs - Xen Control Switch
- *
- * Copyright (c) 2004, Andrew Warfield
- */
-
-/*
-
- Things we need to select on in xcs:
-
- 1. Events arriving on /dev/evtchn
-
- These will kick a function to read everything off the fd, and scan the
- associated control message rings, resulting in notifications sent on
- data channels to connected clients.
-
- 2. New TCP connections on XCS_PORT.
-
- These will either be control (intially) or associated data connections.
-
- Control connections will instantiate or rebind to an existing connnection
- struct. The control channel is used to configure what events will be
- received on an associated data channel. These two channels are split
- out because the control channel is synchronous, all messages will return
- a result from XCS. The data channel is effectively asynchronous, events
- may arrive in the middle of a control message exchange. Additionally,
- Having two TCP connections allows the client side to have a blocking
- listen loop for data messages, while independently interacting on the
- control channel at other places in the code.
-
- Data connections attach to an existing control struct, using a session
- id that is passed during the control connect. There is currently a
- one-to-one relationship between data and control channels, but there
- could just as easily be many data channels, if there were a set of
- clients with identical interests, or if you wanted to trace an existing
- client's data traffic.
-
- 3. Messages arriving on open TCP connections.
- There are three types of open connections:
-
- 3a. Messages arriving on open control channel file descriptors.
-
- [description of the control protocol here]
-
- 3b. Messages arriving on open data channel file descriptors.
-
- [description of the data protocol here]
-
- 3c. Messages arriving on (new) unbound connections.
-
- A connection must issue a XCS_CONNECT message to specify what
- it is, after which the connection is moved into one of the above
- two groups.
-
- Additionally, we need a periodic timer to do housekeeping.
-
- 4. Every XCS_GC_INTERVAL seconds, we need to clean up outstanding state.
- Specifically, we garbage collect any sessions (connection_t structs)
- that have been unconnected for a period of time (XCS_SESSION_TIMEOUT),
- and close any connections that have been openned, but not connected
- as a control or data connection (XCS_UFD_TIMEOUT).
-
-*/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <errno.h>
-#include <malloc.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include "xcs.h"
-
-#undef fd_max
-#define fd_max(x,y) ((x) > (y) ? (x) : (y))
-
-/* ------[ Control channel interfaces ]------------------------------------*/
-
-static control_channel_t *cc_list[NR_EVENT_CHANNELS];
-static int *dom_port_map = 0;
-static int dom_port_map_size = 0;
-
-static void map_dom_to_port(u32 dom, int port)
-{
- if (dom >= dom_port_map_size) {
- dom_port_map = (int *)realloc(dom_port_map,
- (dom + 256) * sizeof(dom_port_map[0]));
-
- if (dom_port_map == NULL) {
- perror("realloc(dom_port_map)");
- exit(1);
- }
-
- for (; dom_port_map_size < dom + 256; dom_port_map_size++) {
- dom_port_map[dom_port_map_size] = -1;
- }
- }
-
- dom_port_map[dom] = port;
-}
-
-static int dom_to_port(u32 dom)
-{
- if (dom >= dom_port_map_size) return -1;
-
- return dom_port_map[dom];
-}
-
-static void init_interfaces(void)
-{
- memset(cc_list, 0, sizeof cc_list);
-}
-
-static control_channel_t *add_interface(u32 dom, int local_port,
- int remote_port)
-{
- control_channel_t *cc=NULL, *oldcc;
- int ret;
-
- if ((dom_to_port(dom) >= 0) && (cc_list[dom_to_port(dom)] != NULL))
- {
- return(cc_list[dom_to_port(dom)]);
- }
-
- if (cc_list[local_port] == NULL)
- {
- cc = ctrl_chan_new(dom, local_port, remote_port);
- }
-
- if (cc == NULL)
- return NULL;
-
- DPRINTF("added a new interface: dom: %u (l:%d,r:%d): %p\n",
- dom, local_port, remote_port, cc);
- DPRINTF("added a new interface: dom: %u (l:%d,r:%d): %p\n",
- dom, cc->local_port, cc->remote_port, cc);
-
- if ((ret = evtchn_bind(cc->local_port)) != 0)
- {
- DPRINTF("Got control interface, but couldn't bind evtchan!(%d)\n",
ret);
- ctrl_chan_free(cc);
- return NULL;
- }
-
- if ( cc_list[cc->local_port] != NULL )
- {
- oldcc = cc_list[cc->local_port];
-
- if ((oldcc->remote_dom != cc->remote_dom) ||
- (oldcc->remote_port != cc->remote_port))
- {
- DPRINTF("CC conflict! (port: %d, old dom: %u, new dom: %u, "
- "old ref_count: %d)\n",
- cc->local_port, oldcc->remote_dom, cc->remote_dom,
- oldcc->ref_count);
- map_dom_to_port(oldcc->remote_dom, -1);
- ctrl_chan_free(cc_list[cc->local_port]);
- cc_list[cc->local_port] = NULL;
- }
- }
-
- cc_list[cc->local_port] = cc;
- map_dom_to_port(cc->remote_dom, cc->local_port);
- cc->type = CC_TYPE_INTERDOMAIN;
- cc->ref_count = 0;
- return cc;
-}
-
-control_channel_t *add_virq(int virq)
-{
- control_channel_t *cc;
- int virq_port;
-
- if (ctrl_chan_bind_virq(virq, &virq_port) == -1)
- return NULL;
-
- if ((cc_list[virq_port] != NULL) &&
- (cc_list[virq_port]->type != CC_TYPE_VIRQ))
- return NULL;
-
- if ((cc_list[virq_port] != NULL) &&
- (cc_list[virq_port]->type == CC_TYPE_VIRQ))
- return cc_list[virq_port];
-
- cc = (control_channel_t *)malloc(sizeof(control_channel_t));
- if ( cc == NULL ) return NULL;
-
- memset(cc, 0, sizeof(control_channel_t));
- cc->type = CC_TYPE_VIRQ;
- cc->local_port = virq_port;
- cc->virq = virq;
- cc->ref_count = 1;
-
- if (evtchn_bind(cc->local_port) != 0)
- {
- DPRINTF("Got control interface, but couldn't bind evtchan!\n");
- free(cc);
- return NULL;
- }
-
- cc_list[cc->local_port] = cc;
-
- return cc;
-}
-
-void get_interface(control_channel_t *cc)
-{
- if (cc != NULL)
- cc->ref_count++;
-}
-
-void put_interface(control_channel_t *cc)
-{
- if (cc != NULL)
- {
- cc->ref_count--;
- if (cc->ref_count <= 0)
- {
- DPRINTF("Freeing cc on port %d.\n", cc->local_port);
- (void)evtchn_unbind(cc->local_port);
- cc_list[cc->local_port] = NULL;
- map_dom_to_port(cc->remote_dom, -1);
- ctrl_chan_free(cc);
- }
- }
-}
-
-/* ------[ Simple helpers ]------------------------------------------------*/
-
-/* listen_socket() is straight from paul sheer's useful select_tut manpage. */
-static int listen_socket (char *listen_path)
-{
- struct sockaddr_un a;
- int s;
- int yes;
-
- if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
- {
- perror ("socket");
- return -1;
- }
-
- yes = 1;
-
- memset (&a, 0, sizeof (a));
- a.sun_family = AF_UNIX;
- strcpy(a.sun_path, listen_path);
-
- /* remove an old socket if it exists. */
- unlink(listen_path);
-
- if (bind(s, (struct sockaddr *) &a, sizeof (a)) < 0)
- {
- fprintf (stderr, "bind('%s'): %s\n", listen_path, strerror(errno));
- close (s);
- return -1;
- }
- DPRINTF ("accepting connections on path %s\n", listen_path);
- listen (s, 10);
- return s;
-}
-
-/* ------[ Message handlers ]----------------------------------------------*/
-
-#define NO_CHANGE 0
-#define CONNECTED 1
-#define DISCONNECTED 2
-int handle_connect_msg( xcs_msg_t *msg, int fd )
-{
- xcs_connect_msg_t *cmsg = &msg->u.connect;
- connection_t *con;
- int ret = NO_CHANGE;
-
- switch (msg->type)
- {
- case XCS_CONNECT_CTRL:
- {
- if ( cmsg->session_id == 0 )
- {
- con = connection_new();
- if ( con == NULL)
- {
- msg->result = XCS_RSLT_FAILED;
- break;
- }
- msg->result = XCS_RSLT_OK;
- cmsg->session_id = con->id;
- con->ctrl_fd = fd;
- ret = CONNECTED;
- DPRINTF("New control connection\n");
- break;
- }
-
- con = get_con_by_session(cmsg->session_id);
- if ( con == NULL )
- {
- msg->result = XCS_RSLT_BADSESSION;
- break;
- }
- if ( con->ctrl_fd != -1 )
- {
- msg->result = XCS_RSLT_CONINUSE;
- break;
- }
- con->ctrl_fd = fd;
- msg->result = XCS_RSLT_OK;
- ret = CONNECTED;
- DPRINTF("Rebound to control connection\n");
- break;
- }
- case XCS_CONNECT_DATA:
- {
- con = get_con_by_session(cmsg->session_id);
- if ( con == NULL )
- {
- msg->result = XCS_RSLT_BADSESSION;
- break;
- }
- if ( con->data_fd != -1 )
- {
- msg->result = XCS_RSLT_CONINUSE;
- break;
- }
- con->data_fd = fd;
- msg->result = XCS_RSLT_OK;
- ret = CONNECTED;
- DPRINTF("Attached data connection\n");
- break;
-
- }
- case XCS_CONNECT_BYE:
- {
- close ( fd );
- ret = DISCONNECTED;
- break;
- }
- }
-
- return ret;
-}
-
-int handle_control_message( connection_t *con, xcs_msg_t *msg )
-{
- int ret;
- int reply_needed = 1;
-
- DPRINTF("Got message, type %u.\n", msg->type);
-
- switch (msg->type)
- {
- case XCS_MSG_BIND:
- {
- xcs_bind_msg_t *bmsg = &msg->u.bind;
-
- if ( ! BIND_MSG_VALID(bmsg) )
- {
- msg->result = XCS_RSLT_BADREQUEST;
- break;
- }
-
- ret = xcs_bind(con, bmsg->port, bmsg->type);
- if (ret == 0) {
- msg->result = XCS_RSLT_OK;
- } else {
- msg->result = XCS_RSLT_FAILED;
- }
- break;
- }
- case XCS_MSG_UNBIND:
- {
- xcs_bind_msg_t *bmsg = &msg->u.bind;
-
- if ( ! BIND_MSG_VALID(bmsg) )
- {
- msg->result = XCS_RSLT_BADREQUEST;
- break;
- }
-
- ret = xcs_unbind(con, bmsg->port, bmsg->type);
- if (ret == 0) {
- msg->result = XCS_RSLT_OK;
- } else {
- msg->result = XCS_RSLT_FAILED;
- }
- break;
- }
- case XCS_VIRQ_BIND:
- {
- control_channel_t *cc;
- xcs_virq_msg_t *vmsg = &msg->u.virq;
- if ( ! VIRQ_MSG_VALID(vmsg) )
- {
- msg->result = XCS_RSLT_BADREQUEST;
- break;
- }
-
- cc = add_virq(vmsg->virq);
- if (cc == NULL)
- {
- msg->result = XCS_RSLT_FAILED;
- break;
- }
- ret = xcs_bind(con, cc->local_port, TYPE_VIRQ);
- if (ret == 0) {
- vmsg->port = cc->local_port;
- msg->result = XCS_RSLT_OK;
- } else {
- msg->result = XCS_RSLT_FAILED;
- }
- break;
- }
-
- case XCS_CIF_NEW_CC:
- {
- control_channel_t *cc;
- xcs_interface_msg_t *imsg = &msg->u.interface;
-
- if ( ! INTERFACE_MSG_VALID(imsg) )
- {
- msg->result = XCS_RSLT_BADREQUEST;
- break;
- }
-
- cc = add_interface(imsg->dom, imsg->local_port, imsg->remote_port);
- if (cc != NULL) {
- get_interface(cc);
- msg->result = XCS_RSLT_OK;
- imsg->local_port = cc->local_port;
- imsg->remote_port = cc->remote_port;
- } else {
- msg->result = XCS_RSLT_FAILED;
- }
- break;
- }
-
- case XCS_CIF_FREE_CC:
- {
- control_channel_t *cc;
- xcs_interface_msg_t *imsg = &msg->u.interface;
-
- if ( ! INTERFACE_MSG_VALID(imsg) )
- {
- msg->result = XCS_RSLT_BADREQUEST;
- break;
- }
-
- cc = add_interface(imsg->dom, imsg->local_port, imsg->remote_port);
- if (cc != NULL) {
- put_interface(cc);
- }
- msg->result = XCS_RSLT_OK;
- break;
- }
- }
- return reply_needed;
-}
-
-void handle_data_message( connection_t *con, xcs_msg_t *msg )
-{
- control_channel_t *cc;
- xcs_control_msg_t *cmsg = &msg->u.control;
- int port;
-
- switch (msg->type)
- {
- case XCS_REQUEST:
- if ( cmsg->remote_dom > MAX_DOMS )
- break;
-
- port = dom_to_port(cmsg->remote_dom);
- if (port == -1) break;
- cc = cc_list[port];
- if ((cc != NULL) && ( cc->type == CC_TYPE_INTERDOMAIN ))
- {
- DPRINTF("DN:REQ: dom:%d port: %d type: %d\n",
- cc->remote_dom, cc->local_port,
- cmsg->msg.type);
- ctrl_chan_write_request(cc, cmsg);
- ctrl_chan_notify(cc);
- } else {
- DPRINTF("tried to send a REQ to a null cc\n.");
- }
- break;
-
- case XCS_RESPONSE:
- if ( cmsg->remote_dom > MAX_DOMS )
- break;
-
- port = dom_to_port(cmsg->remote_dom);
- if (port == -1) break;
- cc = cc_list[port];
- if ((cc != NULL) && ( cc->type == CC_TYPE_INTERDOMAIN ))
- {
- DPRINTF("DN:RSP: dom:%d port: %d type: %d\n",
- cc->remote_dom, cc->local_port,
- cmsg->msg.type);
- ctrl_chan_write_response(cc, cmsg);
- ctrl_chan_notify(cc);
- }
- break;
-
- case XCS_VIRQ:
- if ( !(PORT_VALID(cmsg->local_port)) )
- break;
-
- cc = cc_list[cmsg->local_port];
-
- if ((cc != NULL) && ( cc->type == CC_TYPE_VIRQ ))
- {
- DPRINTF("DN:VIRQ: virq: %d port: %d\n",
- cc->virq, cc->local_port);
- ctrl_chan_notify(cc);
- }
- break;
- }
-}
-
-/* ------[ Control interface handler ]-------------------------------------*/
-
-/* passed as a function pointer to the lookup. */
-void send_kmsg(connection_t *c, void *arg)
-{
- xcs_msg_t *msg = (xcs_msg_t *)arg;
-
- DPRINTF(" -> CONNECTION %d\n", c->data_fd);
- if (c->data_fd > 0)
- {
- send(c->data_fd, msg, sizeof(xcs_msg_t), 0);
- }
-}
-
-int handle_ctrl_if(void)
-{
- control_channel_t *cc;
- control_msg_t *msg;
- xcs_msg_t kmsg;
- int chan, ret;
-
- DPRINTF("Event thread kicked!\n");
-again:
- while ((chan = evtchn_read()) > 0)
- {
- evtchn_unmask(chan);
- cc = cc_list[chan];
- if (cc_list[chan] == NULL) {
- DPRINTF("event from unknown channel (%d)\n", chan);
- continue;
- }
-
- if ( cc_list[chan]->type == CC_TYPE_VIRQ )
- {
- DPRINTF("UP:VIRQ: virq:%d port: %d\n",
- cc->virq, cc->local_port);
- kmsg.type = XCS_VIRQ;
- kmsg.u.control.local_port = cc->local_port;
- xcs_lookup(cc->local_port, TYPE_VIRQ, send_kmsg, &kmsg);
- continue;
- }
-
- while (ctrl_chan_request_to_read(cc))
- {
- msg = &kmsg.u.control.msg;
- kmsg.type = XCS_REQUEST;
- kmsg.u.control.remote_dom = cc->remote_dom;
- kmsg.u.control.local_port = cc->local_port;
- ret = ctrl_chan_read_request(cc, &kmsg.u.control);
- DPRINTF("UP:REQ: dom:%d port: %d type: %d len: %d\n",
- cc->remote_dom, cc->local_port,
- msg->type, msg->length);
- if (ret == 0)
- xcs_lookup(cc->local_port, msg->type, send_kmsg, &kmsg);
- }
-
- while (ctrl_chan_response_to_read(cc))
- {
- msg = &kmsg.u.control.msg;
- kmsg.type = XCS_RESPONSE;
- kmsg.u.control.remote_dom = cc->remote_dom;
- kmsg.u.control.local_port = cc->local_port;
- ret = ctrl_chan_read_response(cc, &kmsg.u.control);
- DPRINTF("UP:RSP: dom:%d port: %d type: %d len: %d\n",
- cc->remote_dom, cc->local_port,
- msg->type, msg->length);
- if (ret == 0)
- xcs_lookup(cc->local_port, msg->type, send_kmsg, &kmsg);
- }
- }
-
- if (chan == -EINTR)
- goto again;
-
- return chan;
-}
-
-
-/* ------[ Main xcs code / big select loop ]-------------------------------*/
-
-
-typedef struct unbound_fd_st {
- int fd;
- struct timeval born;
- struct unbound_fd_st *next;
-} unbound_fd_t;
-
-/* This makes ufd point to the next entry in the list, so need to *
- * break/continue if called while iterating. */
-void delete_ufd(unbound_fd_t **ufd)
-{
- unbound_fd_t *del_ufd;
-
- del_ufd = *ufd;
- *ufd = (*ufd)->next;
- free( del_ufd );
-}
-
-void gc_ufd_list( unbound_fd_t **ufd )
-{
- struct timeval now, delta;
-
- gettimeofday(&now, NULL);
-
- while ( *ufd != NULL )
- {
- timersub(&now, &(*ufd)->born, &delta);
- if (delta.tv_sec > XCS_UFD_TIMEOUT)
- {
- DPRINTF("GC-UFD: closing fd: %d\n", (*ufd)->fd);
- close((*ufd)->fd);
- delete_ufd(ufd);
- continue;
- }
- ufd = &(*ufd)->next;
- }
-}
-
-void daemonize_xcs(void)
-{
-
- /* detach from our controlling tty so that a shell does hang waiting for
- stopped jobs. */
-
- pid_t pid = fork();
- int fd;
-
- if (pid == -1) {
- perror("fork()");
- } else if (pid) {
- exit(0);
- }
-
- fd = open("/var/log/xcs.log", O_WRONLY | O_APPEND | O_CREAT);
- if ( fd == -1 ) {
- fprintf(stderr, "xcs couldn't open logfile. Directing all output to "
- "/dev/null instead.\n");
- fd = open("/dev/null", O_WRONLY);
- }
-
- setsid();
- close(2);
- close(1);
- close(0);
- dup(fd);
- dup(fd);
-}
-
-
-static char *pidfilename = NULL;
-void cleanup(int sig)
-{
- /* throw away our pidfile if we created one. */
- if ( pidfilename != NULL )
- unlink(pidfilename);
- exit(0);
-}
-
-int main (int argc, char *argv[])
-{
- int listen_fd, evtchn_fd;
- unbound_fd_t *unbound_fd_list = NULL, **ufd;
- struct timeval timeout = { XCS_GC_INTERVAL, 0 };
- connection_t **con;
- int c, daemonize;
- FILE *pidfile;
- struct stat s;
-
- daemonize = 1;
- pidfile = NULL;
-
- signal(SIGHUP, cleanup);
- signal(SIGTERM, cleanup);
- signal(SIGINT, cleanup);
-
- /* Do a bunch of stuff before potentially daemonizing so we can
- * print error messages sanely before redirecting output. */
-
- /* Initialize xc and event connections. */
- if (ctrl_chan_init() != 0)
- {
- printf("Couldn't open conneciton to libxc.\n");
- exit(-1);
- }
-
- if ((evtchn_fd = evtchn_open()) < 0)
- {
- printf("Couldn't open event channel driver interface.\n");
- exit(-1);
- }
-
- /* Bind listen_fd to the client socket. */
- listen_fd = listen_socket(XCS_SUN_PATH);
-
- while ((c = getopt (argc, argv, "ip:")) != -1)
- {
- switch (c)
- {
- case 'i': /* interactive */
- daemonize = 0;
- break;
- case 'p': /* pid file */
- pidfilename = optarg;
- break;
- case '?':
- if (isprint (optopt))
- fprintf (stderr, "Unknown option `-%c'.\n", optopt);
- else
- fprintf (stderr,
- "Bad option character `\\x%x'.\n", optopt);
- break;
- }
- }
-
- if ( pidfilename != NULL )
- {
- if ( stat(pidfilename, &s) == 0 )
- {
- fprintf(stderr, "Thre specified pid file (%s) already exists.\n"
- "Is another instance of xcs running?\n", pidfilename);
- exit(-1);
- }
-
- pidfile = fopen(pidfilename, "w");
- if (pidfile == NULL)
- {
- fprintf(stderr, "Error openning pidfile (%s).\n", pidfilename);
- exit(-1);
- }
- }
-
- if (daemonize == 1)
- daemonize_xcs();
-
- if (pidfile != NULL)
- {
- fprintf(pidfile, "%d", getpid());
- fclose(pidfile);
- }
-
-
- /* Initialize control interfaces, bindings. */
- init_interfaces();
- init_bindings();
-
-
- for (;;)
- {
- int n = 0, ret;
- fd_set rd, wr, er;
- FD_ZERO ( &rd );
- FD_ZERO ( &wr );
- FD_ZERO ( &er );
-
- /* TCP listen fd: */
- FD_SET ( listen_fd, &rd );
- n = fd_max ( n, listen_fd );
-
- /* Evtchn fd: */
- FD_SET ( evtchn_fd, &rd );
- n = fd_max ( n, evtchn_fd );
-
- /* unbound connection fds: */
- ufd = &unbound_fd_list;
- while ((*ufd) != NULL)
- {
- FD_SET ( (*ufd)->fd, &rd );
- n = fd_max ( n, (*ufd)->fd );
- ufd = &(*ufd)->next;
- }
-
- /* control and data fds: */
- con = &connection_list;
- while ((*con) != NULL)
- {
- if ((*con)->ctrl_fd > 0)
- {
- FD_SET ( (*con)->ctrl_fd, &rd );
- n = fd_max ( n, (*con)->ctrl_fd );
- }
- if ((*con)->data_fd > 0)
- {
- FD_SET ( (*con)->data_fd, &rd );
- n = fd_max ( n, (*con)->data_fd );
- }
- con = &(*con)->next;
- }
-
- ret = select ( n + 1, &rd, &wr, &er, &timeout );
-
- if ( (timeout.tv_sec == 0) && (timeout.tv_usec == 0) )
- {
- gc_ufd_list(&unbound_fd_list);
- gc_connection_list();
- timeout.tv_sec = XCS_GC_INTERVAL;
- }
-
- if ( (ret == -1) && (errno == EINTR) )
- continue;
- if ( ret < 0 )
- {
- perror ("select()");
- exit(-1);
- }
-
- /* CASE 1: Events arriving on /dev/evtchn. */
-
- if ( FD_ISSET (evtchn_fd, &rd ))
- handle_ctrl_if();
-
- /* CASE 2: New connection on the listen port. */
- if ( FD_ISSET ( listen_fd, &rd ))
- {
- struct sockaddr_un remote_addr;
- int size;
- memset (&remote_addr, 0, sizeof (remote_addr));
- size = sizeof remote_addr;
- ret = accept(listen_fd, (struct sockaddr *)&remote_addr,
(socklen_t *)&size);
- if ( ret < 0 )
- {
- perror("accept()");
- } else {
- unbound_fd_t *new_ufd;
-
- new_ufd = (unbound_fd_t *)malloc(sizeof(*new_ufd));
-
- if (new_ufd != NULL)
- {
- gettimeofday(&new_ufd->born, NULL);
- new_ufd->fd = ret;
- new_ufd->next = unbound_fd_list;
- unbound_fd_list = new_ufd;
- } else {
- perror("malloc unbound connection");
- close(ret);
- }
- }
- }
-
- /* CASE 3a: Handle messages on control connections. */
-
- con = &connection_list;
- while ( *con != NULL )
- {
- if ( ((*con)->ctrl_fd > 0) && (FD_ISSET((*con)->ctrl_fd, &rd)) )
- {
- xcs_msg_t msg;
- memset (&msg, 0, sizeof(msg));
- ret = read( (*con)->ctrl_fd, &msg, sizeof(msg) );
-
- if ( ret < 0 )
- {
- perror("reading ctrl fd.");
- } else if ( ret == 0 )
- {
- DPRINTF("Control connection dropped.\n");
- close ( (*con)->ctrl_fd );
- (*con)->ctrl_fd = -1;
- gettimeofday(&(*con)->disconnect_time, NULL);
- } else
- {
- if ( ret != sizeof(msg) )
- {
- DPRINTF("Unexpected frame size!\n");
- continue;
- }
-
- ret = handle_control_message( *con, &msg );
-
- if ( ret == 1 )
- send( (*con)->ctrl_fd, &msg, sizeof(msg), 0 );
- }
- }
- con = &(*con)->next;
- }
-
- /* CASE 3b: Handle messages on data connections. */
-
- con = &connection_list;
- while ( *con != NULL )
- {
- if ( ((*con)->data_fd > 0) && (FD_ISSET((*con)->data_fd, &rd)) )
- {
- xcs_msg_t msg;
- memset (&msg, 0, sizeof(msg));
- ret = read( (*con)->data_fd, &msg, sizeof(msg) );
-
- if ( ret < 0 )
- {
- perror("reading data fd.");
- } else if ( ret == 0 )
- {
- DPRINTF("Data connection dropped.\n");
- close ( (*con)->data_fd );
- (*con)->data_fd = -1;
- gettimeofday(&(*con)->disconnect_time, NULL);
- } else
- {
- if ( ret != sizeof(msg) )
- {
- DPRINTF("Unexpected frame size!\n");
- continue;
- }
-
- handle_data_message( *con, &msg );
- }
- }
- con = &(*con)->next;
- }
-
- /* CASE 3c: Handle messages arriving on unbound connections. */
- ufd = &unbound_fd_list;
- while ((*ufd) != NULL)
- {
- if ( FD_ISSET( (*ufd)->fd, &rd ) )
- {
- xcs_msg_t msg;
- memset (&msg, 0, sizeof(msg));
- ret = read( (*ufd)->fd, &msg, sizeof(msg) );
-
- if ( ret == 0 )
- {
- close ( (*ufd)->fd );
- delete_ufd(ufd);
- continue; /* we just advanced ufd */
- } else {
- if ( ret != sizeof(msg) )
- {
- DPRINTF("Unexpected frame size!\n");
- continue;
- }
-
- ret = handle_connect_msg( &msg, (*ufd)->fd );
-
- if ( (ret == CONNECTED) || (ret == NO_CHANGE) )
- send( (*ufd)->fd, &msg, sizeof(msg), 0 );
-
- if ( (ret = CONNECTED) || (ret = DISCONNECTED) )
- {
- delete_ufd( ufd );
- continue;
- }
- }
- }
- ufd = &(*ufd)->next;
- }
- }
-}
-
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcs/xcs.h
--- a/tools/xcs/xcs.h Thu Sep 8 15:18:40 2005
+++ /dev/null Fri Sep 9 16:30:54 2005
@@ -1,148 +0,0 @@
-/* xcs.h
- *
- * public interfaces for the control interface switch (xcs).
- *
- * (c) 2004, Andrew Warfield
- *
- */
-
-
-#ifndef __XCS_H__
-#define __XCS_H__
-
-#include <pthread.h>
-#include <xenctrl.h>
-#include <xen/xen.h>
-#include <xen/io/domain_controller.h>
-#include <xen/linux/privcmd.h>
-#include <sys/time.h>
-#include "xcs_proto.h"
-
-/* ------[ Debug macros ]--------------------------------------------------*/
-
-#if 0
-#define DPRINTF(_f, _a...) printf ( _f , ## _a )
-#else
-#define DPRINTF(_f, _a...) ((void)0)
-#endif
-
-/* ------[ XCS-specific defines and types ]--------------------------------*/
-
-#define MAX_DOMS 1024
-#define XCS_SESSION_TIMEOUT 10 /* (secs) disconnected session gc timeout */
-#define XCS_UFD_TIMEOUT 5 /* how long can connections be unbound? */
-#define XCS_GC_INTERVAL 5 /* How often to run gc handlers. */
-
-
-/* ------[ Other required defines ]----------------------------------------*/
-
-/* Size of a machine page frame. */
-#define PAGE_SIZE XC_PAGE_SIZE
-
-#ifndef timersub /* XOPEN and __BSD don't cooperate well... */
-#define timersub(a, b, result) \
- do { \
- (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
- (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
- if ((result)->tv_usec < 0) { \
- --(result)->tv_sec; \
- (result)->tv_usec += 1000000; \
- } \
- } while (0)
-#endif /*timersub*/
-
-/* ------[ Bindings Interface ]--------------------------------------------*/
-
-/*forward declare connection_t */
-typedef struct connection_st connection_t;
-
-typedef struct {
- int port;
- u16 type;
-} binding_key_t;
-
-typedef struct binding_key_ent_st {
- binding_key_t key;
- struct binding_key_ent_st *next;
-} binding_key_ent_t;
-
-#define BINDING_KEYS_EQUAL(_k1, _k2) \
- (((_k1)->port == (_k2)->port) && ((_k1)->type == (_k2)->type))
-
-int xcs_bind(connection_t *con, int port, u16 type);
-int xcs_unbind(connection_t *con, int port, u16 type);
-void xcs_lookup(int port, u16 type, void (*f)(connection_t *, void *),
- void *arg);
-void init_bindings(void);
-
-/* ------[ Connection Interface ]------------------------------------------*/
-
-struct connection_st {
- unsigned long id; /* Unique session id */
- int ctrl_fd; /* TCP descriptors */
- int data_fd; /* */
- binding_key_ent_t *bindings; /* List of bindings */
- connection_t *next; /* Linked list of connections */
- struct timeval disconnect_time; /* " " */
-}; /* previously typedefed as connection_t */
-
-
-extern connection_t *connection_list;
-
-connection_t *get_con_by_session(unsigned long session_id);
-connection_t *connection_new();
-void connection_free(connection_t *con);
-int connection_add_binding(connection_t *con, binding_key_t *key);
-int connection_remove_binding(connection_t *con, binding_key_t *key);
-int connection_has_binding(connection_t *con, binding_key_t *key);
-void gc_connection_list(void);
-
-/* ------[ Control Channel Interfaces ]------------------------------------*/
-
-typedef struct {
- int connected;
- int ref_count;
- int type;
- u32 remote_dom;
- int local_port;
- int remote_port;
- control_if_t *interface;
- ctrl_back_ring_t tx_ring;
- ctrl_front_ring_t rx_ring;
- int virq;
-} control_channel_t;
-
-/* cc types that we care about */
-#define CC_TYPE_INTERDOMAIN 0
-#define CC_TYPE_VIRQ 1
-
-control_channel_t
- *ctrl_chan_new(u32 dom, int local_port, int remote_port);
-void ctrl_chan_free(control_channel_t *cc);
-int ctrl_chan_init(void);
-int ctrl_chan_notify(control_channel_t *cc);
-int ctrl_chan_read_request(control_channel_t *cc, xcs_control_msg_t *);
-int ctrl_chan_write_request(control_channel_t *cc,
- xcs_control_msg_t *smsg);
-int ctrl_chan_read_response(control_channel_t *cc, xcs_control_msg_t *);
-int ctrl_chan_write_response(control_channel_t *cc,
- xcs_control_msg_t *smsg);
-int ctrl_chan_request_to_read(control_channel_t *cc);
-int ctrl_chan_space_to_write_request(control_channel_t *cc);
-int ctrl_chan_response_to_read(control_channel_t *cc);
-int ctrl_chan_space_to_write_response(control_channel_t *cc);
-int ctrl_chan_connect(control_channel_t *cc);
-void ctrl_chan_disconnect(control_channel_t *cc);
-int ctrl_chan_bind_virq(int virq, int *port);
-
-/* ------[ Event notification interfaces ]---------------------------------*/
-
-
-int evtchn_open(void);
-void evtchn_close();
-int evtchn_bind(int idx);
-int evtchn_unbind(int idx);
-void evtchn_unmask(u16 idx);
-int evtchn_read();
-
-#endif /* __XCS_H__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcs/xcs_proto.h
--- a/tools/xcs/xcs_proto.h Thu Sep 8 15:18:40 2005
+++ /dev/null Fri Sep 9 16:30:54 2005
@@ -1,101 +0,0 @@
-/* xcs_proto.h
- *
- * protocol interfaces for the control interface switch (xcs).
- *
- * (c) 2004, Andrew Warfield
- *
- */
-
-#ifndef __XCS_PROTO_H__
-#define __XCS_PROTO_H__
-
-#define XCS_SUN_PATH "/var/lib/xen/xcs_socket"
-
-/* xcs message types: */
-#define XCS_CONNECT_CTRL 0 /* This is a control connection. */
-#define XCS_CONNECT_DATA 1 /* This is a data connection. */
-#define XCS_CONNECT_BYE 2 /* Terminate a session. */
-#define XCS_MSG_BIND 3 /* Register for a message type. */
-#define XCS_MSG_UNBIND 4 /* Unregister for a message type. */
-#define XCS_VIRQ_BIND 5 /* Register for a virq. */
-#define XCS_MSG_WRITELOCK 6 /* Writelock a (dom,type) pair. */
-#define XCS_CIF_NEW_CC 7 /* Create a new control channel. */
-#define XCS_CIF_FREE_CC 8 /* Create a new control channel. */
-#define XCS_REQUEST 9 /* This is a request message. */
-#define XCS_RESPONSE 10 /* this is a response Message. */
-#define XCS_VIRQ 11 /* this is a virq notification. */
-
-/* xcs result values: */
-#define XCS_RSLT_OK 0
-#define XCS_RSLT_FAILED 1 /* something bad happened. */
-#define XCS_RSLT_ARECONNECTED 2 /* attempt to over connect. */
-#define XCS_RSLT_BADSESSION 3 /* request for unknown session id. */
-#define XCS_RSLT_NOSESSION 4 /* tried to do something before NEW. */
-#define XCS_RSLT_CONINUSE 5 /* Requested connection is taken. */
-#define XCS_RSLT_BADREQUEST 6 /* Request message didn't validate. */
-
-/* Binding wildcards */
-#define PORT_WILDCARD 0xefffffff
-#define TYPE_WILDCARD 0xffff
-#define TYPE_VIRQ 0xfffe
-
-typedef struct {
- unsigned long session_id;
-} xcs_connect_msg_t;
-
-typedef struct {
- int port;
- u16 type;
-} xcs_bind_msg_t;
-
-typedef struct {
- int port;
- u16 virq;
-} xcs_virq_msg_t;
-
-typedef struct {
- u32 dom;
- int local_port;
- int remote_port;
-} xcs_interface_msg_t;
-
-typedef struct {
- u32 remote_dom;
- int local_port;
- control_msg_t msg;
-} xcs_control_msg_t;
-
-typedef struct {
- u32 type;
- u32 result;
- union {
- xcs_connect_msg_t connect; /* These are xcs ctrl message types */
- xcs_bind_msg_t bind;
- xcs_virq_msg_t virq;
- xcs_interface_msg_t interface;
-
- xcs_control_msg_t control; /* These are xcs data message types */
- } u;
-} xcs_msg_t;
-
-/* message validation macros. */
-#define PORT_VALID(_p) \
- ( (((_p) >= 0) && ((_p) < NR_EVENT_CHANNELS)) \
- || ((_p) == PORT_WILDCARD) )
-
-#define TYPE_VALID(_t) \
- ( ((_t) < 256) \
- || ((_t) == TYPE_VIRQ) \
- || ((_t) == TYPE_WILDCARD) )
-
-#define BIND_MSG_VALID(_b) \
- ( PORT_VALID((_b)->port) && TYPE_VALID((_b)->type) )
-
-/* Port is overwritten, and we don't currently validate the requested virq. */
-#define VIRQ_MSG_VALID(_v) ( 1 )
-
-/* Interfaces may return with ports of -1, but may not be requested as such */
-#define INTERFACE_MSG_VALID(_i) \
- ( PORT_VALID((_i)->local_port) && PORT_VALID((_i)->remote_port) )
-
-#endif /* __XCS_PROTO_H__ */
diff -r 10b1d30d3f66 -r b2f4823b6ff0 tools/xcs/xcsdump.c
--- a/tools/xcs/xcsdump.c Thu Sep 8 15:18:40 2005
+++ /dev/null Fri Sep 9 16:30:54 2005
@@ -1,206 +0,0 @@
-/* xcsdump.c
- *
- * little tool to sniff control messages.
- *
- * Copyright (c) 2004, Andrew Warfield
- *
- * Modifications by Anthony Liguori <aliguori@xxxxxxxxxx> are:
- * Copyright (C) 2005, International Business Machines, Corp.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <ctype.h>
-#include <xenctrl.h>
-#include <xen/xen.h>
-#include <xen/io/domain_controller.h>
-#include <getopt.h>
-#include "xcs_proto.h"
-#include "xcs.h"
-
-#include "dump.h"
-
-static int xcs_ctrl_fd = -1; /* connection to the xcs server. */
-static int xcs_data_fd = -1; /* connection to the xcs server. */
-
-int sock_connect(char *path)
-{
- struct sockaddr_un addr;
- int ret, len, fd;
-
- fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (fd < 0)
- {
- printf("error creating xcs socket!\n");
- return -1;
- }
-
- addr.sun_family = AF_UNIX;
- strcpy(addr.sun_path, path);
- len = sizeof(addr.sun_family) + strlen(addr.sun_path) + 1;
-
- ret = connect(fd, (struct sockaddr *)&addr, len);
- if (ret < 0)
- {
- printf("error connecting to xcs!\n");
- return -1;
- }
-
- return fd;
-}
-
-void sock_disconnect(int *fd)
-{
- close(*fd);
- *fd = -1;
-}
-
-void xcs_read(int fd, xcs_msg_t *msg)
-{
- int ret;
-
- ret = read(fd, msg, sizeof(xcs_msg_t));
- if (ret != sizeof(xcs_msg_t)) {
- printf("read error\n");
- exit(-1);
- }
-}
-
-void xcs_send(int fd, xcs_msg_t *msg)
-{
- int ret;
-
- ret = send(fd, msg, sizeof(xcs_msg_t), 0);
- if (ret != sizeof(xcs_msg_t) )
- {
- printf("send error\n");
- exit(-1);
- }
-}
-
-
-int main(int argc, char* argv[])
-{
- int ret;
- xcs_msg_t msg;
- control_msg_t *cmsg;
- int verbose = 0;
- int ch;
-
- while ((ch = getopt(argc, argv, "hv:")) != -1)
- {
- switch (ch)
- {
- case 'v':
- verbose = atoi(optarg);
- break;
- case 'h':
- printf("Usage: %s [-v FLAGS]\n"
-"Displays XCS control message traffic.\n"
-"\n"
-"FLAGS is a bitmask where each bit (numbering starts from LSB) represents\n"
-"whether to display a particular message type.\n"
-"\n"
-"For example, -v 1022 will display all messages except for console messages.\n"
- , argv[0]);
- exit(0);
- break;
- }
- }
-
- ret = sock_connect(XCS_SUN_PATH);
- if (ret < 0)
- {
- printf("connect failed!\n");
- exit(-1);
- }
- xcs_ctrl_fd = ret;
-
- memset(&msg, 0, sizeof(msg));
- msg.type = XCS_CONNECT_CTRL;
- xcs_send(xcs_ctrl_fd, &msg);
- xcs_read(xcs_ctrl_fd, &msg);
- if (msg.result != XCS_RSLT_OK)
- {
- printf("Error connecting control channel\n");
- exit(-1);
- }
-
- ret = sock_connect(XCS_SUN_PATH);
- if (ret < 0)
- {
- printf("connect failed!\n");
- exit(-1);
- }
- xcs_data_fd = ret;
-
- msg.type = XCS_CONNECT_DATA;
- /* session id is set from before... */
- xcs_send(xcs_data_fd, &msg);
- xcs_read(xcs_data_fd, &msg);
- if (msg.result != XCS_RSLT_OK)
- {
- printf("Error connecting data channel\n");
- exit(-1);
- }
-
- msg.type = XCS_MSG_BIND;
- msg.u.bind.port = PORT_WILDCARD;
- msg.u.bind.type = TYPE_WILDCARD;
- xcs_send(xcs_ctrl_fd, &msg);
- xcs_read(xcs_ctrl_fd, &msg);
- if (msg.result != XCS_RSLT_OK)
- {
- printf("Error binding.\n");
- exit(-1);
- }
-
-
- while (1)
- {
- xcs_read(xcs_data_fd, &msg);
- cmsg = &msg.u.control.msg;
-
- switch (msg.type)
- {
- case XCS_REQUEST:
- if (!verbose || verbose & (1 << msg.u.control.msg.type))
- {
- printf("[REQUEST ] : (dom:%u port:%d) (type:(%d,%d) len %d)\n",
- msg.u.control.remote_dom,
- msg.u.control.local_port,
- msg.u.control.msg.type,
- msg.u.control.msg.subtype,
- msg.u.control.msg.length);
-
- dump_msg(cmsg, verbose);
- }
- break;
- case XCS_RESPONSE:
- if (!verbose || verbose & (1 << msg.u.control.msg.type))
- {
- printf("[RESPONSE] : (dom:%u port:%d) (type:(%d,%d) len %d)\n",
- msg.u.control.remote_dom,
- msg.u.control.local_port,
- msg.u.control.msg.type,
- msg.u.control.msg.subtype,
- msg.u.control.msg.length);
-
- dump_msg(cmsg, verbose);
- }
- break;
- case XCS_VIRQ:
- printf("[VIRQ ] : %d\n", msg.u.control.local_port);
- break;
- default:
- printf("[UNKNOWN ] : %d\n", msg.type);
- }
- }
-
- return(0);
-}
diff -r 10b1d30d3f66 -r b2f4823b6ff0 xen/common/dom_mem_ops.c
--- a/xen/common/dom_mem_ops.c Thu Sep 8 15:18:40 2005
+++ /dev/null Fri Sep 9 16:30:54 2005
@@ -1,186 +0,0 @@
-/******************************************************************************
- * dom_mem_ops.c
- *
- * Code to handle memory related requests from domains eg. balloon driver.
- *
- * Copyright (c) 2003-2004, B Dragovic & K A Fraser.
- */
-
-#include <xen/config.h>
-#include <xen/types.h>
-#include <xen/lib.h>
-#include <xen/mm.h>
-#include <xen/perfc.h>
-#include <xen/sched.h>
-#include <xen/event.h>
-#include <xen/shadow.h>
-#include <asm/current.h>
-#include <asm/hardirq.h>
-
-/*
- * To allow safe resume of do_dom_mem_op() after preemption, we need to know
- * at what point in the page list to resume. For this purpose I steal the
- * high-order bits of the @op parameter, which are otherwise unused and zero.
- */
-#define START_EXTENT_SHIFT 4 /* op[:4] == start_extent */
-
-#define PREEMPT_CHECK(_op) \
- if ( hypercall_preempt_check() ) \
- return hypercall5_create_continuation( \
- __HYPERVISOR_dom_mem_op, \
- (_op) | (i << START_EXTENT_SHIFT), \
- extent_list, nr_extents, extent_order, \
- (d == current->domain) ? DOMID_SELF : d->domain_id);
-
-static long
-alloc_dom_mem(struct domain *d,
- unsigned long *extent_list,
- unsigned long start_extent,
- unsigned int nr_extents,
- unsigned int extent_order,
- unsigned int flags)
-{
- struct pfn_info *page;
- unsigned long i;
-
- if ( (extent_list != NULL) &&
- !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
- return start_extent;
-
- if ( (extent_order != 0) && !IS_CAPABLE_PHYSDEV(current->domain) )
- {
- DPRINTK("Only I/O-capable domains may allocate > order-0 memory.\n");
- return start_extent;
- }
-
- for ( i = start_extent; i < nr_extents; i++ )
- {
- PREEMPT_CHECK(MEMOP_increase_reservation);
-
- if ( unlikely((page = alloc_domheap_pages(d, extent_order,
- flags)) == NULL) )
- {
- DPRINTK("Could not allocate a frame\n");
- return i;
- }
-
- /* Inform the domain of the new page's machine address. */
- if ( (extent_list != NULL) &&
- (__put_user(page_to_pfn(page), &extent_list[i]) != 0) )
- return i;
- }
-
- return i;
-}
-
-static long
-free_dom_mem(struct domain *d,
- unsigned long *extent_list,
- unsigned long start_extent,
- unsigned int nr_extents,
- unsigned int extent_order)
-{
- struct pfn_info *page;
- unsigned long i, j, mpfn;
-
- if ( !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
- return start_extent;
-
- for ( i = start_extent; i < nr_extents; i++ )
- {
- PREEMPT_CHECK(MEMOP_decrease_reservation);
-
- if ( unlikely(__get_user(mpfn, &extent_list[i]) != 0) )
- return i;
-
- for ( j = 0; j < (1 << extent_order); j++ )
- {
- if ( unlikely((mpfn + j) >= max_page) )
- {
- DPRINTK("Domain %u page number out of range (%lx >= %lx)\n",
- d->domain_id, mpfn + j, max_page);
- return i;
- }
-
- page = &frame_table[mpfn + j];
- if ( unlikely(!get_page(page, d)) )
- {
- DPRINTK("Bad page free for domain %u\n", d->domain_id);
- return i;
- }
-
- if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
- put_page_and_type(page);
-
- if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
- put_page(page);
-
- shadow_sync_and_drop_references(d, page);
-
- put_page(page);
- }
- }
-
- return i;
-}
-
-long
-do_dom_mem_op(unsigned long op,
- unsigned long *extent_list,
- unsigned int nr_extents,
- unsigned int extent_order,
- domid_t domid)
-{
- struct domain *d;
- unsigned long rc, start_extent;
- unsigned int address_bits_order;
-
- /* Extract @start_extent from @op. */
- start_extent = op >> START_EXTENT_SHIFT;
- op &= (1 << START_EXTENT_SHIFT) - 1;
-
- /* seperate extent_order and address_bits_order */
- address_bits_order = (extent_order >> 8) & 0xff;
- extent_order &= 0xff;
-
- if ( unlikely(start_extent > nr_extents) )
- return -EINVAL;
-
- if ( likely(domid == DOMID_SELF) )
- d = current->domain;
- else if ( unlikely(!IS_PRIV(current->domain)) )
- return -EPERM;
- else if ( unlikely((d = find_domain_by_id(domid)) == NULL) )
- return -ESRCH;
-
- switch ( op )
- {
- case MEMOP_increase_reservation:
- rc = alloc_dom_mem(
- d, extent_list, start_extent, nr_extents, extent_order,
- (address_bits_order <= 32) ? ALLOC_DOM_DMA : 0);
- break;
- case MEMOP_decrease_reservation:
- rc = free_dom_mem(
- d, extent_list, start_extent, nr_extents, extent_order);
- break;
- default:
- rc = -ENOSYS;
- break;
- }
-
- if ( unlikely(domid != DOMID_SELF) )
- put_domain(d);
-
- return rc;
-}
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|