Seperate the generic (local) APIC stuff into it's own file and use it from the

other places where previously the same functionality was duplicated. Also
seperated the header which was originally arch_smp.h into apic.h and arch_smp.h
again as some of it is MP and not actually APIC.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36182 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz
2010-04-12 12:56:13 +00:00
parent fec7283a28
commit 655f3b4161
8 changed files with 301 additions and 250 deletions
@@ -6,11 +6,11 @@
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
* Distributed under the terms of the NewOS License.
*/
#ifndef _KERNEL_ARCH_x86_ARCH_APIC_H
#define _KERNEL_ARCH_x86_ARCH_APIC_H
#ifndef _KERNEL_ARCH_x86_APIC_H
#define _KERNEL_ARCH_x86_APIC_H
#define MP_FLOATING_SIGNATURE '_PM_'
#define MP_CONFIG_TABLE_SIGNATURE 'PCMP'
#include <boot/kernel_args.h>
#include <SupportDefs.h>
#define APIC_ENABLE 0x100
#define APIC_FOCUS (~(1 << 9))
@@ -71,7 +71,7 @@
// timer defines
#define APIC_LVT_TIMER_MASK 0xfffcef00
// LINT0/1 defines
// LINT0/1 defines
#define APIC_LVT_LINT_MASK 0xfffe0800
#define APIC_LVT_LINT_INPUT_POLARITY (1 << 13)
@@ -113,83 +113,13 @@
#define IPI_STOP 0x44
*/
struct mp_config_table {
uint32 signature; /* "PCMP" */
uint16 base_table_length; /* length of the base table entries and this structure */
uint8 spec_revision; /* spec supported, 1 for 1.1 or 4 for 1.4 */
uint8 checksum; /* checksum, all bytes add up to zero */
char oem[8]; /* oem identification, not null-terminated */
char product[12]; /* product name, not null-terminated */
void *oem_table; /* addr of oem-defined table, zero if none */
uint16 oem_length; /* length of oem table */
uint16 num_base_entries; /* number of entries in base table */
uint32 apic; /* address of apic */
uint16 ext_length; /* length of extended section */
uint8 ext_checksum; /* checksum of extended table entries */
uint8 reserved;
};
bool apic_available();
uint32 apic_read(uint32 offset);
void apic_write(uint32 offset, uint32 data);
uint32 apic_local_id();
void apic_end_of_interrupt();
struct mp_floating_struct {
uint32 signature; /* "_MP_" */
struct mp_config_table *config_table; /* address of mp configuration table */
uint8 config_length; /* length of the table in 16-byte units */
uint8 spec_revision; /* spec supported, 1 for 1.1 or 4 for 1.4 */
uint8 checksum; /* checksum, all bytes add up to zero */
uint8 mp_feature_1; /* mp system configuration type if no mpc */
uint8 mp_feature_2; /* imcrp */
uint8 mp_feature_3, mp_feature_4, mp_feature_5; /* reserved */
};
status_t apic_init(kernel_args *args);
status_t apic_per_cpu_init(kernel_args *args, int32 cpu);
/* base config entry types */
enum {
MP_BASE_PROCESSOR = 0,
MP_BASE_BUS,
MP_BASE_IO_APIC,
MP_BASE_IO_INTR,
MP_BASE_LOCAL_INTR,
};
struct mp_base_processor {
uint8 type;
uint8 apic_id;
uint8 apic_version;
uint8 cpu_flags;
uint32 signature; /* stepping, model, family, each four bits */
uint32 feature_flags;
uint32 res1, res2;
};
struct mp_base_ioapic {
uint8 type;
uint8 ioapic_id;
uint8 ioapic_version;
uint8 ioapic_flags;
uint32 *addr;
};
struct mp_base_bus {
uint8 type;
uint8 bus_id;
char name[6];
};
struct mp_base_interrupt {
uint8 type;
uint8 interrupt_type;
uint16 polarity : 2;
uint16 trigger_mode : 2;
uint16 _reserved : 12;
uint8 source_bus_id;
uint8 source_bus_irq;
uint8 dest_apic_id;
uint8 dest_apic_int;
};
enum {
MP_INTR_TYPE_INT = 0,
MP_INTR_TYPE_NMI,
MP_INTR_TYPE_SMI,
MP_INTR_TYPE_ExtINT,
};
#endif /* _KERNEL_ARCH_x86_ARCH_APIC_H */
#endif /* _KERNEL_ARCH_x86_APIC_H */
+102
View File
@@ -0,0 +1,102 @@
/*
* Copyright 2008, Dustin Howett, [email protected]. All rights reserved.
* Copyright 2005, Axel Dörfler, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
* Distributed under the terms of the NewOS License.
*/
#ifndef _KERNEL_ARCH_x86_ARCH_SMP_H
#define _KERNEL_ARCH_x86_ARCH_SMP_H
#define MP_FLOATING_SIGNATURE '_PM_'
#define MP_CONFIG_TABLE_SIGNATURE 'PCMP'
/*
#define IPI_CACHE_FLUSH 0x40
#define IPI_INV_TLB 0x41
#define IPI_INV_PTE 0x42
#define IPI_INV_RESCHED 0x43
#define IPI_STOP 0x44
*/
struct mp_config_table {
uint32 signature; /* "PCMP" */
uint16 base_table_length; /* length of the base table entries and this structure */
uint8 spec_revision; /* spec supported, 1 for 1.1 or 4 for 1.4 */
uint8 checksum; /* checksum, all bytes add up to zero */
char oem[8]; /* oem identification, not null-terminated */
char product[12]; /* product name, not null-terminated */
void *oem_table; /* addr of oem-defined table, zero if none */
uint16 oem_length; /* length of oem table */
uint16 num_base_entries; /* number of entries in base table */
uint32 apic; /* address of apic */
uint16 ext_length; /* length of extended section */
uint8 ext_checksum; /* checksum of extended table entries */
uint8 reserved;
};
struct mp_floating_struct {
uint32 signature; /* "_MP_" */
struct mp_config_table *config_table; /* address of mp configuration table */
uint8 config_length; /* length of the table in 16-byte units */
uint8 spec_revision; /* spec supported, 1 for 1.1 or 4 for 1.4 */
uint8 checksum; /* checksum, all bytes add up to zero */
uint8 mp_feature_1; /* mp system configuration type if no mpc */
uint8 mp_feature_2; /* imcrp */
uint8 mp_feature_3, mp_feature_4, mp_feature_5; /* reserved */
};
/* base config entry types */
enum {
MP_BASE_PROCESSOR = 0,
MP_BASE_BUS,
MP_BASE_IO_APIC,
MP_BASE_IO_INTR,
MP_BASE_LOCAL_INTR,
};
struct mp_base_processor {
uint8 type;
uint8 apic_id;
uint8 apic_version;
uint8 cpu_flags;
uint32 signature; /* stepping, model, family, each four bits */
uint32 feature_flags;
uint32 res1, res2;
};
struct mp_base_ioapic {
uint8 type;
uint8 ioapic_id;
uint8 ioapic_version;
uint8 ioapic_flags;
uint32 *addr;
};
struct mp_base_bus {
uint8 type;
uint8 bus_id;
char name[6];
};
struct mp_base_interrupt {
uint8 type;
uint8 interrupt_type;
uint16 polarity : 2;
uint16 trigger_mode : 2;
uint16 _reserved : 12;
uint8 source_bus_id;
uint8 source_bus_irq;
uint8 dest_apic_id;
uint8 dest_apic_int;
};
enum {
MP_INTR_TYPE_INT = 0,
MP_INTR_TYPE_NMI,
MP_INTR_TYPE_SMI,
MP_INTR_TYPE_ExtINT,
};
#endif /* _KERNEL_ARCH_x86_ARCH_SMP_H */
+1
View File
@@ -29,6 +29,7 @@ KernelMergeObject kernel_arch_x86.o :
arch_interrupts.S
arch_system_info.cpp
arch_user_debugger.cpp
apic.cpp
apm.cpp
bios.cpp
cpuid.S
+133
View File
@@ -0,0 +1,133 @@
/*
* Copyright 2010, Michael Lotz, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Copyright 2002-2005, Axel Dörfler, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
* Distributed under the terms of the NewOS License.
*/
#include <arch/x86/apic.h>
#include <debug.h>
#include <vm/vm.h>
#include "timers/apic_timer.h"
static void *sLocalAPIC = NULL;
bool
apic_available()
{
return sLocalAPIC != NULL;
}
uint32
apic_read(uint32 offset)
{
return *(volatile uint32 *)((char *)sLocalAPIC + offset);
}
void
apic_write(uint32 offset, uint32 data)
{
*(volatile uint32 *)((char *)sLocalAPIC + offset) = data;
}
uint32
apic_local_id()
{
return (apic_read(APIC_ID) & 0xffffffff) >> 24;
}
void
apic_end_of_interrupt()
{
apic_write(APIC_EOI, 0);
}
status_t
apic_init(kernel_args *args)
{
if (args->arch_args.apic == NULL)
return B_NO_INIT;
sLocalAPIC = args->arch_args.apic;
dprintf("mapping local apic at %p\n", sLocalAPIC);
if (vm_map_physical_memory(B_SYSTEM_TEAM, "local apic", &sLocalAPIC,
B_EXACT_ADDRESS, B_PAGE_SIZE,
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA,
args->arch_args.apic_phys, true) < 0) {
panic("mapping the local apic failed");
return B_ERROR;
}
return B_OK;
}
status_t
apic_per_cpu_init(kernel_args *args, int32 cpu)
{
dprintf("setting up apic for CPU %ld: apic id %lu, version %lu\n", cpu,
apic_local_id(), apic_read(APIC_VERSION));
/* set spurious interrupt vector to 0xff */
uint32 config = apic_read(APIC_SPURIOUS_INTR_VECTOR) & 0xffffff00;
config |= APIC_ENABLE | 0xff;
apic_write(APIC_SPURIOUS_INTR_VECTOR, config);
// don't touch the LINT0/1 configuration in virtual wire mode
// ToDo: implement support for other modes...
#if 0
if (cpu == 0) {
/* setup LINT0 as ExtINT */
config = (apic_read(APIC_LINT0) & 0xffff00ff);
config |= APIC_LVT_DM_ExtINT | APIC_LVT_IIPP | APIC_LVT_TM;
apic_write(APIC_LINT0, config);
/* setup LINT1 as NMI */
config = (apic_read(APIC_LINT1) & 0xffff00ff);
config |= APIC_LVT_DM_NMI | APIC_LVT_IIPP;
apic_write(APIC_LINT1, config);
}
if (cpu > 0) {
dprintf("LINT0: %p\n", (void *)apic_read(APIC_LINT0));
dprintf("LINT1: %p\n", (void *)apic_read(APIC_LINT1));
/* disable LINT0/1 */
config = apic_read(APIC_LINT0);
apic_write(APIC_LINT0, config | APIC_LVT_MASKED);
config = apic_read(APIC_LINT1);
apic_write(APIC_LINT1, config | APIC_LVT_MASKED);
} else {
dprintf("0: LINT0: %p\n", (void *)apic_read(APIC_LINT0));
dprintf("0: LINT1: %p\n", (void *)apic_read(APIC_LINT1));
}
#endif
apic_timer_per_cpu_init(args, cpu);
/* setup error vector to 0xfe */
config = (apic_read(APIC_LVT_ERROR) & 0xffffff00) | 0xfe;
apic_write(APIC_LVT_ERROR, config);
/* accept all interrupts */
config = apic_read(APIC_TASK_PRIORITY) & 0xffffff00;
apic_write(APIC_TASK_PRIORITY, config);
config = apic_read(APIC_SPURIOUS_INTR_VECTOR);
apic_end_of_interrupt();
return B_OK;
}
+8 -16
View File
@@ -25,7 +25,7 @@
#include <arch/user_debugger.h>
#include <arch/vm.h>
#include <arch/x86/arch_apic.h>
#include <arch/x86/apic.h>
#include <arch/x86/descriptors.h>
#include <arch/x86/vm86.h>
@@ -133,7 +133,6 @@ typedef struct ioapic_s {
static ioapic *sIOAPIC = NULL;
static uint32 sIOAPICMaxRedirectionEntry = 23;
static void *sLocalAPIC = NULL;
static uint32 sIRQToIOAPICPin[256];
@@ -470,7 +469,7 @@ ioapic_is_spurious_interrupt(int32 num)
static void
ioapic_end_of_interrupt(int32 num)
{
*(volatile uint32 *)((char *)sLocalAPIC + APIC_EOI) = 0;
apic_end_of_interrupt();
}
@@ -551,22 +550,15 @@ ioapic_init(kernel_args *args)
&ioapic_end_of_interrupt
};
// always init the local apic as it can be used for timers even if we
// don't end up using the io apic
apic_init(args);
if (args->arch_args.apic == NULL) {
dprintf("no local apic available\n");
return;
}
// always map the local apic as it can be used for timers even if we
// don't end up using the io apic
sLocalAPIC = args->arch_args.apic;
if (vm_map_physical_memory(B_SYSTEM_TEAM, "local apic", &sLocalAPIC,
B_EXACT_ADDRESS, B_PAGE_SIZE,
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA,
args->arch_args.apic_phys, true) < 0) {
panic("mapping the local apic failed");
return;
}
if (args->arch_args.ioapic == NULL) {
dprintf("no ioapic available, not using ioapics for interrupt routing\n");
return;
@@ -666,7 +658,7 @@ ioapic_init(kernel_args *args)
status = read_irq_routing_table(pciModule, acpiModule, &table);
if (status != B_OK)
return;
// configure apic interrupts assume 1:1 mapping
for (int i = 0; i < table.Count(); i++) {
irq_routing_entry& entry = table.ElementAt(i);
@@ -677,7 +669,7 @@ ioapic_init(kernel_args *args)
config |= irqDescriptor.interrupt_mode;
ioapic_configure_io_interrupt(irqDescriptor.irq, config);
}
// prefer the ioapic over the normal pic
dprintf("using ioapic for interrupt routing\n");
sCurrentPIC = &ioapicController;
+8 -83
View File
@@ -17,17 +17,14 @@
#include <arch/vm.h>
#include <arch/smp.h>
#include <timer.h>
#include <arch/x86/apic.h>
#include <arch/x86/arch_smp.h>
#include <arch/x86/smp_priv.h>
#include <arch/x86/arch_apic.h>
#include <arch/x86/timer.h>
#include <string.h>
#include <stdio.h>
#include "timers/apic.h"
//#define TRACE_ARCH_SMP
#ifdef TRACE_ARCH_SMP
@@ -36,7 +33,6 @@
# define TRACE(x) ;
#endif
static void *sLocalAPIC = NULL;
static uint32 sCPUAPICIds[B_MAX_CPU_COUNT];
static uint32 sCPUOSIds[B_MAX_CPU_COUNT];
static uint32 sAPICVersions[B_MAX_CPU_COUNT];
@@ -44,77 +40,6 @@ static uint32 sAPICVersions[B_MAX_CPU_COUNT];
extern bool gUsingIOAPIC;
extern "C" void init_sse(void);
static uint32
apic_read(uint32 offset)
{
return *(volatile uint32 *)((char *)sLocalAPIC + offset);
}
static void
apic_write(uint32 offset, uint32 data)
{
*(volatile uint32 *)((char *)sLocalAPIC + offset) = data;
}
static status_t
setup_apic(kernel_args *args, int32 cpu)
{
TRACE(("setting up the APIC for CPU %ld...\n", cpu));
TRACE((" apic id %ld, version %ld\n", apic_read(APIC_ID), apic_read(APIC_VERSION)));
/* set spurious interrupt vector to 0xff */
uint32 config = apic_read(APIC_SPURIOUS_INTR_VECTOR) & 0xffffff00;
config |= APIC_ENABLE | 0xff;
apic_write(APIC_SPURIOUS_INTR_VECTOR, config);
// don't touch the LINT0/1 configuration in virtual wire mode
// ToDo: implement support for other modes...
#if 0
if (cpu == 0) {
/* setup LINT0 as ExtINT */
config = (apic_read(APIC_LINT0) & 0xffff00ff);
config |= APIC_LVT_DM_ExtINT | APIC_LVT_IIPP | APIC_LVT_TM;
apic_write(APIC_LINT0, config);
/* setup LINT1 as NMI */
config = (apic_read(APIC_LINT1) & 0xffff00ff);
config |= APIC_LVT_DM_NMI | APIC_LVT_IIPP;
apic_write(APIC_LINT1, config);
}
if (cpu > 0) {
dprintf("LINT0: %p\n", (void *)apic_read(APIC_LINT0));
dprintf("LINT1: %p\n", (void *)apic_read(APIC_LINT1));
/* disable LINT0/1 */
config = apic_read(APIC_LINT0);
apic_write(APIC_LINT0, config | APIC_LVT_MASKED);
config = apic_read(APIC_LINT1);
apic_write(APIC_LINT1, config | APIC_LVT_MASKED);
} else {
dprintf("0: LINT0: %p\n", (void *)apic_read(APIC_LINT0));
dprintf("0: LINT1: %p\n", (void *)apic_read(APIC_LINT1));
}
#endif
apic_init_timer(args, cpu);
/* setup error vector to 0xfe */
config = (apic_read(APIC_LVT_ERROR) & 0xffffff00) | 0xfe;
apic_write(APIC_LVT_ERROR, config);
/* accept all interrupts */
config = apic_read(APIC_TASK_PRIORITY) & 0xffffff00;
apic_write(APIC_TASK_PRIORITY, config);
config = apic_read(APIC_SPURIOUS_INTR_VECTOR);
apic_write(APIC_EOI, 0);
return B_OK;
}
static int32
i386_ici_interrupt(void *data)
@@ -126,7 +51,7 @@ i386_ici_interrupt(void *data)
// if we are not using the IO APIC we need to acknowledge the
// interrupt ourselfs
if (!gUsingIOAPIC)
apic_write(APIC_EOI, 0);
apic_end_of_interrupt();
return smp_intercpu_int_handler(cpu);
}
@@ -154,7 +79,7 @@ i386_smp_error_interrupt(void *data)
// if we are not using the IO APIC we need to acknowledge the
// interrupt ourselfs
if (!gUsingIOAPIC)
apic_write(APIC_EOI, 0);
apic_end_of_interrupt();
return B_HANDLED_INTERRUPT;
}
@@ -165,10 +90,10 @@ arch_smp_init(kernel_args *args)
{
TRACE(("arch_smp_init: entry\n"));
if (args->arch_args.apic == NULL)
if (!apic_available()) {
// if we don't have an apic we can't do smp
return B_OK;
sLocalAPIC = args->arch_args.apic;
}
// setup some globals
memcpy(sCPUAPICIds, args->arch_args.cpu_apic_id, sizeof(args->arch_args.cpu_apic_id));
@@ -194,7 +119,7 @@ arch_smp_per_cpu_init(kernel_args *args, int32 cpu)
{
// set up the local apic on the current cpu
TRACE(("arch_smp_init_percpu: setting up the apic on cpu %ld\n", cpu));
setup_apic(args, cpu);
apic_per_cpu_init(args, cpu);
init_sse();
@@ -7,6 +7,6 @@
#include <SupportDefs.h>
status_t apic_init_timer(struct kernel_args *args, int32 cpu);
status_t apic_timer_per_cpu_init(struct kernel_args *args, int32 cpu);
#endif /* _KERNEL_ARCH_x86_TIMERS_APIC_H */
+35 -67
View File
@@ -11,62 +11,47 @@
#include <arch/x86/timer.h>
#include <int.h>
#include <arch/x86/arch_apic.h>
#include <arch/x86/apic.h>
#include <arch/cpu.h>
#include <arch/smp.h>
#include "apic.h"
#include "apic_timer.h"
/* Method Prototypes */
static int apic_get_priority();
static status_t apic_set_hardware_timer(bigtime_t relativeTimeout);
static status_t apic_clear_hardware_timer();
static status_t apic_init(struct kernel_args *args);
static int apic_timer_get_priority();
static status_t apic_timer_set_hardware_timer(bigtime_t relativeTimeout);
static status_t apic_timer_clear_hardware_timer();
static status_t apic_timer_init(struct kernel_args *args);
static void *sApicPtr = NULL;
static uint32 sApicTicsPerSec = 0;
extern bool gUsingIOAPIC;
struct timer_info gAPICTimer = {
"APIC",
&apic_get_priority,
&apic_set_hardware_timer,
&apic_clear_hardware_timer,
&apic_init
&apic_timer_get_priority,
&apic_timer_set_hardware_timer,
&apic_timer_clear_hardware_timer,
&apic_timer_init
};
static int
apic_get_priority()
apic_timer_get_priority()
{
return 3;
}
static uint32
_apic_read(uint32 offset)
{
return *(volatile uint32 *)((char *)sApicPtr + offset);
}
static void
_apic_write(uint32 offset, uint32 data)
{
*(volatile uint32 *)((char *)sApicPtr + offset) = data;
}
static int32
apic_timer_interrupt(void *data)
{
// if we are not using the IO APIC we need to acknowledge the
// interrupt ourselfs
if (!gUsingIOAPIC)
_apic_write(APIC_EOI, 0);
apic_end_of_interrupt();
return timer_interrupt();
}
@@ -75,11 +60,8 @@ apic_timer_interrupt(void *data)
#define MIN_TIMEOUT 1
static status_t
apic_set_hardware_timer(bigtime_t relativeTimeout)
apic_timer_set_hardware_timer(bigtime_t relativeTimeout)
{
if (sApicPtr == NULL)
return B_ERROR;
if (relativeTimeout < MIN_TIMEOUT)
relativeTimeout = MIN_TIMEOUT;
@@ -88,18 +70,18 @@ apic_set_hardware_timer(bigtime_t relativeTimeout)
cpu_status state = disable_interrupts();
uint32 config = _apic_read(APIC_LVT_TIMER) | APIC_LVT_MASKED; // mask the timer
_apic_write(APIC_LVT_TIMER, config);
uint32 config = apic_read(APIC_LVT_TIMER) | APIC_LVT_MASKED; // mask the timer
apic_write(APIC_LVT_TIMER, config);
_apic_write(APIC_INITIAL_TIMER_COUNT, 0); // zero out the timer
apic_write(APIC_INITIAL_TIMER_COUNT, 0); // zero out the timer
config = _apic_read(APIC_LVT_TIMER) & ~APIC_LVT_MASKED; // unmask the timer
_apic_write(APIC_LVT_TIMER, config);
config = apic_read(APIC_LVT_TIMER) & ~APIC_LVT_MASKED; // unmask the timer
apic_write(APIC_LVT_TIMER, config);
//TRACE_TIMER(("arch_smp_set_apic_timer: config 0x%lx, timeout %Ld, tics/sec %lu, tics %lu\n",
// config, relativeTimeout, sApicTicsPerSec, ticks));
_apic_write(APIC_INITIAL_TIMER_COUNT, ticks); // start it up
apic_write(APIC_INITIAL_TIMER_COUNT, ticks); // start it up
restore_interrupts(state);
@@ -108,18 +90,15 @@ apic_set_hardware_timer(bigtime_t relativeTimeout)
static status_t
apic_clear_hardware_timer()
apic_timer_clear_hardware_timer()
{
if (sApicPtr == NULL)
return B_ERROR;
cpu_status state = disable_interrupts();
uint32 config = _apic_read(APIC_LVT_TIMER) | APIC_LVT_MASKED;
uint32 config = apic_read(APIC_LVT_TIMER) | APIC_LVT_MASKED;
// mask the timer
_apic_write(APIC_LVT_TIMER, config);
apic_write(APIC_LVT_TIMER, config);
_apic_write(APIC_INITIAL_TIMER_COUNT, 0); // zero out the timer
apic_write(APIC_INITIAL_TIMER_COUNT, 0); // zero out the timer
restore_interrupts(state);
return B_OK;
@@ -127,42 +106,31 @@ apic_clear_hardware_timer()
static status_t
apic_init(struct kernel_args *args)
apic_timer_init(struct kernel_args *args)
{
/* If we're in this method, arch_smp called the special init function.
Therefore, if we got here with sApicPtr NULL, there is no APIC! */
if (sApicPtr == NULL)
if (!apic_available())
return B_ERROR;
sApicTicsPerSec = args->arch_args.apic_time_cv_factor;
install_io_interrupt_handler(0xfb - ARCH_INTERRUPT_BASE,
&apic_timer_interrupt, NULL, B_NO_LOCK_VECTOR);
return B_OK;
}
status_t
apic_init_timer(struct kernel_args *args, int32 cpu)
apic_timer_per_cpu_init(struct kernel_args *args, int32 cpu)
{
if (args->arch_args.apic == NULL)
return B_ERROR;
/* This is in place of apic_preinit; if we're not already initialized,
register the interrupt handler and set the pointers */
if (sApicPtr == NULL) {
sApicPtr = (void *)args->arch_args.apic;
sApicTicsPerSec = args->arch_args.apic_time_cv_factor;
install_io_interrupt_handler(0xfb - ARCH_INTERRUPT_BASE,
&apic_timer_interrupt, NULL, B_NO_LOCK_VECTOR);
}
/* setup timer */
uint32 config = _apic_read(APIC_LVT_TIMER) & APIC_LVT_TIMER_MASK;
uint32 config = apic_read(APIC_LVT_TIMER) & APIC_LVT_TIMER_MASK;
config |= 0xfb | APIC_LVT_MASKED; // vector 0xfb, timer masked
_apic_write(APIC_LVT_TIMER, config);
apic_write(APIC_LVT_TIMER, config);
_apic_write(APIC_INITIAL_TIMER_COUNT, 0); // zero out the clock
apic_write(APIC_INITIAL_TIMER_COUNT, 0); // zero out the clock
config = _apic_read(APIC_TIMER_DIVIDE_CONFIG) & 0xfffffff0;
config = apic_read(APIC_TIMER_DIVIDE_CONFIG) & 0xfffffff0;
config |= APIC_TIMER_DIVIDE_CONFIG_1; // clock division by 1
_apic_write(APIC_TIMER_DIVIDE_CONFIG, config);
apic_write(APIC_TIMER_DIVIDE_CONFIG, config);
return B_OK;
}