/kernel/trunk/genarch/src/acpi/matd.c |
---|
44,8 → 44,12 |
#ifdef CONFIG_SMP |
/** Standard ISA IRQ map; can be overriden by Interrupt Source Override entries of MADT. */ |
int isa_irq_map[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; |
static void madt_l_apic_entry(struct madt_l_apic *la, __u32 index); |
static void madt_io_apic_entry(struct madt_io_apic *ioa, __u32 index); |
static void madt_intr_src_ovrd_entry(struct madt_intr_src_ovrd *override, __u32 index); |
static int madt_cmp(void * a, void * b); |
struct madt_l_apic *madt_l_apic_entries = NULL; |
79,20 → 83,22 |
static bool madt_cpu_enabled(index_t i); |
static bool madt_cpu_bootstrap(index_t i); |
static __u8 madt_cpu_apic_id(index_t i); |
static int madt_irq_to_pin(int irq); |
struct smp_config_operations madt_config_operations = { |
.cpu_count = madt_cpu_count, |
.cpu_enabled = madt_cpu_enabled, |
.cpu_bootstrap = madt_cpu_bootstrap, |
.cpu_apic_id = madt_cpu_apic_id |
.cpu_apic_id = madt_cpu_apic_id, |
.irq_to_pin = madt_irq_to_pin |
}; |
static count_t madt_cpu_count(void) |
count_t madt_cpu_count(void) |
{ |
return madt_l_apic_entry_cnt; |
} |
static bool madt_cpu_enabled(index_t i) |
bool madt_cpu_enabled(index_t i) |
{ |
ASSERT(i < madt_l_apic_entry_cnt); |
return ((struct madt_l_apic *) madt_entries_index[madt_l_apic_entry_index + i])->flags & 0x1; |
99,18 → 105,24 |
} |
static bool madt_cpu_bootstrap(index_t i) |
bool madt_cpu_bootstrap(index_t i) |
{ |
ASSERT(i < madt_l_apic_entry_cnt); |
return ((struct madt_l_apic *) madt_entries_index[madt_l_apic_entry_index + i])->apic_id == l_apic_id(); |
} |
static __u8 madt_cpu_apic_id(index_t i) |
__u8 madt_cpu_apic_id(index_t i) |
{ |
ASSERT(i < madt_l_apic_entry_cnt); |
return ((struct madt_l_apic *) madt_entries_index[madt_l_apic_entry_index + i])->apic_id; |
} |
int madt_irq_to_pin(int irq) |
{ |
ASSERT(irq < sizeof(isa_irq_map)/sizeof(int)); |
return isa_irq_map[irq]; |
} |
int madt_cmp(void * a, void * b) |
{ |
return |
154,6 → 166,8 |
madt_io_apic_entry((struct madt_io_apic *) h, index); |
break; |
case MADT_INTR_SRC_OVRD: |
madt_intr_src_ovrd_entry((struct madt_intr_src_ovrd *) h, index); |
break; |
case MADT_NMI_SRC: |
case MADT_L_APIC_NMI: |
case MADT_L_APIC_ADDR_OVRD: |
209,5 → 223,12 |
} |
} |
void madt_intr_src_ovrd_entry(struct madt_intr_src_ovrd *override, __u32 index) |
{ |
ASSERT(override->source < sizeof(isa_irq_map)/sizeof(int)); |
printf("Remapping irq%d to IO APIC pin%d\n", override->source, override->global_intr); |
isa_irq_map[override->source] = override->global_intr; |
} |
#endif /* CONFIG_SMP */ |
/kernel/trunk/generic/src/main/kinit.c |
---|
117,6 → 117,11 |
#endif /* CONFIG_SMP */ |
/* |
* At this point SMP, if present, is configured. |
*/ |
arch_post_smp_init(); |
/* |
* Create kernel console. |
*/ |
if (t = thread_create(kconsole, NULL, TASK, 0)) |
164,7 → 169,7 |
#endif /* CONFIG_TEST */ |
while (1) { |
thread_sleep(60); |
thread_sleep(1); |
printf("kinit... "); |
} |
/kernel/trunk/generic/src/main/main.c |
---|
170,7 → 170,6 |
arch_pre_smp_init(); |
smp_init(); |
arch_post_smp_init(); |
printf("config.memory_size=%dM\n", config.memory_size/(1024*1024)); |
printf("config.cpu_count=%d\n", config.cpu_count); |
/kernel/trunk/generic/src/main/kconsole.c |
---|
49,5 → 49,6 |
while (true) { |
printf("%s> ", __FUNCTION__); |
gets(stdin, buf, sizeof(buf)); |
printf("?\n"); |
} |
} |
/kernel/trunk/arch/amd64/src/amd64.c |
---|
69,7 → 69,6 |
if (config.cpu_active == 1) { |
bios_init(); |
i8042_init(); /* a20 bit */ |
i8259_init(); /* PIC */ |
i8254_init(); /* hard clock */ |
102,7 → 101,7 |
void arch_post_smp_init(void) |
{ |
trap_virtual_enable_irqs(1<<IRQ_KBD); |
i8042_init(); /* keyboard controller */ |
} |
void calibrate_delay_loop(void) |
/kernel/trunk/arch/ia32/include/smp/apic.h |
---|
114,7 → 114,56 |
#define IOAPICARB 0x02 |
#define IOREDTBL 0x10 |
/** Delivery modes. */ |
#define DELMOD_FIXED 0x0 |
#define DELMOD_LOWPRI 0x1 |
#define DELMOD_SMI 0x2 |
/* 0x3 reserved */ |
#define DELMOD_NMI 0x4 |
#define DELMOD_INIT 0x5 |
/* 0x6 reserved */ |
#define DELMOD_EXTINT 0x7 |
/** Destination modes. */ |
#define DESTMOD_PHYS 0x0 |
#define DESTMOD_LOGIC 0x1 |
/** Trigger Modes. */ |
#define TRIGMOD_EDGE 0x0 |
#define TRIGMOD_LEVEL 0x1 |
/** Interrupt Input Pin Polarities. */ |
#define POLARITY_HIGH 0x0 |
#define POLARITY_LOW 0x1 |
/** I/O Redirection Register. */ |
struct io_redirection_reg { |
union { |
__u32 lo; |
struct { |
unsigned intvec : 8; /**< Interrupt Vector. */ |
unsigned delmod : 3; /**< Delivery Mode. */ |
unsigned destmod : 1; /**< Destination mode. */ |
unsigned delivs : 1; /**< Delivery status (RO). */ |
unsigned intpol : 1; /**< Interrupt Input Pin Polarity. */ |
unsigned irr : 1; /**< Remote IRR (RO). */ |
unsigned trigger_mode : 1; /**< Trigger Mode. */ |
unsigned masked : 1; /**< Interrupt Mask. */ |
unsigned : 15; /**< Reserved. */ |
}; |
}; |
union { |
__u32 hi; |
struct { |
unsigned : 24; /**< Reserved. */ |
unsigned dest : 8; /**< Destination Field. */ |
}; |
}; |
} __attribute__ ((packed)); |
typedef struct io_redirection_reg io_redirection_reg_t; |
extern volatile __u32 *l_apic; |
extern volatile __u32 *io_apic; |
/kernel/trunk/arch/ia32/include/smp/mps.h |
---|
120,8 → 120,6 |
extern struct smp_config_operations mps_config_operations; |
extern int mps_irq_to_pin(int irq); |
extern void mps_init(void); |
extern void kmp(void *arg); |
/kernel/trunk/arch/ia32/include/smp/smp.h |
---|
32,11 → 32,15 |
#include <arch/types.h> |
#include <typedefs.h> |
/** SMP config opertaions interface. */ |
struct smp_config_operations { |
count_t (* cpu_count)(void); |
bool (* cpu_enabled)(index_t i); |
bool (*cpu_bootstrap)(index_t i); |
__u8 (*cpu_apic_id)(index_t i); |
count_t (* cpu_count)(void); /**< Return number of detected processors. */ |
bool (* cpu_enabled)(index_t i); /**< Check whether the processor of index i is enabled. */ |
bool (*cpu_bootstrap)(index_t i); /**< Check whether the processor of index i is BSP. */ |
__u8 (*cpu_apic_id)(index_t i); /**< Return APIC ID of the processor of index i. */ |
int (*irq_to_pin)(int irq); /**< Return mapping between irq and APIC pin. */ |
}; |
extern int smp_irq_to_pin(int irq); |
#endif |
/kernel/trunk/arch/ia32/src/ia32.c |
---|
56,7 → 56,6 |
if (config.cpu_active == 1) { |
bios_init(); |
i8042_init(); /* keyboard controller */ |
i8259_init(); /* PIC */ |
i8254_init(); /* hard clock */ |
89,7 → 88,7 |
void arch_post_smp_init(void) |
{ |
trap_virtual_enable_irqs(1<<IRQ_KBD); |
i8042_init(); /* keyboard controller */ |
} |
void calibrate_delay_loop(void) |
/kernel/trunk/arch/ia32/src/smp/mps.c |
---|
89,12 → 89,14 |
static bool is_cpu_enabled(index_t i); |
static bool is_bsp(index_t i); |
static __u8 get_cpu_apic_id(index_t i); |
static int mps_irq_to_pin(int irq); |
struct smp_config_operations mps_config_operations = { |
.cpu_count = get_cpu_count, |
.cpu_enabled = is_cpu_enabled, |
.cpu_bootstrap = is_bsp, |
.cpu_apic_id = get_cpu_apic_id |
.cpu_apic_id = get_cpu_apic_id, |
.irq_to_pin = mps_irq_to_pin |
}; |
count_t get_cpu_count(void) |
/kernel/trunk/arch/ia32/src/smp/smp.c |
---|
165,4 → 165,10 |
waitq_wakeup(&kmp_completion_wq, WAKEUP_FIRST); |
} |
int smp_irq_to_pin(int irq) |
{ |
ASSERT(ops != NULL); |
return ops->irq_to_pin(irq); |
} |
#endif /* CONFIG_SMP */ |
/kernel/trunk/arch/ia32/src/smp/apic.c |
---|
40,8 → 40,7 |
#ifdef CONFIG_SMP |
/* |
* This is functional, far-from-general-enough interface to the APIC. |
* Advanced Programmable Interrupt Controller for MP systems. |
* Advanced Programmable Interrupt Controller for SMP systems. |
* Tested on: |
* Bochs 2.0.2 - Bochs 2.2 with 2-8 CPUs |
* Simics 2.0.28 - Simics 2.2.14 2-4 CPUs |
82,11 → 81,12 |
*/ |
io_apic_disable_irqs(0xffff); |
trap_register(VECTOR_CLK, l_apic_timer_interrupt); |
for (i=1; i<16; i++) { |
for (i=0; i<16; i++) { |
int pin; |
if ((pin = mps_irq_to_pin(i)) != -1) |
io_apic_change_ioredtbl(pin,0xf,IVT_IRQBASE+i,LOPRI); |
if ((pin = smp_irq_to_pin(i)) != -1) { |
io_apic_change_ioredtbl(pin,0xff,IVT_IRQBASE+i,LOPRI); |
} |
} |
352,29 → 352,31 |
void io_apic_change_ioredtbl(int signal, int dest, __u8 v, int flags) |
{ |
__u32 reglo, reghi; |
io_redirection_reg_t reg; |
int dlvr = 0; |
if (flags & LOPRI) |
dlvr = 1; |
dlvr = DELMOD_LOWPRI; |
reglo = io_apic_read(IOREDTBL + signal*2); |
reghi = io_apic_read(IOREDTBL + signal*2 + 1); |
reg.lo = io_apic_read(IOREDTBL + signal*2); |
reg.hi = io_apic_read(IOREDTBL + signal*2 + 1); |
reghi &= ~0x0f000000; |
reghi |= (dest<<24); |
reg.dest = dest; |
reg.destmod = DESTMOD_LOGIC; |
reg.trigger_mode = TRIGMOD_EDGE; |
reg.intpol = POLARITY_HIGH; |
reg.delmod = dlvr; |
reg.intvec = v; |
reglo &= (~0x1ffff) | (1<<16); /* don't touch the mask */ |
reglo |= (0<<15) | (0<<13) | (0<<11) | (dlvr<<8) | v; |
io_apic_write(IOREDTBL + signal*2, reglo); |
io_apic_write(IOREDTBL + signal*2 + 1, reghi); |
io_apic_write(IOREDTBL + signal*2, reg.lo); |
io_apic_write(IOREDTBL + signal*2 + 1, reg.hi); |
} |
void io_apic_disable_irqs(__u16 irqmask) |
{ |
int i,pin; |
__u32 reglo; |
io_redirection_reg_t reg; |
int i, pin; |
for (i=0;i<16;i++) { |
if ((irqmask>>i) & 1) { |
382,11 → 384,11 |
* Mask the signal input in IO APIC if there is a |
* mapping for the respective IRQ number. |
*/ |
pin = mps_irq_to_pin(i); |
pin = smp_irq_to_pin(i); |
if (pin != -1) { |
reglo = io_apic_read(IOREDTBL + pin*2); |
reglo |= (1<<16); |
io_apic_write(IOREDTBL + pin*2,reglo); |
reg.lo = io_apic_read(IOREDTBL + pin*2); |
reg.masked = true; |
io_apic_write(IOREDTBL + pin*2, reg.lo); |
} |
} |
395,8 → 397,8 |
void io_apic_enable_irqs(__u16 irqmask) |
{ |
int i,pin; |
__u32 reglo; |
int i, pin; |
io_redirection_reg_t reg; |
for (i=0;i<16;i++) { |
if ((irqmask>>i) & 1) { |
404,11 → 406,11 |
* Unmask the signal input in IO APIC if there is a |
* mapping for the respective IRQ number. |
*/ |
pin = mps_irq_to_pin(i); |
pin = smp_irq_to_pin(i); |
if (pin != -1) { |
reglo = io_apic_read(IOREDTBL + pin*2); |
reglo &= ~(1<<16); |
io_apic_write(IOREDTBL + pin*2,reglo); |
reg.lo = io_apic_read(IOREDTBL + pin*2); |
reg.masked = false; |
io_apic_write(IOREDTBL + pin*2, reg.lo); |
} |
} |
/kernel/trunk/arch/ia32/src/drivers/i8042.c |
---|
43,6 → 43,14 |
* It takes care of low-level keyboard functions. |
*/ |
#define i8042_DATA 0x60 |
#define i8042_STATUS 0x64 |
/** Keyboard commands. */ |
#define KBD_ENABLE 0xf4 |
#define KBD_DISABLE 0xf5 |
#define KBD_ACK 0xfa |
#define SPECIAL '?' |
#define KEY_RELEASE 0x80 |
230,6 → 238,7 |
void i8042_init(void) |
{ |
trap_register(VECTOR_KBD, i8042_interrupt); |
trap_virtual_enable_irqs(1<<IRQ_KBD); |
spinlock_initialize(&keylock); |
chardev_initialize(&kbrd, &ops); |
stdin = &kbrd; |
245,7 → 254,7 |
__u8 x; |
trap_virtual_eoi(); |
x = inb(0x60); |
x = inb(i8042_DATA); |
if (x & KEY_RELEASE) |
key_released(x ^ KEY_RELEASE); |
else |