/SPARTAN/trunk/arch/ia32/src/delay.s |
---|
0,0 → 1,54 |
# |
# Copyright (C) 2001-2004 Jakub Jermar |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
# |
# Micro second delay loop functions. |
# |
.text |
.global asm_delay_loop |
.global asm_fake_loop |
asm_delay_loop: |
pushl %ecx |
movl 8(%esp),%ecx # move argument to %ecx |
0: lahf |
dec %ecx |
jnz 0b |
popl %ecx |
ret |
asm_fake_loop: |
pushl %ecx |
movl 8(%esp),%ecx # move argument to %ecx |
0: lahf |
dec %ecx |
jz 0b |
popl %ecx |
ret |
/SPARTAN/trunk/arch/ia32/src/ia32.c |
---|
0,0 → 1,66 |
/* |
* Copyright (C) 2001-2004 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <arch.h> |
#include <arch/types.h> |
#include <typedefs.h> |
#include <arch/pm.h> |
#include <arch/ega.h> |
#include <arch/i8042.h> |
#include <arch/i8254.h> |
#include <arch/i8259.h> |
#include <arch/context.h> |
#include <config.h> |
#include <arch/interrupt.h> |
void arch_init(void) |
{ |
pm_init(); |
if (config.cpu_active == 1) { |
ega_init(); /* video */ |
i8042_init(); /* a20 bit */ |
i8259_init(); /* PIC */ |
i8254_init(); /* hard clock */ |
trap_register(VECTOR_SYSCALL, syscall); |
} |
} |
void calibrate_delay_loop(void) |
{ |
i8254_calibrate_delay_loop(); |
i8254_normal_operation(); |
} |
/SPARTAN/trunk/arch/ia32/src/smp/ap.S |
---|
0,0 → 1,74 |
# |
# Copyright (C) 2001-2004 Jakub Jermar |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
# |
# Init code for application processors. |
# |
.text |
#ifdef __SMP__ |
.global ap_boot |
KTEXT=8 |
KDATA=16 |
# This piece of code is real-mode and is meant to be alligned at 4K boundary. |
# The requirement for such an alignment comes from MP Specification's STARTUP IPI |
# requirements. |
.align 4096 |
ap_boot: |
.code16 |
cli |
xorw %ax,%ax |
movw %ax,%ds |
lgdt gdtr |
movl %cr0,%eax |
orl $1,%eax |
movl %eax,%cr0 |
ljmp $KTEXT,$jump_to_kernel |
# this is where the AP enters the kernel space |
jump_to_kernel: |
.code32 |
movw $KDATA,%ax |
movw %ax,%ds |
movw %ax,%es |
movw %ax,%ss |
movl $ctx,%eax |
movl (%eax),%esp |
lidt idtr |
ljmp $KTEXT,$main_ap |
#endif /* __SMP__ */ |
/SPARTAN/trunk/arch/ia32/src/smp/apic.c |
---|
0,0 → 1,389 |
/* |
* Copyright (C) 2001-2004 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#ifdef __SMP__ |
#include <arch/types.h> |
#include <arch/apic.h> |
#include <arch/ap.h> |
#include <mm/page.h> |
#include <time/delay.h> |
#include <arch/interrupt.h> |
#include <print.h> |
#include <arch/mp.h> |
#include <arch/asm.h> |
#include <arch.h> |
/* |
* This is functional, far-from-general-enough interface to the APIC. |
* Advanced Programmable Interrupt Controller for MP systems. |
* Tested on: |
* Bochs 2.0.2 with 2-8 CPUs |
* ASUS P/I-P65UP5 + ASUS C-P55T2D REV. 1.41 with 2x 200Mhz Pentium CPUs |
*/ |
/* |
* These variables either stay configured as initilalized, or are changed by |
* the MP configuration code. |
* |
* Pay special attention to the volatile keyword. Without it, gcc -O2 would |
* optimize the code too much and accesses to l_apic and io_apic, that must |
* always be 32-bit, would use byte oriented instructions. |
*/ |
volatile __u32 *l_apic = (__u32 *) 0xfee00000; |
volatile __u32 *io_apic = (__u32 *) 0xfec00000; |
__u32 apic_id_mask = 0; |
int apic_poll_errors(void); |
void apic_init(void) |
{ |
__u32 tmp, id, i; |
trap_register(VECTOR_APIC_SPUR, apic_spurious); |
enable_irqs_function = io_apic_enable_irqs; |
disable_irqs_function = io_apic_disable_irqs; |
eoi_function = l_apic_eoi; |
/* |
* Configure interrupt routing. |
* IRQ 0 remains masked as the time signal is generated by l_apic's themselves. |
* Other interrupts will be forwarded to the lowest priority CPU. |
*/ |
io_apic_disable_irqs(0xffff); |
trap_register(VECTOR_CLK, l_apic_timer_interrupt); |
for (i=1; i<16; i++) { |
int pin; |
if ((pin = mp_irq_to_pin(i)) != -1) |
io_apic_change_ioredtbl(pin,0xf,IVT_IRQBASE+i,LOPRI); |
} |
/* |
* Ensure that io_apic has unique ID. |
*/ |
tmp = io_apic_read(IOAPICID); |
id = (tmp >> 24) & 0xf; |
if ((1<<id) & apic_id_mask) { |
int i; |
for (i=0; i<15; i++) { |
if (!((1<<i) & apic_id_mask)) { |
io_apic_write(IOAPICID, (tmp & (~(0xf<<24))) | (i<<24)); |
break; |
} |
} |
} |
/* |
* Configure the BSP's lapic. |
*/ |
l_apic_init(); |
l_apic_debug(); |
} |
void apic_spurious(__u8 n, __u32 stack[]) |
{ |
printf("cpu%d: APIC spurious interrupt\n", the->cpu->id); |
} |
int apic_poll_errors(void) |
{ |
__u32 esr; |
esr = l_apic[ESR] & ~ESRClear; |
if ((esr>>0) & 1) |
printf("Send CS Error\n"); |
if ((esr>>1) & 1) |
printf("Receive CS Error\n"); |
if ((esr>>2) & 1) |
printf("Send Accept Error\n"); |
if ((esr>>3) & 1) |
printf("Receive Accept Error\n"); |
if ((esr>>5) & 1) |
printf("Send Illegal Vector\n"); |
if ((esr>>6) & 1) |
printf("Received Illegal Vector\n"); |
if ((esr>>7) & 1) |
printf("Illegal Register Address\n"); |
return !esr; |
} |
/* |
* Universal Start-up Algorithm for bringing up the AP processors. |
*/ |
int l_apic_send_init_ipi(__u8 apicid) |
{ |
__u32 lo, hi; |
int i; |
/* |
* Read the ICR register in and zero all non-reserved fields. |
*/ |
lo = l_apic[ICRlo] & ICRloClear; |
hi = l_apic[ICRhi] & ICRhiClear; |
lo |= DLVRMODE_INIT | DESTMODE_PHYS | LEVEL_ASSERT | SHORTHAND_DEST | TRGRMODE_LEVEL; |
hi |= apicid << 24; |
l_apic[ICRhi] = hi; |
l_apic[ICRlo] = lo; |
/* |
* According to MP Specification, 20us should be enough to |
* deliver the IPI. |
*/ |
delay(20); |
if (!apic_poll_errors()) return 0; |
lo = l_apic[ICRlo] & ICRloClear; |
if (lo & SEND_PENDING) |
printf("IPI is pending.\n"); |
l_apic[ICRlo] = lo | DLVRMODE_INIT | DESTMODE_PHYS | LEVEL_DEASSERT | SHORTHAND_DEST | TRGRMODE_LEVEL; |
/* |
* Wait 10ms as MP Specification specifies. |
*/ |
delay(10000); |
/* |
* MP specification says this should not be done for 82489DX-based |
* l_apic's. However, everything is ok as long as STARTUP IPI is ignored |
* by 8249DX. |
*/ |
for (i = 0; i < 2; i++) { |
lo = l_apic[ICRlo] & ICRloClear; |
lo |= ((__address) ap_boot) / 4096; /* calculate the reset vector */ |
l_apic[ICRlo] = lo | DLVRMODE_STUP | DESTMODE_PHYS | LEVEL_ASSERT | SHORTHAND_DEST | TRGRMODE_LEVEL; |
delay(200); |
} |
return apic_poll_errors(); |
} |
void l_apic_init(void) |
{ |
__u32 tmp, t1, t2; |
l_apic[LVT_Err] |= (1<<16); |
l_apic[LVT_LINT0] |= (1<<16); |
l_apic[LVT_LINT1] |= (1<<16); |
tmp = l_apic[SVR] & SVRClear; |
l_apic[SVR] = tmp | (1<<8) | (VECTOR_APIC_SPUR); |
l_apic[TPR] &= TPRClear; |
if (the->cpu->arch.family >= 6) |
enable_l_apic_in_msr(); |
tmp = l_apic[ICRlo] & ICRloClear; |
l_apic[ICRlo] = tmp | DLVRMODE_INIT | DESTMODE_PHYS | LEVEL_DEASSERT | SHORTHAND_INCL | TRGRMODE_LEVEL; |
/* |
* Program the timer for periodic mode and respective vector. |
*/ |
l_apic[TDCR] &= TDCRClear; |
l_apic[TDCR] |= 0xb; |
tmp = l_apic[LVT_Tm] | (1<<17) | (VECTOR_CLK); |
l_apic[LVT_Tm] = tmp & ~(1<<16); |
t1 = l_apic[CCRT]; |
l_apic[ICRT] = 0xffffffff; |
while (l_apic[CCRT] == t1) |
; |
t1 = l_apic[CCRT]; |
delay(1000); |
t2 = l_apic[CCRT]; |
l_apic[ICRT] = t1-t2; |
} |
void l_apic_eoi(void) |
{ |
l_apic[EOI] = 0; |
} |
void l_apic_debug(void) |
{ |
#ifdef LAPIC_VERBOSE |
int i, lint; |
printf("LVT on cpu%d, LAPIC ID: %d\n", the->cpu->id, (l_apic[L_APIC_ID] >> 24)&0xf); |
printf("LVT_Tm: "); |
if (l_apic[LVT_Tm] & (1<<17)) printf("periodic"); else printf("one-shot"); putchar(','); |
if (l_apic[LVT_Tm] & (1<<16)) printf("masked"); else printf("not masked"); putchar(','); |
if (l_apic[LVT_Tm] & (1<<12)) printf("send pending"); else printf("idle"); putchar(','); |
printf("%B\n", l_apic[LVT_Tm] & 0xff); |
for (i=0; i<2; i++) { |
lint = i ? LVT_LINT1 : LVT_LINT0; |
printf("LVT_LINT%d: ", i); |
if (l_apic[lint] & (1<<16)) printf("masked"); else printf("not masked"); putchar(','); |
if (l_apic[lint] & (1<<15)) printf("level"); else printf("edge"); putchar(','); |
printf("%d", l_apic[lint] & (1<<14)); putchar(','); |
printf("%d", l_apic[lint] & (1<<13)); putchar(','); |
if (l_apic[lint] & (1<<12)) printf("send pending"); else printf("idle"); putchar(','); |
switch ((l_apic[lint]>>8)&7) { |
case 0: printf("fixed"); break; |
case 4: printf("NMI"); break; |
case 7: printf("ExtINT"); break; |
} |
putchar(','); |
printf("%B\n", l_apic[lint] & 0xff); |
} |
printf("LVT_Err: "); |
if (l_apic[LVT_Err] & (1<<16)) printf("masked"); else printf("not masked"); putchar(','); |
if (l_apic[LVT_Err] & (1<<12)) printf("send pending"); else printf("idle"); putchar(','); |
printf("%B\n", l_apic[LVT_Err] & 0xff); |
/* |
* This register is supported only on P6 and higher. |
*/ |
if (the->cpu->family > 5) { |
printf("LVT_PCINT: "); |
if (l_apic[LVT_PCINT] & (1<<16)) printf("masked"); else printf("not masked"); putchar(','); |
if (l_apic[LVT_PCINT] & (1<<12)) printf("send pending"); else printf("idle"); putchar(','); |
switch ((l_apic[LVT_PCINT] >> 8)&7) { |
case 0: printf("fixed"); break; |
case 4: printf("NMI"); break; |
case 7: printf("ExtINT"); break; |
} |
putchar(','); |
printf("%B\n", l_apic[LVT_PCINT] & 0xff); |
} |
#endif |
} |
void l_apic_timer_interrupt(__u8 n, __u32 stack[]) |
{ |
l_apic_eoi(); |
clock(); |
} |
__u32 io_apic_read(__u8 address) |
{ |
__u32 tmp; |
tmp = io_apic[IOREGSEL] & ~0xf; |
io_apic[IOREGSEL] = tmp | address; |
return io_apic[IOWIN]; |
} |
void io_apic_write(__u8 address, __u32 x) |
{ |
__u32 tmp; |
tmp = io_apic[IOREGSEL] & ~0xf; |
io_apic[IOREGSEL] = tmp | address; |
io_apic[IOWIN] = x; |
} |
void io_apic_change_ioredtbl(int signal, int dest, __u8 v, int flags) |
{ |
__u32 reglo, reghi; |
int dlvr = 0; |
if (flags & LOPRI) |
dlvr = 1; |
reglo = io_apic_read(IOREDTBL + signal*2); |
reghi = io_apic_read(IOREDTBL + signal*2 + 1); |
reghi &= ~0x0f000000; |
reghi |= (dest<<24); |
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); |
} |
void io_apic_disable_irqs(__u16 irqmask) |
{ |
int i,pin; |
__u32 reglo; |
for (i=0;i<16;i++) { |
if ((irqmask>>i) & 1) { |
/* |
* Mask the signal input in IO APIC if there is a |
* mapping for the respective IRQ number. |
*/ |
pin = mp_irq_to_pin(i); |
if (pin != -1) { |
reglo = io_apic_read(IOREDTBL + pin*2); |
reglo |= (1<<16); |
io_apic_write(IOREDTBL + pin*2,reglo); |
} |
} |
} |
} |
void io_apic_enable_irqs(__u16 irqmask) |
{ |
int i,pin; |
__u32 reglo; |
for (i=0;i<16;i++) { |
if ((irqmask>>i) & 1) { |
/* |
* Unmask the signal input in IO APIC if there is a |
* mapping for the respective IRQ number. |
*/ |
pin = mp_irq_to_pin(i); |
if (pin != -1) { |
reglo = io_apic_read(IOREDTBL + pin*2); |
reglo &= ~(1<<16); |
io_apic_write(IOREDTBL + pin*2,reglo); |
} |
} |
} |
} |
#endif /* __SMP__ */ |
/SPARTAN/trunk/arch/ia32/src/smp/atomic.S |
---|
0,0 → 1,90 |
# |
# Copyright (C) 2001-2004 Jakub Jermar |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
.text |
.global atomic_inc |
atomic_inc: |
pushl %ebx |
movl 8(%esp),%ebx |
lock incl (%ebx) |
popl %ebx |
ret |
.global atomic_dec |
atomic_dec: |
pushl %ebx |
movl 8(%esp),%ebx |
lock decl (%ebx) |
popl %ebx |
ret |
#ifdef __SMP__ |
.global test_and_set |
.global spinlock_arch |
test_and_set: |
pushl %ebx |
movl 8(%esp),%ebx |
movl $1,%eax |
xchgl %eax,(%ebx) # xchg implicitly turns on the LOCK signal |
popl %ebx |
ret |
# |
# This is a bus-and-hyperthreading-friendly implementation of spinlock |
# |
spinlock_arch: |
pushl %eax |
pushl %ebx |
movl 12(%esp),%ebx |
0: |
#ifdef __HT__ |
pause # Pentium 4's with HT love this instruction |
#endif |
movl (%ebx),%eax |
testl %eax,%eax |
jnz 0b # lightweight looping while it is locked |
incl %eax |
xchgl %eax,(%ebx) # now use the atomic operation |
testl %eax,%eax |
jnz 0b |
popl %ebx |
popl %eax |
ret |
#endif |
/SPARTAN/trunk/arch/ia32/src/smp/mp.c |
---|
0,0 → 1,533 |
/* |
* Copyright (C) 2001-2004 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#ifdef __SMP__ |
#include <arch/mp.h> |
#include <arch/ap.h> |
#include <arch/pm.h> |
#include <config.h> |
#include <print.h> |
#include <panic.h> |
#include <arch/apic.h> |
#include <func.h> |
#include <arch/types.h> |
#include <typedefs.h> |
#include <synch/waitq.h> |
#include <time/delay.h> |
#include <mm/heap.h> |
#include <mm/page.h> |
#include <mm/frame.h> |
#include <cpu.h> |
#include <arch/i8259.h> |
#include <arch/asm.h> |
/* |
* Multi-Processor Specification detection code. |
*/ |
#define FS_SIGNATURE 0x5f504d5f |
#define CT_SIGNATURE 0x504d4350 |
int mp_fs_check(__u8 *base); |
int mp_ct_check(void); |
int configure_via_ct(void); |
int configure_via_default(__u8 n); |
int ct_processor_entry(struct __processor_entry *pr); |
void ct_bus_entry(struct __bus_entry *bus); |
void ct_io_apic_entry(struct __io_apic_entry *ioa); |
void ct_io_intr_entry(struct __io_intr_entry *iointr); |
void ct_l_intr_entry(struct __l_intr_entry *lintr); |
void ct_extended_entries(void); |
static struct __mpfs *fs; |
static struct __mpct *ct; |
struct __processor_entry *processor_entries = NULL; |
struct __bus_entry *bus_entries = NULL; |
struct __io_apic_entry *io_apic_entries = NULL; |
struct __io_intr_entry *io_intr_entries = NULL; |
struct __l_intr_entry *l_intr_entries = NULL; |
int processor_entry_cnt = 0; |
int bus_entry_cnt = 0; |
int io_apic_entry_cnt = 0; |
int io_intr_entry_cnt = 0; |
int l_intr_entry_cnt = 0; |
waitq_t ap_completion_wq; |
waitq_t kmp_completion_wq; |
/* |
* Used to check the integrity of the MP Floating Structure. |
*/ |
int mp_fs_check(__u8 *base) |
{ |
int i; |
__u8 sum; |
for (i = 0, sum = 0; i < 16; i++) |
sum += base[i]; |
return !sum; |
} |
/* |
* Used to check the integrity of the MP Configuration Table. |
*/ |
int mp_ct_check(void) |
{ |
__u8 *base = (__u8 *) ct; |
__u8 *ext = base + ct->base_table_length; |
__u8 sum; |
int i; |
/* count the checksum for the base table */ |
for (i=0,sum=0; i < ct->base_table_length; i++) |
sum += base[i]; |
if (sum) |
return 0; |
/* count the checksum for the extended table */ |
for (i=0,sum=0; i < ct->ext_table_length; i++) |
sum += ext[i]; |
return !sum; |
} |
void mp_init(void) |
{ |
__address addr, frame; |
int cnt, n; |
/* |
* First place to search the MP Floating Pointer Structure is the Extended |
* BIOS Data Area. We have to read EBDA segment address from the BIOS Data |
* Area. Unfortunatelly, this memory is in page 0, which has intentionally no |
* mapping. |
*/ |
frame = frame_alloc(FRAME_KA); |
map_page_to_frame(frame,0,PAGE_CACHEABLE,0); |
addr = *((__u16 *) (frame + 0x40e)) * 16; |
map_page_to_frame(frame,frame,PAGE_CACHEABLE,0); |
frame_free(frame); |
/* |
* EBDA can be undefined. In that case addr would be 0. |
*/ |
if (addr >= 0x1000) { |
cnt = 1024; |
while (addr = __u32_search(addr,cnt,FS_SIGNATURE)) { |
if (mp_fs_check((__u8 *) addr)) |
goto fs_found; |
addr++; |
cnt--; |
} |
} |
/* |
* Second place where the MP Floating Pointer Structure may live is the last |
* kilobyte of base memory. |
*/ |
addr = 639*1024; |
cnt = 1024; |
while (addr = __u32_search(addr,cnt,FS_SIGNATURE)) { |
if (mp_fs_check((__u8 *) addr)) |
goto fs_found; |
addr++; |
cnt--; |
} |
/* |
* As the last resort, MP Floating Pointer Structure is searched in the BIOS |
* ROM. |
*/ |
addr = 0xf0000; |
cnt = 64*1024; |
while (addr = __u32_search(addr,cnt,FS_SIGNATURE)) { |
if (mp_fs_check((__u8 *) addr)) |
goto fs_found; |
addr++; |
cnt--; |
} |
return; |
fs_found: |
printf("%L: MP Floating Pointer Structure\n", addr); |
fs = (struct __mpfs *) addr; |
frame_not_free((__address) fs); |
if (fs->config_type == 0 && fs->configuration_table) { |
if (fs->mpfib2 >> 7) { |
printf("mp_init: PIC mode not supported\n"); |
return; |
} |
ct = fs->configuration_table; |
frame_not_free((__address) ct); |
config.cpu_count = configure_via_ct(); |
} |
else |
config.cpu_count = configure_via_default(fs->config_type); |
if (config.cpu_count > 1) { |
map_page_to_frame((__address) l_apic, (__address) l_apic, PAGE_NOT_CACHEABLE, 0); |
} |
/* |
* Must be initialized outside the kmp thread, since it is waited |
* on before the kmp thread is created. |
*/ |
waitq_initialize(&kmp_completion_wq); |
return; |
} |
int configure_via_ct(void) |
{ |
__u8 *cur; |
int i, cnt; |
if (ct->signature != CT_SIGNATURE) { |
printf("configure_via_ct: bad ct->signature\n"); |
return 1; |
} |
if (!mp_ct_check()) { |
printf("configure_via_ct: bad ct checksum\n"); |
return 1; |
} |
if (ct->oem_table) { |
printf("configure_via_ct: ct->oem_table not supported\n"); |
return 1; |
} |
l_apic = ct->l_apic; |
cnt = 0; |
cur = &ct->base_table[0]; |
for (i=0; i < ct->entry_count; i++) { |
switch (*cur) { |
/* Processor entry */ |
case 0: |
processor_entries = processor_entries ? processor_entries : (struct __processor_entry *) cur; |
processor_entry_cnt++; |
cnt += ct_processor_entry((struct __processor_entry *) cur); |
cur += 20; |
break; |
/* Bus entry */ |
case 1: |
bus_entries = bus_entries ? bus_entries : (struct __bus_entry *) cur; |
bus_entry_cnt++; |
ct_bus_entry((struct __bus_entry *) cur); |
cur += 8; |
break; |
/* I/O Apic */ |
case 2: |
io_apic_entries = io_apic_entries ? io_apic_entries : (struct __io_apic_entry *) cur; |
io_apic_entry_cnt++; |
ct_io_apic_entry((struct __io_apic_entry *) cur); |
cur += 8; |
break; |
/* I/O Interrupt Assignment */ |
case 3: |
io_intr_entries = io_intr_entries ? io_intr_entries : (struct __io_intr_entry *) cur; |
io_intr_entry_cnt++; |
ct_io_intr_entry((struct __io_intr_entry *) cur); |
cur += 8; |
break; |
/* Local Interrupt Assignment */ |
case 4: |
l_intr_entries = l_intr_entries ? l_intr_entries : (struct __l_intr_entry *) cur; |
l_intr_entry_cnt++; |
ct_l_intr_entry((struct __l_intr_entry *) cur); |
cur += 8; |
break; |
default: |
/* |
* Something is wrong. Fallback to UP mode. |
*/ |
printf("configure_via_ct: ct badness\n"); |
return 1; |
} |
} |
/* |
* Process extended entries. |
*/ |
ct_extended_entries(); |
return cnt; |
} |
int configure_via_default(__u8 n) |
{ |
/* |
* Not yet implemented. |
*/ |
printf("configure_via_default: not supported\n"); |
return 1; |
} |
int ct_processor_entry(struct __processor_entry *pr) |
{ |
/* |
* Ignore processors which are not marked enabled. |
*/ |
if ((pr->cpu_flags & (1<<0)) == 0) |
return 0; |
apic_id_mask |= (1<<pr->l_apic_id); |
return 1; |
} |
void ct_bus_entry(struct __bus_entry *bus) |
{ |
#ifdef MPCT_VERBOSE |
char buf[7]; |
memcopy((__address) bus->bus_type, (__address) buf,6); |
buf[6] = 0; |
printf("bus%d: %s\n", bus->bus_id, buf); |
#endif |
} |
void ct_io_apic_entry(struct __io_apic_entry *ioa) |
{ |
static int io_apic_count = 0; |
/* this ioapic is marked unusable */ |
if (ioa->io_apic_flags & 1 == 0) |
return; |
if (io_apic_count++ > 0) { |
/* |
* Multiple IO APIC's are currently not supported. |
*/ |
return; |
} |
map_page_to_frame((__address) ioa->io_apic, (__address) ioa->io_apic, PAGE_NOT_CACHEABLE, 0); |
io_apic = ioa->io_apic; |
} |
//#define MPCT_VERBOSE |
void ct_io_intr_entry(struct __io_intr_entry *iointr) |
{ |
#ifdef MPCT_VERBOSE |
switch (iointr->intr_type) { |
case 0: printf("INT"); break; |
case 1: printf("NMI"); break; |
case 2: printf("SMI"); break; |
case 3: printf("ExtINT"); break; |
} |
putchar(','); |
switch (iointr->poel&3) { |
case 0: printf("bus-like"); break; |
case 1: printf("active high"); break; |
case 2: printf("reserved"); break; |
case 3: printf("active low"); break; |
} |
putchar(','); |
switch ((iointr->poel>>2)&3) { |
case 0: printf("bus-like"); break; |
case 1: printf("edge-triggered"); break; |
case 2: printf("reserved"); break; |
case 3: printf("level-triggered"); break; |
} |
putchar(','); |
printf("bus%d,irq%d", iointr->src_bus_id, iointr->src_bus_irq); |
putchar(','); |
printf("io_apic%d,pin%d", iointr->dst_io_apic_id, iointr->dst_io_apic_pin); |
putchar('\n'); |
#endif |
} |
void ct_l_intr_entry(struct __l_intr_entry *lintr) |
{ |
#ifdef MPCT_VERBOSE |
switch (lintr->intr_type) { |
case 0: printf("INT"); break; |
case 1: printf("NMI"); break; |
case 2: printf("SMI"); break; |
case 3: printf("ExtINT"); break; |
} |
putchar(','); |
switch (lintr->poel&3) { |
case 0: printf("bus-like"); break; |
case 1: printf("active high"); break; |
case 2: printf("reserved"); break; |
case 3: printf("active low"); break; |
} |
putchar(','); |
switch ((lintr->poel>>2)&3) { |
case 0: printf("bus-like"); break; |
case 1: printf("edge-triggered"); break; |
case 2: printf("reserved"); break; |
case 3: printf("level-triggered"); break; |
} |
putchar(','); |
printf("bus%d,irq%d", lintr->src_bus_id, lintr->src_bus_irq); |
putchar(','); |
printf("l_apic%d,pin%d", lintr->dst_l_apic_id, lintr->dst_l_apic_pin); |
putchar('\n'); |
#endif |
} |
void ct_extended_entries(void) |
{ |
/* |
* Not yet implemented. |
*/ |
if (ct->ext_table_length) |
panic("ct_extended_entries: not supported\n"); |
} |
/* |
* Kernel thread for bringing up application processors. It becomes clear |
* that we need an arrangement like this (AP's being initialized by a kernel |
* thread), for a thread has its dedicated stack. (The stack used during the |
* BSP initialization (prior the very first call to scheduler()) will be used |
* as an initialization stack for each AP.) |
*/ |
void kmp(void *arg) |
{ |
struct __processor_entry *pr; |
__address src, dst; |
__address frame; |
int i; |
waitq_initialize(&ap_completion_wq); |
/* |
* Processor entries immediately follow the configuration table header. |
*/ |
pr = processor_entries; |
/* |
* Grab a frame and map its address to page 0. This is a hack which |
* accesses data in frame 0. Note that page 0 is not present because |
* of nil reference bug catching. |
*/ |
frame = frame_alloc(FRAME_KA); |
map_page_to_frame(frame,0,PAGE_CACHEABLE,0); |
/* |
* Set the warm-reset vector to the real-mode address of 4K-aligned ap_boot() |
*/ |
*((__u16 *) (frame + 0x467+0)) = ((__address) ap_boot) >> 4; /* segment */ |
*((__u16 *) (frame + 0x467+2)) = 0x0; /* offset */ |
/* |
* Give back the borrowed frame and restore identity mapping for it. |
*/ |
map_page_to_frame(frame,frame,PAGE_CACHEABLE,0); |
frame_free(frame); |
/* |
* Save 0xa to address 0xf of the CMOS RAM. |
* BIOS will not do the POST after the INIT signal. |
*/ |
outb(0x70,0xf); |
outb(0x71,0xa); |
cpu_priority_high(); |
pic_disable_irqs(0xffff); |
apic_init(); |
for (i = 0; i < processor_entry_cnt; i++) { |
struct descriptor *gdt_new; |
/* |
* Skip processors marked unusable. |
*/ |
if (pr[i].cpu_flags & (1<<0) == 0) |
continue; |
/* |
* The bootstrap processor is already up. |
*/ |
if (pr[i].cpu_flags & (1<<1)) |
continue; |
/* |
* Prepare new GDT for CPU in question. |
*/ |
if (!(gdt_new = (struct descriptor *) malloc(GDT_ITEMS*sizeof(struct descriptor)))) |
panic(PANIC "couldn't allocate memory for GDT\n"); |
memcopy(gdt, gdt_new, GDT_ITEMS*sizeof(struct descriptor)); |
gdtr.base = (__address) gdt_new; |
if (l_apic_send_init_ipi(pr[i].l_apic_id)) { |
/* |
* There may be just one AP being initialized at |
* the time. After it comes completely up, it is |
* supposed to wake us up. |
*/ |
waitq_sleep(&ap_completion_wq); |
cpu_priority_high(); |
} |
else { |
printf("INIT IPI for l_apic%d failed\n", pr[i].l_apic_id); |
} |
} |
/* |
* Wakeup the kinit thread so that |
* system initialization can go on. |
*/ |
waitq_wakeup(&kmp_completion_wq, WAKEUP_FIRST); |
} |
int mp_irq_to_pin(int irq) |
{ |
int i; |
for(i=0;i<io_intr_entry_cnt;i++) { |
if (io_intr_entries[i].src_bus_irq == irq && io_intr_entries[i].intr_type == 0) |
return io_intr_entries[i].dst_io_apic_pin; |
} |
return -1; |
} |
#endif /* __SMP__ */ |
/SPARTAN/trunk/arch/ia32/src/asm.s |
---|
0,0 → 1,332 |
# |
# Copyright (C) 2001-2004 Jakub Jermar |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
# very low and hardware-level functions |
.text |
.global cpu_priority_high |
.global cpu_priority_low |
.global cpu_priority_restore |
.global cpu_priority_read |
.global cpu_halt |
.global cpu_sleep |
.global paging_on |
.global cpu_read_dba |
.global cpu_write_dba |
.global cpu_read_cr2 |
.global enable_l_apic_in_msr |
.global interrupt_handlers |
.global inb |
.global inw |
.global inl |
.global outb |
.global outw |
.global outl |
.global memcopy |
.global memsetb |
.global memsetw |
.global memcmp |
# |
# set priority level high |
cpu_priority_high: |
pushf |
pop %eax |
cli |
ret |
# |
# set priority level low |
cpu_priority_low: |
pushf |
pop %eax |
sti |
ret |
# |
# restore priority level |
cpu_priority_restore: |
push 4(%esp) |
popf |
ret |
# return raw priority level |
cpu_priority_read: |
pushf |
pop %eax |
ret |
cpu_halt: |
cpu_sleep: |
hlt |
ret |
paging_on: |
pushl %eax |
movl %cr0,%eax |
orl $(1<<31),%eax # paging on |
andl $~((1<<30)|(1<<29)),%eax # clear Cache Disable and not Write Though |
movl %eax,%cr0 |
jmp 0f |
0: |
popl %eax |
ret |
cpu_read_dba: |
movl %cr3,%eax |
ret |
cpu_write_dba: |
pushl %eax |
movl 8(%esp),%eax |
movl %eax,%cr3 |
popl %eax |
ret |
cpu_read_cr2: |
movl %cr2,%eax |
ret |
enable_l_apic_in_msr: |
pusha |
movl $0x1b, %ecx |
rdmsr |
orl $(1<<11),%eax |
orl $(0xfee00000),%eax |
wrmsr |
popa |
ret |
.macro handler i n |
push %ebp |
movl %esp,%ebp |
pusha |
# we must fill the data segment registers |
movw $16,%ax |
movw %ax,%ds |
movw %ax,%es |
movl $(\i),%edi |
pushl %ebp |
addl $4,(%esp) |
pushl %edi |
call trap_dispatcher |
addl $8,%esp |
popa |
pop %ebp |
iret |
.if (\n-\i)-1 |
handler "(\i+1)",\n |
.endif |
.endm |
# keep in sync with pm.h !!! |
IDT_ITEMS=64 |
interrupt_handlers: |
h_start: |
handler 0 64 |
# handler 64 128 |
# handler 128 192 |
# handler 192 256 |
h_end: |
inb: |
push %edx |
xorl %eax,%eax |
movl 8(%esp),%edx |
inb %dx,%al |
pop %edx |
ret |
inw: |
push %edx |
xorl %eax,%eax |
movl 8(%esp),%edx |
inw %dx,%ax |
pop %edx |
ret |
inl: |
push %edx |
xorl %eax,%eax |
movl 8(%esp),%edx |
inl %dx,%eax |
pop %edx |
ret |
outb: |
push %ebp |
movl %esp,%ebp |
pusha |
movl 8(%ebp),%edx |
movl 12(%ebp),%eax |
outb %al,%dx |
popa |
pop %ebp |
ret |
outw: |
push %ebp |
movl %esp,%ebp |
pusha |
movl 8(%ebp),%edx |
movl 12(%ebp),%eax |
outw %ax,%dx |
popa |
pop %ebp |
ret |
outl: |
push %ebp |
movl %esp,%ebp |
pusha |
movl 8(%ebp),%edx |
movl 12(%ebp),%eax |
outl %eax,%dx |
popa |
pop %ebp |
ret |
SRC=8 |
DST=12 |
CNT=16 |
memcopy: |
push %ebp |
movl %esp,%ebp |
pusha |
cld |
movl CNT(%ebp),%ecx |
movl DST(%ebp),%edi |
movl SRC(%ebp),%esi |
rep movsb %ds:(%esi),%es:(%edi) |
popa |
pop %ebp |
ret |
DST=8 |
CNT=12 |
X=16 |
memsetw: |
push %ebp |
movl %esp,%ebp |
pusha |
cld |
movl CNT(%ebp),%ecx |
movl DST(%ebp),%edi |
movl X(%ebp),%eax |
rep stosw %ax,%es:(%edi) |
popa |
pop %ebp |
ret |
DST=8 |
CNT=12 |
X=16 |
memsetb: |
push %ebp |
movl %esp,%ebp |
pusha |
cld |
movl CNT(%ebp),%ecx |
movl DST(%ebp),%edi |
movl X(%ebp),%eax |
rep stosb %al,%es:(%edi) |
popa |
pop %ebp |
ret |
SRC=12 |
DST=16 |
CNT=20 |
memcmp: |
push %ebp |
subl $4,%esp |
movl %esp,%ebp |
pusha |
cld |
movl CNT(%ebp),%ecx |
movl DST(%ebp),%edi |
movl SRC(%ebp),%esi |
repe cmpsb %es:(%edi),%ds:(%esi) |
movl %ecx,(%ebp) |
popa |
movl (%ebp),%eax # return value => %eax (zero on success) |
addl $4,%esp |
pop %ebp |
ret |
# THIS IS USERSPACE CODE |
.global utext |
utext: |
0: |
movl $0xdeadbeaf, %eax |
int $48 |
jmp 0b |
# not reached |
utext_end: |
.data |
.global utext_size |
utext_size: |
.long utext_end - utext |
.section K_DATA_START |
.global interrupt_handler_size |
interrupt_handler_size: .long (h_end-h_start)/IDT_ITEMS |
/SPARTAN/trunk/arch/ia32/src/boot/boot.S |
---|
0,0 → 1,68 |
# |
# Copyright (C) 2001-2004 Jakub Jermar |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
.section K_TEXT_START |
.global kernel_image_start |
.code16 |
# |
# This is where we require any SPARTAN-kernel-compatible boot loader |
# to pass control in real mode. |
# |
# Protected mode tables are statically initialised during compile |
# time. So we can just load the respective table registers and |
# switch to protected mode. |
# |
kernel_image_start: |
cli |
xorw %ax,%ax |
movw %ax,%ds |
lgdt gdtr |
movl %cr0,%eax |
orl $0x1,%eax |
movl %eax,%cr0 |
jmp 0f |
0: |
movw $16,%ax |
movw %ax,%es |
movw %ax,%gs |
movw %ax,%fs |
movw %ax,%ds # kernel data + stack |
movw %ax,%ss |
movl $0x7c00,%esp |
jmpl $8,$meeting_point |
meeting_point: |
.code32 |
lidt idtr |
call main_bsp # never returns |
cli |
hlt |
/SPARTAN/trunk/arch/ia32/src/context.s |
---|
0,0 → 1,75 |
# |
# Copyright (C) 2001-2004 Jakub Jermar |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
.text |
.global context_save |
.global context_restore |
# |
# save context of this CPU |
context_save: |
push %ebx |
movl 4(%esp),%eax # the caller's return %eip |
movl 8(%esp),%ebx # address of the kernel_context variable to save context to |
movl %eax,4(%ebx) # %eip -> ctx->pc |
movl %esp,(%ebx) # %esp -> ctx->sp |
movl %ebx,%eax |
pop %ebx |
movl %ebx,8(%eax) |
movl %ecx,12(%eax) |
movl %edx,16(%eax) |
movl %esi,20(%eax) |
movl %edi,24(%eax) |
movl %ebp,28(%eax) |
xorl %eax,%eax # context_save returns 1 |
incl %eax |
ret |
# |
# restore saved context on this CPU |
context_restore: |
movl 4(%esp),%eax # address of the kernel_context variable to restore context from |
movl (%eax),%esp # ctx->sp -> %esp |
addl $4,%esp # this is for the pop we don't do |
movl 8(%eax),%ebx |
movl 12(%eax),%ecx |
movl 16(%eax),%edx |
movl 20(%eax),%esi |
movl 24(%eax),%edi |
movl 28(%eax),%ebp |
movl 4(%eax),%eax |
movl %eax,(%esp) # ctx->pc -> saver's return %eip |
xorl %eax,%eax # context_restore returns 0 |
ret |
/SPARTAN/trunk/arch/ia32/src/cpuid.s |
---|
0,0 → 1,79 |
# |
# Copyright (C) 2001-2004 Jakub Jermar |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
# |
# CPU identification functions. |
# The code below just interfaces the CPUID instruction. |
# CPU recognition logic is contained in higher-level functions. |
.text |
.global has_cpuid |
.global cpuid |
.global rdtsc |
has_cpuid: |
push %ebx |
pushf # store flags |
popl %eax # read flags |
movl %eax,%ebx # copy flags |
btcl $21,%ebx # swap the ID bit |
pushl %ebx |
popf # propagate the change into flags |
pushf |
popl %ebx # read flags |
andl $(1<<21),%eax # interested only in ID bit |
andl $(1<<21),%ebx |
xorl %ebx,%eax # 0 if not supported, 1 if supported |
pop %ebx |
ret |
# cpuid(__u32 cmd, struct cpu_info *info) |
cpuid: |
pushl %ebp |
movl %esp,%ebp |
pusha |
movl 8(%ebp),%eax # load the command into %eax |
movl 12(%ebp),%esi # laod the address of the info struct |
cpuid |
movl %eax,0(%esi) |
movl %ebx,4(%esi) |
movl %ecx,8(%esi) |
movl %edx,12(%esi) |
popa |
popl %ebp |
ret |
rdtsc: |
rdtsc |
ret |
/SPARTAN/trunk/arch/ia32/src/debug/panic.s |
---|
0,0 → 1,34 |
# |
# Copyright (C) 2001-2004 Jakub Jermar |
# All rights reserved. |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions |
# are met: |
# |
# - Redistributions of source code must retain the above copyright |
# notice, this list of conditions and the following disclaimer. |
# - Redistributions in binary form must reproduce the above copyright |
# notice, this list of conditions and the following disclaimer in the |
# documentation and/or other materials provided with the distribution. |
# - The name of the author may not be used to endorse or promote products |
# derived from this software without specific prior written permission. |
# |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
# |
.text |
.global panic |
panic: |
movl $halt,(%esp) # fake stack to make printf return to halt |
jmp printf |
/SPARTAN/trunk/arch/ia32/src/cpu/cpu.c |
---|
0,0 → 1,110 |
/* |
* Copyright (C) 2001-2004 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <arch/cpu.h> |
#include <arch/cpuid.h> |
#include <arch/pm.h> |
#include <arch.h> |
#include <arch/types.h> |
#include <print.h> |
#include <typedefs.h> |
/* |
* Identification of CPUs. |
* Contains only non-MP-Specification specific SMP code. |
*/ |
#define AMD_CPUID_EBX 0x68747541 |
#define AMD_CPUID_ECX 0x444d4163 |
#define AMD_CPUID_EDX 0x69746e65 |
#define INTEL_CPUID_EBX 0x756e6547 |
#define INTEL_CPUID_ECX 0x6c65746e |
#define INTEL_CPUID_EDX 0x49656e69 |
enum vendor { |
VendorUnknown=0, |
VendorAMD, |
VendorIntel |
}; |
static char *vendor_str[] = { |
"Unknown Vendor", |
"AuthenticAMD", |
"GenuineIntel" |
}; |
void cpu_arch_init(void) |
{ |
the->cpu->arch.tss = tss_p; |
} |
void cpu_identify(void) |
{ |
cpu_info_t info; |
int i; |
the->cpu->arch.vendor = VendorUnknown; |
if (has_cpuid()) { |
cpuid(0, &info); |
/* |
* Check for AMD processor. |
*/ |
if (info.cpuid_ebx==AMD_CPUID_EBX && |
info.cpuid_ecx==AMD_CPUID_ECX && |
info.cpuid_edx==AMD_CPUID_EDX) { |
the->cpu->arch.vendor = VendorAMD; |
} |
/* |
* Check for Intel processor. |
*/ |
if (info.cpuid_ebx==INTEL_CPUID_EBX && |
info.cpuid_ecx==INTEL_CPUID_ECX && |
info.cpuid_edx==INTEL_CPUID_EDX) { |
the->cpu->arch.vendor = VendorIntel; |
} |
cpuid(1, &info); |
the->cpu->arch.family = (info.cpuid_eax>>8)&0xf; |
the->cpu->arch.model = (info.cpuid_eax>>4)&0xf; |
the->cpu->arch.stepping = (info.cpuid_eax>>0)&0xf; |
} |
} |
void cpu_print_report(struct cpu* m) |
{ |
printf("cpu%d: (%s family=%d model=%d stepping=%d) %dMHz\n", |
m->id, vendor_str[m->arch.vendor], m->arch.family, m->arch.model, m->arch.stepping, |
m->frequency_mhz); |
} |
/SPARTAN/trunk/arch/ia32/src/mm/tlb.c |
---|
0,0 → 1,35 |
/* |
* Copyright (C) 2005 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <mm/tlb.h> |
#include <arch/asm.h> |
void tlb_invalidate(int asid) |
{ |
cpu_write_dba(cpu_read_dba()); |
} |
/SPARTAN/trunk/arch/ia32/src/mm/frame.c |
---|
0,0 → 1,52 |
/* |
* Copyright (C) 2001-2004 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <mm/frame.h> |
#include <arch/mm/frame.h> |
#include <mm/vm.h> |
#include <config.h> |
/* |
* TODO: use the memory map obtained from BIOS |
*/ |
void frame_arch_init(void) |
{ |
if (config.cpu_active == 1) { |
__u32 kernel_frames_max; |
kernel_frames_max = ((KERNEL_ADDRESS_SPACE_END+1)/FRAME_SIZE); |
kernel_frames_free = kernel_frames = frames < kernel_frames_max ? frames : kernel_frames_max; |
frame_kernel_bitmap = frame_bitmap; |
frame_not_free(0x0); |
frame_region_not_free(0xa0000,0xff000); |
frame_region_not_free(0xfec00000,0xffffffff); |
} |
} |
/SPARTAN/trunk/arch/ia32/src/mm/page.c |
---|
0,0 → 1,139 |
/* |
* Copyright (C) 2001-2004 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <arch/types.h> |
#include <config.h> |
#include <func.h> |
#include <mm/frame.h> |
#include <mm/page.h> |
#include <arch/mm/page.h> |
#include <arch/interrupt.h> |
#include <arch/asm.h> |
#include <synch/spinlock.h> |
/* |
* Note. |
* This is the preliminary code for controlling paging mechanism on i386. It is |
* needed by other parts of the kernel for its ability to map virtual addresses |
* to physical. SMP code relies on this feature. Other than that, this code is |
* by no means meant to implement virtual memory in terms of swapping pages in |
* and out. |
*/ |
__address bootstrap_dba; |
void page_arch_init(void) |
{ |
__address dba; |
__u32 i; |
if (config.cpu_active == 1) { |
dba = frame_alloc(FRAME_KA | FRAME_PANIC); |
memsetb(dba, PAGE_SIZE, 0); |
cpu_write_dba(dba); |
bootstrap_dba = dba; |
/* |
* Identity mapping for all but 0th page. |
*/ |
for (i = 1; i < frames; i++) |
map_page_to_frame(i * PAGE_SIZE, i * PAGE_SIZE, PAGE_CACHEABLE, 0); |
trap_register(14, page_fault); |
} |
else { |
/* |
* Application processors need to create their own view of the |
* virtual address space. Because of that, each AP copies |
* already-initialized paging information from the bootstrap |
* processor and adjusts it to fulfill its needs. |
*/ |
dba = frame_alloc(FRAME_KA | FRAME_PANIC); |
memcopy(bootstrap_dba, dba, PAGE_SIZE); |
cpu_write_dba(dba); |
} |
paging_on(); |
} |
/* |
* Besides mapping pages to frames, this function also sets the present bit of |
* the page's specifier in both page directory and respective page table. If |
* the page table for this page has not been allocated so far, it will take |
* care of it and allocate the necessary frame. |
* |
* When the copy parameter is positive, map_page_to_frame will not overwrite |
* the current mapping. It will allocate a new frame and do the mapping on it |
* instead. |
* |
* PAGE_CACHEABLE flag: when set, it turns caches for that page on |
* PAGE_NOT_PRESENT flag: when set, it marks the page not present |
* PAGE_USER flag: when set, the page is accessible from userspace |
*/ |
void map_page_to_frame(__address page, __address frame, int flags, int copy) |
{ |
struct page_specifier *pd, *pt; |
__address dba, newpt; |
int pde, pte; |
dba = cpu_read_dba(); |
pde = page >> 22; /* page directory entry */ |
pte = (page >> 12) & 0x3ff; /* page table entry */ |
pd = (struct page_specifier *) dba; |
if (!pd[pde].present) { |
/* |
* There is currently no page table for this address. Allocate |
* frame for the page table and clean it. |
*/ |
newpt = frame_alloc(FRAME_KA); |
pd[pde].frame_address = newpt >> 12; |
memsetb(newpt, PAGE_SIZE, 0); |
pd[pde].present = 1; |
pd[pde].uaccessible = 1; |
} |
if (copy) { |
newpt = frame_alloc(FRAME_KA); |
memcopy(pd[pde].frame_address << 12, newpt, PAGE_SIZE); |
pd[pde].frame_address = newpt >> 12; |
} |
pt = (struct page_specifier *) (pd[pde].frame_address << 12); |
pt[pte].frame_address = frame >> 12; |
pt[pte].present = !(flags & PAGE_NOT_PRESENT); |
pt[pte].page_cache_disable = !(flags & PAGE_CACHEABLE); |
pt[pte].uaccessible = (flags & PAGE_USER) != 0; |
pt[pte].writeable = (flags & PAGE_WRITE) != 0; |
tlb_invalidate(0); |
} |
/SPARTAN/trunk/arch/ia32/src/userspace.c |
---|
0,0 → 1,59 |
/* |
* Copyright (C) 2005 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <userspace.h> |
#include <arch/pm.h> |
#include <arch/types.h> |
#include <arch.h> |
#include <proc/thread.h> |
#include <mm/vm.h> |
void userspace(void) |
{ |
pri_t pri; |
pri = cpu_priority_high(); |
/* |
* Prepare TSS stack selector and pointers for next syscall. |
*/ |
the->cpu->arch.tss->esp0 = (__address) &the->thread->kstack[THREAD_STACK_SIZE-8]; |
the->cpu->arch.tss->ss0 = selector(KDATA_DES); |
__asm__ volatile ("" |
"pushl %0\n" |
"pushl %1\n" |
"pushl %2\n" |
"pushl %3\n" |
"pushl %4\n" |
"iret" |
: : "i" (selector(UDATA_DES) | PL_USER), "i" (USTACK_ADDRESS+THREAD_STACK_SIZE-1000), "r" (pri), "i" (selector(UTEXT_DES) | PL_USER), "i" (UTEXT_ADDRESS)); |
/* NOT REACHED */ |
for(;;); |
} |
/SPARTAN/trunk/arch/ia32/src/interrupt.c |
---|
0,0 → 1,119 |
/* |
* Copyright (C) 2001-2004 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <arch/interrupt.h> |
#include <print.h> |
#include <panic.h> |
#include <arch/i8259.h> |
#include <func.h> |
#include <cpu.h> |
#include <arch/asm.h> |
/* |
* Interrupt and exception dispatching. |
*/ |
static iroutine ivt[IVT_ITEMS]; |
void (* disable_irqs_function)(__u16 irqmask) = NULL; |
void (* enable_irqs_function)(__u16 irqmask) = NULL; |
void (* eoi_function)(void) = NULL; |
iroutine trap_register(__u8 n, iroutine f) |
{ |
iroutine old; |
old = ivt[n]; |
ivt[n] = f; |
return old; |
} |
/* |
* Called directly from the assembler code. |
* CPU is cpu_priority_high(). |
*/ |
void trap_dispatcher(__u8 n, __u32 stack[]) |
{ |
ivt[n](n,stack); |
} |
void null_interrupt(__u8 n, __u32 stack[]) |
{ |
printf("int %d: null_interrupt\n", n); |
printf("stack: %L, %L, %L, %L\n", stack[0], stack[1], stack[2], stack[3]); |
panic("unserviced interrupt\n"); |
} |
void gp_fault(__u8 n, __u32 stack[]) |
{ |
printf("stack[0]=%X, %%eip=%X, %%cs=%X, flags=%X\n", stack[0], stack[1], stack[2], stack[3]); |
printf("%%eax=%L, %%ebx=%L, %%ecx=%L, %%edx=%L,\n%%edi=%L, %%esi=%L, %%ebp=%L, %%esp=%L\n", stack[-2], stack[-5], stack[-3], stack[-4], stack[-9], stack[-8], stack[-1], stack); |
printf("stack: %X, %X, %X, %X\n", stack[4], stack[5], stack[6], stack[7]); |
panic("general protection fault\n"); |
} |
void page_fault(__u8 n, __u32 stack[]) |
{ |
printf("page fault address: %X\n", cpu_read_cr2()); |
printf("stack[0]=%X, %%eip=%X, %%cs=%X, flags=%X\n", stack[0], stack[1], stack[2], stack[3]); |
printf("%%eax=%L, %%ebx=%L, %%ecx=%L, %%edx=%L,\n%%edi=%L, %%esi=%L, %%ebp=%L, %%esp=%L\n", stack[-2], stack[-5], stack[-3], stack[-4], stack[-9], stack[-8], stack[-1], stack); |
printf("stack: %X, %X, %X, %X\n", stack[4], stack[5], stack[6], stack[7]); |
panic("page fault\n"); |
} |
void syscall(__u8 n, __u32 stack[]) |
{ |
printf("syscall... "); |
thread_sleep(1); |
} |
void trap_virtual_enable_irqs(__u16 irqmask) |
{ |
if (enable_irqs_function) |
enable_irqs_function(irqmask); |
else |
panic(PANIC "no enable_irqs_function\n"); |
} |
void trap_virtual_disable_irqs(__u16 irqmask) |
{ |
if (disable_irqs_function) |
disable_irqs_function(irqmask); |
else |
panic(PANIC "no disable_irqs_function\n"); |
} |
void trap_virtual_eoi(void) |
{ |
if (eoi_function) |
eoi_function(); |
else |
panic(PANIC "no eoi_function\n"); |
} |
/SPARTAN/trunk/arch/ia32/src/pm.c |
---|
0,0 → 1,163 |
/* |
* Copyright (C) 2001-2004 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <arch/pm.h> |
#include <config.h> |
#include <arch/types.h> |
#include <typedefs.h> |
#include <arch/interrupt.h> |
#include <arch/asm.h> |
#include <arch/context.h> |
#include <panic.h> |
/* |
* Early i386 configuration functions and data structures. |
*/ |
/* |
* We have no use for segmentation so we set up flat mode. In this |
* mode, we use, for each privilege level, two segments spanning the |
* whole memory. One is for code and one is for data. |
*/ |
struct descriptor gdt[GDT_ITEMS] = { |
/* NULL descriptor */ |
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, |
/* KTEXT descriptor */ |
{ 0xffff, 0, 0, AR_PRESENT | AR_CODE | DPL_KERNEL, 0xf, 0, 0, 1, 1, 0 }, |
/* KDATA descriptor */ |
{ 0xffff, 0, 0, AR_PRESENT | AR_DATA | AR_WRITABLE | DPL_KERNEL, 0xf, 0, 0, 1, 1, 0 }, |
/* UTEXT descriptor */ |
{ 0xffff, 0, 0, AR_PRESENT | AR_CODE | DPL_USER, 0xf, 0, 0, 1, 1, 0 }, |
/* UDATA descriptor */ |
{ 0xffff, 0, 0, AR_PRESENT | AR_DATA | AR_WRITABLE | DPL_USER, 0xf, 0, 0, 1, 1, 0 }, |
/* TSS descriptor - set up will be completed later */ |
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } |
}; |
static struct idescriptor idt[IDT_ITEMS]; |
static struct tss tss; |
struct tss *tss_p = NULL; |
/* gdtr changes everytime new CPU is initialized */ |
struct ptr_16_32 gdtr = { .limit = sizeof(gdt), .base = (__address) gdt }; |
struct ptr_16_32 idtr = { .limit = sizeof(idt), .base = (__address) idt }; |
void gdt_setbase(struct descriptor *d, __address base) |
{ |
d->base_0_15 = base & 0xffff; |
d->base_16_23 = (base >> 16) & 0xff; |
d->base_24_31 = (base >> 24) & 0xff; |
} |
void gdt_setlimit(struct descriptor *d, __address limit) |
{ |
d->limit_0_15 = limit & 0xffff; |
d->limit_16_19 = (limit >> 16) & 0xf; |
} |
void idt_setoffset(struct idescriptor *d, __address offset) |
{ |
d->offset_0_15 = offset & 0xffff; |
d->offset_16_31 = offset >> 16; |
} |
void tss_initialize(struct tss *t) |
{ |
memsetb((__address) t, sizeof(struct tss), 0); |
} |
/* |
* This function takes care of proper setup of IDT and IDTR. |
*/ |
void idt_init(void) |
{ |
struct idescriptor *d; |
int i; |
for (i = 0; i < IDT_ITEMS; i++) { |
d = &idt[i]; |
d->unused = 0; |
d->selector = selector(KTEXT_DES); |
d->access = AR_PRESENT | AR_INTERRUPT; /* masking interrupt */ |
if (i == VECTOR_SYSCALL) { |
/* |
* The syscall interrupt gate must be calleable from userland. |
*/ |
d->access |= DPL_USER; |
} |
idt_setoffset(d, ((__address) interrupt_handlers) + i*interrupt_handler_size); |
trap_register(i, null_interrupt); |
} |
trap_register(13, gp_fault); |
} |
void pm_init(void) |
{ |
struct descriptor *gdt_p = (struct descriptor *) gdtr.base; |
/* |
* Each CPU has its private GDT and TSS. |
* All CPUs share one IDT. |
*/ |
if (config.cpu_active == 1) { |
idt_init(); |
/* |
* NOTE: bootstrap CPU has statically allocated TSS, because |
* the heap hasn't been initialized so far. |
*/ |
tss_p = &tss; |
} |
else { |
tss_p = (struct tss *) malloc(sizeof(struct tss)); |
if (!tss_p) |
panic(PANIC "could not allocate TSS\n"); |
} |
tss_initialize(tss_p); |
gdt_p[TSS_DES].access = AR_PRESENT | AR_TSS | DPL_KERNEL; |
gdt_p[TSS_DES].special = 1; |
gdt_p[TSS_DES].granularity = 1; |
gdt_setbase(&gdt_p[TSS_DES], (__address) tss_p); |
gdt_setlimit(&gdt_p[TSS_DES], sizeof(struct tss) - 1); |
/* |
* As of this moment, the current CPU has its own GDT pointing |
* to its own TSS. We just need to load the TR register. |
*/ |
__asm__("ltr %0" : : "r" ((__u16) selector(TSS_DES))); |
} |
/SPARTAN/trunk/arch/ia32/src/drivers/i8259.c |
---|
0,0 → 1,120 |
/* |
* Copyright (C) 2001-2004 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <arch/i8259.h> |
#include <cpu.h> |
#include <arch/types.h> |
#include <arch/asm.h> |
#include <arch.h> |
/* |
* This is the PIC driver. |
* Programmable Interrupt Controller for UP systems. |
*/ |
void i8259_init(void) |
{ |
/* ICW1: this is ICW1, ICW4 to follow */ |
outb(PIC_PIC0PORT1, PIC_ICW1 | PIC_NEEDICW4); |
/* ICW2: IRQ 0 maps to INT IRQBASE */ |
outb(PIC_PIC0PORT2, IVT_IRQBASE); |
/* ICW3: pic1 using IRQ IRQ_PIC1 */ |
outb(PIC_PIC0PORT2, 1 << IRQ_PIC1); |
/* ICW4: i8086 mode */ |
outb(PIC_PIC0PORT2, 1); |
/* ICW1: ICW1, ICW4 to follow */ |
outb(PIC_PIC1PORT1, PIC_ICW1 | PIC_NEEDICW4); |
/* ICW2: IRQ 8 maps to INT (IVT_IRQBASE + 8) */ |
outb(PIC_PIC1PORT2, IVT_IRQBASE + 8); |
/* ICW3: pic1 is known as PIC_PIC1ID */ |
outb(PIC_PIC1PORT2, PIC_PIC1ID); |
/* ICW4: i8086 mode */ |
outb(PIC_PIC1PORT2, 1); |
/* |
* Register interrupt handler for the PIC spurious interrupt. |
*/ |
trap_register(VECTOR_PIC_SPUR, pic_spurious); |
/* |
* Set the enable/disable IRQs handlers. |
* Set the End-of-Interrupt handler. |
*/ |
enable_irqs_function = pic_enable_irqs; |
disable_irqs_function = pic_disable_irqs; |
eoi_function = pic_eoi; |
pic_disable_irqs(0xffff); /* disable all irq's */ |
pic_enable_irqs(1<<IRQ_PIC1); /* but enable pic1 */ |
} |
void pic_enable_irqs(__u16 irqmask) |
{ |
__u8 x; |
if (irqmask & 0xff) { |
x = inb(PIC_PIC0PORT2); |
outb(PIC_PIC0PORT2, x & (~(irqmask & 0xff))); |
} |
if (irqmask >> 8) { |
x = inb(PIC_PIC1PORT2); |
outb(PIC_PIC1PORT2, x & (~(irqmask >> 8))); |
} |
} |
void pic_disable_irqs(__u16 irqmask) |
{ |
__u8 x; |
if (irqmask & 0xff) { |
x = inb(PIC_PIC0PORT2); |
outb(PIC_PIC0PORT2, x | (irqmask & 0xff)); |
} |
if (irqmask >> 8) { |
x = inb(PIC_PIC1PORT2); |
outb(PIC_PIC1PORT2, x | (irqmask >> 8)); |
} |
} |
void pic_eoi(void) |
{ |
outb(0x20,0x20); |
outb(0xa0,0x20); |
} |
void pic_spurious(__u8 n, __u32 stack[]) |
{ |
printf("cpu%d: PIC spurious interrupt\n", the->cpu->id); |
} |
/SPARTAN/trunk/arch/ia32/src/drivers/i8042.c |
---|
0,0 → 1,58 |
/* |
* Copyright (C) 2001-2004 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <arch/i8042.h> |
#include <arch/i8259.h> |
#include <arch/interrupt.h> |
#include <cpu.h> |
#include <arch/asm.h> |
#include <arch.h> |
#include <print.h> |
/* |
* i8042 processor driver. |
* Its very essential function is enabling the A20. |
*/ |
void i8042_init(void) |
{ |
/* A20: deadly if not enabled */ |
outb(0x64,0xd1); |
outb(0x60,0xdf); |
trap_register(VECTOR_KBD, i8042_interrupt); |
} |
void i8042_interrupt(__u8 n, __u32 stack[]) |
{ |
__u8 x; |
trap_virtual_eoi(); |
x = inb(0x60); |
printf("%d", the->cpu->id);; |
} |
/SPARTAN/trunk/arch/ia32/src/drivers/i8254.c |
---|
0,0 → 1,130 |
/* |
* Copyright (C) 2001-2004 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <arch/types.h> |
#include <time/clock.h> |
#include <time/delay.h> |
#include <arch/interrupt.h> |
#include <arch/i8259.h> |
#include <arch/i8254.h> |
#include <cpu.h> |
#include <config.h> |
#include <arch/pm.h> |
#include <arch/asm.h> |
#include <arch.h> |
/* |
* i8254 chip driver. |
* Low level time functions. |
*/ |
#define CLK_PORT1 0x40 |
#define CLK_PORT4 0x43 |
#define CLK_CONST 1193180 |
#define MAGIC_NUMBER 1194 |
void i8254_init(void) |
{ |
i8254_normal_operation(); |
} |
void i8254_normal_operation(void) |
{ |
outb(CLK_PORT4, 0x36); |
trap_virtual_disable_irqs(1<<IRQ_CLK); |
outb(CLK_PORT1, (CLK_CONST/HZ) & 0xf); |
outb(CLK_PORT1, (CLK_CONST/HZ) >> 8); |
trap_virtual_enable_irqs(1<<IRQ_CLK); |
trap_register(VECTOR_CLK, i8254_interrupt); |
} |
#define LOOPS 150000 |
#define SHIFT 11 |
void i8254_calibrate_delay_loop(void) |
{ |
__u64 clk1, clk2; |
__u32 t1, t2, o1, o2; |
__u8 not_ok; |
/* |
* One-shot timer. Count-down from 0xffff at 1193180Hz |
* MAGIC_NUMBER is the magic value for 1ms. |
*/ |
outb(CLK_PORT4, 0x30); |
outb(CLK_PORT1, 0xff); |
outb(CLK_PORT1, 0xff); |
do { |
/* will read both status and count */ |
outb(CLK_PORT4, 0xc2); |
not_ok = (inb(CLK_PORT1)>>6)&1; |
t1 = inb(CLK_PORT1); |
t1 |= inb(CLK_PORT1) << 8; |
} while (not_ok); |
asm_delay_loop(LOOPS); |
outb(CLK_PORT4, 0xd2); |
t2 = inb(CLK_PORT1); |
t2 |= inb(CLK_PORT1) << 8; |
/* |
* We want to determine the overhead of the calibrating mechanism. |
*/ |
outb(CLK_PORT4, 0xd2); |
o1 = inb(CLK_PORT1); |
o1 |= inb(CLK_PORT1) << 8; |
asm_fake_loop(LOOPS); |
outb(CLK_PORT4, 0xd2); |
o2 = inb(CLK_PORT1); |
o2 |= inb(CLK_PORT1) << 8; |
the->cpu->delay_loop_const = ((MAGIC_NUMBER*LOOPS)/1000) / ((t1-t2)-(o1-o2)) + |
(((MAGIC_NUMBER*LOOPS)/1000) % ((t1-t2)-(o1-o2)) ? 1 : 0); |
clk1 = rdtsc(); |
delay(1<<SHIFT); |
clk2 = rdtsc(); |
the->cpu->frequency_mhz = (clk2-clk1)>>SHIFT; |
return; |
} |
void i8254_interrupt(__u8 n, __u32 stack[]) |
{ |
trap_virtual_eoi(); |
clock(); |
} |
/SPARTAN/trunk/arch/ia32/src/drivers/ega.c |
---|
0,0 → 1,116 |
/* |
* Copyright (C) 2001-2004 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <arch/ega.h> |
#include <putchar.h> |
#include <mm/page.h> |
#include <synch/spinlock.h> |
#include <arch/types.h> |
#include <arch/asm.h> |
/* |
* The EGA driver. |
* Simple and short. Function for displaying characters and "scrolling". |
*/ |
static spinlock_t egalock; |
static __u32 ega_cursor; |
void ega_move_cursor(void); |
void ega_init(void) |
{ |
__u8 hi, lo; |
map_page_to_frame(VIDEORAM, VIDEORAM, PAGE_NOT_CACHEABLE, 0); |
outb(0x3d4,0xe); |
hi = inb(0x3d5); |
outb(0x3d4,0xf); |
lo = inb(0x3d5); |
ega_cursor = (hi<<8)|lo; |
ega_putchar('\n'); |
} |
void ega_display_char(char ch) |
{ |
__u8 *vram = (__u8 *) VIDEORAM; |
vram[ega_cursor*2] = ch; |
} |
/* |
* This function takes care of scrolling. |
*/ |
void ega_check_cursor(void) |
{ |
if (ega_cursor < SCREEN) |
return; |
memcopy(VIDEORAM + ROW*2, VIDEORAM, (SCREEN - ROW)*2); |
memsetw(VIDEORAM + (SCREEN - ROW)*2, ROW, 0x0720); |
ega_cursor = ega_cursor - ROW; |
} |
void ega_putchar(char ch) |
{ |
pri_t pri; |
pri = cpu_priority_high(); |
spinlock_lock(&egalock); |
switch (ch) { |
case '\n': |
ega_cursor = (ega_cursor + ROW) - ega_cursor % ROW; |
break; |
case '\t': |
ega_cursor = (ega_cursor + 8) - ega_cursor % 8; |
break; |
default: |
ega_display_char(ch); |
ega_cursor++; |
break; |
} |
ega_check_cursor(); |
ega_move_cursor(); |
spinlock_unlock(&egalock); |
cpu_priority_restore(pri); |
} |
void ega_move_cursor(void) |
{ |
outb(0x3d4,0xe); |
outb(0x3d5,(ega_cursor>>8)&0xff); |
outb(0x3d4,0xf); |
outb(0x3d5,ega_cursor&0xff); |
} |
void putchar(char ch) |
{ |
ega_putchar(ch); |
} |