Project

General

Profile

Bug #13085

fast_syscall state should be tracked

Added by Patrick Mooney 8 months ago. Updated 8 months ago.

Status:
Closed
Priority:
Normal
Category:
kernel
Start date:
Due date:
% Done:

100%

Estimated time:
Difficulty:
Medium
Tags:
Gerrit CR:

Description

Upstreaming OS-7084 from SmartOS:

The i86pc platform disables fast syscalls on a CPU (SYSENTER/SYSCALL) via cpu_fast_syscall_disable when an LDT is configured in a 32-bit process. Process-wide ctxops will re-enable that functionality when its threads are departing the CPU. This disabled state is kept only in the relevant MSRs, not tracked in a structure that's easily accessible from mdb (on a live system or a dump).

It would be nice to track that in the struct machcpu for inspection.

To test, I booted a machine up on a PI with the fix. In its normal state, all CPUs reported having SYSCALL/SYSENTER enabled:

> ::walk cpu | ::print cpu_t cpu_m.mcpu_fast_syscall_state ! uniq -c
40 cpu_m.mcpu_fast_syscall_state = 0x3 (FSS_{ASYSC_ENABLED|SEP_ENABLED})

I modified a copy of ldt.c from the in-gate tests to busy-spin in its worker threads (rather than sleeping like the original test). With 10 threads active in a 32-bit process utilizing a custom LDT, the OS reported SYSCALL/SYSENTER as disabled for the CPUs in question:

> ::walk cpu | ::print cpu_t cpu_m.mcpu_fast_syscall_state ! sort | uniq -c
10 cpu_m.mcpu_fast_syscall_state = 0 (0)
30 cpu_m.mcpu_fast_syscall_state = 0x3 (FSS_{ASYSC_ENABLED|SEP_ENABLED})

The updated donothing function in ldt.c which definitely does something now:

static void *
donothing(void *nothing)
{
        timespec_t start, ts;

        clock_gettime(CLOCK_REALTIME, &start);

        for (;;) {
                clock_gettime(CLOCK_REALTIME, &ts);
                if ((ts.tv_sec - start.tv_sec) > 10)
                        break;
        }
        return (NULL);
}

Also available in: Atom PDF