diff -uprN xen-unstable.hg.orig/tools/examples/xmexample1 xen-unstable.hg/tools/examples/xmexample1 --- xen-unstable.hg.orig/tools/examples/xmexample1 2005-07-19 11:35:21.000000000 -0400 +++ xen-unstable.hg/tools/examples/xmexample1 2005-08-16 21:45:32.000000000 -0400 @@ -48,6 +48,20 @@ name = "ExampleDomain" 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 -uprN xen-unstable.hg.orig/tools/examples/xmexample2 xen-unstable.hg/tools/examples/xmexample2 --- xen-unstable.hg.orig/tools/examples/xmexample2 2005-07-19 11:35:21.000000000 -0400 +++ xen-unstable.hg/tools/examples/xmexample2 2005-08-16 21:45:34.000000000 -0400 @@ -84,6 +84,20 @@ disk = [ 'phy:sda%d,sda1,w' % (7+vmid), '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 -uprN xen-unstable.hg.orig/tools/examples/xmexample3 xen-unstable.hg/tools/examples/xmexample3 --- xen-unstable.hg.orig/tools/examples/xmexample3 2005-07-19 11:35:21.000000000 -0400 +++ xen-unstable.hg/tools/examples/xmexample3 2005-08-16 21:45:53.000000000 -0400 @@ -80,6 +80,20 @@ vif = [ 'ip=192.168.%d.1/24' % (vmid)] 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 -uprN xen-unstable.hg.orig/tools/python/xen/lowlevel/xu/xu.c xen-unstable.hg/tools/python/xen/lowlevel/xu/xu.c --- xen-unstable.hg.orig/tools/python/xen/lowlevel/xu/xu.c 2005-08-15 23:32:29.000000000 -0400 +++ xen-unstable.hg/tools/python/xen/lowlevel/xu/xu.c 2005-08-16 17:06:02.000000000 -0400 @@ -437,8 +437,8 @@ static PyTypeObject xu_notifier_type = { * *********************** MESSAGE *********************** */ -#define TYPE(_x,_y) (((_x)<<8)|(_y)) +#define TYPE(_x,_y) (((_x)<<8)|(_y)) #define P2C(_struct, _field, _ctype) \ do { \ PyObject *obj; \ @@ -558,6 +558,9 @@ static PyObject *xu_message_set_response case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS): P2C(netif_fe_driver_status_t, max_handle, u32); break; + case TYPE(CMSG_TPMIF_FE, CMSG_TPMIF_FE_DRIVER_STATUS): + P2C(tpmif_fe_driver_status_t, max_handle, u32); + break; } if ( dict_items_parsed != PyDict_Size(payload) ) @@ -755,6 +758,52 @@ static PyObject *xu_message_get_payload( C2P(vcpu_hotplug_t, vcpu, Int, Long); C2P(vcpu_hotplug_t, status, Int, Long); return dict; + case TYPE(CMSG_TPMIF_FE, CMSG_TPMIF_FE_INTERFACE_STATUS): + C2P(tpmif_fe_interface_status_t, handle, Int, Long); + C2P(tpmif_fe_interface_status_t, status, Int, Long); + C2P(tpmif_fe_interface_status_t, evtchn, Int, Long); + return dict; + case TYPE(CMSG_TPMIF_FE, CMSG_TPMIF_FE_DRIVER_STATUS): + C2P(tpmif_fe_driver_status_t, status, Int, Long); + C2P(tpmif_fe_driver_status_t, max_handle, Int, Long); + return dict; + case TYPE(CMSG_TPMIF_FE, CMSG_TPMIF_FE_INTERFACE_CONNECT): + C2P(tpmif_fe_interface_connect_t, handle, Int, Long); + C2P(tpmif_fe_interface_connect_t, shmem_frame, Int, Long); + C2P(tpmif_fe_interface_connect_t, shmem_ref, Int, Long); + return dict; + case TYPE(CMSG_TPMIF_FE, CMSG_TPMIF_FE_INTERFACE_DISCONNECT): + C2P(tpmif_fe_interface_disconnect_t, handle, Int, Long); + return dict; + case TYPE(CMSG_TPMIF_FE, CMSG_TPMIF_FE_STARTUP): + return dict; + case TYPE(CMSG_TPMIF_BE, CMSG_TPMIF_BE_CREATE): + C2P(tpmif_be_create_t, domid, Int, Long); + C2P(tpmif_be_create_t, tpmif_handle, Int, Long); + C2P(tpmif_be_create_t, tpm_instance, Int, Long); + C2P(tpmif_be_create_t, status, Int, Long); + return dict; + case TYPE(CMSG_TPMIF_BE, CMSG_TPMIF_BE_DESTROY): + C2P(tpmif_be_destroy_t, domid, Int, Long); + C2P(tpmif_be_destroy_t, tpmif_handle, Int, Long); + C2P(tpmif_be_destroy_t, status, Int, Long); + return dict; + case TYPE(CMSG_TPMIF_BE, CMSG_TPMIF_BE_CONNECT): + C2P(tpmif_be_connect_t, domid, Int, Long); + C2P(tpmif_be_connect_t, tpmif_handle, Int, Long); + C2P(tpmif_be_connect_t, shmem_frame, Int, Long); + C2P(tpmif_be_connect_t, evtchn, Int, Long); + C2P(tpmif_be_connect_t, status, Int, Long); + C2P(tpmif_be_connect_t, shmem_ref, Int, Long); + return dict; + case TYPE(CMSG_TPMIF_BE, CMSG_TPMIF_BE_DISCONNECT): + C2P(tpmif_be_disconnect_t, domid, Int, Long); + C2P(tpmif_be_disconnect_t, tpmif_handle, Int, Long); + C2P(tpmif_be_disconnect_t, status, Int, Long); + return dict; + case TYPE(CMSG_TPMIF_BE, CMSG_TPMIF_BE_DRIVER_STATUS): + C2P(tpmif_be_driver_status_t, status, Int, Long); + return dict; } return PyString_FromStringAndSize((char *)xum->msg.msg, xum->msg.length); @@ -978,6 +1027,38 @@ static PyObject *xu_message_new(PyObject case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_RELEASE_PORT): PSTR2CHAR(usbif_be_release_port_t, path); break; + case TYPE(CMSG_TPMIF_FE, CMSG_TPMIF_FE_INTERFACE_STATUS): + P2C(tpmif_fe_interface_status_t, handle, u32); + P2C(tpmif_fe_interface_status_t, status, u32); + P2C(tpmif_fe_interface_status_t, evtchn, u16); + P2C(tpmif_fe_interface_status_t, domid, u16); + break; + case TYPE(CMSG_TPMIF_BE, CMSG_TPMIF_BE_CREATE): + P2C(tpmif_be_create_t, domid, u32); + P2C(tpmif_be_create_t, tpmif_handle, u32); + P2C(tpmif_be_create_t, tpm_instance, u32); + break; + case TYPE(CMSG_TPMIF_BE, CMSG_TPMIF_BE_DESTROY): + P2C(tpmif_be_destroy_t, domid, u32); + P2C(tpmif_be_destroy_t, tpmif_handle, u32); + break; + case TYPE(CMSG_TPMIF_BE, CMSG_TPMIF_BE_CONNECT): + P2C(tpmif_be_connect_t, domid, u32); + P2C(tpmif_be_connect_t, tpmif_handle, u32); + P2C(tpmif_be_connect_t, shmem_frame, memory_t); + P2C(tpmif_be_connect_t, evtchn, u16); + P2C(tpmif_be_connect_t, shmem_ref, u32); + break; + case TYPE(CMSG_TPMIF_BE, CMSG_TPMIF_BE_DISCONNECT): + P2C(tpmif_be_disconnect_t, domid, u32); + P2C(tpmif_be_disconnect_t, tpmif_handle, u32); + break; + case TYPE(CMSG_TPMIF_FE, CMSG_TPMIF_FE_DRIVER_STATUS): + P2C(tpmif_fe_driver_status_t, status, u32); + P2C(tpmif_fe_driver_status_t, max_handle, u32); + break; + case TYPE(CMSG_TPMIF_FE, CMSG_TPMIF_FE_STARTUP): + break; case TYPE(CMSG_SHUTDOWN, CMSG_SHUTDOWN_SYSRQ): P2C(shutdown_sysrq_t, key, char); break; diff -uprN xen-unstable.hg.orig/tools/python/xen/xend/image.py xen-unstable.hg/tools/python/xen/xend/image.py --- xen-unstable.hg.orig/tools/python/xen/xend/image.py 2005-08-16 10:13:15.000000000 -0400 +++ xen-unstable.hg/tools/python/xen/xend/image.py 2005-08-16 17:06:02.000000000 -0400 @@ -32,6 +32,9 @@ SIF_BLK_BE_DOMAIN = (1<<4) """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. @@ -194,6 +197,7 @@ class ImageHandler: 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 diff -uprN xen-unstable.hg.orig/tools/python/xen/xend/server/messages.py xen-unstable.hg/tools/python/xen/xend/server/messages.py --- xen-unstable.hg.orig/tools/python/xen/xend/server/messages.py 2005-08-09 13:46:09.000000000 -0400 +++ xen-unstable.hg/tools/python/xen/xend/server/messages.py 2005-08-16 17:06:02.000000000 -0400 @@ -270,6 +270,65 @@ usbif_formats = { msg_formats.update(usbif_formats) #============================================================================ +# TPM interface message types. +#============================================================================ + +CMSG_TPMIF_BE = 12 +CMSG_TPMIF_FE = 13 + +CMSG_TPMIF_FE_INTERFACE_STATUS = 0 +CMSG_TPMIF_FE_STARTUP = 1 +CMSG_TPMIF_FE_DRIVER_STATUS = 32 +CMSG_TPMIF_FE_INTERFACE_CONNECT = 33 +CMSG_TPMIF_FE_INTERFACE_DISCONNECT = 34 +CMSG_TPMIF_FE_INTERFACE_QUERY = 35 + +CMSG_TPMIF_BE_CREATE = 0 +CMSG_TPMIF_BE_DESTROY = 1 +CMSG_TPMIF_BE_CONNECT = 2 +CMSG_TPMIF_BE_DISCONNECT = 3 +CMSG_TPMIF_BE_DRIVER_STATUS = 32 + +TPMIF_INTERFACE_STATUS_CLOSED = 0 #/* Interface doesn't exist. */ +TPMIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */ +TPMIF_INTERFACE_STATUS_CONNECTED = 2 #/* Exists and is connected. */ +TPMIF_INTERFACE_STATUS_CHANGED = 3 #/* A device has been added or removed. */ + +TPMIF_DRIVER_STATUS_DOWN = 0 +TPMIF_DRIVER_STATUS_UP = 1 + +tpmif_formats = { + 'tpmif_be_connect_t': + (CMSG_TPMIF_BE, CMSG_TPMIF_BE_CONNECT), + + 'tpmif_be_create_t': + (CMSG_TPMIF_BE, CMSG_TPMIF_BE_CREATE), + + 'tpmif_be_disconnect_t': + (CMSG_TPMIF_BE, CMSG_TPMIF_BE_DISCONNECT), + + 'tpmif_be_destroy_t': + (CMSG_TPMIF_BE, CMSG_TPMIF_BE_DESTROY), + + 'tpmif_be_driver_status_t': + (CMSG_TPMIF_BE, CMSG_TPMIF_BE_DRIVER_STATUS), + + 'tpmif_fe_driver_status_t': + (CMSG_TPMIF_FE, CMSG_TPMIF_FE_DRIVER_STATUS), + + 'tpmif_fe_interface_connect_t': + (CMSG_TPMIF_FE, CMSG_TPMIF_FE_INTERFACE_CONNECT), + + 'tpmif_fe_interface_status_t': + (CMSG_TPMIF_FE, CMSG_TPMIF_FE_INTERFACE_STATUS), + + 'tpmif_fe_driver_startup_t': + (CMSG_TPMIF_FE, CMSG_TPMIF_FE_STARTUP), + } + +msg_formats.update(tpmif_formats) + +#============================================================================ # Domain shutdown message types. #============================================================================ diff -uprN xen-unstable.hg.orig/tools/python/xen/xend/server/tpmif.py xen-unstable.hg/tools/python/xen/xend/server/tpmif.py --- xen-unstable.hg.orig/tools/python/xen/xend/server/tpmif.py 1969-12-31 19:00:00.000000000 -0500 +++ xen-unstable.hg/tools/python/xen/xend/server/tpmif.py 2005-08-16 18:09:20.000000000 -0400 @@ -0,0 +1,369 @@ +# Copyright (C) 2005 IBM Corporation +# Authort: Stefan Berger, stefanb@us.ibm.com +# Derived from netif.py: +# Copyright (C) 2004 Mike Wray +"""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 import channel +from xen.xend.server.controller import CtrlMsgRcvr, Dev, DevController +from xen.xend.server.messages import * + +class TPMDev(Dev): + """A TPM device. + """ + + # State: + # inherited + + # ./config + # + # ./tpm_instance + # + # + # + # Poss should have no backend state here - except for ref to backend's own tree + # for the device? And a status - the one we want. + # ./back/dom + # ./back/devid - id for back-end (tpmif_handle) - same as front/devid + # ./back/id - backend id (if more than one b/e per domain) + # ./back/status + # ./back/shmem_frame - actually these belong in back-end state + # ./back/shmem_ref - shared memory reference needed for grant tables + # + # ./front/dom + # ./front/devid + # ./front/status - need 2: one for requested, one for actual? Or drive from dev status + # and this is front status only. + # ./front/shmem_frame + # ./front/shmem_ref + # + # ./evtchn/front - here or in front/back? + # ./evtchn/back + # ./evtchn/status ? + # At present created by dev: but should be created unbound by front/back + # separately and then bound (by back)? + + __exports__ = Dev.__exports__ + [ + DBVar('config', ty='sxpr'), + DBVar('tpm_instance', ty='int'), + ] + + 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.configure(self.config, recreate=recreate) + + 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 = TPMIF_INTERFACE_STATUS_DISCONNECTED + self.frontendDomain = self.getDomain() + self.frontendChannel = self.getChannel() + cf = channel.channelFactory() + self.backendChannel = cf.openChannel(self.backendDomain) + + def _get_config_instance(self, config): + instance = sxp.child_value(config, 'instance') + if not instance: return None + return instance + + def _get_config_backend(self, config): + backend = sxp.child_value(config, 'backend') + if not backend: return None + return backend + + def configure(self, config, change=False, recreate=False): + if change: + return self.reconfigure(config) + self.config = config + self.backendDomain = self._get_config_backend(config) + if self.backendDomain is None: + self.backendDomain = 0 + self.tpm_instance = self._get_config_instance(config) + log.debug('from config: tpm_instance=%d', int(self.tpm_instance)) + if self.tpm_instance is None: + raise XendError("invalid TPM instance") + try: + if recreate: + self.backendDomain = int(sxp.child_value(config, 'backend', '0')) + else: + #todo: Code below will fail on xend restart when backend is not domain 0. + xd = get_component('xen.xend.XendDomain') + self.backendDomain = xd.domain_lookup_by_name(sxp.child_value(config, 'backend', '0')).id + except: + raise XendError('invalid backend domain') + return self.config + + def reconfigure(self, config): + """Reconfigure the interface with new values. + Not all configuration parameters can be changed: + can, + tpm_instance cannot. + + To leave a parameter unchanged, omit it from the changes. + + @param config configuration changes + @return updated interface configuration + @raise XendError on errors + """ + changes = {} + tpm_instance = self._get_config_instance(config) + + xd = get_component('xen.xend.XendDomain') + backendDomain = xd.domain_lookup_by_name(sxp.child_value(config, 'backend', '0')).id + + if (tpm_instance is not None) and (tpm_instance != self.tpm_instance): + raise XendError("cannot change tpm instance") + + if changes: + for (k, v) in changes.items(): + setattr(self, k, v) + self.config = sxp.merge(config, self.config) + + return self.config + + def sxpr(self): + vif = str(self.vif) + val = ['vtpm', + ['id', self.id], + ['backend', self.backendDomain], + ['tpm_instance', self.tpm_instance], + ] + + if self.evtchn: + val.append(['evtchn', + self.evtchn['port1'], + self.evtchn['port2']]) + return val + + def get_instance(self): + """Get the TPM instance as a string. + """ + return ':'.join(map(lambda x: "%02x" % x, self.instance)) + + def attach(self, recreate=False, change=False): + if recreate: + pass + else: + self.send_be_create() + + 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): + log.debug('In send_be_create') + log.debug('Sending tpmif_be_create with TPM instance=%d', int(self.tpm_instance)) + msg = packMsg('tpmif_be_create_t', + { 'domid' : self.frontendDomain, + 'tpmif_handle' : self.vif, + 'tpm_instance' : int(self.tpm_instance) + }) + msg = self.backendChannel.requestResponse(msg) + val = unpackMsg('tpmif_be_create_t', msg) + status = val['status'] + if int(status) != 0: + log.debug("Error %d creating backend.") + self.destroy() + # 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. + + @param change: change flag + """ + self.destroyed = True + self.status = TPMIF_INTERFACE_STATUS_CLOSED + log.debug("Destroying vtpm domain=%d vtpm=%d", self.frontendDomain, self.vif) + self.closeEvtchn() + self.send_be_disconnect() + self.send_be_destroy() + if change: + self.reportStatus() + + def send_be_disconnect(self): + log.debug("Disconnecting from domain=%d ", self.frontendDomain) + log.debug(" handle=%d ", self.vif) + msg = packMsg('tpmif_be_disconnect_t', + { 'domid' : self.frontendDomain, + 'tpmif_handle' : self.vif }) + self.backendChannel.requestResponse(msg) + #todo: check return status + + def send_be_destroy(self, response=None): + msg = packMsg('tpmif_be_destroy_t', + { 'domid' : self.frontendDomain, + 'tpmif_handle' : self.vif }) + self.backendChannel.requestResponse(msg) + #todo: check return status + + def recv_fe_interface_connect(self, val): + self.openEvtchn() + log.debug('In recv_fe_interface_connect: sending be_connect') + log.debug('Sending tpmif_be_connect with TPM instance=%d', int(self.tpm_instance)) + msg = packMsg('tpmif_be_connect_t', + { 'domid' : self.frontendDomain, + 'tpmif_handle' : self.vif, + 'evtchn' : self.getEventChannelBackend(), + 'shmem_frame' : val['shmem_frame'], + 'shmem_ref' : val['shmem_ref'] }) + msg = self.backendChannel.requestResponse(msg) + #todo: check return status + self.status = TPMIF_INTERFACE_STATUS_CONNECTED + self.reportStatus() + + def reportStatus(self, resp=False): + msg = packMsg('tpmif_fe_interface_status_t', + { 'handle' : self.vif, + 'status' : self.status, + 'evtchn' : self.getEventChannelFrontend(), + 'domid' : self.backendDomain }) + 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() + +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) + 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_TPMIF_FE, + CMSG_TPMIF_FE_DRIVER_STATUS, + self.recv_fe_driver_status) + self.rcvr.addHandler(CMSG_TPMIF_FE, + CMSG_TPMIF_FE_INTERFACE_STATUS, + self.recv_fe_interface_status) + self.rcvr.addHandler(CMSG_TPMIF_FE, + CMSG_TPMIF_FE_INTERFACE_CONNECT, + self.recv_fe_interface_connect) + self.rcvr.registerChannel() + if reboot: + self.rebootDevices() + + def destroyController(self, reboot=False): + """Destroy the controller and all devices. + """ + self.destroyed = True + log.debug("Destroying tpmif domain=%d", self.getDomain()) + self.destroyDevices(reboot=reboot) + if self.rcvr: + self.rcvr.deregisterChannel() + + 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 TPMDev(self, id, config, recreate=recreate) + + def recv_fe_driver_status(self, msg): + msg = packMsg('tpmif_fe_driver_status_t', + { 'status' : TPMIF_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('tpmif_fe_interface_status_t', msg) + vif = val['handle'] + dev = self.findDevice(vif) + if dev: + dev.reportStatus(resp=True) + else: + log.error('Received tpmif_fe_interface_status for unknown vif: dom=%d vif=%d', + self.getDomain(), vif) + msg = packMsg('tpmif_fe_interface_status_t', + { 'handle' : -1, + 'status' : TPMIF_INTERFACE_STATUS_CLOSED, + }); + self.channel.writeResponse(msg) + return True + + def recv_fe_interface_connect(self, msg): + val = unpackMsg('tpmif_fe_interface_connect_t', msg) + vif = val['handle'] + dev = self.getDevice(vif) + if dev: + dev.recv_fe_interface_connect(val) + else: + log.error('Received tpmif_fe_interface_connect for unknown vif: dom=%d vif=%d', + self.getDomain(), vif) + diff -uprN xen-unstable.hg.orig/tools/python/xen/xend/XendDomainInfo.py xen-unstable.hg/tools/python/xen/xend/XendDomainInfo.py --- xen-unstable.hg.orig/tools/python/xen/xend/XendDomainInfo.py 2005-08-16 14:23:59.000000000 -0400 +++ xen-unstable.hg/tools/python/xen/xend/XendDomainInfo.py 2005-08-16 17:06:02.000000000 -0400 @@ -260,6 +260,7 @@ class XendDomainInfo: self.info = None self.blkif_backend = False self.netif_backend = False + self.tpmif_backend = False #todo: state: running, suspended self.state = STATE_VM_OK self.state_updated = threading.Condition() @@ -906,6 +907,9 @@ class XendDomainInfo: self.netif_backend = True elif name == 'usbif': self.usbif_backend = True + elif name == 'tpmif': + log.debug("Creating a TPM Backend domain!") + self.tpmif_backend = True else: raise VmError('invalid backend type:' + str(name)) @@ -1065,6 +1069,10 @@ from server import netif 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 -uprN xen-unstable.hg.orig/tools/python/xen/xm/create.py xen-unstable.hg/tools/python/xen/xm/create.py --- xen-unstable.hg.orig/tools/python/xen/xm/create.py 2005-08-16 17:05:35.000000000 -0400 +++ xen-unstable.hg/tools/python/xen/xm/create.py 2005-08-16 17:06:02.000000000 -0400 @@ -174,6 +174,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=[], use="""Add a disk device to a domain. The physical device is DEV, @@ -212,6 +218,12 @@ gopts.var('vif', val="mac=MAC,be_mac=MAC 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. @@ -368,6 +380,46 @@ def configure_usb(opts, config_devs, val 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. @@ -478,6 +530,8 @@ def make_config(opts, vals): 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]) @@ -490,6 +544,7 @@ def make_config(opts, vals): 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 @@ -538,6 +593,38 @@ def preprocess_vifs(opts, vals): 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' @@ -626,6 +713,8 @@ def preprocess(opts, vals): 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.