[haiku-commits] BRANCH pdziepak-github.scheduler [2bd8f82] src/system/kernel/arch/x86 headers/private/kernel/arch/x86 src/system/kernel src/add-ons/kernel/power/cpuidle/intel_cstates

  • From: pdziepak-github.scheduler <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 19 Dec 2013 22:00:34 +0100 (CET)

added 3 changesets to branch 'refs/remotes/pdziepak-github/scheduler'
old head: 7ce234bf2444831f6340230e9e42900ce25c0173
new head: 2bd8f82b29e3b322d196227cccb5ddc0e5c5db34
overview: https://github.com/pdziepak/Haiku/compare/7ce234b...2bd8f82

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

b9ff6bd: x86: Implement multicast ICIs

6df1741: kernel: Fix topology node count being decreased twice per node

2bd8f82: intel_cstates: Computing C-state requires constant time step

                                    [ Pawel Dziepak <pdziepak@xxxxxxxxxxx> ]

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

8 files changed, 171 insertions(+), 86 deletions(-)
headers/private/kernel/arch/smp.h                |   3 +
headers/private/kernel/arch/x86/apic.h           |  10 +-
headers/private/kernel/arch/x86/arch_cpu.h       |   2 +
.../cpuidle/intel_cstates/intel_cstates.cpp      |   7 +-
src/system/kernel/arch/x86/apic.cpp              | 111 +++++++++++--------
src/system/kernel/arch/x86/arch_smp.cpp          | 110 +++++++++++++-----
src/system/kernel/smp.cpp                        |  12 +-
src/system/kernel/system_info.cpp                |   2 +-

############################################################################

Commit:      b9ff6bdae4e34d76fd6ebdc005acfbe30b085695
Author:      Pawel Dziepak <pdziepak@xxxxxxxxxxx>
Date:        Thu Dec 19 18:20:10 2013 UTC

x86: Implement multicast ICIs

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

diff --git a/headers/private/kernel/arch/smp.h 
b/headers/private/kernel/arch/smp.h
index f85fcf1..440617b 100644
--- a/headers/private/kernel/arch/smp.h
+++ b/headers/private/kernel/arch/smp.h
@@ -10,6 +10,8 @@
 
 struct kernel_args;
 
+class CPUSet;
+
 
 #ifdef __cplusplus
 extern "C" {
@@ -19,6 +21,7 @@ status_t arch_smp_init(struct kernel_args *args);
 status_t arch_smp_per_cpu_init(struct kernel_args *args, int32 cpu);
 void arch_smp_send_ici(int32 target_cpu);
 void arch_smp_send_broadcast_ici(void);
+void arch_smp_send_multicast_ici(CPUSet& cpuSet);
 
 #ifdef __cplusplus
 }
diff --git a/headers/private/kernel/arch/x86/apic.h 
b/headers/private/kernel/arch/x86/apic.h
index 9c3d922..a9dbed7 100644
--- a/headers/private/kernel/arch/x86/apic.h
+++ b/headers/private/kernel/arch/x86/apic.h
@@ -52,7 +52,7 @@
 #define APIC_TRIGGER_MODE_LEVEL                                        (1 << 
15)
 
 /* Interrupt Command defines */
-#define APIC_INTR_COMMAND_1_MASK                               0xfff3f000
+#define APIC_INTR_COMMAND_1_MASK                               0xfff32000
 #define APIC_INTR_COMMAND_2_MASK                               0x00ffffff
 
 #define APIC_INTR_COMMAND_1_DEST_MODE_PHYSICAL 0
@@ -110,6 +110,7 @@
 #if !_BOOT_MODE
 
 bool           apic_available();
+bool           x2apic_available();
 uint32         apic_read(uint32 offset);
 void           apic_write(uint32 offset, uint32 data);
 uint32         apic_local_id();
@@ -122,10 +123,9 @@ void               apic_disable_local_ints();
 
 uint32         apic_spurious_intr_vector();
 void           apic_set_spurious_intr_vector(uint32 config);
-uint32         apic_intr_command_1();
-void           apic_set_intr_command_1(uint32 config);
-uint32         apic_intr_command_2();
-void           apic_set_intr_command_2(uint32 config);
+
+void           apic_set_interrupt_command(uint32 destination, uint32 mode);
+bool           apic_interrupt_delivered(void);
 
 uint32         apic_lvt_timer();
 void           apic_set_lvt_timer(uint32 config);
diff --git a/headers/private/kernel/arch/x86/arch_cpu.h 
b/headers/private/kernel/arch/x86/arch_cpu.h
index 516b5fc..f745c50 100644
--- a/headers/private/kernel/arch/x86/arch_cpu.h
+++ b/headers/private/kernel/arch/x86/arch_cpu.h
@@ -326,6 +326,8 @@ typedef struct arch_cpu_info {
        int                                     model;
        int                                     extended_model;
 
+       uint32                          logical_apic_id;
+
        struct X86PagingStructures* active_paging_structures;
 
        size_t                          dr6;    // temporary storage for debug 
registers (cf.
diff --git a/src/system/kernel/arch/x86/apic.cpp 
b/src/system/kernel/arch/x86/apic.cpp
index 4758706..c6719cc 100644
--- a/src/system/kernel/arch/x86/apic.cpp
+++ b/src/system/kernel/arch/x86/apic.cpp
@@ -15,6 +15,7 @@
 #include <debug.h>
 #include <safemode.h>
 #include <vm/vm.h>
+#include <util/AutoLock.h>
 
 #include "timers/apic_timer.h"
 
@@ -30,6 +31,12 @@ apic_available()
 }
 
 
+bool x2apic_available()
+{
+       return sX2APIC;
+}
+
+
 uint32
 apic_read(uint32 offset)
 {
@@ -94,6 +101,16 @@ apic_end_of_interrupt()
 }
 
 
+uint32
+apic_logical_apic_id()
+{
+       if (sX2APIC)
+               return x86_read_msr(IA32_MSR_APIC_LOGICAL_DEST);
+       else
+               return apic_read(APIC_LOGICAL_DEST);
+}
+
+
 void
 apic_disable_local_ints()
 {
@@ -128,49 +145,36 @@ apic_set_spurious_intr_vector(uint32 config)
 }
 
 
-uint32
-apic_intr_command_1()
-{
-       if (sX2APIC)
-               return x86_read_msr(IA32_MSR_APIC_INTR_COMMAND) & 0xffffffff;
-       else
-               return apic_read(APIC_INTR_COMMAND_1);
-}
-
-
 void
-apic_set_intr_command_1(uint32 config)
+apic_set_interrupt_command(uint32 destination, uint32 mode)
 {
        if (sX2APIC) {
-               uint64 value = x86_read_msr(IA32_MSR_APIC_INTR_COMMAND);
-               arch_cpu_memory_read_write_barrier();
-               x86_write_msr(IA32_MSR_APIC_INTR_COMMAND,
-                       (value & 0xffffffff00000000LL) | config);
-       } else
-               apic_write(APIC_INTR_COMMAND_1, config);
+               uint64 command = x86_read_msr(IA32_MSR_APIC_INTR_COMMAND);
+               command &= APIC_INTR_COMMAND_1_MASK;
+               command |= (uint64)destination << 32;
+               command |= mode;
+               x86_write_msr(IA32_MSR_APIC_INTR_COMMAND, command);
+       } else {
+               uint32 command2 = apic_read(APIC_INTR_COMMAND_2)
+                               & APIC_INTR_COMMAND_2_MASK;
+               command2 |= destination << 24;
+               apic_write(APIC_INTR_COMMAND_2, command2);
+
+               uint32 command1 = apic_read(APIC_INTR_COMMAND_1)
+                               & APIC_INTR_COMMAND_1_MASK;
+               command1 |= mode;
+               apic_write(APIC_INTR_COMMAND_1, command1);
+       }
 }
 
 
-uint32
-apic_intr_command_2()
+bool
+apic_interrupt_delivered(void)
 {
        if (sX2APIC)
-               return x86_read_msr(IA32_MSR_APIC_INTR_COMMAND) >> 32;
+               return true;
        else
-               return apic_read(APIC_INTR_COMMAND_2);
-}
-
-
-void
-apic_set_intr_command_2(uint32 config)
-{
-       if (sX2APIC) {
-               uint64 value = x86_read_msr(IA32_MSR_APIC_INTR_COMMAND);
-               arch_cpu_memory_read_write_barrier();
-               x86_write_msr(IA32_MSR_APIC_INTR_COMMAND,
-                       (value & 0xffffffff) | ((uint64)config << 32));
-       } else
-               apic_write(APIC_INTR_COMMAND_2, config);
+               return (apic_read(APIC_INTR_COMMAND_1) & APIC_DELIVERY_STATUS) 
== 0;
 }
 
 
@@ -264,11 +268,6 @@ apic_init(kernel_args *args)
                dprintf("found x2apic\n");
 #if 0
                if (!get_safemode_boolean(B_SAFEMODE_DISABLE_X2APIC, false)) {
-                       uint64 apic_base = x86_read_msr(IA32_MSR_APIC_BASE);
-                       if ((apic_base & IA32_MSR_APIC_BASE_X2APIC) == 0) {
-                               x86_write_msr(IA32_MSR_APIC_BASE, apic_base
-                                       | IA32_MSR_APIC_BASE_X2APIC);
-                       }
                        sX2APIC = true;
                        return B_OK;
                }
@@ -276,11 +275,6 @@ apic_init(kernel_args *args)
                dprintf("x2apic disabled per safemode setting\n");
 #else
                if (get_safemode_boolean(B_SAFEMODE_ENABLE_X2APIC, false)) {
-                       uint64 apic_base = x86_read_msr(IA32_MSR_APIC_BASE);
-                       if ((apic_base & IA32_MSR_APIC_BASE_X2APIC) == 0) {
-                               x86_write_msr(IA32_MSR_APIC_BASE, apic_base
-                                       | IA32_MSR_APIC_BASE_X2APIC);
-                       }
                        sX2APIC = true;
 
                        dprintf("x2apic enabled per safemode setting\n");
@@ -306,8 +300,33 @@ apic_init(kernel_args *args)
 status_t
 apic_per_cpu_init(kernel_args *args, int32 cpu)
 {
-       dprintf("setting up apic for CPU %" B_PRId32 ": apic id %" B_PRIu32 ", "
-               "version %" B_PRIu32 "\n", cpu, apic_local_id(), 
apic_version());
+       if (sX2APIC) {
+               uint64 apic_base = x86_read_msr(IA32_MSR_APIC_BASE);
+               if ((apic_base & IA32_MSR_APIC_BASE_X2APIC) == 0) {
+                       x86_write_msr(IA32_MSR_APIC_BASE, apic_base
+                               | IA32_MSR_APIC_BASE_X2APIC);
+               }
+       }
+
+       dprintf("setting up %sapic for CPU %" B_PRId32 ": apic id %" B_PRIu32 
", "
+               "version %" B_PRIu32 "\n", sX2APIC ? "x2" : "", cpu, 
apic_local_id(),
+               apic_version());
+
+       if (!sX2APIC && cpu < 8) {
+               apic_write(APIC_DEST_FORMAT, uint32(-1));
+
+               uint8 logical_apic_id = 1 << cpu;
+               uint32 value = apic_read(APIC_LOGICAL_DEST);
+               value &= 0xffffff;
+               apic_write(APIC_LOGICAL_DEST, value | (logical_apic_id << 24));
+       }
+
+       // get logical APIC ID
+       gCPU[cpu].arch.logical_apic_id = apic_logical_apic_id();
+       if (!sX2APIC)
+               gCPU[cpu].arch.logical_apic_id >>= 24;
+       dprintf("CPU %" B_PRId32 ": logical apic id: %#" B_PRIx32 "\n", cpu,
+               gCPU[cpu].arch.logical_apic_id);
 
        /* set spurious interrupt vector to 0xff */
        uint32 config = apic_spurious_intr_vector() & 0xffffff00;
diff --git a/src/system/kernel/arch/x86/arch_smp.cpp 
b/src/system/kernel/arch/x86/arch_smp.cpp
index adf89a2..bb95501 100644
--- a/src/system/kernel/arch/x86/arch_smp.cpp
+++ b/src/system/kernel/arch/x86/arch_smp.cpp
@@ -1,4 +1,5 @@
 /*
+ * Copyright 2013, Paweł Dziepak, pdziepak@xxxxxxxxxxx.
  * Copyright 2002-2005, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx. All rights 
reserved.
  * Distributed under the terms of the MIT License.
  *
@@ -25,6 +26,8 @@
 #include <string.h>
 #include <stdio.h>
 
+#include <algorithm>
+
 
 //#define TRACE_ARCH_SMP
 #ifdef TRACE_ARCH_SMP
@@ -34,6 +37,9 @@
 #endif
 
 
+#define        ICI_VECTOR              0xfd
+
+
 static uint32 sCPUAPICIds[SMP_MAX_CPUS];
 static uint32 sAPICVersions[SMP_MAX_CPUS];
 
@@ -125,46 +131,94 @@ arch_smp_per_cpu_init(kernel_args *args, int32 cpu)
 
 
 void
-arch_smp_send_broadcast_ici(void)
+arch_smp_send_multicast_ici(CPUSet& cpuSet)
 {
-       uint32 config;
-       cpu_status state = disable_interrupts();
+#if KDEBUG
+       if (are_interrupts_enabled())
+               panic("arch_smp_send_multicast_ici: called with interrupts 
enabled");
+#endif
+
+       arch_cpu_memory_write_barrier();
 
-       config = apic_intr_command_1() & APIC_INTR_COMMAND_1_MASK;
-       apic_set_intr_command_1(config | 0xfd | APIC_DELIVERY_MODE_FIXED
-               | APIC_INTR_COMMAND_1_ASSERT
-               | APIC_INTR_COMMAND_1_DEST_MODE_PHYSICAL
-               | APIC_INTR_COMMAND_1_DEST_ALL_BUT_SELF);
+       int32 i = 0;
+       int32 cpuCount = smp_get_num_cpus();
 
-       restore_interrupts(state);
+       int32 logicalModeCPUs;
+       if (x2apic_available())
+               logicalModeCPUs = cpuCount;
+       else
+               logicalModeCPUs = std::min(cpuCount, int32(8));
+
+       uint32 destination = 0;
+       for (; i < logicalModeCPUs; i++) {
+               if (cpuSet.GetBit(i) && i != smp_get_current_cpu())
+                       destination |= gCPU[i].arch.logical_apic_id;
+       }
+
+       uint32 mode = ICI_VECTOR | APIC_DELIVERY_MODE_FIXED
+                       | APIC_INTR_COMMAND_1_ASSERT
+                       | APIC_INTR_COMMAND_1_DEST_MODE_LOGICAL
+                       | APIC_INTR_COMMAND_1_DEST_FIELD;
+
+       while (!apic_interrupt_delivered())
+               cpu_pause();
+       apic_set_interrupt_command(destination, mode);
+
+       for (; i < cpuCount; i++) {
+               if (cpuSet.GetBit(i)) {
+                       uint32 destination = sCPUAPICIds[i];
+                       uint32 mode = ICI_VECTOR | APIC_DELIVERY_MODE_FIXED
+                                       | APIC_INTR_COMMAND_1_ASSERT
+                                       | APIC_INTR_COMMAND_1_DEST_MODE_PHYSICAL
+                                       | APIC_INTR_COMMAND_1_DEST_FIELD;
+
+                       while (!apic_interrupt_delivered())
+                               cpu_pause();
+                       apic_set_interrupt_command(destination, mode);
+               }
+       }
 }
 
 
 void
-arch_smp_send_ici(int32 target_cpu)
+arch_smp_send_broadcast_ici(void)
 {
-       uint32 config;
-       uint32 timeout;
-       cpu_status state;
+#if KDEBUG
+       if (are_interrupts_enabled())
+               panic("arch_smp_send_broadcast_ici: called with interrupts 
enabled");
+#endif
+
+       arch_cpu_memory_write_barrier();
 
-       state = disable_interrupts();
+       uint32 mode = ICI_VECTOR | APIC_DELIVERY_MODE_FIXED
+                       | APIC_INTR_COMMAND_1_ASSERT
+                       | APIC_INTR_COMMAND_1_DEST_MODE_PHYSICAL
+                       | APIC_INTR_COMMAND_1_DEST_ALL_BUT_SELF;
+
+       while (!apic_interrupt_delivered())
+               cpu_pause();
+       apic_set_interrupt_command(0, mode);
+}
 
-       config = apic_intr_command_2() & APIC_INTR_COMMAND_2_MASK;
-       apic_set_intr_command_2(config | sCPUAPICIds[target_cpu] << 24);
 
-       config = apic_intr_command_1() & APIC_INTR_COMMAND_1_MASK;
-       apic_set_intr_command_1(config | 0xfd | APIC_DELIVERY_MODE_FIXED
-               | APIC_INTR_COMMAND_1_ASSERT
-               | APIC_INTR_COMMAND_1_DEST_MODE_PHYSICAL
-               | APIC_INTR_COMMAND_1_DEST_FIELD);
+void
+arch_smp_send_ici(int32 target_cpu)
+{
+#if KDEBUG
+       if (are_interrupts_enabled())
+               panic("arch_smp_send_ici: called with interrupts enabled");
+#endif
 
-       timeout = 100000000;
-       // wait for message to be sent
-       while ((apic_intr_command_1() & APIC_DELIVERY_STATUS) != 0 && --timeout 
!= 0)
-               asm volatile ("pause;");
+       arch_cpu_memory_write_barrier();
 
-       if (timeout == 0)
-               panic("arch_smp_send_ici: timeout, target_cpu %" B_PRId32, 
target_cpu);
+       uint32 destination = sCPUAPICIds[target_cpu];
+       uint32 mode = ICI_VECTOR | APIC_DELIVERY_MODE_FIXED
+                       | APIC_INTR_COMMAND_1_ASSERT
+                       | APIC_INTR_COMMAND_1_DEST_MODE_PHYSICAL
+                       | APIC_INTR_COMMAND_1_DEST_FIELD;
 
-       restore_interrupts(state);
+       while (!apic_interrupt_delivered())
+               cpu_pause();
+       apic_set_interrupt_command(destination, mode);
 }
+
diff --git a/src/system/kernel/smp.cpp b/src/system/kernel/smp.cpp
index bc7f583..780912a 100644
--- a/src/system/kernel/smp.cpp
+++ b/src/system/kernel/smp.cpp
@@ -1112,11 +1112,16 @@ smp_send_multicast_ici(CPUSet& cpuMask, int32 message, 
addr_t data,
        if (!sICIEnabled)
                return;
 
+       int currentCPU = smp_get_current_cpu();
+       bool broadcast = true;
+
        // count target CPUs
        int32 targetCPUs = 0;
        for (int32 i = 0; i < sNumCPUs; i++) {
                if (cpuMask.GetBit(i))
                        targetCPUs++;
+               else if (i != currentCPU)
+                       broadcast = false;
        }
 
        // find_free_message leaves interrupts disabled
@@ -1132,7 +1137,6 @@ smp_send_multicast_ici(CPUSet& cpuMask, int32 message, 
addr_t data,
        msg->flags = flags;
        msg->done = 0;
 
-       int currentCPU = smp_get_current_cpu();
        msg->proc_bitmap = cpuMask;
        msg->proc_bitmap.ClearBit(currentCPU);
        if (msg->proc_bitmap.IsEmpty()) {
@@ -1153,8 +1157,10 @@ smp_send_multicast_ici(CPUSet& cpuMask, int32 message, 
addr_t data,
                        atomic_add(&gCPU[i].ici_counter, 1);
        }
 
-       arch_smp_send_broadcast_ici();
-               // TODO: Introduce a call that only bothers the target CPUs!
+       if (broadcast)
+               arch_smp_send_broadcast_ici();
+       else
+               arch_smp_send_multicast_ici(cpuMask);
 
        if ((flags & SMP_MSG_FLAG_SYNC) != 0) {
                // wait for the other cpus to finish processing it

############################################################################

Commit:      6df1741df5d266298442c456b040621372b87647
Author:      Pawel Dziepak <pdziepak@xxxxxxxxxxx>
Date:        Thu Dec 19 19:24:34 2013 UTC

kernel: Fix topology node count being decreased twice per node

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

diff --git a/src/system/kernel/system_info.cpp 
b/src/system/kernel/system_info.cpp
index 82929d0..7f7287c 100644
--- a/src/system/kernel/system_info.cpp
+++ b/src/system/kernel/system_info.cpp
@@ -574,7 +574,7 @@ generate_topology_array(cpu_topology_node_info* topology,
 
        count--;
        topology++;
-       for (int32 i = 0; i < node->children_count && count > 0; i++, count--)
+       for (int32 i = 0; i < node->children_count && count > 0; i++)
                topology = generate_topology_array(topology, node->children[i], 
count);
        return topology;
 }

############################################################################

Commit:      2bd8f82b29e3b322d196227cccb5ddc0e5c5db34
Author:      Pawel Dziepak <pdziepak@xxxxxxxxxxx>
Date:        Thu Dec 19 19:47:22 2013 UTC

intel_cstates: Computing C-state requires constant time step

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

diff --git a/src/add-ons/kernel/power/cpuidle/intel_cstates/intel_cstates.cpp 
b/src/add-ons/kernel/power/cpuidle/intel_cstates/intel_cstates.cpp
index c90b010..9827c91 100644
--- a/src/add-ons/kernel/power/cpuidle/intel_cstates/intel_cstates.cpp
+++ b/src/add-ons/kernel/power/cpuidle/intel_cstates/intel_cstates.cpp
@@ -76,13 +76,14 @@ cstates_idle(void)
        ASSERT(thread_get_current_thread()->pinned_to_cpu > 0);
        int32 cpu = smp_get_current_cpu();
 
+       bigtime_t timeStep = sTimeStep;
        bigtime_t idleTime = sIdleTime[cpu];
-       int state = min_c(idleTime / sTimeStep, sCStateCount - 1);
+       int state = min_c(idleTime / timeStep, sCStateCount - 1);
 
        ASSERT(state >= 0 && state < sCStateCount);
 
-       int subState = idleTime % sTimeStep;
-       subState /= sTimeStep / sCStates[state].fSubStatesCount;
+       int subState = idleTime % timeStep;
+       subState /= timeStep / sCStates[state].fSubStatesCount;
 
        ASSERT(subState >= 0 && subState < sCStates[state].fSubStatesCount);
 


Other related posts: