/SPARTAN/trunk/arch/ia32/include/atomic.h |
---|
31,10 → 31,36 |
#include <arch/types.h> |
extern void atomic_inc(volatile int *val); |
extern void atomic_dec(volatile int *val); |
static inline void atomic_inc(volatile int *val) { |
#ifdef __SMP__ |
__asm__ volatile ("lock incl (%0)\n" : : "r" (val)); |
#else |
__asm__ volatile ("incl (%0)\n" : : "r" (val)); |
#endif /* __SMP__ */ |
} |
extern int test_and_set(int *val); |
static inline void atomic_dec(volatile int *val) { |
#ifdef __SMP__ |
__asm__ volatile ("lock decl (%0)\n" : : "r" (val)); |
#else |
__asm__ volatile ("decl (%0)\n" : : "r" (val)); |
#endif /* __SMP__ */ |
} |
static inline int test_and_set(int *val) { |
int v; |
__asm__ volatile ( |
"movl $1, %0\n" |
"xchgl %0, (%1)\n" |
: "=r" (v) |
: "r" (val) |
); |
return v; |
} |
extern void spinlock_arch(int *val); |
#endif |
/SPARTAN/trunk/arch/ia32/include/asm.h |
---|
37,11 → 37,7 |
extern __u32 interrupt_handler_size; |
extern void paging_on(void); |
extern __address cpu_read_dba(void); |
extern void cpu_write_dba(__address dba); |
extern __address cpu_read_cr2(void); |
extern void interrupt_handlers(void); |
extern __u8 inb(int port); |
54,13 → 50,109 |
extern void enable_l_apic_in_msr(void); |
extern void halt_cpu(void); |
extern void cpu_sleep(void); |
/** Halt CPU |
* |
* Halt the current CPU until interrupt event. |
*/ |
static inline void cpu_halt(void) { __asm__("hlt"); }; |
static inline void cpu_sleep(void) { __asm__("hlt"); }; |
static inline void write_dr0(__u32 v); |
static inline __u32 read_dr0(void); |
/** Read CR2 |
* |
* Return value in CR2 |
* |
* @return Value read. |
*/ |
static inline __u32 read_cr2(void) { __u32 v; __asm__ volatile ("movl %%cr2,%0" : "=r" (v)); return v; } |
inline void write_dr0(__u32 v) { __asm__ volatile ("movl %0,%%dr0\n" : : "r" (v)); } |
inline __u32 read_dr0(void) { __u32 v; __asm__ volatile ("movl %%dr0,%0" : "=r" (v)); return v; } |
/** Write CR3 |
* |
* Write value to CR3. |
* |
* @param v Value to be written. |
*/ |
static inline void write_cr3(__u32 v) { __asm__ volatile ("movl %0,%%cr3\n" : : "r" (v)); } |
/** Read CR3 |
* |
* Return value in CR3 |
* |
* @return Value read. |
*/ |
static inline __u32 read_cr3(void) { __u32 v; __asm__ volatile ("movl %%cr3,%0" : "=r" (v)); return v; } |
/** Write DR0 |
* |
* Write value to DR0. |
* |
* @param v Value to be written. |
*/ |
static inline void write_dr0(__u32 v) { __asm__ volatile ("movl %0,%%dr0\n" : : "r" (v)); } |
/** Read DR0 |
* |
* Return value in DR0 |
* |
* @return Value read. |
*/ |
static inline __u32 read_dr0(void) { __u32 v; __asm__ volatile ("movl %%dr0,%0" : "=r" (v)); return v; } |
/** Set priority level low |
* |
* Enable interrupts and return previous |
* value of EFLAGS. |
*/ |
static inline pri_t cpu_priority_low(void) { |
pri_t v; |
__asm__ volatile ( |
"pushf\n" |
"popl %0\n" |
"sti\n" |
: "=r" (v) |
); |
return v; |
} |
/** Set priority level high |
* |
* Disable interrupts and return previous |
* value of EFLAGS. |
*/ |
static inline pri_t cpu_priority_high(void) { |
pri_t v; |
__asm__ volatile ( |
"pushf\n" |
"popl %0\n" |
"cli\n" |
: "=r" (v) |
); |
return v; |
} |
/** Restore priority level |
* |
* Restore EFLAGS. |
*/ |
static inline void cpu_priority_restore(pri_t pri) { |
__asm__ volatile ( |
"pushl %0\n" |
"popf\n" |
: : "r" (pri) |
); |
} |
/** Return raw priority level |
* |
* Return EFLAFS. |
*/ |
static inline pri_t cpu_priority_read(void) { |
pri_t v; |
__asm__ volatile ( |
"pushf\n" |
"popl %0\n" |
: "=r" (v) |
); |
return v; |
} |
#endif |
/SPARTAN/trunk/arch/ia32/src/asm.s |
---|
30,16 → 30,9 |
.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 |
54,59 → 47,6 |
.global memcmp |
## Set priority level high |
# |
# Disable interrupts and return previous |
# EFLAGS in EAX. |
# |
cpu_priority_high: |
pushf |
pop %eax |
cli |
ret |
## Set priority level low |
# |
# Enable interrupts and return previous |
# EFLAGS in EAX. |
# |
cpu_priority_low: |
pushf |
pop %eax |
sti |
ret |
## Restore priority level |
# |
# Restore EFLAGS. |
# |
cpu_priority_restore: |
push 4(%esp) |
popf |
ret |
## Return raw priority level |
# |
# Return EFLAFS in EAX. |
# |
cpu_priority_read: |
pushf |
pop %eax |
ret |
## Halt the CPU |
# |
# Halt the CPU using HLT. |
# |
cpu_halt: |
cpu_sleep: |
hlt |
ret |
## Turn paging on |
# |
# Enable paging and write-back caching in CR0. |
123,36 → 63,6 |
ret |
## Read CR3 |
# |
# Store CR3 in EAX. |
# |
cpu_read_dba: |
movl %cr3,%eax |
ret |
## Write CR3 |
# |
# Set CR3. |
# |
cpu_write_dba: |
pushl %eax |
movl 8(%esp),%eax |
movl %eax,%cr3 |
popl %eax |
ret |
## Read CR2 |
# |
# Store CR2 in EAX. |
# |
cpu_read_cr2: |
movl %cr2,%eax |
ret |
## Enable local APIC |
# |
# Enable local APIC in MSR. |
/SPARTAN/trunk/arch/ia32/src/smp/apic.c |
---|
44,6 → 44,7 |
* Advanced Programmable Interrupt Controller for MP systems. |
* Tested on: |
* Bochs 2.0.2 - Bochs 2.2 with 2-8 CPUs |
* Simics 2.0.28 |
* ASUS P/I-P65UP5 + ASUS C-P55T2D REV. 1.41 with 2x 200Mhz Pentium CPUs |
*/ |
/SPARTAN/trunk/arch/ia32/src/mm/tlb.c |
---|
31,5 → 31,5 |
void tlb_invalidate(int asid) |
{ |
cpu_write_dba(cpu_read_dba()); |
write_cr3(read_cr3()); |
} |
/SPARTAN/trunk/arch/ia32/src/mm/page.c |
---|
69,7 → 69,7 |
} |
trap_register(14, page_fault); |
cpu_write_dba(KA2PA(dba)); |
write_cr3(KA2PA(dba)); |
} |
else { |
/* |
81,7 → 81,7 |
dba = frame_alloc(FRAME_KA | FRAME_PANIC); |
memcopy(bootstrap_dba, dba, PAGE_SIZE); |
cpu_write_dba(KA2PA(dba)); |
write_cr3(KA2PA(dba)); |
} |
paging_on(); |
107,7 → 107,7 |
int pde, pte; |
if (root) dba = root; |
else dba = cpu_read_dba(); |
else dba = read_cr3(); |
pde = page >> 22; /* page directory entry */ |
pte = (page >> 12) & 0x3ff; /* page table entry */ |
/SPARTAN/trunk/arch/ia32/src/interrupt.c |
---|
111,7 → 111,7 |
void page_fault(__u8 n, __u32 stack[]) |
{ |
printf("page fault address: %X\n", cpu_read_cr2()); |
printf("page fault address: %X\n", 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]); |
/SPARTAN/trunk/arch/ia32/src/atomic.S |
---|
28,48 → 28,10 |
.text |
.global atomic_inc |
atomic_inc: |
pushl %ebx |
movl 8(%esp),%ebx |
#ifdef __SMP__ |
lock incl (%ebx) |
#else |
incl (%ebx) |
#endif |
popl %ebx |
ret |
.global atomic_dec |
atomic_dec: |
pushl %ebx |
movl 8(%esp),%ebx |
#ifdef __SMP__ |
lock decl (%ebx) |
#else |
decl (%ebx) |
#endif |
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 |
# |