From owner-freebsd-current Fri Nov 3 22:04:48 1995 Return-Path: owner-current Received: (from root@localhost) by freefall.freebsd.org (8.6.12/8.6.6) id WAA07751 for current-outgoing; Fri, 3 Nov 1995 22:04:48 -0800 Received: from ast.com (irvine.ast.com [165.164.128.2]) by freefall.freebsd.org (8.6.12/8.6.6) with SMTP id WAA07746 for ; Fri, 3 Nov 1995 22:04:46 -0800 Received: from fw.ast.com by ast.com with SMTP id AA12334 (5.67b/IDA-1.5 for ); Fri, 3 Nov 1995 22:05:59 -0800 Received: from nemesis by fw.ast.com with uucp (Smail3.1.29.1 #4) id m0tBbXe-00008AC; Fri, 3 Nov 95 23:53 CST Received: by nemesis.lonestar.org (Smail3.1.27.1 #19) id m0tBbW4-000J4YC; Fri, 3 Nov 95 23:51 WET Message-Id: Date: Fri, 3 Nov 95 23:51 WET To: current@FreeBSD.org From: uhclem%nemesis@fw.ast.com (Frank Durda IV) Sent: Fri Nov 3 1995, 23:51:43 CST Subject: Re: Opcode sequencing Sender: owner-current@FreeBSD.org Precedence: bulk [3]Bruce Evans writes: [3]Perhaps the 8254 clock is being accessed too fast. Try adding some delays [3]before each inb() and outb() in clock.c:getit(). Count to 100 or so to [3]get at least 1 usec delay. [4]Uh, I don't think this will work as you expect on a Pentium or a P6. It is [4]too easy for the parallel integer unit(s) to execute the inb/outbs in one [4]unit and do the nice delay loop in the other, thus wrecking your timing [4]delay. On the Pentium and up you must force these types of "timed" [4]instruction sequences to be done sequentially. [4] [4]Execution Time is no longer linear.... :-) [5]Rod Grimes rgrimes@gndrsh.aac.dev.com writes: [5]I suggest you go read the book again, IN and OUT instructions are [5]``serailization'' instuctions. All code between them will have _completed_ [5]execution before the external cycle runs. Uh, I did. 18-8.5 of Volume 3 of the 1994 Pentium songbook says: "The I/O instructions are *not* completely serializing; the processor does *not* wait for these instructions to complete before it prefetches the next instruction. However, they do have some serializing properties that cause them to function in a manner that is compatible with processor generations prior to the Pentium processor." [Ed: even the 486 and to a lesser extend the 386 had a habit of having the I/O cycle from an OUT instruction occur AFTER the next instruction was well-underway. More on this below.] and Chapter 15.4 "Ordering of I/O" says: "To optimize performance, the Pentium CPU allows memory reads to be reordered ahead of buffered writes in most situations. Internally, the CPU reads (cache hits) can be reordered around buffered writes. Memory reordering does not occur externally at the pins, read (cache miss) and writes appear in-order. The Intel486 CPU allows memory reads to be reordered ahead of buffered writes in certain precisely-defined circumstances. (See the Intel486TM Microprocessor Hardware Reference Manual for further details about the operation of the write buffer.) Using memory-mapped I/O, therefore, creates the possibility that an I/O read might be performed before the memory write of a previous instruction. To eliminate this possibility on the Intel486CPU, use an I/O instruction for the read. ****To eliminate this possibility on the Pentium processor, insert one of the serializing instructions, such as CPUID, between operations.**** [Ed: the reverse is also true on a 486 according to the HP 486 Logic Analyzer. An OUT followed by a memory read obtained data from the wrong location because the OUT I/O cycle had not occurred by the time the memory read was performed. (The OUT cycle would have changed memory banks in an expanded memory system, so the wrong bank was accessed even though the OUT appeared in the code before the MOV.) The solution was to insert a JMP $+2 between OUT and MOV opcodes. I don't know if similar or fancier action is required on the Pentium and this particular case isn't clearly covered in the Pentium manual.] When I/O instructions are used instead of memory-mapped I/O, the situation is different in two respects: 1. Some I/O writes are never buffered. The only I/O writes that the the Intel486 CPU buffers are those from the OUTS instruction. The Pentium processor does not buffer any I/O writes. Therefore, strict ordering of I/O operations is enforced by the processor. [Ed: Symantics. A plain OUT on a 486 may not be "buffered", but the I/O WRITE cycle also does not occur during the actual execution clocks of the OUT instruction. It occurs during or after the next instruction is performed. So you might call that "deferred". I think they are using "buffered" to say the I/O cycle does not occur only forced out onto the bus for some reason, and I agree that is not how it works. The I/O cycle occurs at a reasonably predictable point. It just isn't in the confines of the OUT instruction execution period.] 2. The [Pentium] processor synchronizes I/O instruction execution with *external* bus activity. Refer to Table 15-1. Table 15-1 [Pentium] I/O Serialization Processor Holds Awaiting for Completion of... Execution of... Current Current Next Pending Current Instruction Instruction? Instruction Stores? Store? IN Yes - Yes - INS Yes - Yes - REP INS Yes - Yes - OUT - Yes Yes Yes OUTS - Yes Yes Yes REP OUTS - Yes Yes Yes " Sorry, I don't know what the difference is between "Current Instruction" and "Current Instruction?". Perhaps it means an instruction in the other execution unit (if any) is held while this I/O instruction is performed. So much for this bit of trivia. Frank Durda IV |You want something here or uhclem%nemesis@fw.ast.com (Fastest Route)|every time? ...letni!rwsys!nemesis!uhclem | ...decvax!fw.ast.com!nemesis!uhclem |