From mboxrd@z Thu Jan 1 00:00:00 1970 From: Stefan Berger Subject: Errors on MMIO read access on VM suspend / resume operations Date: Tue, 11 Jan 2011 11:19:17 -0500 Message-ID: <4D2C8305.2090609@linux.vnet.ibm.com> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit To: kvm@vger.kernel.org Return-path: Received: from e5.ny.us.ibm.com ([32.97.182.145]:48064 "EHLO e5.ny.us.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756125Ab1AKQTT (ORCPT ); Tue, 11 Jan 2011 11:19:19 -0500 Received: from d01dlp02.pok.ibm.com (d01dlp02.pok.ibm.com [9.56.224.85]) by e5.ny.us.ibm.com (8.14.4/8.13.1) with ESMTP id p0BFtr7m000471 for ; Tue, 11 Jan 2011 10:56:07 -0500 Received: from d01relay02.pok.ibm.com (d01relay02.pok.ibm.com [9.56.227.234]) by d01dlp02.pok.ibm.com (Postfix) with ESMTP id 898134DE8046 for ; Tue, 11 Jan 2011 11:16:17 -0500 (EST) Received: from d03av06.boulder.ibm.com (d03av06.boulder.ibm.com [9.17.195.245]) by d01relay02.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id p0BGJIQT449468 for ; Tue, 11 Jan 2011 11:19:18 -0500 Received: from d03av06.boulder.ibm.com (loopback [127.0.0.1]) by d03av06.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id p0BGNif3011805 for ; Tue, 11 Jan 2011 09:23:44 -0700 Received: from [9.59.241.154] (d941e-10.watson.ibm.com [9.59.241.154]) by d03av06.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id p0BGNiTb011780 for ; Tue, 11 Jan 2011 09:23:44 -0700 Sender: kvm-owner@vger.kernel.org List-ID: Hi! I am currently doing some long-term testing of a device model using memory mapped IO (TPM TIS) and am seeing some strange errors when the suspend occurs in the middle of a read operation in the Linux TPM TIS device driver where the driver reads the result packet from the mmio location. Short background: The TPM response packet is read in 2 chunks. First the first 10 bytes are read containing the response's header. Subsequently the rest of the packet is read using knowledge of the total size of the response packet from the header (bytes 2-5 in big endian format). The corresponding code reading the data from the hardware interface is here: http://lxr.linux.no/#linux+v2.6.37/drivers/char/tpm/tpm_tis.c#L228 The test I am running is setup as follows: - inside the VM keys are permanently generated by sending commands to the TPM; packets read from the interface are dumped to the screen - on the host a script suspends the VM every 6 seconds and resumes it immediately afterwards (using libvirt) As it happens, sometimes the VM is suspended in the middle of a read operation on the TPM TIS interface -- see above code reference. I see that because I do dump the state of the TPM TIS when suspending and see that the read offset is pointing to a location somewhere in the middle of the packet - so the TPM TIS Linux driver is in the above loop currently reading the data. I am observing two types of results if this happens: - either the result read by the Linux TPM TIS driver is ok, so no problem here - or the problematic case where the TPM TIS driver reads a packet with a byte missing and then at the end gets a zero byte from the TPM TIS interface indicating that it read beyond the available data. If the suspend happened while reading the first chunk of data (header), the TPM TIS driver will also complain that the available data for the 2nd chunk (burst size) is less than what's expected -- it's an off-by-one error So, I then modified the TPM TIS device model to decrement the read offset pointer by '1' in case it was detected that the suspend happened in the middle of the read operation -- in Qemu I do this in the post-load 'method'. This then leads to the following types of results: - the problematic(!) case where the read packet was ok - the expected case where the TPM TIS driver reads the packet and ends up having two same bytes in the result in consecutive array locations; besides that the TPM TIS driver will in this case complain that it has left-over data So my conclusion from the above tests are: - for some reason the memory read to the MMIO location happens as the last instruction executed on suspend and again as the very first on executed on resume. This explains to me that the TPM TIS model internal pointer into the packet was advanced by '1' (the packet is read by subsequently reading from the same memory location) and the above problematic cases make sense - the other instruction in the Linux TPM TIS drivers that for example advance the buffer location do not execute twice, i.e., size++ in the buf[size++] = ... in the Linux driver. What puzzles me is that the read operation may be run twice but others don't. If you have insights as why the above may be occurring, please let me know. A simple solution to work around this may be to introduce a register holding the index into the result packet where to read the next byte from (rather than advancing an internal pointer to the next byte), though this would deviate the driver from the standard interface the model currently implements. Regards, Stefan