From 3e16170919ce88b7e920f72dfc776d69461ab6b2 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 3 Mar 2006 10:34:03 +0100 Subject: [PATCH 01/12] Add a 'clear trap table' path to set_trap_table hypercall, taken when the input table is NULL. Also, no need for set_trap_table to take the per-domain biglock. Signed-off-by: Keir Fraser --- xen/arch/x86/traps.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 97cf8bb5ab..78bff071d8 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -1410,7 +1410,13 @@ long do_set_trap_table(struct trap_info *traps) struct trap_info *dst = current->arch.guest_context.trap_ctxt; long rc = 0; - LOCK_BIGLOCK(current->domain); + /* If no table is presented then clear the entire virtual IDT. */ + if ( traps == NULL ) + { + memset(dst, 0, 256 * sizeof(*dst)); + init_int80_direct_trap(current); + return 0; + } for ( ; ; ) { @@ -1440,8 +1446,6 @@ long do_set_trap_table(struct trap_info *traps) traps++; } - UNLOCK_BIGLOCK(current->domain); - return rc; } From f7145c633e136994b0dd8813445a1013e54f5996 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 3 Mar 2006 10:44:40 +0100 Subject: [PATCH 02/12] Ignore external (user-provided) CFLAGS when building vmxassist and hvmloader. They do more harm than good. Signed-off-by: Keir Fraser --- tools/firmware/hvmloader/Makefile | 3 +++ tools/firmware/vmxassist/Makefile | 3 +++ 2 files changed, 6 insertions(+) diff --git a/tools/firmware/hvmloader/Makefile b/tools/firmware/hvmloader/Makefile index 421224c60a..ff95836e90 100644 --- a/tools/firmware/hvmloader/Makefile +++ b/tools/firmware/hvmloader/Makefile @@ -18,6 +18,9 @@ # Place - Suite 330, Boston, MA 02111-1307 USA. # +# External CFLAGS can do more harm than good. +CFLAGS := + XEN_ROOT = ../../.. include $(XEN_ROOT)/Config.mk diff --git a/tools/firmware/vmxassist/Makefile b/tools/firmware/vmxassist/Makefile index 814bf16396..aabd32cc1a 100644 --- a/tools/firmware/vmxassist/Makefile +++ b/tools/firmware/vmxassist/Makefile @@ -18,6 +18,9 @@ # Place - Suite 330, Boston, MA 02111-1307 USA. # +# External CFLAGS can do more harm than good. +CFLAGS := + XEN_ROOT = ../../.. include $(XEN_ROOT)/Config.mk From b8d1d84a4f6938350faf24f1516015f17a547a14 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 3 Mar 2006 10:46:06 +0100 Subject: [PATCH 03/12] VTPM_Tools: Fix error when closing only vtpm, and fix restore bug when no dmis exist The first bug prevented the TPM tests from running successfully more than once in a row. Signed-off-by: Vinnie Scarlata --- tools/vtpm_manager/manager/dmictl.c | 9 ++++++++- tools/vtpm_manager/manager/securestorage.c | 13 +++++++------ tools/vtpm_manager/manager/vtpm_manager.c | 1 + tools/vtpm_manager/manager/vtpmpriv.h | 1 + 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/tools/vtpm_manager/manager/dmictl.c b/tools/vtpm_manager/manager/dmictl.c index 17625bc633..ffbd5cd7f2 100644 --- a/tools/vtpm_manager/manager/dmictl.c +++ b/tools/vtpm_manager/manager/dmictl.c @@ -74,7 +74,13 @@ TPM_RESULT close_dmi( VTPM_DMI_RESOURCE *dmi_res) { close(dmi_res->guest_tx_fh); dmi_res->guest_tx_fh = -1; close(dmi_res->vtpm_tx_fh); dmi_res->vtpm_tx_fh = -1; - + vtpm_globals->connected_dmis--; + + if (vtpm_globals->connected_dmis == 0) { + // No more DMI's connected. Close fifo to prevent a broken pipe. + close(vtpm_globals->guest_rx_fh); + vtpm_globals->guest_rx_fh = -1; + } #ifndef MANUAL_DM_LAUNCH if (dmi_res->dmi_id != VTPM_CTL_DM) { if (dmi_res->dmi_pid != 0) { @@ -118,6 +124,7 @@ TPM_RESULT VTPM_Handle_New_DMI( const buffer_t *param_buf) { status = TPM_BAD_PARAMETER; goto abort_egress; } else { + vtpm_globals->connected_dmis++; // Put this here so we don't count Dom0 BSG_UnpackList( param_buf->bytes, 3, BSG_TYPE_BYTE, &type, BSG_TYPE_UINT32, &domain_id, diff --git a/tools/vtpm_manager/manager/securestorage.c b/tools/vtpm_manager/manager/securestorage.c index 4df8531c40..1c4bd4931e 100644 --- a/tools/vtpm_manager/manager/securestorage.c +++ b/tools/vtpm_manager/manager/securestorage.c @@ -307,8 +307,8 @@ TPM_RESULT VTPM_SaveService(void) { TPM_RESULT status=TPM_SUCCESS; int fh, dmis=-1; - BYTE *flat_boot_key, *flat_dmis, *flat_enc; - buffer_t clear_flat_global, enc_flat_global; + BYTE *flat_boot_key=NULL, *flat_dmis=NULL, *flat_enc=NULL; + buffer_t clear_flat_global=NULL_BUF, enc_flat_global=NULL_BUF; UINT32 storageKeySize = buffer_len(&vtpm_globals->storageKeyWrap); UINT32 bootKeySize = buffer_len(&vtpm_globals->bootKeyWrap); struct pack_buf_t storage_key_pack = {storageKeySize, vtpm_globals->storageKeyWrap.bytes}; @@ -328,12 +328,9 @@ TPM_RESULT VTPM_SaveService(void) { sizeof(UINT32) +// storagekeysize storageKeySize, NULL) ); // storage key - flat_dmis_size = (hashtable_count(vtpm_globals->dmi_map) - 1) * // num DMIS (-1 for Dom0) - (sizeof(UINT32) + 2*sizeof(TPM_DIGEST)); // Per DMI info flat_boot_key = (BYTE *) malloc( boot_key_size ); flat_enc = (BYTE *) malloc( sizeof(UINT32) ); - flat_dmis = (BYTE *) malloc( flat_dmis_size ); boot_key_size = BSG_PackList(flat_boot_key, 1, BSG_TPM_SIZE32_DATA, &boot_key_pack); @@ -349,9 +346,13 @@ TPM_RESULT VTPM_SaveService(void) { BSG_PackConst(buffer_len(&enc_flat_global), 4, flat_enc); - // Per DMI values to be saved + // Per DMI values to be saved (if any exit) if (hashtable_count(vtpm_globals->dmi_map) > 0) { + flat_dmis_size = (hashtable_count(vtpm_globals->dmi_map) - 1) * // num DMIS (-1 for Dom0) + (sizeof(UINT32) + 2*sizeof(TPM_DIGEST)); // Per DMI info + flat_dmis = (BYTE *) malloc( flat_dmis_size ); + dmi_itr = hashtable_iterator(vtpm_globals->dmi_map); do { dmi_res = (VTPM_DMI_RESOURCE *) hashtable_iterator_value(dmi_itr); diff --git a/tools/vtpm_manager/manager/vtpm_manager.c b/tools/vtpm_manager/manager/vtpm_manager.c index ab391a6ccc..e9061aabed 100644 --- a/tools/vtpm_manager/manager/vtpm_manager.c +++ b/tools/vtpm_manager/manager/vtpm_manager.c @@ -754,6 +754,7 @@ TPM_RESULT VTPM_Init_Service() { #ifndef VTPM_MULTI_VM vtpm_globals->vtpm_rx_fh = -1; vtpm_globals->guest_rx_fh = -1; + vtpm_globals->connected_dmis = 0; #endif if ((vtpm_globals->dmi_map = create_hashtable(10, hashfunc32, equals32)) == NULL){ status = TPM_FAIL; diff --git a/tools/vtpm_manager/manager/vtpmpriv.h b/tools/vtpm_manager/manager/vtpmpriv.h index 845cf011dd..c579d50518 100644 --- a/tools/vtpm_manager/manager/vtpmpriv.h +++ b/tools/vtpm_manager/manager/vtpmpriv.h @@ -98,6 +98,7 @@ typedef struct tdVTPM_GLOBALS { #ifndef VTPM_MULTI_VM int vtpm_rx_fh; int guest_rx_fh; + int connected_dmis; // Used to close guest_rx when no dmis are connected pid_t master_pid; #endif From 7cca11754fb68f1f35468092442d7b1485d2633e Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 3 Mar 2006 10:53:58 +0100 Subject: [PATCH 04/12] Fix up some issues I found when porting PPC to the new common gdb stub code: - cosmetic changes in the messages printed - 'flags' must always be unsigned long. - explicitly calling initialize_gdb() is not difficult. For x86 and ia64 I placed this call immediately before do_initcalls(), since that's where it's being called from now so we know it's safe. Architecture people can move it earlier as appropriate. - I don't understand all these ASSERT(!local_irq_is_enabled()) statements, sometimes bracketing a single call like receive_command(). How exactly would receive_command() manage to re-enable irqs? Also, a failing ASSERT would just call into the stub again anways... - initialize_gdb() was overcomplicated. serial_parse_handle() already handles the parsing for us, and there's no need to panic there. Signed-off-by: Hollis Blanchard --- xen/arch/ia64/xen/xensetup.c | 4 +++- xen/arch/x86/setup.c | 3 +++ xen/common/gdbstub.c | 34 +++++++--------------------------- xen/include/xen/gdbstub.h | 10 ++++++++++ 4 files changed, 23 insertions(+), 28 deletions(-) diff --git a/xen/arch/ia64/xen/xensetup.c b/xen/arch/ia64/xen/xensetup.c index 8b6faeed26..38784f77df 100644 --- a/xen/arch/ia64/xen/xensetup.c +++ b/xen/arch/ia64/xen/xensetup.c @@ -12,7 +12,7 @@ #include #include #include -//#include +#include #include #include #include @@ -360,6 +360,8 @@ printk("About to call __cpu_up(%d)\n",i); smp_cpus_done(max_cpus); #endif + initialise_gdb(); /* could be moved earlier */ + do_initcalls(); printk("About to call sort_main_extable()\n"); sort_main_extable(); diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index ae73fe6ca9..b5b0fd68e0 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -479,6 +480,8 @@ void __init __start_xen(multiboot_info_t *mbi) printk("Brought up %ld CPUs\n", (long)num_online_cpus()); smp_cpus_done(max_cpus); + initialise_gdb(); /* could be moved earlier */ + do_initcalls(); schedulers_start(); diff --git a/xen/common/gdbstub.c b/xen/common/gdbstub.c index 48c1b0a41f..5f5beb690a 100644 --- a/xen/common/gdbstub.c +++ b/xen/common/gdbstub.c @@ -376,7 +376,6 @@ process_command(struct cpu_user_regs *regs, struct gdb_context *ctx) break; case 'g': /* Read registers */ gdb_arch_read_reg_array(regs, ctx); - ASSERT(!local_irq_is_enabled()); break; case 'G': /* Write registers */ gdb_arch_write_reg_array(regs, ctx->in_buf + 1, ctx); @@ -395,7 +394,6 @@ process_command(struct cpu_user_regs *regs, struct gdb_context *ctx) return 0; } gdb_cmd_read_mem(addr, length, ctx); - ASSERT(!local_irq_is_enabled()); break; case 'M': /* Write memory */ addr = simple_strtoul(ctx->in_buf + 1, &ptr, 16); @@ -477,7 +475,7 @@ __trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie) { int resume = 0; int r; - unsigned flags; + unsigned long flags; if ( gdb_ctx->serhnd < 0 ) { @@ -506,7 +504,7 @@ __trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie) if ( !gdb_ctx->connected ) { - printk("GDB connection activated\n"); + printk("GDB connection activated.\n"); gdb_arch_print_state(regs); gdb_ctx->connected = 1; } @@ -522,7 +520,7 @@ __trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie) /* Shouldn't really do this, but otherwise we stop for no obvious reason, which is Bad */ - printk("Waiting for GDB to attach to Gdb\n"); + printk("Waiting for GDB to attach...\n"); gdb_arch_enter(regs); gdb_ctx->signum = gdb_arch_signal_num(regs, cookie); @@ -535,9 +533,7 @@ __trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie) while ( resume == 0 ) { - ASSERT(!local_irq_is_enabled()); r = receive_command(gdb_ctx); - ASSERT(!local_irq_is_enabled()); if ( r < 0 ) { dbg_printk("GDB disappeared, trying to resume Xen...\n"); @@ -545,9 +541,7 @@ __trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie) } else { - ASSERT(!local_irq_is_enabled()); resume = process_command(regs, gdb_ctx); - ASSERT(!local_irq_is_enabled()); } } @@ -561,28 +555,14 @@ __trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie) return 0; } -/* - * initialization - * XXX TODO - * This should be an explicit call from architecture code. - * initcall is far too late for some early debugging, and only the - * architecture code knows when this call can be made. - */ -static int -initialize_gdb(void) +void +initialise_gdb(void) { - if ( !strcmp(opt_gdb, "none") ) - return 0; gdb_ctx->serhnd = serial_parse_handle(opt_gdb); - if ( gdb_ctx->serhnd == -1 ) - panic("Can't parse %s as GDB serial info.\n", opt_gdb); - - printk("Gdb initialised.\n"); - return 0; + if ( gdb_ctx->serhnd != -1 ) + printk("GDB stub initialised.\n"); } -__initcall(initialize_gdb); - /* * Local variables: * mode: C diff --git a/xen/include/xen/gdbstub.h b/xen/include/xen/gdbstub.h index 9d2e323aed..609831de95 100644 --- a/xen/include/xen/gdbstub.h +++ b/xen/include/xen/gdbstub.h @@ -21,6 +21,8 @@ #ifndef __XEN_GDBSTUB_H__ #define __XEN_GDBSTUB_H__ +#ifdef CRASH_DEBUG + /* value <-> char (de)serialzers for arch specific gdb backends */ char hex2char(unsigned long x); int char2hex(unsigned char c); @@ -84,6 +86,14 @@ void gdb_arch_exit(struct cpu_user_regs *regs); #define SIGALRM 14 #define SIGTERM 15 +void initialise_gdb(void); + +#else + +#define initialise_gdb() ((void)0) + +#endif + #endif /* __XEN_GDBSTUB_H__ */ /* From 6d794f8a045d69f2243f4f119e90195f59cf9c53 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 3 Mar 2006 10:55:11 +0100 Subject: [PATCH 05/12] VTPM fixes: - fixes a problem in the vTPM backend where the timer was killed when the timer function was run - removes a variable from being put in the ring by the frontend - reformatting due to indent tool running over some of the files Has been tested with the vtpm-relevant parts of xm-test. Signed-off-by: Stefan Berger --- .../drivers/xen/tpmback/interface.c | 33 +- .../drivers/xen/tpmback/tpmback.c | 550 ++++++++---------- .../drivers/xen/tpmfront/tpmfront.c | 1 - xen/include/public/io/tpmif.h | 2 +- 4 files changed, 259 insertions(+), 327 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c b/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c index 28e8b49c43..93ab2b70a8 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c @@ -19,8 +19,7 @@ int num_frontends = 0; LIST_HEAD(tpmif_list); -tpmif_t * -alloc_tpmif(domid_t domid, long int instance) +static tpmif_t *alloc_tpmif(domid_t domid, long int instance) { struct page *page; tpmif_t *tpmif; @@ -45,16 +44,14 @@ alloc_tpmif(domid_t domid, long int instance) return tpmif; } -void -free_tpmif(tpmif_t * tpmif) +static void free_tpmif(tpmif_t * tpmif) { num_frontends--; list_del(&tpmif->tpmif_list); kmem_cache_free(tpmif_cachep, tpmif); } -tpmif_t * -tpmif_find(domid_t domid, long int instance) +tpmif_t *tpmif_find(domid_t domid, long int instance) { tpmif_t *tpmif; @@ -72,8 +69,7 @@ tpmif_find(domid_t domid, long int instance) return alloc_tpmif(domid, instance); } -static int -map_frontend_page(tpmif_t *tpmif, unsigned long shared_page) +static int map_frontend_page(tpmif_t *tpmif, unsigned long shared_page) { int ret; struct gnttab_map_grant_ref op = { @@ -99,8 +95,7 @@ map_frontend_page(tpmif_t *tpmif, unsigned long shared_page) return 0; } -static void -unmap_frontend_page(tpmif_t *tpmif) +static void unmap_frontend_page(tpmif_t *tpmif) { struct gnttab_unmap_grant_ref op; int ret; @@ -115,14 +110,14 @@ unmap_frontend_page(tpmif_t *tpmif) BUG_ON(ret); } -int -tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn) +int tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn) { int err; evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain, .u.bind_interdomain.remote_dom = tpmif->domid, - .u.bind_interdomain.remote_port = evtchn }; + .u.bind_interdomain.remote_port = evtchn, + }; if (tpmif->irq) { return 0; @@ -156,8 +151,7 @@ tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn) return 0; } -static void -__tpmif_disconnect_complete(void *arg) +static void __tpmif_disconnect_complete(void *arg) { tpmif_t *tpmif = (tpmif_t *) arg; @@ -172,22 +166,19 @@ __tpmif_disconnect_complete(void *arg) free_tpmif(tpmif); } -void -tpmif_disconnect_complete(tpmif_t * tpmif) +void tpmif_disconnect_complete(tpmif_t * tpmif) { INIT_WORK(&tpmif->work, __tpmif_disconnect_complete, (void *)tpmif); schedule_work(&tpmif->work); } -void __init -tpmif_interface_init(void) +void __init tpmif_interface_init(void) { tpmif_cachep = kmem_cache_create("tpmif_cache", sizeof (tpmif_t), 0, 0, NULL, NULL); } -void __init -tpmif_interface_exit(void) +void __init tpmif_interface_exit(void) { kmem_cache_destroy(tpmif_cachep); } diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c b/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c index d20542f6a2..1fda74eb43 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c @@ -22,17 +22,23 @@ #include #include - /* local data structures */ struct data_exchange { struct list_head pending_pak; struct list_head current_pak; unsigned int copied_so_far; u8 has_opener; - rwlock_t pak_lock; // protects all of the previous fields + rwlock_t pak_lock; // protects all of the previous fields wait_queue_head_t wait_queue; }; +struct vtpm_resp_hdr { + uint32_t instance_no; + uint16_t tag_no; + uint32_t len_no; + uint32_t ordinal_no; +} __attribute__ ((packed)); + struct packet { struct list_head next; unsigned int data_len; @@ -50,36 +56,43 @@ enum { PACKET_FLAG_CHECK_RESPONSESTATUS = 2, }; +/* local variables */ 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); + const char *data, size_t size, int userbuffer); static void processing_timeout(unsigned long ptr); -static int packet_read_shmem(struct packet *pak, - tpmif_t *tpmif, - u32 offset, - char *buffer, - int isuserbuffer, - u32 left); - +static int packet_read_shmem(struct packet *pak, + tpmif_t * tpmif, + u32 offset, + char *buffer, int isuserbuffer, u32 left); +static int vtpm_queue_packet(struct packet *pak); #define MIN(x,y) (x) < (y) ? (x) : (y) - /*************************************************************** - Buffer copying + Buffer copying fo user and kernel space buffes. ***************************************************************/ -static inline int -copy_from_buffer(void *to, - const void *from, - unsigned long size, - int userbuffer) +static inline int copy_from_buffer(void *to, + const void *from, unsigned long size, + int isuserbuffer) { - if (userbuffer) { - if (copy_from_user(to, from, size)) + if (isuserbuffer) { + if (copy_from_user(to, (void __user *)from, size)) + return -EFAULT; + } else { + memcpy(to, from, size); + } + return 0; +} + +static inline int copy_to_buffer(void *to, + const void *from, unsigned long size, + int isuserbuffer) +{ + if (isuserbuffer) { + if (copy_to_user((void __user *)to, from, size)) return -EFAULT; } else { memcpy(to, from, size); @@ -91,17 +104,19 @@ copy_from_buffer(void *to, Packet-related functions ***************************************************************/ -static struct packet * -packet_find_instance(struct list_head *head, u32 tpm_instance) +static struct packet *packet_find_instance(struct list_head *head, + u32 tpm_instance) { struct packet *pak; struct list_head *p; + /* * traverse the list of packets and return the first * one with the given instance number */ list_for_each(p, head) { pak = list_entry(p, struct packet, next); + if (pak->tpm_instance == tpm_instance) { return pak; } @@ -109,17 +124,18 @@ packet_find_instance(struct list_head *head, u32 tpm_instance) return NULL; } -static struct packet * -packet_find_packet(struct list_head *head, void *packet) +static struct packet *packet_find_packet(struct list_head *head, void *packet) { struct packet *pak; struct list_head *p; + /* * traverse the list of packets and return the first * one with the given instance number */ list_for_each(p, head) { pak = list_entry(p, struct packet, next); + if (pak == packet) { return pak; } @@ -127,22 +143,20 @@ packet_find_packet(struct list_head *head, void *packet) return NULL; } -static struct packet * -packet_alloc(tpmif_t *tpmif, u32 size, u8 req_tag, u8 flags) +static struct packet *packet_alloc(tpmif_t * tpmif, + u32 size, u8 req_tag, u8 flags) { struct packet *pak = NULL; - pak = kmalloc(sizeof(struct packet), - GFP_KERNEL); + pak = kzalloc(sizeof (struct packet), GFP_KERNEL); if (NULL != pak) { - memset(pak, 0x0, sizeof(*pak)); if (tpmif) { pak->tpmif = tpmif; pak->tpm_instance = tpmif->tpm_instance; } - pak->data_len = size; - pak->req_tag = req_tag; + pak->data_len = size; + pak->req_tag = req_tag; pak->last_read = 0; - pak->flags = flags; + pak->flags = flags; /* * cannot do tpmif_get(tpmif); bad things happen @@ -155,16 +169,16 @@ packet_alloc(tpmif_t *tpmif, u32 size, u8 req_tag, u8 flags) return pak; } -static void inline -packet_reset(struct packet *pak) +static void inline packet_reset(struct packet *pak) { pak->last_read = 0; } -static void inline -packet_free(struct packet *pak) +static void packet_free(struct packet *pak) { - del_singleshot_timer_sync(&pak->processing_timer); + if (timer_pending(&pak->processing_timer)) { + BUG(); + } kfree(pak->data_buffer); /* * cannot do tpmif_put(pak->tpmif); bad things happen @@ -173,13 +187,13 @@ packet_free(struct packet *pak) kfree(pak); } -static int -packet_set(struct packet *pak, - const unsigned char *buffer, u32 size) +static int packet_set(struct packet *pak, + const unsigned char *buffer, u32 size) { int rc = 0; unsigned char *buf = kmalloc(size, GFP_KERNEL); - if (NULL != buf) { + + if (buf) { pak->data_buffer = buf; memcpy(buf, buffer, size); pak->data_len = size; @@ -189,27 +203,21 @@ packet_set(struct packet *pak, return rc; } - /* * Write data to the shared memory and send it to the FE. */ -static int -packet_write(struct packet *pak, - const char *data, size_t size, - int userbuffer) +static int packet_write(struct packet *pak, + const char *data, size_t size, int isuserbuffer) { int rc = 0; - DPRINTK("Supposed to send %d bytes to front-end!\n", - size); - - if (0 != (pak->flags & PACKET_FLAG_CHECK_RESPONSESTATUS)) { + if ((pak->flags & PACKET_FLAG_CHECK_RESPONSESTATUS)) { #ifdef CONFIG_XEN_TPMDEV_CLOSE_IF_VTPM_FAILS u32 res; + if (copy_from_buffer(&res, - &data[2+4], - sizeof(res), - userbuffer)) { + &data[2 + 4], sizeof (res), + isuserbuffer)) { return -EFAULT; } @@ -230,17 +238,14 @@ packet_write(struct packet *pak, /* Don't send a respone to this packet. Just acknowledge it. */ rc = size; } else { - rc = _packet_write(pak, data, size, userbuffer); + rc = _packet_write(pak, data, size, isuserbuffer); } return rc; } - -static int -_packet_write(struct packet *pak, - const char *data, size_t size, - int userbuffer) +int _packet_write(struct packet *pak, + const char *data, size_t size, int isuserbuffer) { /* * Write into the shared memory pages directly @@ -254,7 +259,7 @@ _packet_write(struct packet *pak, if (tpmif == NULL) { return -EFAULT; - } + } if (tpmif->status == DISCONNECTED) { return size; @@ -273,16 +278,13 @@ _packet_write(struct packet *pak, 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; + 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))) { + if (unlikely(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, + &map_op, 1))) { BUG(); } @@ -292,28 +294,27 @@ _packet_write(struct packet *pak, DPRINTK(" Grant table operation failure !\n"); return 0; } - set_phys_to_machine(__pa(MMAP_VADDR(tpmif,i)) >> PAGE_SHIFT, - FOREIGN_FRAME(map_op.dev_bus_addr >> PAGE_SHIFT)); + set_phys_to_machine(__pa(MMAP_VADDR(tpmif, i)) >> PAGE_SHIFT, + FOREIGN_FRAME(map_op. + dev_bus_addr >> PAGE_SHIFT)); tocopy = MIN(size - offset, PAGE_SIZE); - if (copy_from_buffer((void *)(MMAP_VADDR(tpmif,i)| - (tx->addr & ~PAGE_MASK)), - &data[offset], - tocopy, - userbuffer)) { + if (copy_from_buffer((void *)(MMAP_VADDR(tpmif, i) | + (tx->addr & ~PAGE_MASK)), + &data[offset], tocopy, isuserbuffer)) { tpmif_put(tpmif); return -EFAULT; } tx->size = tocopy; - unmap_op.host_addr = MMAP_VADDR(tpmif, i); - unmap_op.handle = handle; + unmap_op.host_addr = MMAP_VADDR(tpmif, i); + unmap_op.handle = handle; unmap_op.dev_bus_addr = 0; - if(unlikely(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, - &unmap_op, - 1))) { + if (unlikely + (HYPERVISOR_grant_table_op + (GNTTABOP_unmap_grant_ref, &unmap_op, 1))) { BUG(); } @@ -322,8 +323,7 @@ _packet_write(struct packet *pak, } rc = offset; - DPRINTK("Notifying frontend via irq %d\n", - tpmif->irq); + DPRINTK("Notifying frontend via irq %d\n", tpmif->irq); notify_remote_via_irq(tpmif->irq); return rc; @@ -334,26 +334,19 @@ _packet_write(struct packet *pak, * provided buffer. Advance the read_last indicator which tells * how many bytes have already been read. */ -static int -packet_read(struct packet *pak, size_t numbytes, - char *buffer, size_t buffersize, - int userbuffer) +static int packet_read(struct packet *pak, size_t numbytes, + char *buffer, size_t buffersize, int isuserbuffer) { tpmif_t *tpmif = pak->tpmif; + /* - * I am supposed to read 'numbytes' of data from the - * buffer. - * The first 4 bytes that are read are the instance number in - * network byte order, after that comes the data from the - * shared memory buffer. + * Read 'numbytes' of data from the buffer. The first 4 + * bytes are the instance number in network byte order, + * after that come the data from the shared memory buffer. */ u32 to_copy; u32 offset = 0; u32 room_left = buffersize; - /* - * Ensure that we see the request when we copy it. - */ - mb(); if (pak->last_read < 4) { /* @@ -361,18 +354,13 @@ packet_read(struct packet *pak, size_t numbytes, */ u32 instance_no = htonl(pak->tpm_instance); u32 last_read = pak->last_read; + to_copy = MIN(4 - last_read, numbytes); - if (userbuffer) { - if (copy_to_user(&buffer[0], - &(((u8 *)&instance_no)[last_read]), - to_copy)) { - return -EFAULT; - } - } else { - memcpy(&buffer[0], - &(((u8 *)&instance_no)[last_read]), - to_copy); + if (copy_to_buffer(&buffer[0], + &(((u8 *) & instance_no)[last_read]), + to_copy, isuserbuffer)) { + return -EFAULT; } pak->last_read += to_copy; @@ -388,39 +376,30 @@ packet_read(struct packet *pak, size_t numbytes, if (pak->data_buffer) { u32 to_copy = MIN(pak->data_len - offset, room_left); u32 last_read = pak->last_read - 4; - if (userbuffer) { - if (copy_to_user(&buffer[offset], - &pak->data_buffer[last_read], - to_copy)) { - return -EFAULT; - } - } else { - memcpy(&buffer[offset], - &pak->data_buffer[last_read], - to_copy); + + if (copy_to_buffer(&buffer[offset], + &pak->data_buffer[last_read], + to_copy, isuserbuffer)) { + return -EFAULT; } pak->last_read += to_copy; offset += to_copy; } else { offset = packet_read_shmem(pak, - tpmif, - offset, - buffer, - userbuffer, - room_left); + tpmif, + offset, + buffer, + isuserbuffer, room_left); } } return offset; } - -static int -packet_read_shmem(struct packet *pak, - tpmif_t *tpmif, - u32 offset, - char *buffer, - int isuserbuffer, - u32 room_left) { +static int packet_read_shmem(struct packet *pak, + tpmif_t * tpmif, + u32 offset, char *buffer, int isuserbuffer, + u32 room_left) +{ u32 last_read = pak->last_read - 4; u32 i = (last_read / PAGE_SIZE); u32 pg_offset = last_read & (PAGE_SIZE - 1); @@ -428,6 +407,7 @@ packet_read_shmem(struct packet *pak, grant_handle_t handle; tpmif_tx_request_t *tx; + tx = &tpmif->tx->ring[0].req; /* * Start copying data at the page with index 'index' @@ -443,13 +423,12 @@ packet_read_shmem(struct packet *pak, 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; + 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))) { + if (unlikely(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, + &map_op, 1))) { BUG(); } @@ -462,41 +441,33 @@ packet_read_shmem(struct packet *pak, if (to_copy > tx->size) { /* - * This is the case when the user wants to read more - * than what we have. So we just give him what we - * have. + * User requests more than what's available */ to_copy = MIN(tx->size, to_copy); } DPRINTK("Copying from mapped memory at %08lx\n", - (unsigned long)(MMAP_VADDR(tpmif,i) | - (tx->addr & ~PAGE_MASK))); + (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); + src = (void *)(MMAP_VADDR(tpmif, i) | + ((tx->addr & ~PAGE_MASK) + pg_offset)); + if (copy_to_buffer(&buffer[offset], + src, to_copy, isuserbuffer)) { + return -EFAULT; } - DPRINTK("Data from TPM-FE of domain %d are %d %d %d %d\n", - tpmif->domid, buffer[offset], buffer[offset+1],buffer[offset+2],buffer[offset+3]); + 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.host_addr = MMAP_VADDR(tpmif, i); + unmap_op.handle = handle; unmap_op.dev_bus_addr = 0; - if(unlikely(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, - &unmap_op, - 1))) { + if (unlikely + (HYPERVISOR_grant_table_op + (GNTTABOP_unmap_grant_ref, &unmap_op, 1))) { BUG(); } @@ -507,7 +478,7 @@ packet_read_shmem(struct packet *pak, to_copy = MIN(PAGE_SIZE, room_left); i++; - } /* while (to_copy > 0) */ + } /* while (to_copy > 0) */ /* * Adjust the last_read pointer */ @@ -515,13 +486,11 @@ packet_read_shmem(struct packet *pak, return offset; } - /* ============================================================ * The file layer for reading data from this device * ============================================================ */ -static int -vtpm_op_open(struct inode *inode, struct file *f) +static int vtpm_op_open(struct inode *inode, struct file *f) { int rc = 0; unsigned long flags; @@ -536,9 +505,8 @@ vtpm_op_open(struct inode *inode, struct file *f) return rc; } -static ssize_t -vtpm_op_read(struct file *file, - char __user * data, size_t size, loff_t * offset) +static ssize_t vtpm_op_read(struct file *file, + char __user * data, size_t size, loff_t * offset) { int ret_size = -ENODATA; struct packet *pak = NULL; @@ -549,7 +517,7 @@ vtpm_op_read(struct file *file, if (list_empty(&dataex.pending_pak)) { write_unlock_irqrestore(&dataex.pak_lock, flags); wait_event_interruptible(dataex.wait_queue, - !list_empty(&dataex.pending_pak)); + !list_empty(&dataex.pending_pak)); write_lock_irqsave(&dataex.pak_lock, flags); } @@ -561,7 +529,7 @@ vtpm_op_read(struct file *file, DPRINTK("size given by app: %d, available: %d\n", size, left); - ret_size = MIN(size,left); + ret_size = MIN(size, left); ret_size = packet_read(pak, ret_size, data, size, 1); if (ret_size < 0) { @@ -574,7 +542,8 @@ vtpm_op_read(struct file *file, DPRINTK("All data from this packet given to app.\n"); /* All data given to app */ - del_singleshot_timer_sync(&pak->processing_timer); + del_singleshot_timer_sync(&pak-> + processing_timer); list_del(&pak->next); list_add_tail(&pak->next, &dataex.current_pak); /* @@ -582,7 +551,7 @@ vtpm_op_read(struct file *file, * the more time we give the TPM to process the request. */ mod_timer(&pak->processing_timer, - jiffies + (num_frontends * 60 * HZ)); + jiffies + (num_frontends * 60 * HZ)); dataex.copied_so_far = 0; } } @@ -597,16 +566,15 @@ vtpm_op_read(struct file *file, /* * Write operation - only works after a previous read operation! */ -static ssize_t -vtpm_op_write(struct file *file, const char __user * data, size_t size, - loff_t * offset) +static ssize_t vtpm_op_write(struct file *file, + const char __user * data, size_t size, + loff_t * offset) { struct packet *pak; int rc = 0; unsigned int off = 4; unsigned long flags; - u32 instance_no = 0; - u32 len_no = 0; + struct vtpm_resp_hdr vrh; /* * Minimum required packet size is: @@ -616,45 +584,38 @@ vtpm_op_write(struct file *file, const char __user * data, size_t size, * 4 bytes for the ordinal * sum: 14 bytes */ - if ( size < off + 10 ) { + if (size < sizeof (vrh)) return -EFAULT; - } - if (copy_from_user(&instance_no, - (void __user *)&data[0], - 4)) { + if (copy_from_user(&vrh, data, sizeof (vrh))) return -EFAULT; - } - if (copy_from_user(&len_no, - (void __user *)&data[off+2], - 4) || - (off + ntohl(len_no) != size)) { + /* malformed packet? */ + if ((off + ntohl(vrh.len_no)) != size) return -EFAULT; - } write_lock_irqsave(&dataex.pak_lock, flags); - pak = packet_find_instance(&dataex.current_pak, ntohl(instance_no)); + pak = packet_find_instance(&dataex.current_pak, + ntohl(vrh.instance_no)); if (pak == NULL) { write_unlock_irqrestore(&dataex.pak_lock, flags); - printk(KERN_ALERT "No associated packet!\n"); + printk(KERN_ALERT "No associated packet! (inst=%d)\n", + ntohl(vrh.instance_no)); return -EFAULT; - } else { - del_singleshot_timer_sync(&pak->processing_timer); - list_del(&pak->next); } + del_singleshot_timer_sync(&pak->processing_timer); + list_del(&pak->next); + write_unlock_irqrestore(&dataex.pak_lock, flags); /* - * The first 'offset' bytes must be the instance number. - * I will just pull that from the packet. + * The first 'offset' bytes must be the instance number - skip them. */ size -= off; - data = &data[off]; - rc = packet_write(pak, data, size, 1); + rc = packet_write(pak, &data[off], size, 1); if (rc > 0) { /* I neglected the first 4 bytes */ @@ -664,10 +625,10 @@ vtpm_op_write(struct file *file, const char __user * data, size_t size, return rc; } -static int -vtpm_op_release(struct inode *inode, struct file *file) +static int vtpm_op_release(struct inode *inode, struct file *file) { unsigned long flags; + vtpm_release_packets(NULL, 1); write_lock_irqsave(&dataex.pak_lock, flags); dataex.has_opener = 0; @@ -675,10 +636,11 @@ vtpm_op_release(struct inode *inode, struct file *file) return 0; } -static unsigned int -vtpm_op_poll(struct file *file, struct poll_table_struct *pts) +static unsigned int vtpm_op_poll(struct file *file, + struct poll_table_struct *pts) { unsigned int flags = POLLOUT | POLLWRNORM; + poll_wait(file, &dataex.wait_queue, pts); if (!list_empty(&dataex.pending_pak)) { flags |= POLLIN | POLLRDNORM; @@ -696,54 +658,47 @@ static struct file_operations vtpm_ops = { .poll = vtpm_op_poll, }; -static struct miscdevice ibmvtpms_miscdevice = { +static struct miscdevice vtpms_miscdevice = { .minor = 225, .name = "vtpm", .fops = &vtpm_ops, }; - /*************************************************************** Virtual TPM functions and data stuctures ***************************************************************/ static u8 create_cmd[] = { - 1,193, /* 0: TPM_TAG_RQU_COMMAMD */ - 0,0,0,19, /* 2: length */ - 0,0,0,0x1, /* 6: VTPM_ORD_OPEN */ - 0, /* 10: VTPM type */ - 0,0,0,0, /* 11: domain id */ - 0,0,0,0 /* 15: instance id */ + 1, 193, /* 0: TPM_TAG_RQU_COMMAMD */ + 0, 0, 0, 19, /* 2: length */ + 0, 0, 0, 0x1, /* 6: VTPM_ORD_OPEN */ + 0, /* 10: VTPM type */ + 0, 0, 0, 0, /* 11: domain id */ + 0, 0, 0, 0 /* 15: instance id */ }; -static u8 destroy_cmd[] = { - 1,193, /* 0: TPM_TAG_RQU_COMMAMD */ - 0,0,0,14, /* 2: length */ - 0,0,0,0x2, /* 6: VTPM_ORD_CLOSE */ - 0,0,0,0 /* 10: instance id */ -}; - -int tpmif_vtpm_open(tpmif_t *tpmif, domid_t domid, u32 instance) +int tpmif_vtpm_open(tpmif_t * tpmif, domid_t domid, u32 instance) { int rc = 0; struct packet *pak; pak = packet_alloc(tpmif, - sizeof(create_cmd), - create_cmd[0], - PACKET_FLAG_DISCARD_RESPONSE| - PACKET_FLAG_CHECK_RESPONSESTATUS); + sizeof (create_cmd), + create_cmd[1], + PACKET_FLAG_DISCARD_RESPONSE | + PACKET_FLAG_CHECK_RESPONSESTATUS); if (pak) { - u8 buf[sizeof(create_cmd)]; - u32 domid_no = htonl((u32)domid); + u8 buf[sizeof (create_cmd)]; + u32 domid_no = htonl((u32) domid); u32 instance_no = htonl(instance); - memcpy(buf, create_cmd, sizeof(create_cmd)); - memcpy(&buf[11], &domid_no, sizeof(u32)); - memcpy(&buf[15], &instance_no, sizeof(u32)); + memcpy(buf, create_cmd, sizeof (create_cmd)); + + memcpy(&buf[11], &domid_no, sizeof (u32)); + memcpy(&buf[15], &instance_no, sizeof (u32)); /* copy the buffer into the packet */ - rc = packet_set(pak, buf, sizeof(buf)); + rc = packet_set(pak, buf, sizeof (buf)); if (rc == 0) { pak->tpm_instance = 0; @@ -759,23 +714,30 @@ int tpmif_vtpm_open(tpmif_t *tpmif, domid_t domid, u32 instance) return rc; } +static u8 destroy_cmd[] = { + 1, 193, /* 0: TPM_TAG_RQU_COMMAMD */ + 0, 0, 0, 14, /* 2: length */ + 0, 0, 0, 0x2, /* 6: VTPM_ORD_CLOSE */ + 0, 0, 0, 0 /* 10: instance id */ +}; + int tpmif_vtpm_close(u32 instid) { int rc = 0; struct packet *pak; pak = packet_alloc(NULL, - sizeof(create_cmd), - create_cmd[0], - PACKET_FLAG_DISCARD_RESPONSE); + sizeof (destroy_cmd), + destroy_cmd[1], PACKET_FLAG_DISCARD_RESPONSE); if (pak) { - u8 buf[sizeof(destroy_cmd)]; + u8 buf[sizeof (destroy_cmd)]; u32 instid_no = htonl(instid); - memcpy(buf, destroy_cmd, sizeof(destroy_cmd)); - memcpy(&buf[10], &instid_no, sizeof(u32)); + + memcpy(buf, destroy_cmd, sizeof (destroy_cmd)); + memcpy(&buf[10], &instid_no, sizeof (u32)); /* copy the buffer into the packet */ - rc = packet_set(pak, buf, sizeof(buf)); + rc = packet_set(pak, buf, sizeof (buf)); if (rc == 0) { pak->tpm_instance = 0; @@ -791,23 +753,22 @@ int tpmif_vtpm_close(u32 instid) return rc; } - /*************************************************************** Utility functions ***************************************************************/ -static int -tpm_send_fail_message(struct packet *pak, u8 req_tag) +static int tpm_send_fail_message(struct packet *pak, u8 req_tag) { int rc; static const unsigned char tpm_error_message_fail[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, - 0x00, 0x00, 0x00, 0x09 /* TPM_FAIL */ + 0x00, 0x00, 0x00, 0x09 /* TPM_FAIL */ }; - unsigned char buffer[sizeof(tpm_error_message_fail)]; + unsigned char buffer[sizeof (tpm_error_message_fail)]; - memcpy(buffer, tpm_error_message_fail, sizeof(tpm_error_message_fail)); + memcpy(buffer, tpm_error_message_fail, + sizeof (tpm_error_message_fail)); /* * Insert the right response tag depending on the given tag * All response tags are '+3' to the request tag. @@ -817,23 +778,24 @@ tpm_send_fail_message(struct packet *pak, u8 req_tag) /* * Write the data to shared memory and notify the front-end */ - rc = packet_write(pak, buffer, sizeof(buffer), 0); + rc = packet_write(pak, buffer, sizeof (buffer), 0); return rc; } - -static void -_vtpm_release_packets(struct list_head *head, tpmif_t *tpmif, - int send_msgs) +static void _vtpm_release_packets(struct list_head *head, + tpmif_t * tpmif, int send_msgs) { struct packet *pak; - struct list_head *pos, *tmp; + struct list_head *pos, + *tmp; list_for_each_safe(pos, tmp, head) { pak = list_entry(pos, struct packet, next); + if (tpmif == NULL || pak->tpmif == tpmif) { int can_send = 0; + del_singleshot_timer_sync(&pak->processing_timer); list_del(&pak->next); @@ -849,9 +811,7 @@ _vtpm_release_packets(struct list_head *head, tpmif_t *tpmif, } } - -int -vtpm_release_packets(tpmif_t *tpmif, int send_msgs) +int vtpm_release_packets(tpmif_t * tpmif, int send_msgs) { unsigned long flags; @@ -860,23 +820,22 @@ vtpm_release_packets(tpmif_t *tpmif, int send_msgs) _vtpm_release_packets(&dataex.pending_pak, tpmif, send_msgs); _vtpm_release_packets(&dataex.current_pak, tpmif, send_msgs); - write_unlock_irqrestore(&dataex.pak_lock, - flags); + write_unlock_irqrestore(&dataex.pak_lock, flags); return 0; } - static int vtpm_queue_packet(struct packet *pak) { int rc = 0; + if (dataex.has_opener) { unsigned long flags; + write_lock_irqsave(&dataex.pak_lock, flags); list_add_tail(&pak->next, &dataex.pending_pak); /* give the TPM some time to pick up the request */ mod_timer(&pak->processing_timer, jiffies + (30 * HZ)); - write_unlock_irqrestore(&dataex.pak_lock, - flags); + write_unlock_irqrestore(&dataex.pak_lock, flags); wake_up_interruptible(&dataex.wait_queue); } else { @@ -885,24 +844,22 @@ static int vtpm_queue_packet(struct packet *pak) return rc; } - -static int vtpm_receive(tpmif_t *tpmif, u32 size) +static int vtpm_receive(tpmif_t * tpmif, u32 size) { int rc = 0; unsigned char buffer[10]; __be32 *native_size; + struct packet *pak = packet_alloc(tpmif, size, 0, 0); - struct packet *pak = packet_alloc(tpmif, size, buffer[4], 0); - if (NULL == pak) { + if (!pak) return -ENOMEM; - } /* * Read 10 bytes from the received buffer to test its * content for validity. */ - if (sizeof(buffer) != packet_read(pak, - sizeof(buffer), buffer, - sizeof(buffer), 0)) { + if (sizeof (buffer) != packet_read(pak, + sizeof (buffer), buffer, + sizeof (buffer), 0)) { goto failexit; } /* @@ -911,7 +868,7 @@ static int vtpm_receive(tpmif_t *tpmif, u32 size) */ packet_reset(pak); - native_size = (__force __be32 *)(&buffer[4+2]); + native_size = (__force __be32 *) (&buffer[4 + 2]); /* * Verify that the size of the packet is correct * as indicated and that there's actually someone reading packets. @@ -920,26 +877,24 @@ static int vtpm_receive(tpmif_t *tpmif, u32 size) */ if (size < 10 || be32_to_cpu(*native_size) != size || - 0 == dataex.has_opener || - tpmif->status != CONNECTED) { - rc = -EINVAL; - goto failexit; + 0 == dataex.has_opener || tpmif->status != CONNECTED) { + rc = -EINVAL; + goto failexit; } else { - if ((rc = vtpm_queue_packet(pak)) < 0) { + rc = vtpm_queue_packet(pak); + if (rc < 0) goto failexit; - } } return 0; -failexit: + failexit: if (pak) { - tpm_send_fail_message(pak, buffer[4+1]); + tpm_send_fail_message(pak, buffer[4 + 1]); packet_free(pak); } return rc; } - /* * Timeout function that gets invoked when a packet has not been processed * during the timeout period. @@ -951,44 +906,42 @@ 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) ) { + pak == packet_find_packet(&dataex.current_pak, pak)) { list_del(&pak->next); - tpm_send_fail_message(pak, pak->req_tag); + if ((pak->flags & PACKET_FLAG_DISCARD_RESPONSE) == 0) { + tpm_send_fail_message(pak, pak->req_tag); + } packet_free(pak); } write_unlock_irqrestore(&dataex.pak_lock, flags); } - - static void tpm_tx_action(unsigned long unused); static DECLARE_TASKLET(tpm_tx_tasklet, tpm_tx_action, 0); static struct list_head tpm_schedule_list; static spinlock_t tpm_schedule_list_lock; -static inline void -maybe_schedule_tx_action(void) +static inline void maybe_schedule_tx_action(void) { smp_mb(); tasklet_schedule(&tpm_tx_tasklet); } -static inline int -__on_tpm_schedule_list(tpmif_t * tpmif) +static inline int __on_tpm_schedule_list(tpmif_t * tpmif) { return tpmif->list.next != NULL; } -static void -remove_from_tpm_schedule_list(tpmif_t * tpmif) +static void remove_from_tpm_schedule_list(tpmif_t * tpmif) { spin_lock_irq(&tpm_schedule_list_lock); if (likely(__on_tpm_schedule_list(tpmif))) { @@ -999,8 +952,7 @@ remove_from_tpm_schedule_list(tpmif_t * tpmif) spin_unlock_irq(&tpm_schedule_list_lock); } -static void -add_to_tpm_schedule_list_tail(tpmif_t * tpmif) +static void add_to_tpm_schedule_list_tail(tpmif_t * tpmif) { if (__on_tpm_schedule_list(tpmif)) return; @@ -1013,22 +965,18 @@ add_to_tpm_schedule_list_tail(tpmif_t * tpmif) spin_unlock_irq(&tpm_schedule_list_lock); } -void -tpmif_schedule_work(tpmif_t * tpmif) +void tpmif_schedule_work(tpmif_t * tpmif) { add_to_tpm_schedule_list_tail(tpmif); maybe_schedule_tx_action(); } -void -tpmif_deschedule_work(tpmif_t * tpmif) +void tpmif_deschedule_work(tpmif_t * tpmif) { remove_from_tpm_schedule_list(tpmif); } - -static void -tpm_tx_action(unsigned long unused) +static void tpm_tx_action(unsigned long unused) { struct list_head *ent; tpmif_t *tpmif; @@ -1042,10 +990,6 @@ tpm_tx_action(unsigned long unused) tpmif = list_entry(ent, tpmif_t, list); tpmif_get(tpmif); remove_from_tpm_schedule_list(tpmif); - /* - * Ensure that we see the request when we read from it. - */ - mb(); tx = &tpmif->tx->ring[0].req; @@ -1056,22 +1000,22 @@ tpm_tx_action(unsigned long unused) } } -irqreturn_t -tpmif_be_int(int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t tpmif_be_int(int irq, void *dev_id, struct pt_regs *regs) { - tpmif_t *tpmif = dev_id; + tpmif_t *tpmif = (tpmif_t *) dev_id; + add_to_tpm_schedule_list_tail(tpmif); maybe_schedule_tx_action(); return IRQ_HANDLED; } -static int __init -tpmback_init(void) +static int __init tpmback_init(void) { int rc; - if ((rc = misc_register(&ibmvtpms_miscdevice)) != 0) { - printk(KERN_ALERT "Could not register misc device for TPM BE.\n"); + if ((rc = misc_register(&vtpms_miscdevice)) != 0) { + printk(KERN_ALERT + "Could not register misc device for TPM BE.\n"); return rc; } @@ -1094,13 +1038,11 @@ tpmback_init(void) module_init(tpmback_init); -static void __exit -tpmback_exit(void) +static void __exit tpmback_exit(void) { - tpmif_xenbus_exit(); tpmif_interface_exit(); - misc_deregister(&ibmvtpms_miscdevice); + misc_deregister(&vtpms_miscdevice); } module_exit(tpmback_exit); diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c index 6f53299f42..62e3d568a1 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c @@ -602,7 +602,6 @@ tpm_xmit(struct tpm_private *tp, tx = &tp->tx->ring[i].req; - tx->id = i; tx->addr = virt_to_machine(txb->data); tx->size = txb->len; diff --git a/xen/include/public/io/tpmif.h b/xen/include/public/io/tpmif.h index 7b4a863ea9..6d02f33b4c 100644 --- a/xen/include/public/io/tpmif.h +++ b/xen/include/public/io/tpmif.h @@ -21,7 +21,7 @@ typedef struct { unsigned long addr; /* Machine address of packet. */ grant_ref_t ref; /* grant table access reference */ - uint16_t id; /* Echoed in response message. */ + uint16_t unused; uint16_t size; /* Packet size in bytes. */ } tpmif_tx_request_t; From da538487143fc14cfabf08c5b464ccc6ab8816c8 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 3 Mar 2006 10:56:13 +0100 Subject: [PATCH 06/12] Raises an explicit error message when the domain config file specifies an incorrect path to a file-backed VBD (disk image) or the file-backed VBD does not exist. Without this patch, if someone mis-types the path to the disk image, he/she would have no indication as to what's wrong when the domain fails to get created. Signed-off-by: Khoa Huynh --- tools/python/xen/xend/image.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py index 4d58c25d9a..f9b061a4ec 100644 --- a/tools/python/xen/xend/image.py +++ b/tools/python/xen/xend/image.py @@ -274,6 +274,10 @@ class HVMImageHandler(ImageHandler): uname = sxp.child_value(info, 'uname') typedev = sxp.child_value(info, 'dev') (_, vbdparam) = string.split(uname, ':', 1) + + if 'file:' in uname and not os.path.isfile(vbdparam): + raise VmError('Disk image does not exist: %s' % vbdparam) + if 'ioemu:' in typedev: (emtype, vbddev) = string.split(typedev, ':', 1) else: From 59d0a0335d7c199d5b680b63521c0ebaadb4c850 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 3 Mar 2006 10:56:54 +0100 Subject: [PATCH 07/12] This patch undoes 8697 and makes xm reboot/shutdown work again. This code does expose a bug in xenstored when it is killed & restarted, but that is not caused by this code. My sincere appology to Ke Yu for the long wait and assuming his code was broken. His code was perfectly fine. Its just that my test scripts did something for a historical reason that I should have removed a long time ago. Signed-Off-By: Leendert van Doorn --- tools/python/xen/xend/server/blkif.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tools/python/xen/xend/server/blkif.py b/tools/python/xen/xend/server/blkif.py index 23135aa08b..02cd4f26f7 100644 --- a/tools/python/xen/xend/server/blkif.py +++ b/tools/python/xen/xend/server/blkif.py @@ -42,10 +42,6 @@ class BlkifController(DevController): """@see DevController.getDeviceDetails""" dev = sxp.child_value(config, 'dev') - if 'ioemu:' in dev: - return (None,{},{}) - - devid = blkif.blkdev_name_to_number(dev) (typ, params) = string.split(sxp.child_value(config, 'uname'), ':', 1) back = { 'dev' : dev, @@ -54,7 +50,13 @@ class BlkifController(DevController): 'mode' : sxp.child_value(config, 'mode', 'r') } - front = { 'virtual-device' : "%i" % devid } + if 'ioemu:' in dev: + (dummy, dev1) = string.split(dev, ':', 1) + devid = blkif.blkdev_name_to_number(dev1) + front = {} + else: + devid = blkif.blkdev_name_to_number(dev) + front = { 'virtual-device' : "%i" % devid } return (devid, back, front) From 596095de11eb7ef510eec066f69e127e077d9ee9 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 3 Mar 2006 10:57:37 +0100 Subject: [PATCH 08/12] Add a description of the virtual TPM interface to the interface document and explain some of the internals of the device driver. Signed-off-by: Stefan Berger --- docs/src/interface.tex | 97 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/docs/src/interface.tex b/docs/src/interface.tex index 5169b3878c..b5b3d76b13 100644 --- a/docs/src/interface.tex +++ b/docs/src/interface.tex @@ -1059,6 +1059,21 @@ This path contains: \item[domain] the name of the frontend \end{description} \end{description} + + \item[vtpm/] a directory containin vtpm backends + \begin{description} + \item[$<$domid$>$/] a directory containing vtpm's for domid + \begin{description} + \item[$<$vtpm number$>$/] a directory for each vtpm + \item[frontend-id] the domain id of the frontend + \item[frontend] the path to the frontend + \item[instance] the instance of the virtual TPM that is used + \item[pref{\textunderscore}instance] the instance number as given in the VM configuration file; + may be different from {\bf instance} + \item[domain] the name of the domain of the frontend + \end{description} + \end{description} + \end{description} \item[device/] a directory containing the frontend devices for the @@ -1094,6 +1109,18 @@ This path contains: \item[event-channel] the event channel used for the two ring queues \end{description} \end{description} + + \item[vtpm/] a directory containing the vtpm frontend device for the + domain + \begin{description} + \item[$<$id$>$] a directory for vtpm id frontend device for the domain + \begin{description} + \item[backend-id] the backend domain id + \item[backend] a path to the backend's store entry + \item[ring-ref] the grant table reference for the tx/rx ring + \item[event-channel] the event channel used for the ring + \end{description} + \end{description} \item[device-misc/] miscellanous information for devices \begin{description} @@ -1450,6 +1477,76 @@ The fields are as follows: value of {\tt first\_sect}. \end{description} +\section{Virtual TPM} + +Virtual TPM (VTPM) support provides TPM functionality to each virtual +machine that requests this functionality in its configuration file. +The interface enables domains to access therr own private TPM like it +was a hardware TPM built into the machine. + +The virtual TPM interface is implemented as a split driver, +similar to the network and block interfaces described above. +The user domain hosting the frontend exports a character device /dev/tpm0 +to user-level applications for communicating with the virtual TPM. +This is the same device interface that is also offered if a hardware TPM +is available in the system. The backend provides a single interface +/dev/vtpm where the virtual TPM is waiting for commands from all domains +that have located their backend in a given domain. + +\subsection{Data Transfer} + +A single shared memory ring is used between the frontend and backend +drivers. TPM requests and responses are sent in pages where a pointer +to those pages and other information is placed into the ring such that +the backend can map the pages into its memory space using the grant +table mechanism. + +The backend driver has been implemented to only accept well-formed +TPM requests. To meet this requirement, the length inidicator in the +TPM request must correctly indicate the length of the request. +Otherwise an error message is automatically sent back by the device driver. + +The virtual TPM implementation listenes for TPM request on /dev/vtpm. Since +it must be able to apply the TPM request packet to the virtual TPM instance +associated with the virtual machine, a 4-byte virtual TPM instance +identifier is prepended to each packet by the backend driver (in network +byte order) for internal routing of the request. + +\subsection{Virtual TPM ring interface} + +The TPM protocol is a strict request/response protocol and therefore +only one ring is used to send requests from the frontend to the backend +and responses on the reverse path. + +The request/response structure is defined as follows: + +\scriptsize +\begin{verbatim} +typedef struct { + unsigned long addr; /* Machine address of packet. */ + grant_ref_t ref; /* grant table access reference. */ + uint16_t unused; /* unused */ + uint16_t size; /* Packet size in bytes. */ +} tpmif_tx_request_t; +\end{verbatim} +\normalsize + +The fields are as follows: + +\begin{description} +\item[addr] The machine address of the page asscoiated with the TPM + request/response; a request/response may span multiple + pages +\item[ref] The grant table reference associated with the address. +\item[size] The size of the remaining packet; up to + PAGE{\textunderscore}SIZE bytes can be found in the + page referenced by 'addr' +\end{description} + +The frontend initially allocates several pages whose addresses +are stored in the ring. Only these pages are used for exchange of +requests and responses. + \chapter{Further Information} From 01d546796c96ef629a81187b36c0edbfa92083cb Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 3 Mar 2006 10:58:42 +0100 Subject: [PATCH 09/12] It's not necessary to define a function for dumping virtual IOAPIC table entry, that makes the code hard to comply with condition compiling of HVM_DBG_LOG. Signed-off-by: Xin Li --- xen/arch/x86/hvm/vioapic.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/xen/arch/x86/hvm/vioapic.c b/xen/arch/x86/hvm/vioapic.c index 33c1ed1fdf..f3bde8d9ba 100644 --- a/xen/arch/x86/hvm/vioapic.c +++ b/xen/arch/x86/hvm/vioapic.c @@ -52,20 +52,6 @@ static void ioapic_enable(hvm_vioapic_t *s, uint8_t enable) s->flags &= ~IOAPIC_ENABLE_FLAG; } -static void ioapic_dump_redir(hvm_vioapic_t *s, uint8_t entry) -{ - RedirStatus redir = s->redirtbl[entry]; - - printk("ioapic_dump_redir entry %x vector %x " - "deliver_mod %x destmode %x delivestatus %x " - "polarity %x remote_irr %x trigmod %x mask %x dest_id %x\n", - entry, redir.RedirForm.vector, redir.RedirForm.deliver_mode, - redir.RedirForm.destmode, redir.RedirForm.delivestatus, - redir.RedirForm.polarity, redir.RedirForm.remoteirr, - redir.RedirForm.trigmod, redir.RedirForm.mask, - redir.RedirForm.dest_id); -} - #ifdef HVM_DOMAIN_SAVE_RESTORE void ioapic_save(QEMUFile* f, void* opaque) { @@ -534,7 +520,19 @@ void hvm_vioapic_set_irq(struct domain *d, int irq, int level) if (!IOAPICEnabled(s) || s->redirtbl[irq].RedirForm.mask) return; - ioapic_dump_redir(s, irq); + HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "hvm_vioapic_set_irq entry %x " + "vector %x deliver_mod %x destmode %x delivestatus %x " + "polarity %x remote_irr %x trigmod %x mask %x dest_id %x\n", + irq, + s->redirtbl[irq].RedirForm.vector, + s->redirtbl[irq].RedirForm.deliver_mode, + s->redirtbl[irq].RedirForm.destmode, + s->redirtbl[irq].RedirForm.delivestatus, + s->redirtbl[irq].RedirForm.polarity, + s->redirtbl[irq].RedirForm.remoteirr, + s->redirtbl[irq].RedirForm.trigmod, + s->redirtbl[irq].RedirForm.mask, + s->redirtbl[irq].RedirForm.dest_id); if (irq >= 0 && irq < IOAPIC_NUM_PINS) { uint32_t bit = 1 << irq; From 0814867e269e797e1c69f3fc7635a6749d3873ba Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 3 Mar 2006 11:17:09 +0100 Subject: [PATCH 10/12] Minor enhancements to gdbbuild, the build script for gdbserver-xen. 1. Use $MAKE if set 2. Make mirror configurable from environment From: Horms Signed-off-by: Keir Fraser --- tools/debugger/gdb/gdbbuild | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/debugger/gdb/gdbbuild b/tools/debugger/gdb/gdbbuild index 9b106971ea..fbd225a0c0 100755 --- a/tools/debugger/gdb/gdbbuild +++ b/tools/debugger/gdb/gdbbuild @@ -1,7 +1,9 @@ #!/bin/sh +[ "$GDB_MIRROR" ] || GDB_MIRROR="ftp://ftp.gnu.org/gnu/gdb/" + rm -rf gdb-6.2.1 gdb-6.2.1-linux-i386-xen -[ -a gdb-6.2.1.tar.bz2 ] || wget -c ftp://ftp.gnu.org/gnu/gdb/gdb-6.2.1.tar.bz2 +[ -a gdb-6.2.1.tar.bz2 ] || wget -c "$GDB_MIRROR/gdb-6.2.1.tar.bz2" tar xjf gdb-6.2.1.tar.bz2 cd gdb-6.2.1-xen-sparse @@ -12,8 +14,10 @@ mkdir gdb-6.2.1-linux-i386-xen cd gdb-6.2.1-linux-i386-xen ../gdb-6.2.1/configure -# some people don't have gmake -if which gmake ; then +# Use $MAKE if set, else use gmake if present, otherwise use make +if [ "$MAKE" ]; then + $MAKE +elif which gmake ; then gmake -j4 else make -j4 From 2f6b43b5622713e0906275bfd067eec1cb98413b Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 3 Mar 2006 14:10:35 +0100 Subject: [PATCH 11/12] Clean up PIT-thru-ioapic setup. We don't need the legacy missed-tick logic and so do not need to keep the PIT enabled thru the 8259 PIC. Todo: arguable we should sync with x86/64 platform files, assuming they do not throw out 'recent legacy' stuff (e.g., 32-bit only platforms like P6). Getting rid of all the 82489DX and 486-era SMP stuff would be great. Signed-off-by: Keir Fraser --- xen/arch/x86/io_apic.c | 7 ++++--- xen/arch/x86/time.c | 11 ----------- xen/include/asm-x86/time.h | 2 -- 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/xen/arch/x86/io_apic.c b/xen/arch/x86/io_apic.c index 46e5c0c9f8..aef5d64b5a 100644 --- a/xen/arch/x86/io_apic.c +++ b/xen/arch/x86/io_apic.c @@ -1548,8 +1548,9 @@ static inline void check_timer(void) */ apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); init_8259A(1); - timer_ack = 1; - enable_8259A_irq(0); + /* XEN: Ripped out the legacy missed-tick logic, so below is not needed. */ + /*timer_ack = 1;*/ + /*enable_8259A_irq(0);*/ pin1 = find_isa_irq_pin(0, mp_INT); apic1 = find_isa_irq_apic(0, mp_INT); @@ -1617,7 +1618,7 @@ static inline void check_timer(void) printk(KERN_INFO "...trying to set up timer as ExtINT IRQ..."); - timer_ack = 0; + /*timer_ack = 0;*/ init_8259A(0); make_8259A_irq(0); apic_write_around(APIC_LVT0, APIC_DM_EXTINT); diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c index 1bd15c6702..59fa0bfe04 100644 --- a/xen/arch/x86/time.c +++ b/xen/arch/x86/time.c @@ -41,7 +41,6 @@ boolean_param("hpet_force", opt_hpet_force); unsigned long cpu_khz; /* CPU clock frequency in kHz. */ unsigned long hpet_address; spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; -int timer_ack = 0; unsigned long volatile jiffies; static u32 wc_sec, wc_nsec; /* UTC time at last 'time update'. */ static spinlock_t wc_lock = SPIN_LOCK_UNLOCKED; @@ -148,16 +147,6 @@ void timer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs) { ASSERT(local_irq_is_enabled()); - if ( timer_ack ) - { - extern spinlock_t i8259A_lock; - spin_lock_irq(&i8259A_lock); - outb(0x0c, 0x20); - /* Ack the IRQ; AEOI will end it automatically. */ - inb(0x20); - spin_unlock_irq(&i8259A_lock); - } - /* Update jiffies counter. */ (*(unsigned long *)&jiffies)++; diff --git a/xen/include/asm-x86/time.h b/xen/include/asm-x86/time.h index b192f55c82..38e4dffcf2 100644 --- a/xen/include/asm-x86/time.h +++ b/xen/include/asm-x86/time.h @@ -4,8 +4,6 @@ #include -extern int timer_ack; - extern void calibrate_tsc_bp(void); extern void calibrate_tsc_ap(void); From 63c30e3123bcc4a1dc52cb5c7dece0efe4faf62a Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 3 Mar 2006 15:05:25 +0100 Subject: [PATCH 12/12] Domain0 identifies IOAPIC by physical base address rather than BIOS-assigned identifier. This seems a more reliable method since it seems that we always trust the base address and we don't need to work around renumbering/rebasing as we do with APICIDs. This is an alternative to the Yonah networking patch from Allen Kay at Intel. Signed-off-by: Keir Fraser --- .../arch/i386/kernel/io_apic-xen.c | 8 +-- .../arch/x86_64/kernel/io_apic-xen.c | 8 +-- xen/arch/x86/io_apic.c | 67 +++++++------------ xen/arch/x86/physdev.c | 16 +++-- xen/include/public/physdev.h | 4 +- 5 files changed, 47 insertions(+), 56 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c index 003300858a..53704a58d7 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c @@ -61,8 +61,8 @@ static inline unsigned int xen_io_apic_read(unsigned int apic, unsigned int reg) int ret; op.cmd = PHYSDEVOP_APIC_READ; - op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid; - op.u.apic_op.offset = reg; + op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr; + op.u.apic_op.reg = reg; ret = HYPERVISOR_physdev_op(&op); if (ret) return ret; @@ -74,8 +74,8 @@ static inline void xen_io_apic_write(unsigned int apic, unsigned int reg, unsign physdev_op_t op; op.cmd = PHYSDEVOP_APIC_WRITE; - op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid; - op.u.apic_op.offset = reg; + op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr; + op.u.apic_op.reg = reg; op.u.apic_op.value = value; HYPERVISOR_physdev_op(&op); } diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/io_apic-xen.c b/linux-2.6-xen-sparse/arch/x86_64/kernel/io_apic-xen.c index 5d51a7f3b7..fd72947df7 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/io_apic-xen.c +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/io_apic-xen.c @@ -108,8 +108,8 @@ static inline unsigned int xen_io_apic_read(unsigned int apic, unsigned int reg) int ret; op.cmd = PHYSDEVOP_APIC_READ; - op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid; - op.u.apic_op.offset = reg; + op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr; + op.u.apic_op.reg = reg; ret = HYPERVISOR_physdev_op(&op); if (ret) return ret; @@ -121,8 +121,8 @@ static inline void xen_io_apic_write(unsigned int apic, unsigned int reg, unsign physdev_op_t op; op.cmd = PHYSDEVOP_APIC_WRITE; - op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid; - op.u.apic_op.offset = reg; + op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr; + op.u.apic_op.reg = reg; op.u.apic_op.value = value; HYPERVISOR_physdev_op(&op); } diff --git a/xen/arch/x86/io_apic.c b/xen/arch/x86/io_apic.c index aef5d64b5a..e71603c125 100644 --- a/xen/arch/x86/io_apic.c +++ b/xen/arch/x86/io_apic.c @@ -1634,16 +1634,6 @@ static inline void check_timer(void) "report. Then try booting with the 'noapic' option"); } -#define NR_IOAPIC_BIOSIDS 256 -static u8 ioapic_biosid_to_apic_enum[NR_IOAPIC_BIOSIDS]; -static void store_ioapic_biosid_mapping(void) -{ - u8 apic; - memset(ioapic_biosid_to_apic_enum, ~0, NR_IOAPIC_BIOSIDS); - for ( apic = 0; apic < nr_ioapics; apic++ ) - ioapic_biosid_to_apic_enum[mp_ioapics[apic].mpc_apicid] = apic; -} - /* * * IRQ's that are handled by the PIC in the MPS IOAPIC case. @@ -1655,8 +1645,6 @@ static void store_ioapic_biosid_mapping(void) void __init setup_IO_APIC(void) { - store_ioapic_biosid_mapping(); - enable_IO_APIC(); if (acpi_ioapic) @@ -1840,50 +1828,45 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a #endif /*CONFIG_ACPI_BOOT*/ - -int ioapic_guest_read(int apicid, int address, u32 *pval) +static int ioapic_physbase_to_id(unsigned long physbase) { - u32 val; - int apicenum; - union IO_APIC_reg_00 reg_00; + int apic; + for ( apic = 0; apic < nr_ioapics; apic++ ) + if ( mp_ioapics[apic].mpc_apicaddr == physbase ) + return apic; + return -EINVAL; +} + +int ioapic_guest_read(unsigned long physbase, unsigned int reg, u32 *pval) +{ + int apic; unsigned long flags; - if ( (apicid >= NR_IOAPIC_BIOSIDS) || - ((apicenum = ioapic_biosid_to_apic_enum[apicid]) >= nr_ioapics) ) - return -EINVAL; + if ( (apic = ioapic_physbase_to_id(physbase)) < 0 ) + return apic; spin_lock_irqsave(&ioapic_lock, flags); - val = io_apic_read(apicenum, address); + *pval = io_apic_read(apic, reg); spin_unlock_irqrestore(&ioapic_lock, flags); - /* Rewrite APIC ID to what the BIOS originally specified. */ - if ( address == 0 ) - { - reg_00.raw = val; - reg_00.bits.ID = apicid; - val = reg_00.raw; - } - - *pval = val; return 0; } -int ioapic_guest_write(int apicid, int address, u32 val) +int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val) { - int apicenum, pin, irq; + int apic, pin, irq; struct IO_APIC_route_entry rte = { 0 }; struct irq_pin_list *entry; unsigned long flags; - if ( (apicid >= NR_IOAPIC_BIOSIDS) || - ((apicenum = ioapic_biosid_to_apic_enum[apicid]) >= nr_ioapics) ) - return -EINVAL; + if ( (apic = ioapic_physbase_to_id(physbase)) < 0 ) + return apic; /* Only write to the first half of a route entry. */ - if ( (address < 0x10) || (address & 1) ) + if ( (reg < 0x10) || (reg & 1) ) return 0; - pin = (address - 0x10) >> 1; + pin = (reg - 0x10) >> 1; *(u32 *)&rte = val; rte.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS); @@ -1899,7 +1882,7 @@ int ioapic_guest_write(int apicid, int address, u32 val) if ( rte.delivery_mode > dest_LowestPrio ) { printk("ERROR: Attempt to write weird IOAPIC destination mode!\n"); - printk(" APIC=%d/%d, lo-reg=%x\n", apicid, pin, val); + printk(" APIC=%d/%d, lo-reg=%x\n", apic, pin, val); return -EINVAL; } @@ -1924,19 +1907,19 @@ int ioapic_guest_write(int apicid, int address, u32 val) /* Record the pin<->irq mapping. */ for ( entry = &irq_2_pin[irq]; ; entry = &irq_2_pin[entry->next] ) { - if ( (entry->apic == apicenum) && (entry->pin == pin) ) + if ( (entry->apic == apic) && (entry->pin == pin) ) break; if ( !entry->next ) { - add_pin_to_irq(irq, apicenum, pin); + add_pin_to_irq(irq, apic, pin); break; } } } spin_lock_irqsave(&ioapic_lock, flags); - io_apic_write(apicenum, 0x10 + 2 * pin, *(((int *)&rte) + 0)); - io_apic_write(apicenum, 0x11 + 2 * pin, *(((int *)&rte) + 1)); + io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&rte) + 0)); + io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&rte) + 1)); spin_unlock_irqrestore(&ioapic_lock, flags); return 0; diff --git a/xen/arch/x86/physdev.c b/xen/arch/x86/physdev.c index 418392da92..c3baee8572 100644 --- a/xen/arch/x86/physdev.c +++ b/xen/arch/x86/physdev.c @@ -11,8 +11,12 @@ #include #include -extern int ioapic_guest_read(int apicid, int address, u32 *pval); -extern int ioapic_guest_write(int apicid, int address, u32 pval); +extern int +ioapic_guest_read( + unsigned long physbase, unsigned int reg, u32 *pval); +extern int +ioapic_guest_write( + unsigned long physbase, unsigned int reg, u32 pval); /* * Demuxing hypercall. @@ -49,7 +53,9 @@ long do_physdev_op(struct physdev_op *uop) if ( !IS_PRIV(current->domain) ) break; ret = ioapic_guest_read( - op.u.apic_op.apic, op.u.apic_op.offset, &op.u.apic_op.value); + op.u.apic_op.apic_physbase, + op.u.apic_op.reg, + &op.u.apic_op.value); break; case PHYSDEVOP_APIC_WRITE: @@ -57,7 +63,9 @@ long do_physdev_op(struct physdev_op *uop) if ( !IS_PRIV(current->domain) ) break; ret = ioapic_guest_write( - op.u.apic_op.apic, op.u.apic_op.offset, op.u.apic_op.value); + op.u.apic_op.apic_physbase, + op.u.apic_op.reg, + op.u.apic_op.value); break; case PHYSDEVOP_ASSIGN_VECTOR: diff --git a/xen/include/public/physdev.h b/xen/include/public/physdev.h index 9124ca5474..b9486d5fa9 100644 --- a/xen/include/public/physdev.h +++ b/xen/include/public/physdev.h @@ -33,8 +33,8 @@ typedef struct physdevop_set_iobitmap { typedef struct physdevop_apic { /* IN */ - uint32_t apic; - uint32_t offset; + unsigned long apic_physbase; + uint32_t reg; /* IN or OUT */ uint32_t value; } physdevop_apic_t;