Added x2APIC support.
* Mostly useful for virtualization at the moment. Works in QEmu. * Can be enabled by safemode settings/menu. * Please note that x2APIC normally requires use of VT-d interrupt remapping feature on real hardware, which we don't support yet.
This commit is contained in:
parent
e9eb899aa4
commit
787773400c
|
@ -113,10 +113,29 @@ bool apic_available();
|
||||||
uint32 apic_read(uint32 offset);
|
uint32 apic_read(uint32 offset);
|
||||||
void apic_write(uint32 offset, uint32 data);
|
void apic_write(uint32 offset, uint32 data);
|
||||||
uint32 apic_local_id();
|
uint32 apic_local_id();
|
||||||
|
uint32 apic_local_version();
|
||||||
|
uint32 apic_task_priority();
|
||||||
|
void apic_set_task_priority(uint32 config);
|
||||||
void apic_end_of_interrupt();
|
void apic_end_of_interrupt();
|
||||||
|
|
||||||
void apic_disable_local_ints();
|
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);
|
||||||
|
|
||||||
|
uint32 apic_lvt_timer();
|
||||||
|
void apic_set_lvt_timer(uint32 config);
|
||||||
|
uint32 apic_lvt_error();
|
||||||
|
void apic_set_lvt_error(uint32 config);
|
||||||
|
uint32 apic_lvt_initial_timer_count();
|
||||||
|
void apic_set_lvt_initial_timer_count(uint32 config);
|
||||||
|
uint32 apic_lvt_timer_divide_config();
|
||||||
|
void apic_set_lvt_timer_divide_config(uint32 config);
|
||||||
|
|
||||||
status_t apic_init(kernel_args *args);
|
status_t apic_init(kernel_args *args);
|
||||||
status_t apic_per_cpu_init(kernel_args *args, int32 cpu);
|
status_t apic_per_cpu_init(kernel_args *args, int32 cpu);
|
||||||
|
|
||||||
|
|
|
@ -39,11 +39,38 @@
|
||||||
|
|
||||||
#define IA32_MSR_EFER 0xc0000080
|
#define IA32_MSR_EFER 0xc0000080
|
||||||
|
|
||||||
|
|
||||||
|
// MSR APIC BASE bits
|
||||||
|
#define IA32_MSR_APIC_BASE_BSP 0x00000100
|
||||||
|
#define IA32_MSR_APIC_BASE_X2APIC 0x00000400
|
||||||
|
#define IA32_MSR_APIC_BASE_ENABLED 0x00000800
|
||||||
|
#define IA32_MSR_APIC_BASE_ADDRESS 0xfffff000
|
||||||
|
|
||||||
// MSR EFER bits
|
// MSR EFER bits
|
||||||
// reference
|
// reference
|
||||||
#define IA32_MSR_EFER_SYSCALL (1 << 0)
|
#define IA32_MSR_EFER_SYSCALL (1 << 0)
|
||||||
#define IA32_MSR_EFER_NX (1 << 11)
|
#define IA32_MSR_EFER_NX (1 << 11)
|
||||||
|
|
||||||
|
// X2APIC MSRs.
|
||||||
|
#define IA32_MSR_APIC_ID 0x00000802
|
||||||
|
#define IA32_MSR_APIC_VERSION 0x00000803
|
||||||
|
#define IA32_MSR_APIC_TASK_PRIORITY 0x00000808
|
||||||
|
#define IA32_MSR_APIC_PROCESSOR_PRIORITY 0x0000080a
|
||||||
|
#define IA32_MSR_APIC_EOI 0x0000080b
|
||||||
|
#define IA32_MSR_APIC_LOGICAL_DEST 0x0000080d
|
||||||
|
#define IA32_MSR_APIC_SPURIOUS_INTR_VECTOR 0x0000080f
|
||||||
|
#define IA32_MSR_APIC_ERROR_STATUS 0x00000828
|
||||||
|
#define IA32_MSR_APIC_INTR_COMMAND 0x00000830
|
||||||
|
#define IA32_MSR_APIC_LVT_TIMER 0x00000832
|
||||||
|
#define IA32_MSR_APIC_LVT_THERMAL_SENSOR 0x00000833
|
||||||
|
#define IA32_MSR_APIC_LVT_PERFMON_COUNTERS 0x00000834
|
||||||
|
#define IA32_MSR_APIC_LVT_LINT0 0x00000835
|
||||||
|
#define IA32_MSR_APIC_LVT_LINT1 0x00000836
|
||||||
|
#define IA32_MSR_APIC_LVT_ERROR 0x00000837
|
||||||
|
#define IA32_MSR_APIC_INITIAL_TIMER_COUNT 0x00000838
|
||||||
|
#define IA32_MSR_APIC_CURRENT_TIMER_COUNT 0x00000839
|
||||||
|
#define IA32_MSR_APIC_TIMER_DIVIDE_CONFIG 0x0000083e
|
||||||
|
|
||||||
// x86_64 MSRs.
|
// x86_64 MSRs.
|
||||||
#define IA32_MSR_STAR 0xc0000081
|
#define IA32_MSR_STAR 0xc0000081
|
||||||
#define IA32_MSR_LSTAR 0xc0000082
|
#define IA32_MSR_LSTAR 0xc0000082
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#define B_SAFEMODE_DISABLE_IOAPIC "disable_ioapic"
|
#define B_SAFEMODE_DISABLE_IOAPIC "disable_ioapic"
|
||||||
#define B_SAFEMODE_DISABLE_ACPI "disable_acpi"
|
#define B_SAFEMODE_DISABLE_ACPI "disable_acpi"
|
||||||
#define B_SAFEMODE_DISABLE_APIC "disable_apic"
|
#define B_SAFEMODE_DISABLE_APIC "disable_apic"
|
||||||
|
#define B_SAFEMODE_ENABLE_X2APIC "enable_x2apic"
|
||||||
#define B_SAFEMODE_DISABLE_APM "disable_apm"
|
#define B_SAFEMODE_DISABLE_APM "disable_apm"
|
||||||
#define B_SAFEMODE_DISABLE_SMP "disable_smp"
|
#define B_SAFEMODE_DISABLE_SMP "disable_smp"
|
||||||
#define B_SAFEMODE_DISABLE_HYPER_THREADING "disable_hyperthreading"
|
#define B_SAFEMODE_DISABLE_HYPER_THREADING "disable_hyperthreading"
|
||||||
|
|
|
@ -579,6 +579,22 @@ smp_add_safemode_menus(Menu *menu)
|
||||||
item->SetType(MENU_ITEM_MARKABLE);
|
item->SetType(MENU_ITEM_MARKABLE);
|
||||||
item->SetData(B_SAFEMODE_DISABLE_APIC);
|
item->SetData(B_SAFEMODE_DISABLE_APIC);
|
||||||
item->SetHelpText("Disables using the local APIC, also disables SMP.");
|
item->SetHelpText("Disables using the local APIC, also disables SMP.");
|
||||||
|
|
||||||
|
cpuid_info info;
|
||||||
|
if (get_current_cpuid(&info, 1) == B_OK
|
||||||
|
&& (info.regs.ecx & IA32_FEATURE_EXT_X2APIC) != 0) {
|
||||||
|
#if 0
|
||||||
|
menu->AddItem(item = new(nothrow) MenuItem("Disable X2APIC"));
|
||||||
|
item->SetType(MENU_ITEM_MARKABLE);
|
||||||
|
item->SetData(B_SAFEMODE_DISABLE_X2APIC);
|
||||||
|
item->SetHelpText("Disables using X2APIC.");
|
||||||
|
#else
|
||||||
|
menu->AddItem(item = new(nothrow) MenuItem("Enable X2APIC"));
|
||||||
|
item->SetType(MENU_ITEM_MARKABLE);
|
||||||
|
item->SetData(B_SAFEMODE_ENABLE_X2APIC);
|
||||||
|
item->SetHelpText("Enables using X2APIC.");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gKernelArgs.num_cpus < 2)
|
if (gKernelArgs.num_cpus < 2)
|
||||||
|
|
|
@ -13,18 +13,20 @@
|
||||||
#include <arch/x86/msi.h>
|
#include <arch/x86/msi.h>
|
||||||
|
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
#include <safemode.h>
|
||||||
#include <vm/vm.h>
|
#include <vm/vm.h>
|
||||||
|
|
||||||
#include "timers/apic_timer.h"
|
#include "timers/apic_timer.h"
|
||||||
|
|
||||||
|
|
||||||
static void *sLocalAPIC = NULL;
|
static void *sLocalAPIC = NULL;
|
||||||
|
static bool sX2APIC = false;
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
apic_available()
|
apic_available()
|
||||||
{
|
{
|
||||||
return sLocalAPIC != NULL;
|
return sLocalAPIC != NULL || sX2APIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -45,13 +47,49 @@ apic_write(uint32 offset, uint32 data)
|
||||||
uint32
|
uint32
|
||||||
apic_local_id()
|
apic_local_id()
|
||||||
{
|
{
|
||||||
|
if (sX2APIC)
|
||||||
|
return x86_read_msr(IA32_MSR_APIC_ID);
|
||||||
|
else
|
||||||
return (apic_read(APIC_ID) & 0xffffffff) >> 24;
|
return (apic_read(APIC_ID) & 0xffffffff) >> 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
apic_version()
|
||||||
|
{
|
||||||
|
if (sX2APIC)
|
||||||
|
return x86_read_msr(IA32_MSR_APIC_VERSION);
|
||||||
|
else
|
||||||
|
return apic_read(APIC_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
apic_task_priority()
|
||||||
|
{
|
||||||
|
if (sX2APIC)
|
||||||
|
return x86_read_msr(IA32_MSR_APIC_TASK_PRIORITY);
|
||||||
|
else
|
||||||
|
return apic_read(APIC_TASK_PRIORITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
apic_set_task_priority(uint32 config)
|
||||||
|
{
|
||||||
|
if (sX2APIC)
|
||||||
|
x86_write_msr(IA32_MSR_APIC_TASK_PRIORITY, config);
|
||||||
|
else
|
||||||
|
apic_write(APIC_TASK_PRIORITY, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
apic_end_of_interrupt()
|
apic_end_of_interrupt()
|
||||||
{
|
{
|
||||||
|
if (sX2APIC)
|
||||||
|
x86_write_msr(IA32_MSR_APIC_EOI, 0);
|
||||||
|
else
|
||||||
apic_write(APIC_EOI, 0);
|
apic_write(APIC_EOI, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,8 +98,156 @@ void
|
||||||
apic_disable_local_ints()
|
apic_disable_local_ints()
|
||||||
{
|
{
|
||||||
// just clear them out completely
|
// just clear them out completely
|
||||||
|
if (sX2APIC) {
|
||||||
|
x86_write_msr(IA32_MSR_APIC_LVT_LINT0, APIC_LVT_MASKED);
|
||||||
|
x86_write_msr(IA32_MSR_APIC_LVT_LINT1, APIC_LVT_MASKED);
|
||||||
|
} else {
|
||||||
apic_write(APIC_LVT_LINT0, APIC_LVT_MASKED);
|
apic_write(APIC_LVT_LINT0, APIC_LVT_MASKED);
|
||||||
apic_write(APIC_LVT_LINT1, APIC_LVT_MASKED);
|
apic_write(APIC_LVT_LINT1, APIC_LVT_MASKED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
apic_spurious_intr_vector()
|
||||||
|
{
|
||||||
|
if (sX2APIC)
|
||||||
|
return x86_read_msr(IA32_MSR_APIC_SPURIOUS_INTR_VECTOR);
|
||||||
|
else
|
||||||
|
return apic_read(APIC_SPURIOUS_INTR_VECTOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
apic_set_spurious_intr_vector(uint32 config)
|
||||||
|
{
|
||||||
|
if (sX2APIC)
|
||||||
|
x86_write_msr(IA32_MSR_APIC_SPURIOUS_INTR_VECTOR, config);
|
||||||
|
else
|
||||||
|
apic_write(APIC_SPURIOUS_INTR_VECTOR, 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)
|
||||||
|
{
|
||||||
|
if (sX2APIC) {
|
||||||
|
x86_write_msr(IA32_MSR_APIC_INTR_COMMAND,
|
||||||
|
(x86_read_msr(IA32_MSR_APIC_INTR_COMMAND) & 0xffffffff00000000LL) | config);
|
||||||
|
} else
|
||||||
|
apic_write(APIC_INTR_COMMAND_1, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
apic_intr_command_2()
|
||||||
|
{
|
||||||
|
if (sX2APIC)
|
||||||
|
return x86_read_msr(IA32_MSR_APIC_INTR_COMMAND) >> 32;
|
||||||
|
else
|
||||||
|
return apic_read(APIC_INTR_COMMAND_2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
apic_set_intr_command_2(uint32 config)
|
||||||
|
{
|
||||||
|
if (sX2APIC) {
|
||||||
|
x86_write_msr(IA32_MSR_APIC_INTR_COMMAND,
|
||||||
|
(x86_read_msr(IA32_MSR_APIC_INTR_COMMAND) & 0xffffffff)
|
||||||
|
| ((uint64)config << 32));
|
||||||
|
} else
|
||||||
|
apic_write(APIC_INTR_COMMAND_2, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
apic_lvt_timer()
|
||||||
|
{
|
||||||
|
if (sX2APIC)
|
||||||
|
return x86_read_msr(IA32_MSR_APIC_LVT_TIMER);
|
||||||
|
else
|
||||||
|
return apic_read(APIC_LVT_TIMER);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
apic_set_lvt_timer(uint32 config)
|
||||||
|
{
|
||||||
|
if (sX2APIC)
|
||||||
|
x86_write_msr(IA32_MSR_APIC_LVT_TIMER, config);
|
||||||
|
else
|
||||||
|
apic_write(APIC_LVT_TIMER, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
apic_lvt_error()
|
||||||
|
{
|
||||||
|
if (sX2APIC)
|
||||||
|
return x86_read_msr(IA32_MSR_APIC_LVT_ERROR);
|
||||||
|
else
|
||||||
|
return apic_read(APIC_LVT_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
apic_set_lvt_error(uint32 config)
|
||||||
|
{
|
||||||
|
if (sX2APIC)
|
||||||
|
x86_write_msr(IA32_MSR_APIC_LVT_ERROR, config);
|
||||||
|
else
|
||||||
|
apic_write(APIC_LVT_ERROR, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
apic_lvt_initial_timer_count()
|
||||||
|
{
|
||||||
|
if (sX2APIC)
|
||||||
|
return x86_read_msr(IA32_MSR_APIC_INITIAL_TIMER_COUNT);
|
||||||
|
else
|
||||||
|
return apic_read(APIC_INITIAL_TIMER_COUNT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
apic_set_lvt_initial_timer_count(uint32 config)
|
||||||
|
{
|
||||||
|
if (sX2APIC)
|
||||||
|
x86_write_msr(IA32_MSR_APIC_INITIAL_TIMER_COUNT, config);
|
||||||
|
else
|
||||||
|
apic_write(APIC_INITIAL_TIMER_COUNT, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
apic_lvt_timer_divide_config()
|
||||||
|
{
|
||||||
|
if (sX2APIC)
|
||||||
|
return x86_read_msr(IA32_MSR_APIC_TIMER_DIVIDE_CONFIG);
|
||||||
|
else
|
||||||
|
return apic_read(APIC_TIMER_DIVIDE_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
apic_set_lvt_timer_divide_config(uint32 config)
|
||||||
|
{
|
||||||
|
if (sX2APIC)
|
||||||
|
x86_write_msr(IA32_MSR_APIC_TIMER_DIVIDE_CONFIG, config);
|
||||||
|
else
|
||||||
|
apic_write(APIC_TIMER_DIVIDE_CONFIG, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -71,6 +257,35 @@ apic_init(kernel_args *args)
|
||||||
if (args->arch_args.apic == NULL)
|
if (args->arch_args.apic == NULL)
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
|
|
||||||
|
if (x86_check_feature(IA32_FEATURE_EXT_X2APIC, FEATURE_EXT)) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
sLocalAPIC = args->arch_args.apic;
|
sLocalAPIC = args->arch_args.apic;
|
||||||
dprintf("mapping local apic at %p\n", sLocalAPIC);
|
dprintf("mapping local apic at %p\n", sLocalAPIC);
|
||||||
if (vm_map_physical_memory(B_SYSTEM_TEAM, "local apic", &sLocalAPIC,
|
if (vm_map_physical_memory(B_SYSTEM_TEAM, "local apic", &sLocalAPIC,
|
||||||
|
@ -89,13 +304,12 @@ status_t
|
||||||
apic_per_cpu_init(kernel_args *args, int32 cpu)
|
apic_per_cpu_init(kernel_args *args, int32 cpu)
|
||||||
{
|
{
|
||||||
dprintf("setting up apic for CPU %" B_PRId32 ": apic id %" B_PRIu32 ", "
|
dprintf("setting up apic for CPU %" B_PRId32 ": apic id %" B_PRIu32 ", "
|
||||||
"version %" B_PRIu32 "\n", cpu, apic_local_id(),
|
"version %" B_PRIu32 "\n", cpu, apic_local_id(), apic_version());
|
||||||
apic_read(APIC_VERSION));
|
|
||||||
|
|
||||||
/* set spurious interrupt vector to 0xff */
|
/* set spurious interrupt vector to 0xff */
|
||||||
uint32 config = apic_read(APIC_SPURIOUS_INTR_VECTOR) & 0xffffff00;
|
uint32 config = apic_spurious_intr_vector() & 0xffffff00;
|
||||||
config |= APIC_ENABLE | 0xff;
|
config |= APIC_ENABLE | 0xff;
|
||||||
apic_write(APIC_SPURIOUS_INTR_VECTOR, config);
|
apic_set_spurious_intr_vector(config);
|
||||||
|
|
||||||
// don't touch the LINT0/1 configuration in virtual wire mode
|
// don't touch the LINT0/1 configuration in virtual wire mode
|
||||||
// ToDo: implement support for other modes...
|
// ToDo: implement support for other modes...
|
||||||
|
@ -130,14 +344,14 @@ apic_per_cpu_init(kernel_args *args, int32 cpu)
|
||||||
apic_timer_per_cpu_init(args, cpu);
|
apic_timer_per_cpu_init(args, cpu);
|
||||||
|
|
||||||
/* setup error vector to 0xfe */
|
/* setup error vector to 0xfe */
|
||||||
config = (apic_read(APIC_LVT_ERROR) & 0xffffff00) | 0xfe;
|
config = (apic_lvt_error() & 0xffffff00) | 0xfe;
|
||||||
apic_write(APIC_LVT_ERROR, config);
|
apic_set_lvt_error(config);
|
||||||
|
|
||||||
/* accept all interrupts */
|
/* accept all interrupts */
|
||||||
config = apic_read(APIC_TASK_PRIORITY) & 0xffffff00;
|
config = apic_task_priority() & 0xffffff00;
|
||||||
apic_write(APIC_TASK_PRIORITY, config);
|
apic_set_task_priority(config);
|
||||||
|
|
||||||
config = apic_read(APIC_SPURIOUS_INTR_VECTOR);
|
config = apic_spurious_intr_vector();
|
||||||
apic_end_of_interrupt();
|
apic_end_of_interrupt();
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
|
@ -121,8 +121,8 @@ arch_smp_send_broadcast_ici(void)
|
||||||
uint32 config;
|
uint32 config;
|
||||||
cpu_status state = disable_interrupts();
|
cpu_status state = disable_interrupts();
|
||||||
|
|
||||||
config = apic_read(APIC_INTR_COMMAND_1) & APIC_INTR_COMMAND_1_MASK;
|
config = apic_intr_command_1() & APIC_INTR_COMMAND_1_MASK;
|
||||||
apic_write(APIC_INTR_COMMAND_1, config | 0xfd | APIC_DELIVERY_MODE_FIXED
|
apic_set_intr_command_1(config | 0xfd | APIC_DELIVERY_MODE_FIXED
|
||||||
| APIC_INTR_COMMAND_1_ASSERT
|
| APIC_INTR_COMMAND_1_ASSERT
|
||||||
| APIC_INTR_COMMAND_1_DEST_MODE_PHYSICAL
|
| APIC_INTR_COMMAND_1_DEST_MODE_PHYSICAL
|
||||||
| APIC_INTR_COMMAND_1_DEST_ALL_BUT_SELF);
|
| APIC_INTR_COMMAND_1_DEST_ALL_BUT_SELF);
|
||||||
|
@ -140,18 +140,18 @@ arch_smp_send_ici(int32 target_cpu)
|
||||||
|
|
||||||
state = disable_interrupts();
|
state = disable_interrupts();
|
||||||
|
|
||||||
config = apic_read(APIC_INTR_COMMAND_2) & APIC_INTR_COMMAND_2_MASK;
|
config = apic_intr_command_2() & APIC_INTR_COMMAND_2_MASK;
|
||||||
apic_write(APIC_INTR_COMMAND_2, config | sCPUAPICIds[target_cpu] << 24);
|
apic_set_intr_command_2(config | sCPUAPICIds[target_cpu] << 24);
|
||||||
|
|
||||||
config = apic_read(APIC_INTR_COMMAND_1) & APIC_INTR_COMMAND_1_MASK;
|
config = apic_intr_command_1() & APIC_INTR_COMMAND_1_MASK;
|
||||||
apic_write(APIC_INTR_COMMAND_1, config | 0xfd | APIC_DELIVERY_MODE_FIXED
|
apic_set_intr_command_1(config | 0xfd | APIC_DELIVERY_MODE_FIXED
|
||||||
| APIC_INTR_COMMAND_1_ASSERT
|
| APIC_INTR_COMMAND_1_ASSERT
|
||||||
| APIC_INTR_COMMAND_1_DEST_MODE_PHYSICAL
|
| APIC_INTR_COMMAND_1_DEST_MODE_PHYSICAL
|
||||||
| APIC_INTR_COMMAND_1_DEST_FIELD);
|
| APIC_INTR_COMMAND_1_DEST_FIELD);
|
||||||
|
|
||||||
timeout = 100000000;
|
timeout = 100000000;
|
||||||
// wait for message to be sent
|
// wait for message to be sent
|
||||||
while ((apic_read(APIC_INTR_COMMAND_1) & APIC_DELIVERY_STATUS) != 0 && --timeout != 0)
|
while ((apic_intr_command_1() & APIC_DELIVERY_STATUS) != 0 && --timeout != 0)
|
||||||
asm volatile ("pause;");
|
asm volatile ("pause;");
|
||||||
|
|
||||||
if (timeout == 0)
|
if (timeout == 0)
|
||||||
|
|
|
@ -63,18 +63,18 @@ apic_timer_set_hardware_timer(bigtime_t relativeTimeout)
|
||||||
|
|
||||||
cpu_status state = disable_interrupts();
|
cpu_status state = disable_interrupts();
|
||||||
|
|
||||||
uint32 config = apic_read(APIC_LVT_TIMER) | APIC_LVT_MASKED; // mask the timer
|
uint32 config = apic_lvt_timer() | APIC_LVT_MASKED; // mask the timer
|
||||||
apic_write(APIC_LVT_TIMER, config);
|
apic_set_lvt_timer(config);
|
||||||
|
|
||||||
apic_write(APIC_INITIAL_TIMER_COUNT, 0); // zero out the timer
|
apic_set_lvt_initial_timer_count(0); // zero out the timer
|
||||||
|
|
||||||
config = apic_read(APIC_LVT_TIMER) & ~APIC_LVT_MASKED; // unmask the timer
|
config = apic_lvt_timer() & ~APIC_LVT_MASKED; // unmask the timer
|
||||||
apic_write(APIC_LVT_TIMER, config);
|
apic_set_lvt_timer(config);
|
||||||
|
|
||||||
//TRACE_TIMER(("arch_smp_set_apic_timer: config 0x%lx, timeout %Ld, tics/sec %lu, tics %lu\n",
|
//TRACE_TIMER(("arch_smp_set_apic_timer: config 0x%lx, timeout %Ld, tics/sec %lu, tics %lu\n",
|
||||||
// config, relativeTimeout, sApicTicsPerSec, ticks));
|
// config, relativeTimeout, sApicTicsPerSec, ticks));
|
||||||
|
|
||||||
apic_write(APIC_INITIAL_TIMER_COUNT, ticks); // start it up
|
apic_set_lvt_initial_timer_count(ticks); // start it up
|
||||||
|
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
|
|
||||||
|
@ -87,11 +87,11 @@ apic_timer_clear_hardware_timer()
|
||||||
{
|
{
|
||||||
cpu_status state = disable_interrupts();
|
cpu_status state = disable_interrupts();
|
||||||
|
|
||||||
uint32 config = apic_read(APIC_LVT_TIMER) | APIC_LVT_MASKED;
|
uint32 config = apic_lvt_timer() | APIC_LVT_MASKED;
|
||||||
// mask the timer
|
// mask the timer
|
||||||
apic_write(APIC_LVT_TIMER, config);
|
apic_set_lvt_timer(config);
|
||||||
|
|
||||||
apic_write(APIC_INITIAL_TIMER_COUNT, 0); // zero out the timer
|
apic_set_lvt_initial_timer_count(0); // zero out the timer
|
||||||
|
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
@ -118,14 +118,14 @@ status_t
|
||||||
apic_timer_per_cpu_init(struct kernel_args *args, int32 cpu)
|
apic_timer_per_cpu_init(struct kernel_args *args, int32 cpu)
|
||||||
{
|
{
|
||||||
/* setup timer */
|
/* setup timer */
|
||||||
uint32 config = apic_read(APIC_LVT_TIMER) & APIC_LVT_TIMER_MASK;
|
uint32 config = apic_lvt_timer() & APIC_LVT_TIMER_MASK;
|
||||||
config |= 0xfb | APIC_LVT_MASKED; // vector 0xfb, timer masked
|
config |= 0xfb | APIC_LVT_MASKED; // vector 0xfb, timer masked
|
||||||
apic_write(APIC_LVT_TIMER, config);
|
apic_set_lvt_timer(config);
|
||||||
|
|
||||||
apic_write(APIC_INITIAL_TIMER_COUNT, 0); // zero out the clock
|
apic_set_lvt_initial_timer_count(0); // zero out the clock
|
||||||
|
|
||||||
config = apic_read(APIC_TIMER_DIVIDE_CONFIG) & 0xfffffff0;
|
config = apic_lvt_timer_divide_config() & 0xfffffff0;
|
||||||
config |= APIC_TIMER_DIVIDE_CONFIG_1; // clock division by 1
|
config |= APIC_TIMER_DIVIDE_CONFIG_1; // clock division by 1
|
||||||
apic_write(APIC_TIMER_DIVIDE_CONFIG, config);
|
apic_set_lvt_timer_divide_config(config);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue