Skip to content

Commit

Permalink
Update patches for 6.13
Browse files Browse the repository at this point in the history
  • Loading branch information
tannisroot committed Aug 1, 2021
1 parent 10eede4 commit 9ead2ff
Show file tree
Hide file tree
Showing 109 changed files with 8,407 additions and 29,013 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -978,3 +978,229 @@ index 2253591f6fa..07fb6decb62 100644
{
struct object *root;
struct mapping *mapping;
From 3b066b60d21e0fa03ee713a5c11ecfc5252de53c Mon Sep 17 00:00:00 2001
From: Arkadiusz Hiler <[email protected]>
Date: Thu, 3 Jun 2021 22:56:08 +0300
Subject: [PATCH] wineboot: Check if the kernel trusts TSC before using it for
Qpc.

Even if the bits are claiming that TSC meets our requirements the
hardware implementation may still be broken.

The Linux kernel does a lot of quality testing before deciding to use as
the clock source. If it (or the user, through an override) does not trust
the TSC we should not trust it either.

CW-Bug-Id: #18918
CW-Bug-Id: #18958
---
programs/wineboot/wineboot.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)

diff --git a/programs/wineboot/wineboot.c b/programs/wineboot/wineboot.c
index 9bebededa4f..79a4bda4d67 100644
--- a/programs/wineboot/wineboot.c
+++ b/programs/wineboot/wineboot.c
@@ -315,6 +315,30 @@ static UINT64 read_tsc_frequency(void)
return freq;
}

+static BOOL is_tsc_trusted_by_the_kernel(void)
+{
+ char buf[4] = {};
+ DWORD num_read;
+ HANDLE handle;
+ BOOL ret = TRUE;
+
+ handle = CreateFileA( "\\??\\unix\\sys\\bus\\clocksource\\devices\\clocksource0\\current_clocksource",
+ GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
+
+ if (handle == INVALID_HANDLE_VALUE)
+ return TRUE;
+
+ if (ReadFile( handle, buf, sizeof(buf)-1, &num_read, NULL ))
+ {
+ if (!!strcmp( "tsc", buf ))
+ ret = FALSE;
+ }
+
+ CloseHandle( handle );
+
+ return ret;
+}
+
static void initialize_qpc_features(struct _KUSER_SHARED_DATA *data)
{
int regs[4];
@@ -346,6 +370,13 @@ static void initialize_qpc_features(struct _KUSER_SHARED_DATA *data)
WARN("No invariant TSC, disabling QpcBypass\n");
return;
}
+
+ if (!is_tsc_trusted_by_the_kernel())
+ {
+ WARN("TSC is not trusted by the kernel, disabling QpcBypass.\n");
+ return;
+ }
+
data->QpcBypassEnabled |= SHARED_GLOBAL_FLAGS_QPC_BYPASS_ENABLED;

/* check for rdtscp support bit */
From 69f2470f937f46ae362d0ba5c144f170f5850a8e Mon Sep 17 00:00:00 2001
From: Joshua Ashton <[email protected]>
Date: Thu, 3 Jun 2021 20:27:49 +0100
Subject: [PATCH] wineboot: Return TSC frequency in ~Mhz

Some games such as Horizon Zero Dawn use this registry value to correlate values from rtdsc -> real time.

In my testing across a few devices, Windows always returns the tsc frequency in this entry, not the current/maximum frequency of the processor.

Returning the nominal/maximum cpu frequency here causes the game to run in slow motion as it may not match the tsc frequency of the processor.

Ideally we'd not have to measure this and the kernel would return tsc_khz to userspace, but this is a good enough stop-gap until https://lkml.org/lkml/2020/12/31/72 or something similar is merged.

Fixes: #4125 (Slow motion bug)

Signed-off-by: Joshua Ashton <[email protected]>
---
programs/wineboot/wineboot.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/programs/wineboot/wineboot.c b/programs/wineboot/wineboot.c
index 79a4bda4d67..0662feac9ce 100644
--- a/programs/wineboot/wineboot.c
+++ b/programs/wineboot/wineboot.c
@@ -969,12 +969,15 @@ static void create_hardware_registry_keys(void)
if (!RegCreateKeyExW( cpu_key, numW, 0, NULL, REG_OPTION_VOLATILE,
KEY_ALL_ACCESS, NULL, &hkey, NULL ))
{
+ UINT64 tsc_freq = read_tsc_frequency(); /* Hz */
+ DWORD tsc_freq_mhz = (DWORD)(tsc_freq / 1000000ull);
+
RegSetValueExW( hkey, L"FeatureSet", 0, REG_DWORD, (BYTE *)&sci.ProcessorFeatureBits, sizeof(DWORD) );
set_reg_value( hkey, L"Identifier", id );
/* TODO: report ARM properly */
set_reg_value( hkey, L"ProcessorNameString", namestr );
set_reg_value( hkey, L"VendorIdentifier", vendorid );
- RegSetValueExW( hkey, L"~MHz", 0, REG_DWORD, (BYTE *)&power_info[i].MaxMhz, sizeof(DWORD) );
+ RegSetValueExW( hkey, L"~MHz", 0, REG_DWORD, (BYTE *)&tsc_freq_mhz, sizeof(DWORD) );
RegCloseKey( hkey );
}
if (sci.ProcessorArchitecture != PROCESSOR_ARCHITECTURE_ARM &&
From 2bde7d53b3874dfc6f3066819e00da142443a48f Mon Sep 17 00:00:00 2001
From: Joshua Ashton <[email protected]>
Date: Fri, 4 Jun 2021 10:20:51 +0200
Subject: [PATCH] wineboot: Calculate TSC frequency once at the start

This calculates the TSC frequency once at the very start of wineboot.

This avoids needing to calculate this multiple times which can lead to stalls.

Signed-off-by: Joshua Ashton <[email protected]>
---
programs/wineboot/wineboot.c | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/programs/wineboot/wineboot.c b/programs/wineboot/wineboot.c
index 0662feac9ce..dc0e645dd09 100644
--- a/programs/wineboot/wineboot.c
+++ b/programs/wineboot/wineboot.c
@@ -339,7 +339,7 @@ static BOOL is_tsc_trusted_by_the_kernel(void)
return ret;
}

-static void initialize_qpc_features(struct _KUSER_SHARED_DATA *data)
+static void initialize_qpc_features(struct _KUSER_SHARED_DATA *data, UINT64 tsc_frequency)
{
int regs[4];

@@ -388,7 +388,7 @@ static void initialize_qpc_features(struct _KUSER_SHARED_DATA *data)
else
data->QpcBypassEnabled |= SHARED_GLOBAL_FLAGS_QPC_BYPASS_USE_MFENCE;

- if ((data->QpcFrequency = (read_tsc_frequency() >> 10)))
+ if ((data->QpcFrequency = (tsc_frequency >> 10)))
{
data->QpcShift = 10;
data->QpcBias = 0;
@@ -433,7 +433,7 @@ static UINT64 muldiv_tsc(UINT64 a, UINT64 b, UINT64 c)
return ka * kb * c + kb * ra + ka * rb + (ra * rb + c / 2) / c;
}

-static void create_hypervisor_shared_data(void)
+static void create_hypervisor_shared_data(UINT64 tsc_frequency)
{
struct _KUSER_SHARED_DATA *user_shared_data = (void *)0x7ffe0000;
struct hypervisor_shared_data *hypervisor_shared_data;
@@ -480,7 +480,7 @@ static void create_hypervisor_shared_data(void)

if (user_shared_data->QpcBypassEnabled & SHARED_GLOBAL_FLAGS_QPC_BYPASS_ENABLED)
{
- hypervisor_shared_data->QpcMultiplier = muldiv_tsc((UINT64)5000 << 32, (UINT64)2000 << 32, read_tsc_frequency());
+ hypervisor_shared_data->QpcMultiplier = muldiv_tsc((UINT64)5000 << 32, (UINT64)2000 << 32, tsc_frequency);
user_shared_data->QpcBypassEnabled |= SHARED_GLOBAL_FLAGS_QPC_BYPASS_USE_HV_PAGE;
user_shared_data->QpcInterruptTimeIncrement = (ULONGLONG)1 << 63;
user_shared_data->QpcInterruptTimeIncrementShift = 1;
@@ -495,7 +495,7 @@ static void create_hypervisor_shared_data(void)
UnmapViewOfFile( hypervisor_shared_data );
}

-static void create_user_shared_data(void)
+static void create_user_shared_data(UINT64 tsc_frequency)
{
struct _KUSER_SHARED_DATA *data;
RTL_OSVERSIONINFOEXW version;
@@ -582,7 +582,7 @@ static void create_user_shared_data(void)
data->ActiveGroupCount = 1;

initialize_xstate_features( data );
- initialize_qpc_features( data );
+ initialize_qpc_features( data, tsc_frequency );

UnmapViewOfFile( data );
}
@@ -894,7 +894,7 @@ static void create_bios_key( HKEY system_key )
}

/* create the volatile hardware registry keys */
-static void create_hardware_registry_keys(void)
+static void create_hardware_registry_keys(UINT64 tsc_frequency)
{
unsigned int i;
HKEY hkey, system_key, cpu_key, fpu_key;
@@ -969,8 +969,7 @@ static void create_hardware_registry_keys(void)
if (!RegCreateKeyExW( cpu_key, numW, 0, NULL, REG_OPTION_VOLATILE,
KEY_ALL_ACCESS, NULL, &hkey, NULL ))
{
- UINT64 tsc_freq = read_tsc_frequency(); /* Hz */
- DWORD tsc_freq_mhz = (DWORD)(tsc_freq / 1000000ull);
+ DWORD tsc_freq_mhz = (DWORD)(tsc_frequency / 1000000ull); /* Hz -> Mhz */

RegSetValueExW( hkey, L"FeatureSet", 0, REG_DWORD, (BYTE *)&sci.FeatureSet, sizeof(DWORD) );
set_reg_value( hkey, L"Identifier", id );
@@ -1896,9 +1895,12 @@ int __cdecl main( int argc, char *argv[] )
BOOL end_session, force, init, kill, restart, shutdown, update;
HANDLE event;
OBJECT_ATTRIBUTES attr;
+ UINT64 tsc_frequency;
UNICODE_STRING nameW;
BOOL is_wow64;

+ tsc_frequency = read_tsc_frequency();
+
end_session = force = init = kill = restart = shutdown = update = FALSE;
GetWindowsDirectoryW( windowsdir, MAX_PATH );
if( !SetCurrentDirectoryW( windowsdir ) )
@@ -1981,9 +1983,9 @@ int __cdecl main( int argc, char *argv[] )

ResetEvent( event ); /* in case this is a restart */

- create_user_shared_data();
- create_hypervisor_shared_data();
- create_hardware_registry_keys();
+ create_user_shared_data(tsc_frequency);
+ create_hypervisor_shared_data(tsc_frequency);
+ create_hardware_registry_keys(tsc_frequency);
create_dynamic_registry_keys();
create_environment_registry_keys();
create_computer_name_keys();
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
From 99d2e546fb21ae93114834142692518ce4730ee5 Mon Sep 17 00:00:00 2001
From: Thomas Crider <[email protected]>
Date: Wed, 30 Jun 2021 19:57:23 -0600
Subject: [PATCH] winegstreamer: adjust GetSlowestRate and GetFastestRate
values

Per the docs, 0 would not render additional frames:

https://docs.microsoft.com/en-us/windows/win32/medfound/about-rate-control
A rate of zero causes one frame to be rendered; after that, the presentation
clock does not advance. To get another frame at the rate of zero, the
application must seek to a new position.

Having this set to 0 causes Godfall's new character intro video to
black screen, seemingly because it only renders one frame.

Based on the current GetFastestRate value attempt, if we approach the logic on
numerical positive/negative values, the fastest forward rate would be
1e6f (1000000f) and slowest 1.0f, while in reverse the fastest would
be -1.0f and slowest -1e6f (-1000000f).

This fixes Godfall's new character intro video playback and does not
appear to break other tested games.

Signed-off-by: Thomas Crider <[email protected]>
---
dlls/winegstreamer/media_source.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
index eaf4b9b6815..79e51ca3977 100644
--- a/dlls/winegstreamer/media_source.c
+++ b/dlls/winegstreamer/media_source.c
@@ -936,7 +936,7 @@ static HRESULT WINAPI media_source_rate_support_GetSlowestRate(IMFRateSupport *i
{
TRACE("%p, %d, %d, %p.\n", iface, direction, thin, rate);

- *rate = 0.0f;
+ *rate = direction == MFRATE_FORWARD ? 1.0f : -1e6f;

return S_OK;
}
@@ -945,7 +945,7 @@ static HRESULT WINAPI media_source_rate_support_GetFastestRate(IMFRateSupport *i
{
TRACE("%p, %d, %d, %p.\n", iface, direction, thin, rate);

- *rate = direction == MFRATE_FORWARD ? 1e6f : -1e6f;
+ *rate = direction == MFRATE_FORWARD ? 1e6f : -1.0f;

return S_OK;
}
--
2.31.1
Loading

0 comments on commit 9ead2ff

Please sign in to comment.