[haiku-commits] haiku: hrev53768 - in src/system/boot: platform/bios_ia32 platform/efi arch/x86

  • From: Adrien Destugues <pulkomandy@xxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sat, 25 Jan 2020 06:56:50 -0500 (EST)

hrev53768 adds 1 changeset to branch 'master'
old head: edad811b963e9d524417216d54cd800a95afefd4
new head: 7b4d924f98c08c57e6566b33aeda00cac2f6fec7
overview: 
https://git.haiku-os.org/haiku/log/?qt=range&q=7b4d924f98c0+%5Eedad811b963e

----------------------------------------------------------------------------

7b4d924f98c0: cpu: Extract shared x86 code from efi & bios_ia32
  
  This issue was initially detected by PVS Studio (issue number V547) and fixed
  as part of Google Code-in 2019.
  
  The initial problem was the calculate_cpu_conversion_factor function
  which had been copied in the BIOS and EFI versions of the boot code.
  Further investigation led to more duplicated or very similar functions
  being identified.
  
  Introduce an arch_cpu.h for the x86 boot platform to group these things
  in a single place, and adjust the BIOS and EFI code to call into that.
  Note that the BIOS and EFI code is still a little platform specific,
  ideally there should be a boot_arch_cpu_init() function for each
  architecture as already done for openfirmware and u-boot.
  
  Also remove some irrelevant comments from copypasted files for other
  architectures, as that was filling my git grep with useless noise.
  
  Change-Id: I16d815f0bf015cec0b4e03cc14f3cc447c7164c5
  Reviewed-on: https://review.haiku-os.org/c/haiku/+/1985
  Reviewed-by: Adrien Destugues <pulkomandy@xxxxxxxxx>

                                 [ Andrej Antunovikj <tunas@xxxxxxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev53768
Commit:      7b4d924f98c08c57e6566b33aeda00cac2f6fec7
URL:         https://git.haiku-os.org/haiku/commit/?id=7b4d924f98c0
Author:      Andrej Antunovikj <tunas@xxxxxxxxxxxxx>
Date:        Wed Dec  4 11:52:31 2019 UTC
Committer:   Adrien Destugues <pulkomandy@xxxxxxxxx>
Commit-Date: Sat Jan 25 11:56:46 2020 UTC

----------------------------------------------------------------------------

12 files changed, 340 insertions(+), 688 deletions(-)
.../private/kernel/boot/arch/x86/arch_cpu.h      |   9 +-
src/system/boot/arch/x86/Jamfile                 |   1 +
src/system/boot/arch/x86/cpu.cpp                 | 318 ++++++++++++++++++
src/system/boot/platform/amiga_m68k/cpu.cpp      |   3 -
src/system/boot/platform/bios_ia32/cpu.cpp       | 308 +----------------
src/system/boot/platform/bios_ia32/start.cpp     |   5 +-
src/system/boot/platform/bios_ia32/support.S     |  19 --
src/system/boot/platform/efi/cpu.cpp             | 332 +------------------
src/system/boot/platform/efi/cpu.h               |  22 --
src/system/boot/platform/efi/start.cpp           |   5 +-
.../boot/platform/u-boot/arch/ppc/arch_cpu.cpp   |   3 -
src/system/boot/platform/u-boot/cpu.cpp          |   3 -

----------------------------------------------------------------------------

diff --git a/src/system/boot/platform/bios_ia32/cpu.h 
b/headers/private/kernel/boot/arch/x86/arch_cpu.h
similarity index 67%
rename from src/system/boot/platform/bios_ia32/cpu.h
rename to headers/private/kernel/boot/arch/x86/arch_cpu.h
index f8eff4f44a..771f11a6d1 100644
--- a/src/system/boot/platform/bios_ia32/cpu.h
+++ b/headers/private/kernel/boot/arch/x86/arch_cpu.h
@@ -2,8 +2,8 @@
  * Copyright 2004-2005, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx. All rights 
reserved.
  * Distributed under the terms of the MIT License.
  */
-#ifndef CPU_H
-#define CPU_H
+#ifndef BOOT_ARCH_CPU_H
+#define BOOT_ARCH_CPU_H
 
 
 #include <SupportDefs.h>
@@ -15,8 +15,11 @@ extern "C" {
 
 extern void cpu_init(void);
 
+void calculate_cpu_conversion_factor(uint8 channel);
+
+
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* CPU_H */
+#endif /* BOOT_ARCH_CPU_H */
diff --git a/src/system/boot/arch/x86/Jamfile b/src/system/boot/arch/x86/Jamfile
index 8bf9087dab..448a50b4be 100644
--- a/src/system/boot/arch/x86/Jamfile
+++ b/src/system/boot/arch/x86/Jamfile
@@ -28,6 +28,7 @@ for platform in [ MultiBootSubDirSetup bios_ia32 efi pxe_ia32 
] {
                        $(kernelArchSpecificSources)
                        $(kernelLibArchSpecificSources)
                        $(librootOsArchSources)
+                       cpu.cpp
                        : -std=c++11 # additional flags
                ;
 
diff --git a/src/system/boot/arch/x86/cpu.cpp b/src/system/boot/arch/x86/cpu.cpp
new file mode 100644
index 0000000000..3541daf6c7
--- /dev/null
+++ b/src/system/boot/arch/x86/cpu.cpp
@@ -0,0 +1,318 @@
+/*
+ * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx.
+ * Copyright 2004-2005, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx. All rights 
reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * calculate_cpu_conversion_factor() was written by Travis Geiselbrecht and
+ * licensed under the NewOS license.
+ */
+
+
+#include <OS.h>
+
+#include <boot/arch/x86/arch_cpu.h>
+#include <boot/kernel_args.h>
+#include <boot/platform.h>
+#include <boot/stage2.h>
+#include <boot/stdio.h>
+
+#include <arch/cpu.h>
+#include <arch_kernel.h>
+#include <arch_system_info.h>
+
+#include <string.h>
+
+
+extern "C" uint64 rdtsc();
+
+uint32 gTimeConversionFactor;
+
+// PIT definitions
+#define TIMER_CLKNUM_HZ                                        (14318180 / 12)
+
+// PIT IO Ports
+#define PIT_CHANNEL_PORT_BASE                  0x40
+#define PIT_CONTROL                                            0x43
+
+// Channel selection
+#define PIT_SELECT_CHANNEL_SHIFT               6
+
+// Access mode
+#define PIT_ACCESS_LATCH_COUNTER               (0 << 4)
+#define PIT_ACCESS_LOW_BYTE_ONLY               (1 << 4)
+#define PIT_ACCESS_HIGH_BYTE_ONLY              (2 << 4)
+#define PIT_ACCESS_LOW_THEN_HIGH_BYTE  (3 << 4)
+
+// Operating modes
+#define PIT_MODE_INTERRUPT_ON_0                        (0 << 1)
+#define PIT_MODE_HARDWARE_COUNTDOWN            (1 << 1)
+#define PIT_MODE_RATE_GENERATOR                        (2 << 1)
+#define PIT_MODE_SQUARE_WAVE_GENERATOR (3 << 1)
+#define PIT_MODE_SOFTWARE_STROBE               (4 << 1)
+#define PIT_MODE_HARDWARE_STROBE               (5 << 1)
+
+// BCD/Binary mode
+#define PIT_BINARY_MODE                                        0
+#define PIT_BCD_MODE                                   1
+
+// Channel 2 control (speaker)
+#define PIT_CHANNEL_2_CONTROL                  0x61
+#define PIT_CHANNEL_2_GATE_HIGH                        0x01
+#define PIT_CHANNEL_2_SPEAKER_OFF_MASK ~0x02
+
+// Maximum values
+#define MAX_QUICK_SAMPLES                              20
+#define MAX_SLOW_SAMPLES                               20
+       // TODO: These are arbitrary. They are here to avoid spinning 
indefinitely
+       // if the TSC just isn't stable and we can't get our desired error 
range.
+
+
+struct uint128 {
+       uint128(uint64 low, uint64 high = 0)
+               :
+               low(low),
+               high(high)
+       {
+       }
+
+       bool operator<(const uint128& other) const
+       {
+               return high < other.high || (high == other.high && low < 
other.low);
+       }
+
+       bool operator<=(const uint128& other) const
+       {
+               return !(other < *this);
+       }
+
+       uint128 operator<<(int count) const
+       {
+               if (count == 0)
+                       return *this;
+
+               if (count >= 128)
+                       return 0;
+
+               if (count >= 64)
+                       return uint128(0, low << (count - 64));
+
+               return uint128(low << count, (high << count) | (low >> (64 - 
count)));
+       }
+
+       uint128 operator>>(int count) const
+       {
+               if (count == 0)
+                       return *this;
+
+               if (count >= 128)
+                       return 0;
+
+               if (count >= 64)
+                       return uint128(high >> (count - 64), 0);
+
+               return uint128((low >> count) | (high << (64 - count)), high >> 
count);
+       }
+
+       uint128 operator+(const uint128& other) const
+       {
+               uint64 resultLow = low + other.low;
+               return uint128(resultLow,
+                       high + other.high + (resultLow < low ? 1 : 0));
+       }
+
+       uint128 operator-(const uint128& other) const
+       {
+               uint64 resultLow = low - other.low;
+               return uint128(resultLow,
+                       high - other.high - (resultLow > low ? 1 : 0));
+       }
+
+       uint128 operator*(uint32 other) const
+       {
+               uint64 resultMid = (low >> 32) * other;
+               uint64 resultLow = (low & 0xffffffff) * other + (resultMid << 
32);
+               return uint128(resultLow,
+                       high * other + (resultMid >> 32)
+                               + (resultLow < resultMid << 32 ? 1 : 0));
+       }
+
+       uint128 operator/(const uint128& other) const
+       {
+               int shift = 0;
+               uint128 shiftedDivider = other;
+               while (shiftedDivider.high >> 63 == 0 && shiftedDivider < 
*this) {
+                       shiftedDivider = shiftedDivider << 1;
+                       shift++;
+               }
+
+               uint128 result = 0;
+               uint128 temp = *this;
+               for (; shift >= 0; shift--, shiftedDivider = shiftedDivider >> 
1) {
+                       if (shiftedDivider <= temp) {
+                               result = result + (uint128(1) << shift);
+                               temp = temp - shiftedDivider;
+                       }
+               }
+
+               return result;
+       }
+
+       operator uint64() const
+       {
+               return low;
+       }
+
+private:
+       uint64  low;
+       uint64  high;
+};
+
+
+static inline void
+calibration_loop(uint8 desiredHighByte, uint8 channel, uint64& tscDelta,
+       double& conversionFactor, uint16& expired)
+{
+       uint8 select = channel << PIT_SELECT_CHANNEL_SHIFT;
+       out8(select | PIT_ACCESS_LOW_THEN_HIGH_BYTE | PIT_MODE_INTERRUPT_ON_0
+               | PIT_BINARY_MODE, PIT_CONTROL);
+
+       // Fill in count of 0xffff, low then high byte
+       uint8 channelPort = PIT_CHANNEL_PORT_BASE + channel;
+       out8(0xff, channelPort);
+       out8(0xff, channelPort);
+
+       // Read the count back once to delay the start. This ensures that we've
+       // waited long enough for the counter to actually start counting down, 
as
+       // this only happens on the next clock cycle after reload.
+       in8(channelPort);
+       in8(channelPort);
+
+       // We're expecting the PIT to be at the starting position (high byte 
0xff)
+       // as we just programmed it, but if it isn't we wait for it to wrap.
+       uint8 startLow;
+       uint8 startHigh;
+       do {
+               out8(select | PIT_ACCESS_LATCH_COUNTER, PIT_CONTROL);
+               startLow = in8(channelPort);
+               startHigh = in8(channelPort);
+       } while (startHigh != 255);
+
+       // Read in the first TSC value
+       uint64 startTSC = rdtsc();
+
+       // Wait for the PIT to count down to our desired value
+       uint8 endLow;
+       uint8 endHigh;
+       do {
+               out8(select | PIT_ACCESS_LATCH_COUNTER, PIT_CONTROL);
+               endLow = in8(channelPort);
+               endHigh = in8(channelPort);
+       } while (endHigh > desiredHighByte);
+
+       // And read the second TSC value
+       uint64 endTSC = rdtsc();
+
+       tscDelta = endTSC - startTSC;
+       expired = ((startHigh << 8) | startLow) - ((endHigh << 8) | endLow);
+       conversionFactor = (double)tscDelta / (double)expired;
+}
+
+
+void
+calculate_cpu_conversion_factor(uint8 channel)
+{
+       // When using channel 2, enable the input and disable the speaker.
+       if (channel == 2) {
+               uint8 control = in8(PIT_CHANNEL_2_CONTROL);
+               control &= PIT_CHANNEL_2_SPEAKER_OFF_MASK;
+               control |= PIT_CHANNEL_2_GATE_HIGH;
+               out8(control, PIT_CHANNEL_2_CONTROL);
+       }
+
+       uint64 tscDeltaQuick, tscDeltaSlower, tscDeltaSlow;
+       double conversionFactorQuick, conversionFactorSlower, 
conversionFactorSlow;
+       uint16 expired;
+
+       uint32 quickSampleCount = 1;
+       uint32 slowSampleCount = 1;
+
+quick_sample:
+       calibration_loop(224, channel, tscDeltaQuick, conversionFactorQuick,
+               expired);
+
+slower_sample:
+       calibration_loop(192, channel, tscDeltaSlower, conversionFactorSlower,
+               expired);
+
+       double deviation = conversionFactorQuick / conversionFactorSlower;
+       if (deviation < 0.99 || deviation > 1.01) {
+               // We might have been hit by a SMI or were otherwise stalled
+               if (quickSampleCount++ < MAX_QUICK_SAMPLES)
+                       goto quick_sample;
+       }
+
+       // Slow sample
+       calibration_loop(128, channel, tscDeltaSlow, conversionFactorSlow,
+               expired);
+
+       deviation = conversionFactorSlower / conversionFactorSlow;
+       if (deviation < 0.99 || deviation > 1.01) {
+               // We might have been hit by a SMI or were otherwise stalled
+               if (slowSampleCount++ < MAX_SLOW_SAMPLES)
+                       goto slower_sample;
+       }
+
+       // Scale the TSC delta to timer units
+       tscDeltaSlow *= TIMER_CLKNUM_HZ;
+
+       uint64 clockSpeed = tscDeltaSlow / expired;
+       gTimeConversionFactor = ((uint128(expired) * uint32(1000000)) << 32)
+               / uint128(tscDeltaSlow);
+
+#ifdef TRACE_CPU
+       if (clockSpeed > 1000000000LL) {
+               dprintf("CPU at %Ld.%03Ld GHz\n", clockSpeed / 1000000000LL,
+                       (clockSpeed % 1000000000LL) / 1000000LL);
+       } else {
+               dprintf("CPU at %Ld.%03Ld MHz\n", clockSpeed / 1000000LL,
+                       (clockSpeed % 1000000LL) / 1000LL);
+       }
+#endif
+
+       gKernelArgs.arch_args.system_time_cv_factor = gTimeConversionFactor;
+       gKernelArgs.arch_args.cpu_clock_speed = clockSpeed;
+       //dprintf("factors: %lu %llu\n", gTimeConversionFactor, clockSpeed);
+
+       if (quickSampleCount > 1) {
+               dprintf("needed %" B_PRIu32 " quick samples for TSC 
calibration\n",
+                       quickSampleCount);
+       }
+
+       if (slowSampleCount > 1) {
+               dprintf("needed %" B_PRIu32 " slow samples for TSC 
calibration\n",
+                       slowSampleCount);
+       }
+
+       if (channel == 2) {
+               // Set the gate low again
+               out8(in8(PIT_CHANNEL_2_CONTROL) & ~PIT_CHANNEL_2_GATE_HIGH,
+                       PIT_CHANNEL_2_CONTROL);
+       }
+}
+
+
+extern "C" bigtime_t
+system_time()
+{
+       return rdtsc() * gTimeConversionFactor;
+}
+
+
+extern "C" void
+spin(bigtime_t microseconds)
+{
+       bigtime_t time = system_time();
+
+       while ((system_time() - time) < microseconds)
+               asm volatile ("pause;");
+}
diff --git a/src/system/boot/platform/amiga_m68k/cpu.cpp 
b/src/system/boot/platform/amiga_m68k/cpu.cpp
index 31fb6d4dac..5432f1d87d 100644
--- a/src/system/boot/platform/amiga_m68k/cpu.cpp
+++ b/src/system/boot/platform/amiga_m68k/cpu.cpp
@@ -1,9 +1,6 @@
 /*
  * Copyright 2004-2005, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx. All rights 
reserved.
  * Distributed under the terms of the MIT License.
- *
- * calculate_cpu_conversion_factor() was written by Travis Geiselbrecht and
- * licensed under the NewOS license.
  */
 
 
diff --git a/src/system/boot/platform/bios_ia32/cpu.cpp 
b/src/system/boot/platform/bios_ia32/cpu.cpp
index cc70cbaba9..2d9e00f11e 100644
--- a/src/system/boot/platform/bios_ia32/cpu.cpp
+++ b/src/system/boot/platform/bios_ia32/cpu.cpp
@@ -2,20 +2,18 @@
  * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx.
  * Copyright 2004-2005, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx. All rights 
reserved.
  * Distributed under the terms of the MIT License.
- *
- * calculate_cpu_conversion_factor() was written by Travis Geiselbrecht and
- * licensed under the NewOS license.
  */
 
 
-#include "cpu.h"
-
 #include <OS.h>
-#include <boot/platform.h>
-#include <boot/stdio.h>
+
+#include <boot/arch/x86/arch_cpu.h>
 #include <boot/kernel_args.h>
+#include <boot/platform.h>
 #include <boot/stage2.h>
-#include <arch/cpu.h>
+#include <boot/stdio.h>
+
+#include <arch/x86/arch_cpu.h>
 #include <arch_kernel.h>
 #include <arch_system_info.h>
 
@@ -30,291 +28,10 @@
 #endif
 
 
-extern "C" uint64 rdtsc();
-
-uint32 gTimeConversionFactor;
-
-// PIT definitions
-#define TIMER_CLKNUM_HZ                                        (14318180 / 12)
-
-// PIT IO Ports
-#define PIT_CHANNEL_PORT_BASE                  0x40
-#define PIT_CONTROL                                            0x43
-
-// Channel selection
-#define PIT_SELECT_CHANNEL_SHIFT               6
-
-// Access mode
-#define PIT_ACCESS_LATCH_COUNTER               (0 << 4)
-#define PIT_ACCESS_LOW_BYTE_ONLY               (1 << 4)
-#define PIT_ACCESS_HIGH_BYTE_ONLY              (2 << 4)
-#define PIT_ACCESS_LOW_THEN_HIGH_BYTE  (3 << 4)
-
-// Operating modes
-#define PIT_MODE_INTERRUPT_ON_0                        (0 << 1)
-#define PIT_MODE_HARDWARE_COUNTDOWN            (1 << 1)
-#define PIT_MODE_RATE_GENERATOR                        (2 << 1)
-#define PIT_MODE_SQUARE_WAVE_GENERATOR (3 << 1)
-#define PIT_MODE_SOFTWARE_STROBE               (4 << 1)
-#define PIT_MODE_HARDWARE_STROBE               (5 << 1)
-
-// BCD/Binary mode
-#define PIT_BINARY_MODE                                        0
-#define PIT_BCD_MODE                                   1
-
-// Channel 2 control (speaker)
-#define PIT_CHANNEL_2_CONTROL                  0x61
-#define PIT_CHANNEL_2_GATE_HIGH                        0x01
-#define PIT_CHANNEL_2_SPEAKER_OFF_MASK ~0x02
-
-
-// Maximum values
-#define MAX_QUICK_SAMPLES                              20
-#define MAX_SLOW_SAMPLES                               20
-       // TODO: These are arbitrary. They are here to avoid spinning 
indefinitely
-       // if the TSC just isn't stable and we can't get our desired error 
range.
-
-
 #define CPUID_EFLAGS   (1UL << 21)
 #define RDTSC_FEATURE  (1UL << 4)
 
 
-struct uint128 {
-       uint128(uint64 low, uint64 high = 0)
-               :
-               low(low),
-               high(high)
-       {
-       }
-
-       bool operator<(const uint128& other) const
-       {
-               return high < other.high || (high == other.high && low < 
other.low);
-       }
-
-       bool operator<=(const uint128& other) const
-       {
-               return !(other < *this);
-       }
-
-       uint128 operator<<(int count) const
-       {
-               if (count == 0)
-                       return *this;
-
-               if (count >= 128)
-                       return 0;
-
-               if (count >= 64)
-                       return uint128(0, low << (count - 64));
-
-               return uint128(low << count, (high << count) | (low >> (64 - 
count)));
-       }
-
-       uint128 operator>>(int count) const
-       {
-               if (count == 0)
-                       return *this;
-
-               if (count >= 128)
-                       return 0;
-
-               if (count >= 64)
-                       return uint128(high >> (count - 64), 0);
-
-               return uint128((low >> count) | (high << (64 - count)), high >> 
count);
-       }
-
-       uint128 operator+(const uint128& other) const
-       {
-               uint64 resultLow = low + other.low;
-               return uint128(resultLow,
-                       high + other.high + (resultLow < low ? 1 : 0));
-       }
-
-       uint128 operator-(const uint128& other) const
-       {
-               uint64 resultLow = low - other.low;
-               return uint128(resultLow,
-                       high - other.high - (resultLow > low ? 1 : 0));
-       }
-
-       uint128 operator*(uint32 other) const
-       {
-               uint64 resultMid = (low >> 32) * other;
-               uint64 resultLow = (low & 0xffffffff) * other + (resultMid << 
32);
-               return uint128(resultLow,
-                       high * other + (resultMid >> 32)
-                               + (resultLow < resultMid << 32 ? 1 : 0));
-       }
-
-       uint128 operator/(const uint128& other) const
-       {
-               int shift = 0;
-               uint128 shiftedDivider = other;
-               while (shiftedDivider.high >> 63 == 0 && shiftedDivider < 
*this) {
-                       shiftedDivider = shiftedDivider << 1;
-                       shift++;
-               }
-
-               uint128 result = 0;
-               uint128 temp = *this;
-               for (; shift >= 0; shift--, shiftedDivider = shiftedDivider >> 
1) {
-                       if (shiftedDivider <= temp) {
-                               result = result + (uint128(1) << shift);
-                               temp = temp - shiftedDivider;
-                       }
-               }
-
-               return result;
-       }
-
-       operator uint64() const
-       {
-               return low;
-       }
-
-private:
-       uint64  low;
-       uint64  high;
-};
-
-
-static inline void
-calibration_loop(uint8 desiredHighByte, uint8 channel, uint64& tscDelta,
-       double& conversionFactor, uint16& expired)
-{
-       uint8 select = channel << PIT_SELECT_CHANNEL_SHIFT;
-       out8(select | PIT_ACCESS_LOW_THEN_HIGH_BYTE | PIT_MODE_INTERRUPT_ON_0
-               | PIT_BINARY_MODE, PIT_CONTROL);
-
-       // Fill in count of 0xffff, low then high byte
-       uint8 channelPort = PIT_CHANNEL_PORT_BASE + channel;
-       out8(0xff, channelPort);
-       out8(0xff, channelPort);
-
-       // Read the count back once to delay the start. This ensures that we've
-       // waited long enough for the counter to actually start counting down, 
as
-       // this only happens on the next clock cycle after reload.
-       in8(channelPort);
-       in8(channelPort);
-
-       // We're expecting the PIT to be at the starting position (high byte 
0xff)
-       // as we just programmed it, but if it isn't we wait for it to wrap.
-       uint8 startLow;
-       uint8 startHigh;
-       do {
-               out8(select | PIT_ACCESS_LATCH_COUNTER, PIT_CONTROL);
-               startLow = in8(channelPort);
-               startHigh = in8(channelPort);
-       } while (startHigh != 255);
-
-       // Read in the first TSC value
-       uint64 startTSC = rdtsc();
-
-       // Wait for the PIT to count down to our desired value
-       uint8 endLow;
-       uint8 endHigh;
-       do {
-               out8(select | PIT_ACCESS_LATCH_COUNTER, PIT_CONTROL);
-               endLow = in8(channelPort);
-               endHigh = in8(channelPort);
-       } while (endHigh > desiredHighByte);
-
-       // And read the second TSC value
-       uint64 endTSC = rdtsc();
-
-       tscDelta = endTSC - startTSC;
-       expired = ((startHigh << 8) | startLow) - ((endHigh << 8) | endLow);
-       conversionFactor = (double)tscDelta / (double)expired;
-}
-
-
-static void
-calculate_cpu_conversion_factor()
-{
-       uint8 channel = 0;
-
-       // When using channel 2, enable the input and disable the speaker.
-       if (channel == 2) {
-               uint8 control = in8(PIT_CHANNEL_2_CONTROL);
-               control &= PIT_CHANNEL_2_SPEAKER_OFF_MASK;
-               control |= PIT_CHANNEL_2_GATE_HIGH;
-               out8(control, PIT_CHANNEL_2_CONTROL);
-       }
-
-       uint64 tscDeltaQuick, tscDeltaSlower, tscDeltaSlow;
-       double conversionFactorQuick, conversionFactorSlower, 
conversionFactorSlow;
-       uint16 expired;
-
-       uint32 quickSampleCount = 1;
-       uint32 slowSampleCount = 1;
-
-quick_sample:
-       calibration_loop(224, channel, tscDeltaQuick, conversionFactorQuick,
-               expired);
-
-slower_sample:
-       calibration_loop(192, channel, tscDeltaSlower, conversionFactorSlower,
-               expired);
-
-       double deviation = conversionFactorQuick / conversionFactorSlower;
-       if (deviation < 0.99 || deviation > 1.01) {
-               // We might have been hit by a SMI or were otherwise stalled
-               if (quickSampleCount++ < MAX_QUICK_SAMPLES)
-                       goto quick_sample;
-       }
-
-       // Slow sample
-       calibration_loop(128, channel, tscDeltaSlow, conversionFactorSlow,
-               expired);
-
-       deviation = conversionFactorSlower / conversionFactorSlow;
-       if (deviation < 0.99 || deviation > 1.01) {
-               // We might have been hit by a SMI or were otherwise stalled
-               if (slowSampleCount++ < MAX_SLOW_SAMPLES)
-                       goto slower_sample;
-       }
-
-       // Scale the TSC delta to timer units
-       tscDeltaSlow *= TIMER_CLKNUM_HZ;
-
-       uint64 clockSpeed = tscDeltaSlow / expired;
-       gTimeConversionFactor = ((uint128(expired) * uint32(1000000)) << 32)
-               / uint128(tscDeltaSlow);
-
-#ifdef TRACE_CPU
-       if (clockSpeed > 1000000000LL) {
-               dprintf("CPU at %Ld.%03Ld GHz\n", clockSpeed / 1000000000LL,
-                       (clockSpeed % 1000000000LL) / 1000000LL);
-       } else {
-               dprintf("CPU at %Ld.%03Ld MHz\n", clockSpeed / 1000000LL,
-                       (clockSpeed % 1000000LL) / 1000LL);
-       }
-#endif
-
-       gKernelArgs.arch_args.system_time_cv_factor = gTimeConversionFactor;
-       gKernelArgs.arch_args.cpu_clock_speed = clockSpeed;
-       //dprintf("factors: %lu %llu\n", gTimeConversionFactor, clockSpeed);
-
-       if (quickSampleCount > 1) {
-               dprintf("needed %lu quick samples for TSC calibration\n",
-                       quickSampleCount);
-       }
-
-       if (slowSampleCount > 1) {
-               dprintf("needed %lu slow samples for TSC calibration\n",
-                       slowSampleCount);
-       }
-
-       if (channel == 2) {
-               // Set the gate low again
-               out8(in8(PIT_CHANNEL_2_CONTROL) & ~PIT_CHANNEL_2_GATE_HIGH,
-                       PIT_CHANNEL_2_CONTROL);
-       }
-}
-
-
 static status_t
 check_cpu_features()
 {
@@ -342,25 +59,14 @@ check_cpu_features()
 //     #pragma mark -
 
 
-extern "C" void
-spin(bigtime_t microseconds)
-{
-       bigtime_t time = system_time();
-
-       while ((system_time() - time) < microseconds)
-               asm volatile ("pause;");
-}
-
-
 extern "C" void
 cpu_init()
 {
        if (check_cpu_features() != B_OK)
                panic("You need a Pentium or higher in order to boot!\n");
 
-       calculate_cpu_conversion_factor();
+       calculate_cpu_conversion_factor(0);
 
        gKernelArgs.num_cpus = 1;
                // this will eventually be corrected later on
 }
-
diff --git a/src/system/boot/platform/bios_ia32/start.cpp 
b/src/system/boot/platform/bios_ia32/start.cpp
index 7222ff377c..5c788750f8 100644
--- a/src/system/boot/platform/bios_ia32/start.cpp
+++ b/src/system/boot/platform/bios_ia32/start.cpp
@@ -8,7 +8,9 @@
 
 #include <KernelExport.h>
 
-#include <arch/cpu.h>
+#include <arch/x86/arch_cpu.h>
+
+#include <boot/arch/x86/arch_cpu.h>
 #include <boot/platform.h>
 #include <boot/heap.h>
 #include <boot/stage2.h>
@@ -17,7 +19,6 @@
 #include "apm.h"
 #include "bios.h"
 #include "console.h"
-#include "cpu.h"
 #include "debug.h"
 #include "hpet.h"
 #include "interrupts.h"
diff --git a/src/system/boot/platform/bios_ia32/support.S 
b/src/system/boot/platform/bios_ia32/support.S
index 525faf588d..ce89d6d892 100644
--- a/src/system/boot/platform/bios_ia32/support.S
+++ b/src/system/boot/platform/bios_ia32/support.S
@@ -35,25 +35,6 @@ FUNCTION(execute_n_instructions):
        loop    .again
        ret
 
-FUNCTION(system_time):
-       /* load 64-bit factor into %eax (low), %edx (high) */
-       /* hand-assemble rdtsc -- read time stamp counter */
-       rdtsc           /* time in %edx,%eax */
-
-       pushl   %ebx
-       movl    gTimeConversionFactor, %ebx
-       movl    %edx, %ecx      /* save high half */
-       mull    %ebx            /* truncate %eax, but keep %edx */
-       movl    %ecx, %eax
-       movl    %edx, %ecx      /* save high half of low */
-       mull    %ebx                    /*, %eax*/
-       /* now compute  [%edx, %eax] + [%ecx], propagating carry */
-       subl    %ebx, %ebx      /* need zero to propagate carry */
-       addl    %ecx, %eax
-       adc             %ebx, %edx
-       popl    %ebx
-       ret
-
 null_idt_descr:
        .word   0
        .word   0,0
diff --git a/src/system/boot/platform/efi/cpu.cpp 
b/src/system/boot/platform/efi/cpu.cpp
index 66f8748cc9..5093cfe322 100644
--- a/src/system/boot/platform/efi/cpu.cpp
+++ b/src/system/boot/platform/efi/cpu.cpp
@@ -2,347 +2,19 @@
  * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx.
  * Copyright 2004-2005, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx. All rights 
reserved.
  * Distributed under the terms of the MIT License.
- *
- * calculate_cpu_conversion_factor() was written by Travis Geiselbrecht and
- * licensed under the NewOS license.
  */
 
 
-#include "cpu.h"
-
-#include "efi_platform.h"
-
-#include <OS.h>
-#include <boot/platform.h>
-#include <boot/stdio.h>
 #include <boot/kernel_args.h>
 #include <boot/stage2.h>
 #include <arch/cpu.h>
-#include <arch_kernel.h>
-#include <arch_system_info.h>
-
-#include <string.h>
-
-
-//#define TRACE_CPU
-#ifdef TRACE_CPU
-#      define TRACE(x) dprintf x
-#else
-#      define TRACE(x) ;
-#endif
-
-
-extern "C" uint64 rdtsc();
-
-uint32 gTimeConversionFactor;
-
-// PIT definitions
-#define TIMER_CLKNUM_HZ                                        (14318180 / 12)
-
-// PIT IO Ports
-#define PIT_CHANNEL_PORT_BASE                  0x40
-#define PIT_CONTROL                                            0x43
-
-// Channel selection
-#define PIT_SELECT_CHANNEL_SHIFT               6
-
-// Access mode
-#define PIT_ACCESS_LATCH_COUNTER               (0 << 4)
-#define PIT_ACCESS_LOW_BYTE_ONLY               (1 << 4)
-#define PIT_ACCESS_HIGH_BYTE_ONLY              (2 << 4)
-#define PIT_ACCESS_LOW_THEN_HIGH_BYTE  (3 << 4)
-
-// Operating modes
-#define PIT_MODE_INTERRUPT_ON_0                        (0 << 1)
-#define PIT_MODE_HARDWARE_COUNTDOWN            (1 << 1)
-#define PIT_MODE_RATE_GENERATOR                        (2 << 1)
-#define PIT_MODE_SQUARE_WAVE_GENERATOR (3 << 1)
-#define PIT_MODE_SOFTWARE_STROBE               (4 << 1)
-#define PIT_MODE_HARDWARE_STROBE               (5 << 1)
-
-// BCD/Binary mode
-#define PIT_BINARY_MODE                                        0
-#define PIT_BCD_MODE                                   1
-
-// Channel 2 control (speaker)
-#define PIT_CHANNEL_2_CONTROL                  0x61
-#define PIT_CHANNEL_2_GATE_HIGH                        0x01
-#define PIT_CHANNEL_2_SPEAKER_OFF_MASK ~0x02
-
-
-// Maximum values
-#define MAX_QUICK_SAMPLES                              20
-#define MAX_SLOW_SAMPLES                               20
-       // TODO: These are arbitrary. They are here to avoid spinning 
indefinitely
-       // if the TSC just isn't stable and we can't get our desired error 
range.
-
-
-#define CPUID_EFLAGS   (1UL << 21)
-#define RDTSC_FEATURE  (1UL << 4)
-
-
-struct uint128 {
-       uint128(uint64 low, uint64 high = 0)
-               :
-               low(low),
-               high(high)
-       {
-       }
-
-       bool operator<(const uint128& other) const
-       {
-               return high < other.high || (high == other.high && low < 
other.low);
-       }
-
-       bool operator<=(const uint128& other) const
-       {
-               return !(other < *this);
-       }
-
-       uint128 operator<<(int count) const
-       {
-               if (count == 0)
-                       return *this;
-
-               if (count >= 128)
-                       return 0;
-
-               if (count >= 64)
-                       return uint128(0, low << (count - 64));
-
-               return uint128(low << count, (high << count) | (low >> (64 - 
count)));
-       }
-
-       uint128 operator>>(int count) const
-       {
-               if (count == 0)
-                       return *this;
-
-               if (count >= 128)
-                       return 0;
-
-               if (count >= 64)
-                       return uint128(high >> (count - 64), 0);
-
-               return uint128((low >> count) | (high << (64 - count)), high >> 
count);
-       }
-
-       uint128 operator+(const uint128& other) const
-       {
-               uint64 resultLow = low + other.low;
-               return uint128(resultLow,
-                       high + other.high + (resultLow < low ? 1 : 0));
-       }
-
-       uint128 operator-(const uint128& other) const
-       {
-               uint64 resultLow = low - other.low;
-               return uint128(resultLow,
-                       high - other.high - (resultLow > low ? 1 : 0));
-       }
-
-       uint128 operator*(uint32 other) const
-       {
-               uint64 resultMid = (low >> 32) * other;
-               uint64 resultLow = (low & 0xffffffff) * other + (resultMid << 
32);
-               return uint128(resultLow,
-                       high * other + (resultMid >> 32)
-                               + (resultLow < resultMid << 32 ? 1 : 0));
-       }
-
-       uint128 operator/(const uint128& other) const
-       {
-               int shift = 0;
-               uint128 shiftedDivider = other;
-               while (shiftedDivider.high >> 63 == 0 && shiftedDivider < 
*this) {
-                       shiftedDivider = shiftedDivider << 1;
-                       shift++;
-               }
-
-               uint128 result = 0;
-               uint128 temp = *this;
-               for (; shift >= 0; shift--, shiftedDivider = shiftedDivider >> 
1) {
-                       if (shiftedDivider <= temp) {
-                               result = result + (uint128(1) << shift);
-                               temp = temp - shiftedDivider;
-                       }
-               }
-
-               return result;
-       }
-
-       operator uint64() const
-       {
-               return low;
-       }
-
-private:
-       uint64  low;
-       uint64  high;
-};
-
-
-static inline void
-calibration_loop(uint8 desiredHighByte, uint8 channel, uint64& tscDelta,
-       double& conversionFactor, uint16& expired)
-{
-       uint8 select = channel << PIT_SELECT_CHANNEL_SHIFT;
-       out8(select | PIT_ACCESS_LOW_THEN_HIGH_BYTE | PIT_MODE_INTERRUPT_ON_0
-               | PIT_BINARY_MODE, PIT_CONTROL);
-
-       // Fill in count of 0xffff, low then high byte
-       uint8 channelPort = PIT_CHANNEL_PORT_BASE + channel;
-       out8(0xff, channelPort);
-       out8(0xff, channelPort);
-
-       // Read the count back once to delay the start. This ensures that we've
-       // waited long enough for the counter to actually start counting down, 
as
-       // this only happens on the next clock cycle after reload.
-       in8(channelPort);
-       in8(channelPort);
-
-       // We're expecting the PIT to be at the starting position (high byte 
0xff)
-       // as we just programmed it, but if it isn't we wait for it to wrap.
-       uint8 startLow;
-       uint8 startHigh;
-       do {
-               out8(select | PIT_ACCESS_LATCH_COUNTER, PIT_CONTROL);
-               startLow = in8(channelPort);
-               startHigh = in8(channelPort);
-       } while (startHigh != 255);
-
-       // Read in the first TSC value
-       uint64 startTSC = rdtsc();
-
-       // Wait for the PIT to count down to our desired value
-       uint8 endLow;
-       uint8 endHigh;
-       do {
-               out8(select | PIT_ACCESS_LATCH_COUNTER, PIT_CONTROL);
-               endLow = in8(channelPort);
-               endHigh = in8(channelPort);
-       } while (endHigh > desiredHighByte);
-
-       // And read the second TSC value
-       uint64 endTSC = rdtsc();
-
-       tscDelta = endTSC - startTSC;
-       expired = ((startHigh << 8) | startLow) - ((endHigh << 8) | endLow);
-       conversionFactor = (double)tscDelta / (double)expired;
-}
-
-
-static void
-calculate_cpu_conversion_factor()
-{
-       uint8 channel = 2;
-
-       // When using channel 2, enable the input and disable the speaker.
-       if (channel == 2) {
-               uint8 control = in8(PIT_CHANNEL_2_CONTROL);
-               control &= PIT_CHANNEL_2_SPEAKER_OFF_MASK;
-               control |= PIT_CHANNEL_2_GATE_HIGH;
-               out8(control, PIT_CHANNEL_2_CONTROL);
-       }
-
-       uint64 tscDeltaQuick, tscDeltaSlower, tscDeltaSlow;
-       double conversionFactorQuick, conversionFactorSlower, 
conversionFactorSlow;
-       uint16 expired;
-
-       uint32 quickSampleCount = 1;
-       uint32 slowSampleCount = 1;
-
-quick_sample:
-       calibration_loop(224, channel, tscDeltaQuick, conversionFactorQuick,
-               expired);
-
-slower_sample:
-       calibration_loop(192, channel, tscDeltaSlower, conversionFactorSlower,
-               expired);
-
-       double deviation = conversionFactorQuick / conversionFactorSlower;
-       if (deviation < 0.99 || deviation > 1.01) {
-               // We might have been hit by a SMI or were otherwise stalled
-               if (quickSampleCount++ < MAX_QUICK_SAMPLES)
-                       goto quick_sample;
-       }
-
-       // Slow sample
-       calibration_loop(128, channel, tscDeltaSlow, conversionFactorSlow,
-               expired);
-
-       deviation = conversionFactorSlower / conversionFactorSlow;
-       if (deviation < 0.99 || deviation > 1.01) {
-               // We might have been hit by a SMI or were otherwise stalled
-               if (slowSampleCount++ < MAX_SLOW_SAMPLES)
-                       goto slower_sample;
-       }
-
-       // Scale the TSC delta to timer units
-       tscDeltaSlow *= TIMER_CLKNUM_HZ;
-
-       uint64 clockSpeed = tscDeltaSlow / expired;
-       gTimeConversionFactor = ((uint128(expired) * uint32(1000000)) << 32)
-               / uint128(tscDeltaSlow);
-
-#ifdef TRACE_CPU
-       if (clockSpeed > 1000000000LL) {
-               dprintf("CPU at %Ld.%03Ld GHz\n", clockSpeed / 1000000000LL,
-                       (clockSpeed % 1000000000LL) / 1000000LL);
-       } else {
-               dprintf("CPU at %Ld.%03Ld MHz\n", clockSpeed / 1000000LL,
-                       (clockSpeed % 1000000LL) / 1000LL);
-       }
-#endif
-
-       gKernelArgs.arch_args.system_time_cv_factor = gTimeConversionFactor;
-       gKernelArgs.arch_args.cpu_clock_speed = clockSpeed;
-       //dprintf("factors: %lu %llu\n", gTimeConversionFactor, clockSpeed);
-
-       if (quickSampleCount > 1) {
-               dprintf("needed %u quick samples for TSC calibration\n",
-                       quickSampleCount);
-       }
-
-       if (slowSampleCount > 1) {
-               dprintf("needed %u slow samples for TSC calibration\n",
-                       slowSampleCount);
-       }
-
-       if (channel == 2) {
-               // Set the gate low again
-               out8(in8(PIT_CHANNEL_2_CONTROL) & ~PIT_CHANNEL_2_GATE_HIGH,
-                       PIT_CHANNEL_2_CONTROL);
-       }
-}
-
-
-//     #pragma mark -
-
-
-extern "C" bigtime_t
-system_time()
-{
-       uint64 lo, hi;
-       asm("rdtsc": "=a"(lo), "=d"(hi));
-       return ((lo * gTimeConversionFactor) >> 32) + hi * 
gTimeConversionFactor;
-}
-
-
-extern "C" void
-spin(bigtime_t microseconds)
-{
-       bigtime_t time = system_time();
-
-       while ((system_time() - time) < microseconds)
-               asm volatile ("pause;");
-}
+#include <arch/x86/arch_cpu.h>
 
 
 extern "C" void
 cpu_init()
 {
-       calculate_cpu_conversion_factor();
+       calculate_cpu_conversion_factor(2);
 
        gKernelArgs.num_cpus = 1;
                // this will eventually be corrected later on
diff --git a/src/system/boot/platform/efi/cpu.h 
b/src/system/boot/platform/efi/cpu.h
deleted file mode 100644
index f8eff4f44a..0000000000
--- a/src/system/boot/platform/efi/cpu.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2004-2005, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx. All rights 
reserved.
- * Distributed under the terms of the MIT License.
- */
-#ifndef CPU_H
-#define CPU_H
-
-
-#include <SupportDefs.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern void cpu_init(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* CPU_H */
diff --git a/src/system/boot/platform/efi/start.cpp 
b/src/system/boot/platform/efi/start.cpp
index 4b9d794061..dc48a55fff 100644
--- a/src/system/boot/platform/efi/start.cpp
+++ b/src/system/boot/platform/efi/start.cpp
@@ -12,17 +12,18 @@
 #include <KernelExport.h>
 
 #include <arch/cpu.h>
+#include <kernel.h>
+
+#include <boot/arch/x86/arch_cpu.h>
 #include <boot/kernel_args.h>
 #include <boot/platform.h>
 #include <boot/stage2.h>
 #include <boot/stdio.h>
-#include <kernel.h>
 
 #include "arch_mmu.h"
 #include "acpi.h"
 #include "console.h"
 #include "efi_platform.h"
-#include "cpu.h"
 #include "mmu.h"
 #include "serial.h"
 #include "smp.h"
diff --git a/src/system/boot/platform/u-boot/arch/ppc/arch_cpu.cpp 
b/src/system/boot/platform/u-boot/arch/ppc/arch_cpu.cpp
index 5ec43c1d4f..68c338e8f5 100644
--- a/src/system/boot/platform/u-boot/arch/ppc/arch_cpu.cpp
+++ b/src/system/boot/platform/u-boot/arch/ppc/arch_cpu.cpp
@@ -1,9 +1,6 @@
 /*
  * Copyright 2004-2005, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx. All rights 
reserved.
  * Distributed under the terms of the MIT License.
- *
- * calculate_cpu_conversion_factor() was written by Travis Geiselbrecht and
- * licensed under the NewOS license.
  */
 
 
diff --git a/src/system/boot/platform/u-boot/cpu.cpp 
b/src/system/boot/platform/u-boot/cpu.cpp
index 5df276f07d..96c4265552 100644
--- a/src/system/boot/platform/u-boot/cpu.cpp
+++ b/src/system/boot/platform/u-boot/cpu.cpp
@@ -1,9 +1,6 @@
 /*
  * Copyright 2004-2005, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx. All rights 
reserved.
  * Distributed under the terms of the MIT License.
- *
- * calculate_cpu_conversion_factor() was written by Travis Geiselbrecht and
- * licensed under the NewOS license.
  */
 
 


Other related posts:

  • » [haiku-commits] haiku: hrev53768 - in src/system/boot: platform/bios_ia32 platform/efi arch/x86 - Adrien Destugues