ASoC: Updates for v6.10

This is a very big update, in large part due to extensive work the Intel
people have been doing in their drivers though it's also been busy
elsewhere.  There's also a big overhaul of the DAPM documentation from
Luca Ceresoli arising from the work he did putting together his recent
ELC talk, and he also contributed a new tool for visualising the DAPM
state.

 - A new tool dapm-graph for visualising the DAPM state.
 - Substantial fixes and clarifications for the DAPM documentation.
 - Very large updates throughout the Intel audio drivers.
 - Cleanups of accessors for driver data, module labelling, and for
   constification.
 - Modernsation and cleanup work in the Mediatek drivers.
 - Several fixes and features for the DaVinci I2S driver.
 - New drivers for several AMD and Intel platforms, Nuvoton NAU8325,
   Rockchip RK3308 and Texas Instruments PCM6240.
This commit is contained in:
Takashi Iwai
2024-05-13 11:39:49 +02:00
1365 changed files with 28588 additions and 16668 deletions

View File

@@ -986,10 +986,12 @@ static void dpa_perf_setup(struct cxl_port *endpoint, struct range *range,
{
dpa_perf->qos_class = FAKE_QTG_ID;
dpa_perf->dpa_range = *range;
dpa_perf->coord.read_latency = 500;
dpa_perf->coord.write_latency = 500;
dpa_perf->coord.read_bandwidth = 1000;
dpa_perf->coord.write_bandwidth = 1000;
for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) {
dpa_perf->coord[i].read_latency = 500;
dpa_perf->coord[i].write_latency = 500;
dpa_perf->coord[i].read_bandwidth = 1000;
dpa_perf->coord[i].write_bandwidth = 1000;
}
}
static void mock_cxl_endpoint_parse_cdat(struct cxl_port *port)

View File

@@ -18,7 +18,7 @@ echo 'sched:*' > set_event
yield
count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
count=`head -n 100 trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
if [ $count -lt 3 ]; then
fail "at least fork, exec and exit events should be recorded"
fi
@@ -29,7 +29,7 @@ echo 1 > events/sched/enable
yield
count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
count=`head -n 100 trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
if [ $count -lt 3 ]; then
fail "at least fork, exec and exit events should be recorded"
fi
@@ -40,7 +40,7 @@ echo 0 > events/sched/enable
yield
count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
count=`head -n 100 trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
if [ $count -ne 0 ]; then
fail "any of scheduler events should not be recorded"
fi

View File

@@ -1,3 +1,5 @@
CONFIG_IOMMUFD=y
CONFIG_FAULT_INJECTION_DEBUG_FS=y
CONFIG_FAULT_INJECTION=y
CONFIG_IOMMUFD_TEST=y
CONFIG_FAILSLAB=y

View File

@@ -51,6 +51,7 @@
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include <sys/utsname.h>
#endif
#ifndef ARRAY_SIZE
@@ -79,6 +80,9 @@
#define KSFT_XPASS 3
#define KSFT_SKIP 4
#ifndef __noreturn
#define __noreturn __attribute__((__noreturn__))
#endif
#define __printf(a, b) __attribute__((format(printf, a, b)))
/* counters */
@@ -288,24 +292,26 @@ void ksft_test_result_code(int exit_code, const char *test_name,
}
/* Docs seem to call for double space if directive is absent */
if (!directive[0] && msg[0])
if (!directive[0] && msg)
directive = " # ";
va_start(args, msg);
printf("%s %u %s%s", tap_code, ksft_test_num(), test_name, directive);
errno = saved_errno;
vprintf(msg, args);
if (msg) {
va_start(args, msg);
vprintf(msg, args);
va_end(args);
}
printf("\n");
va_end(args);
}
static inline int ksft_exit_pass(void)
static inline __noreturn int ksft_exit_pass(void)
{
ksft_print_cnts();
exit(KSFT_PASS);
}
static inline int ksft_exit_fail(void)
static inline __noreturn int ksft_exit_fail(void)
{
ksft_print_cnts();
exit(KSFT_FAIL);
@@ -332,7 +338,7 @@ static inline int ksft_exit_fail(void)
ksft_cnt.ksft_xfail + \
ksft_cnt.ksft_xskip)
static inline __printf(1, 2) int ksft_exit_fail_msg(const char *msg, ...)
static inline __noreturn __printf(1, 2) int ksft_exit_fail_msg(const char *msg, ...)
{
int saved_errno = errno;
va_list args;
@@ -347,19 +353,19 @@ static inline __printf(1, 2) int ksft_exit_fail_msg(const char *msg, ...)
exit(KSFT_FAIL);
}
static inline int ksft_exit_xfail(void)
static inline __noreturn int ksft_exit_xfail(void)
{
ksft_print_cnts();
exit(KSFT_XFAIL);
}
static inline int ksft_exit_xpass(void)
static inline __noreturn int ksft_exit_xpass(void)
{
ksft_print_cnts();
exit(KSFT_XPASS);
}
static inline __printf(1, 2) int ksft_exit_skip(const char *msg, ...)
static inline __noreturn __printf(1, 2) int ksft_exit_skip(const char *msg, ...)
{
int saved_errno = errno;
va_list args;
@@ -388,4 +394,21 @@ static inline __printf(1, 2) int ksft_exit_skip(const char *msg, ...)
exit(KSFT_SKIP);
}
static inline int ksft_min_kernel_version(unsigned int min_major,
unsigned int min_minor)
{
#ifdef NOLIBC
ksft_print_msg("NOLIBC: Can't check kernel version: Function not implemented\n");
return 0;
#else
unsigned int major, minor;
struct utsname info;
if (uname(&info) || sscanf(info.release, "%u.%u.", &major, &minor) != 2)
ksft_exit_fail_msg("Can't parse kernel version\n");
return major > min_major || (major == min_major && minor >= min_minor);
#endif
}
#endif /* __KSELFTEST_H */

View File

@@ -383,6 +383,7 @@
FIXTURE_DATA(fixture_name) self; \
pid_t child = 1; \
int status = 0; \
bool jmp = false; \
memset(&self, 0, sizeof(FIXTURE_DATA(fixture_name))); \
if (setjmp(_metadata->env) == 0) { \
/* Use the same _metadata. */ \
@@ -399,8 +400,10 @@
_metadata->exit_code = KSFT_FAIL; \
} \
} \
else \
jmp = true; \
if (child == 0) { \
if (_metadata->setup_completed && !_metadata->teardown_parent) \
if (_metadata->setup_completed && !_metadata->teardown_parent && !jmp) \
fixture_name##_teardown(_metadata, &self, variant->data); \
_exit(0); \
} \
@@ -1202,7 +1205,7 @@ void __run_test(struct __fixture_metadata *f,
diagnostic = "unknown";
ksft_test_result_code(t->exit_code, test_name,
diagnostic ? "%s" : "", diagnostic);
diagnostic ? "%s" : NULL, diagnostic);
}
static int test_harness_run(int argc, char **argv)

View File

@@ -22,10 +22,11 @@ static void guest_code(uint64_t start_gpa, uint64_t end_gpa, uint64_t stride)
{
uint64_t gpa;
for (gpa = start_gpa; gpa < end_gpa; gpa += stride)
*((volatile uint64_t *)gpa) = gpa;
GUEST_DONE();
for (;;) {
for (gpa = start_gpa; gpa < end_gpa; gpa += stride)
*((volatile uint64_t *)gpa) = gpa;
GUEST_SYNC(0);
}
}
struct vcpu_info {
@@ -55,7 +56,7 @@ static void rendezvous_with_boss(void)
static void run_vcpu(struct kvm_vcpu *vcpu)
{
vcpu_run(vcpu);
TEST_ASSERT_EQ(get_ucall(vcpu, NULL), UCALL_DONE);
TEST_ASSERT_EQ(get_ucall(vcpu, NULL), UCALL_SYNC);
}
static void *vcpu_worker(void *data)
@@ -64,17 +65,13 @@ static void *vcpu_worker(void *data)
struct kvm_vcpu *vcpu = info->vcpu;
struct kvm_vm *vm = vcpu->vm;
struct kvm_sregs sregs;
struct kvm_regs regs;
vcpu_args_set(vcpu, 3, info->start_gpa, info->end_gpa, vm->page_size);
/* Snapshot regs before the first run. */
vcpu_regs_get(vcpu, &regs);
rendezvous_with_boss();
run_vcpu(vcpu);
rendezvous_with_boss();
vcpu_regs_set(vcpu, &regs);
vcpu_sregs_get(vcpu, &sregs);
#ifdef __x86_64__
/* Toggle CR0.WP to trigger a MMU context reset. */

View File

@@ -333,7 +333,7 @@ static void test_invalid_memory_region_flags(void)
struct kvm_vm *vm;
int r, i;
#if defined __aarch64__ || defined __x86_64__
#if defined __aarch64__ || defined __riscv || defined __x86_64__
supported_flags |= KVM_MEM_READONLY;
#endif

View File

@@ -416,12 +416,30 @@ static void guest_rd_wr_counters(uint32_t base_msr, uint8_t nr_possible_counters
static void guest_test_gp_counters(void)
{
uint8_t pmu_version = guest_get_pmu_version();
uint8_t nr_gp_counters = 0;
uint32_t base_msr;
if (guest_get_pmu_version())
if (pmu_version)
nr_gp_counters = this_cpu_property(X86_PROPERTY_PMU_NR_GP_COUNTERS);
/*
* For v2+ PMUs, PERF_GLOBAL_CTRL's architectural post-RESET value is
* "Sets bits n-1:0 and clears the upper bits", where 'n' is the number
* of GP counters. If there are no GP counters, require KVM to leave
* PERF_GLOBAL_CTRL '0'. This edge case isn't covered by the SDM, but
* follow the spirit of the architecture and only globally enable GP
* counters, of which there are none.
*/
if (pmu_version > 1) {
uint64_t global_ctrl = rdmsr(MSR_CORE_PERF_GLOBAL_CTRL);
if (nr_gp_counters)
GUEST_ASSERT_EQ(global_ctrl, GENMASK_ULL(nr_gp_counters - 1, 0));
else
GUEST_ASSERT_EQ(global_ctrl, 0);
}
if (this_cpu_has(X86_FEATURE_PDCM) &&
rdmsr(MSR_IA32_PERF_CAPABILITIES) & PMU_CAP_FW_WRITES)
base_msr = MSR_IA32_PMC0;

View File

@@ -28,16 +28,16 @@
#define NESTED_TEST_MEM1 0xc0001000
#define NESTED_TEST_MEM2 0xc0002000
static void l2_guest_code(void)
static void l2_guest_code(u64 *a, u64 *b)
{
*(volatile uint64_t *)NESTED_TEST_MEM1;
*(volatile uint64_t *)NESTED_TEST_MEM1 = 1;
READ_ONCE(*a);
WRITE_ONCE(*a, 1);
GUEST_SYNC(true);
GUEST_SYNC(false);
*(volatile uint64_t *)NESTED_TEST_MEM2 = 1;
WRITE_ONCE(*b, 1);
GUEST_SYNC(true);
*(volatile uint64_t *)NESTED_TEST_MEM2 = 1;
WRITE_ONCE(*b, 1);
GUEST_SYNC(true);
GUEST_SYNC(false);
@@ -45,17 +45,33 @@ static void l2_guest_code(void)
vmcall();
}
static void l2_guest_code_ept_enabled(void)
{
l2_guest_code((u64 *)NESTED_TEST_MEM1, (u64 *)NESTED_TEST_MEM2);
}
static void l2_guest_code_ept_disabled(void)
{
/* Access the same L1 GPAs as l2_guest_code_ept_enabled() */
l2_guest_code((u64 *)GUEST_TEST_MEM, (u64 *)GUEST_TEST_MEM);
}
void l1_guest_code(struct vmx_pages *vmx)
{
#define L2_GUEST_STACK_SIZE 64
unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE];
void *l2_rip;
GUEST_ASSERT(vmx->vmcs_gpa);
GUEST_ASSERT(prepare_for_vmx_operation(vmx));
GUEST_ASSERT(load_vmcs(vmx));
prepare_vmcs(vmx, l2_guest_code,
&l2_guest_stack[L2_GUEST_STACK_SIZE]);
if (vmx->eptp_gpa)
l2_rip = l2_guest_code_ept_enabled;
else
l2_rip = l2_guest_code_ept_disabled;
prepare_vmcs(vmx, l2_rip, &l2_guest_stack[L2_GUEST_STACK_SIZE]);
GUEST_SYNC(false);
GUEST_ASSERT(!vmlaunch());
@@ -64,7 +80,7 @@ void l1_guest_code(struct vmx_pages *vmx)
GUEST_DONE();
}
int main(int argc, char *argv[])
static void test_vmx_dirty_log(bool enable_ept)
{
vm_vaddr_t vmx_pages_gva = 0;
struct vmx_pages *vmx;
@@ -76,8 +92,7 @@ int main(int argc, char *argv[])
struct ucall uc;
bool done = false;
TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX));
TEST_REQUIRE(kvm_cpu_has_ept());
pr_info("Nested EPT: %s\n", enable_ept ? "enabled" : "disabled");
/* Create VM */
vm = vm_create_with_one_vcpu(&vcpu, l1_guest_code);
@@ -103,11 +118,16 @@ int main(int argc, char *argv[])
*
* Note that prepare_eptp should be called only L1's GPA map is done,
* meaning after the last call to virt_map.
*
* When EPT is disabled, the L2 guest code will still access the same L1
* GPAs as the EPT enabled case.
*/
prepare_eptp(vmx, vm, 0);
nested_map_memslot(vmx, vm, 0);
nested_map(vmx, vm, NESTED_TEST_MEM1, GUEST_TEST_MEM, 4096);
nested_map(vmx, vm, NESTED_TEST_MEM2, GUEST_TEST_MEM, 4096);
if (enable_ept) {
prepare_eptp(vmx, vm, 0);
nested_map_memslot(vmx, vm, 0);
nested_map(vmx, vm, NESTED_TEST_MEM1, GUEST_TEST_MEM, 4096);
nested_map(vmx, vm, NESTED_TEST_MEM2, GUEST_TEST_MEM, 4096);
}
bmap = bitmap_zalloc(TEST_MEM_PAGES);
host_test_mem = addr_gpa2hva(vm, GUEST_TEST_MEM);
@@ -148,3 +168,15 @@ int main(int argc, char *argv[])
}
}
}
int main(int argc, char *argv[])
{
TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX));
test_vmx_dirty_log(/*enable_ept=*/false);
if (kvm_cpu_has_ept())
test_vmx_dirty_log(/*enable_ept=*/true);
return 0;
}

View File

@@ -86,7 +86,7 @@ static void netstat_read_type(FILE *fnetstat, struct netstat **dest, char *line)
pos = strchr(line, ' ') + 1;
if (fscanf(fnetstat, type->header_name) == EOF)
if (fscanf(fnetstat, "%[^ :]", type->header_name) == EOF)
test_error("fscanf(%s)", type->header_name);
if (fread(&tmp, 1, 1, fnetstat) != 1 || tmp != ':')
test_error("Unexpected netstat format (%c)", tmp);

View File

@@ -17,37 +17,37 @@ static pthread_mutex_t ksft_print_lock = PTHREAD_MUTEX_INITIALIZER;
void __test_msg(const char *buf)
{
pthread_mutex_lock(&ksft_print_lock);
ksft_print_msg(buf);
ksft_print_msg("%s", buf);
pthread_mutex_unlock(&ksft_print_lock);
}
void __test_ok(const char *buf)
{
pthread_mutex_lock(&ksft_print_lock);
ksft_test_result_pass(buf);
ksft_test_result_pass("%s", buf);
pthread_mutex_unlock(&ksft_print_lock);
}
void __test_fail(const char *buf)
{
pthread_mutex_lock(&ksft_print_lock);
ksft_test_result_fail(buf);
ksft_test_result_fail("%s", buf);
pthread_mutex_unlock(&ksft_print_lock);
}
void __test_xfail(const char *buf)
{
pthread_mutex_lock(&ksft_print_lock);
ksft_test_result_xfail(buf);
ksft_test_result_xfail("%s", buf);
pthread_mutex_unlock(&ksft_print_lock);
}
void __test_error(const char *buf)
{
pthread_mutex_lock(&ksft_print_lock);
ksft_test_result_error(buf);
ksft_test_result_error("%s", buf);
pthread_mutex_unlock(&ksft_print_lock);
}
void __test_skip(const char *buf)
{
pthread_mutex_lock(&ksft_print_lock);
ksft_test_result_skip(buf);
ksft_test_result_skip("%s", buf);
pthread_mutex_unlock(&ksft_print_lock);
}

View File

@@ -256,8 +256,6 @@ static int test_wait_fds(int sk[], size_t nr, bool is_writable[],
static void test_client_active_rst(unsigned int port)
{
/* one in queue, another accept()ed */
unsigned int wait_for = backlog + 2;
int i, sk[3], err;
bool is_writable[ARRAY_SIZE(sk)] = {false};
unsigned int last = ARRAY_SIZE(sk) - 1;
@@ -275,16 +273,20 @@ static void test_client_active_rst(unsigned int port)
for (i = 0; i < last; i++) {
err = _test_connect_socket(sk[i], this_ip_dest, port,
(i == 0) ? TEST_TIMEOUT_SEC : -1);
if (err < 0)
test_error("failed to connect()");
}
synchronize_threads(); /* 2: connection accept()ed, another queued */
err = test_wait_fds(sk, last, is_writable, wait_for, TEST_TIMEOUT_SEC);
synchronize_threads(); /* 2: two connections: one accept()ed, another queued */
err = test_wait_fds(sk, last, is_writable, last, TEST_TIMEOUT_SEC);
if (err < 0)
test_error("test_wait_fds(): %d", err);
/* async connect() with third sk to get into request_sock_queue */
err = _test_connect_socket(sk[last], this_ip_dest, port, -1);
if (err < 0)
test_error("failed to connect()");
synchronize_threads(); /* 3: close listen socket */
if (test_client_verify(sk[0], packet_sz, quota / packet_sz, TEST_TIMEOUT_SEC))
test_fail("Failed to send data on connected socket");
@@ -292,13 +294,14 @@ static void test_client_active_rst(unsigned int port)
test_ok("Verified established tcp connection");
synchronize_threads(); /* 4: finishing up */
err = _test_connect_socket(sk[last], this_ip_dest, port, -1);
if (err < 0)
test_error("failed to connect()");
synchronize_threads(); /* 5: closed active sk */
err = test_wait_fds(sk, ARRAY_SIZE(sk), NULL,
wait_for, TEST_TIMEOUT_SEC);
/*
* Wait for 2 connections: one accepted, another in the accept queue,
* the one in request_sock_queue won't get fully established, so
* doesn't receive an active RST, see inet_csk_listen_stop().
*/
err = test_wait_fds(sk, last, NULL, last, TEST_TIMEOUT_SEC);
if (err < 0)
test_error("select(): %d", err);

View File

@@ -21,7 +21,7 @@ static void make_listen(int sk)
static void test_vefify_ao_info(int sk, struct tcp_ao_info_opt *info,
const char *tst)
{
struct tcp_ao_info_opt tmp;
struct tcp_ao_info_opt tmp = {};
socklen_t len = sizeof(tmp);
if (getsockopt(sk, IPPROTO_TCP, TCP_AO_INFO, &tmp, &len))

View File

@@ -34,7 +34,7 @@
#endif
#ifndef UDP_MAX_SEGMENTS
#define UDP_MAX_SEGMENTS (1 << 6UL)
#define UDP_MAX_SEGMENTS (1 << 7UL)
#endif
#define CONST_MTU_TEST 1500

View File

@@ -154,7 +154,7 @@ static int dev_papr_vpd_null_handle(void)
static int papr_vpd_close_handle_without_reading(void)
{
const int devfd = open(DEVPATH, O_RDONLY);
struct papr_location_code lc;
struct papr_location_code lc = { .str = "", };
int fd;
SKIP_IF_MSG(devfd < 0 && errno == ENOENT,

View File

@@ -66,7 +66,7 @@ static int check_diff(struct timeval start, struct timeval end)
diff = end.tv_usec - start.tv_usec;
diff += (end.tv_sec - start.tv_sec) * USECS_PER_SEC;
if (abs(diff - DELAY * USECS_PER_SEC) > USECS_PER_SEC / 2) {
if (llabs(diff - DELAY * USECS_PER_SEC) > USECS_PER_SEC / 2) {
printf("Diff too high: %lld..", diff);
return -1;
}
@@ -184,80 +184,71 @@ static int check_timer_create(int which)
return 0;
}
int remain;
__thread int got_signal;
static pthread_t ctd_thread;
static volatile int ctd_count, ctd_failed;
static void *distribution_thread(void *arg)
static void ctd_sighandler(int sig)
{
while (__atomic_load_n(&remain, __ATOMIC_RELAXED));
return NULL;
if (pthread_self() != ctd_thread)
ctd_failed = 1;
ctd_count--;
}
static void distribution_handler(int nr)
static void *ctd_thread_func(void *arg)
{
if (!__atomic_exchange_n(&got_signal, 1, __ATOMIC_RELAXED))
__atomic_fetch_sub(&remain, 1, __ATOMIC_RELAXED);
}
/*
* Test that all running threads _eventually_ receive CLOCK_PROCESS_CPUTIME_ID
* timer signals. This primarily tests that the kernel does not favour any one.
*/
static int check_timer_distribution(void)
{
int err, i;
timer_t id;
const int nthreads = 10;
pthread_t threads[nthreads];
struct itimerspec val = {
.it_value.tv_sec = 0,
.it_value.tv_nsec = 1000 * 1000,
.it_interval.tv_sec = 0,
.it_interval.tv_nsec = 1000 * 1000,
};
timer_t id;
remain = nthreads + 1; /* worker threads + this thread */
signal(SIGALRM, distribution_handler);
err = timer_create(CLOCK_PROCESS_CPUTIME_ID, NULL, &id);
if (err < 0) {
ksft_perror("Can't create timer");
return -1;
}
err = timer_settime(id, 0, &val, NULL);
if (err < 0) {
ksft_perror("Can't set timer");
return -1;
}
/* 1/10 seconds to ensure the leader sleeps */
usleep(10000);
for (i = 0; i < nthreads; i++) {
err = pthread_create(&threads[i], NULL, distribution_thread,
NULL);
if (err) {
ksft_print_msg("Can't create thread: %s (%d)\n",
strerror(errno), errno);
return -1;
}
}
ctd_count = 100;
if (timer_create(CLOCK_PROCESS_CPUTIME_ID, NULL, &id))
return "Can't create timer\n";
if (timer_settime(id, 0, &val, NULL))
return "Can't set timer\n";
/* Wait for all threads to receive the signal. */
while (__atomic_load_n(&remain, __ATOMIC_RELAXED));
while (ctd_count > 0 && !ctd_failed)
;
for (i = 0; i < nthreads; i++) {
err = pthread_join(threads[i], NULL);
if (err) {
ksft_print_msg("Can't join thread: %s (%d)\n",
strerror(errno), errno);
return -1;
}
}
if (timer_delete(id))
return "Can't delete timer\n";
if (timer_delete(id)) {
ksft_perror("Can't delete timer");
return -1;
}
return NULL;
}
ksft_test_result_pass("check_timer_distribution\n");
/*
* Test that only the running thread receives the timer signal.
*/
static int check_timer_distribution(void)
{
const char *errmsg;
signal(SIGALRM, ctd_sighandler);
errmsg = "Can't create thread\n";
if (pthread_create(&ctd_thread, NULL, ctd_thread_func, NULL))
goto err;
errmsg = "Can't join thread\n";
if (pthread_join(ctd_thread, (void **)&errmsg) || errmsg)
goto err;
if (!ctd_failed)
ksft_test_result_pass("check signal distribution\n");
else if (ksft_min_kernel_version(6, 3))
ksft_test_result_fail("check signal distribution\n");
else
ksft_test_result_skip("check signal distribution (old kernel)\n");
return 0;
err:
ksft_print_msg("%s", errmsg);
return -1;
}
int main(int argc, char **argv)

View File

@@ -21,9 +21,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
@@ -62,45 +59,47 @@ int clear_time_state(void)
#define NUM_FREQ_OUTOFRANGE 4
#define NUM_FREQ_INVALID 2
#define SHIFTED_PPM (1 << 16)
long valid_freq[NUM_FREQ_VALID] = {
-499<<16,
-450<<16,
-400<<16,
-350<<16,
-300<<16,
-250<<16,
-200<<16,
-150<<16,
-100<<16,
-75<<16,
-50<<16,
-25<<16,
-10<<16,
-5<<16,
-1<<16,
-499 * SHIFTED_PPM,
-450 * SHIFTED_PPM,
-400 * SHIFTED_PPM,
-350 * SHIFTED_PPM,
-300 * SHIFTED_PPM,
-250 * SHIFTED_PPM,
-200 * SHIFTED_PPM,
-150 * SHIFTED_PPM,
-100 * SHIFTED_PPM,
-75 * SHIFTED_PPM,
-50 * SHIFTED_PPM,
-25 * SHIFTED_PPM,
-10 * SHIFTED_PPM,
-5 * SHIFTED_PPM,
-1 * SHIFTED_PPM,
-1000,
1<<16,
5<<16,
10<<16,
25<<16,
50<<16,
75<<16,
100<<16,
150<<16,
200<<16,
250<<16,
300<<16,
350<<16,
400<<16,
450<<16,
499<<16,
1 * SHIFTED_PPM,
5 * SHIFTED_PPM,
10 * SHIFTED_PPM,
25 * SHIFTED_PPM,
50 * SHIFTED_PPM,
75 * SHIFTED_PPM,
100 * SHIFTED_PPM,
150 * SHIFTED_PPM,
200 * SHIFTED_PPM,
250 * SHIFTED_PPM,
300 * SHIFTED_PPM,
350 * SHIFTED_PPM,
400 * SHIFTED_PPM,
450 * SHIFTED_PPM,
499 * SHIFTED_PPM,
};
long outofrange_freq[NUM_FREQ_OUTOFRANGE] = {
-1000<<16,
-550<<16,
550<<16,
1000<<16,
-1000 * SHIFTED_PPM,
-550 * SHIFTED_PPM,
550 * SHIFTED_PPM,
1000 * SHIFTED_PPM,
};
#define LONG_MAX (~0UL>>1)

View File

@@ -0,0 +1,60 @@
#!/bin/env python3
# SPDX-License-Identifier: GPL-2.0
import subprocess
from shutil import which
turbostat = which('turbostat')
if turbostat is None:
print('Could not find turbostat binary')
exit(1)
timeout = which('timeout')
if timeout is None:
print('Could not find timeout binary')
exit(1)
proc_turbostat = subprocess.run([turbostat, '--list'], capture_output = True)
if proc_turbostat.returncode != 0:
print(f'turbostat failed with {proc_turbostat.returncode}')
exit(1)
#
# By default --list reports also "usec" and "Time_Of_Day_Seconds" columns
# which are only visible when running with --debug.
#
expected_columns_debug = proc_turbostat.stdout.replace(b',', b'\t').strip()
expected_columns = expected_columns_debug.replace(b'usec\t', b'').replace(b'Time_Of_Day_Seconds\t', b'').replace(b'X2APIC\t', b'').replace(b'APIC\t', b'')
#
# Run turbostat with no options for 10 seconds and send SIGINT
#
timeout_argv = [timeout, '--preserve-status', '-s', 'SIGINT', '-k', '3', '1s']
turbostat_argv = [turbostat, '-i', '0.250']
print(f'Running turbostat with {turbostat_argv=}... ', end = '', flush = True)
proc_turbostat = subprocess.run(timeout_argv + turbostat_argv, capture_output = True)
if proc_turbostat.returncode != 0:
print(f'turbostat failed with {proc_turbostat.returncode}')
exit(1)
actual_columns = proc_turbostat.stdout.split(b'\n')[0]
if expected_columns != actual_columns:
print(f'turbostat column check failed\n{expected_columns=}\n{actual_columns=}')
exit(1)
print('OK')
#
# Same, but with --debug
#
turbostat_argv.append('--debug')
print(f'Running turbostat with {turbostat_argv=}... ', end = '', flush = True)
proc_turbostat = subprocess.run(timeout_argv + turbostat_argv, capture_output = True)
if proc_turbostat.returncode != 0:
print(f'turbostat failed with {proc_turbostat.returncode}')
exit(1)
actual_columns = proc_turbostat.stdout.split(b'\n')[0]
if expected_columns_debug != actual_columns:
print(f'turbostat column check failed\n{expected_columns_debug=}\n{actual_columns=}')
exit(1)
print('OK')