/kernel/trunk/arch/sparc64/include/interrupt.h |
---|
30,6 → 30,7 |
#define __sparc64_INTERRUPT_H__ |
#include <typedefs.h> |
#include <arch/types.h> |
#define IRQ_COUNT 1 /* TODO */ |
43,6 → 44,14 |
#define trap_virtual_enable_irqs(x) |
#define trap_virtual_eoi() |
struct istate { |
}; |
static inline void istate_set_retaddr(istate_t *istate, __address retaddr) |
{ |
/* TODO */ |
} |
extern void interrupt_register(int n, const char *name, iroutine f); |
#endif |
/kernel/trunk/arch/sparc64/src/asm.S |
---|
29,12 → 29,24 |
.text |
.global memcpy |
.global memcpy_from_uspace |
.global memcpy_to_uspace |
.global memcpy_from_uspace_failover_address |
.global memcpy_to_uspace_failover_address |
.global memsetb |
memcpy: |
memcpy_from_uspace: |
memcpy_to_uspace: |
b _memcpy |
nop |
memcpy_from_uspace_failover_address: |
memcpy_to_uspace_failover_address: |
b memcpy_from_uspace_failover_address |
nop |
memsetb: |
b _memsetb |
nop |
/kernel/trunk/arch/ia64/include/interrupt.h |
---|
106,6 → 106,11 |
__u64 in4; |
}; |
static inline void istate_set_retaddr(istate_t *istate, __address retaddr) |
{ |
/* TODO */ |
} |
extern void *ivt; |
extern void general_exception(__u64 vector, istate_t *istate); |
/kernel/trunk/arch/ia64/src/asm.S |
---|
30,9 → 30,25 |
.text |
/** Copy memory from/to userspace. |
* |
* @param in0 Destination address. |
* @param in1 Source address. |
* @param in2 Number of byte to copy. |
*/ |
.global memcpy |
.global memcpy_from_uspace |
.global memcpy_to_uspace |
.global memcpy_from_uspace_failover_address |
.global memcpy_to_uspace_failover_address |
memcpy: |
memcpy_from_uspace: |
memcpy_to_uspace: |
br _memcpy |
memcpy_from_uspace_failover_address: |
memcpy_to_uspace_failover_address: |
br memcpy_from_uspace_failover_address |
.global memsetb |
memsetb: |
/kernel/trunk/arch/ia64/src/mm/tlb.c |
---|
447,7 → 447,7 |
* Forward the page fault to address space page fault handler. |
*/ |
page_table_unlock(AS, true); |
if (!as_page_fault(va)) { |
if (as_page_fault(va, istate) == AS_PF_FAULT) { |
panic("%s: va=%p, rid=%d, iip=%p\n", __FUNCTION__, istate->cr_ifa, rr.map.rid, istate->cr_iip); |
} |
} |
493,7 → 493,7 |
* Forward the page fault to address space page fault handler. |
*/ |
page_table_unlock(AS, true); |
if (!as_page_fault(va)) { |
if (as_page_fault(va, istate) == AS_PF_FAULT) { |
panic("%s: va=%p, rid=%d, iip=%p\n", __FUNCTION__, va, rid, istate->cr_iip); |
} |
} |
608,7 → 608,7 |
page_table_unlock(AS, true); |
} else { |
page_table_unlock(AS, true); |
if (!as_page_fault(va)) { |
if (as_page_fault(va, istate) == AS_PF_FAULT) { |
panic("%s: va=%p, rid=%d\n", __FUNCTION__, va, rr.map.rid); |
} |
} |
/kernel/trunk/arch/ppc32/include/interrupt.h |
---|
29,6 → 29,8 |
#ifndef __ppc32_INTERRUPT_H__ |
#define __ppc32_INTERRUPT_H__ |
#include <arch/exception.h> |
#define IRQ_COUNT 1 |
#define IVT_ITEMS 15 |
#define INT_OFFSET 0 |
/kernel/trunk/arch/ppc32/include/exception.h |
---|
76,4 → 76,9 |
__u32 sp; |
}; |
static inline void istate_set_retaddr(istate_t *istate, __address retaddr) |
{ |
/* TODO */ |
} |
#endif |
/kernel/trunk/arch/ppc32/src/asm.S |
---|
35,6 → 35,10 |
.global iret_syscall |
.global memsetb |
.global memcpy |
.global memcpy_from_uspace |
.global memcpy_to_uspace |
.global memcpy_from_uspace_failover_address |
.global memcpy_to_uspace_failover_address |
userspace_asm: |
233,6 → 237,9 |
blr |
memcpy: |
memcpy_from_uspace: |
memcpy_to_uspace: |
srwi. r7, r5, 3 |
addi r6, r3, -4 |
addi r4, r4, -4 |
293,3 → 300,7 |
beq 2b |
mtctr r7 |
b 1b |
memcpy_from_uspace_failover_address: |
memcpy_to_uspace_failover_address: |
b memcpy_from_uspace_failover_address |
/kernel/trunk/arch/ppc32/src/mm/tlb.c |
---|
68,10 → 68,12 |
* The AS->lock must be held on entry to this function. |
* |
* @param badvaddr Faulting virtual address. |
* @param istate Pointer to interrupted state. |
* @param pfrc Pointer to variable where as_page_fault() return code will be stored. |
* @return PTE on success, NULL otherwise. |
* |
*/ |
static pte_t *find_mapping_and_check(__address badvaddr) |
static pte_t *find_mapping_and_check(__address badvaddr, istate_t *istate, int *pfcr) |
{ |
/* |
* Check if the mapping exists in page tables. |
84,12 → 86,15 |
*/ |
return pte; |
} else { |
int rc; |
/* |
* Mapping not found in page tables. |
* Resort to higher-level page fault handler. |
*/ |
page_table_unlock(AS, true); |
if (as_page_fault(badvaddr)) { |
switch (rc = as_page_fault(badvaddr, istate)) { |
case AS_PF_OK: |
/* |
* The higher-level page fault handler succeeded, |
* The mapping ought to be in place. |
98,12 → 103,22 |
pte = page_mapping_find(AS, badvaddr); |
ASSERT((pte) && (pte->p)); |
return pte; |
} else { |
break; |
case AS_PF_DEFER: |
page_table_lock(AS, true); |
*pfcr = rc; |
return NULL; |
break; |
case AS_PF_FAULT: |
page_table_lock(AS, true); |
printf("Page fault.\n"); |
*pfcr = rc; |
return NULL; |
} |
break; |
default: |
panic("unexpected rc (%d)\n", rc); |
break; |
} |
} |
} |
139,6 → 154,7 |
__u32 vsid; |
__u32 hash; |
__u32 i; |
int pfcr; |
if (data) { |
asm volatile ( |
154,9 → 170,24 |
page_table_lock(AS, true); |
pte = find_mapping_and_check(badvaddr); |
if (!pte) |
goto fail; |
pte = find_mapping_and_check(badvaddr, istate, &pfcr); |
if (!pte) { |
switch (pfcr) { |
case AS_PF_FAULT: |
goto fail; |
break; |
case AS_PF_DEFER: |
/* |
* The page fault came during copy_from_uspace() |
* or copy_to_uspace(). |
*/ |
page_table_unlock(AS, true); |
return; |
default: |
panic("Unexpected pfrc (%d)\n", pfcr); |
break; |
} |
} |
/* Record access to PTE */ |
pte->a = 1; |
/kernel/trunk/arch/amd64/include/interrupt.h |
---|
86,6 → 86,11 |
__u64 stack[]; /* Additional data on stack */ |
}; |
static inline void istate_set_retaddr(istate_t *istate, __address retaddr) |
{ |
istate->rip = retaddr; |
} |
extern void (* disable_irqs_function)(__u16 irqmask); |
extern void (* enable_irqs_function)(__u16 irqmask); |
extern void (* eoi_function)(void); |
/kernel/trunk/arch/amd64/src/asm_utils.S |
---|
60,16 → 60,60 |
movq $halt, (%rsp) |
jmp printf |
.global memcpy |
memcpy: |
jmp _memcpy |
.global cpuid |
.global has_cpuid |
.global rdtsc |
.global read_efer_flag |
.global set_efer_flag |
.global memcpy |
.global memcpy_from_uspace |
.global memcpy_to_uspace |
.global memcpy_from_uspace_failover_address |
.global memcpy_to_uspace_failover_address |
#define MEMCPY_DST %rdi |
#define MEMCPY_SRC %rsi |
#define MEMCPY_SIZE %rdx |
/** |
* Copy memory from/to userspace. |
* |
* This is almost conventional memcpy(). |
* The difference is that there is a failover part |
* to where control is returned from a page fault if |
* the page fault occurs during copy_from_uspace() |
* or copy_to_uspace(). |
* |
* @param MEMCPY_DST Destination address. |
* @param MEMCPY_SRC Source address. |
* @param MEMCPY_SIZE Number of bytes to copy. |
* |
* @retrun MEMCPY_SRC on success, 0 on failure. |
*/ |
memcpy: |
memcpy_from_uspace: |
memcpy_to_uspace: |
movq MEMCPY_SRC, %rax |
movq MEMCPY_SIZE, %rcx |
shrq $3, %rcx /* size / 8 */ |
rep movsq /* copy as much as possible word by word */ |
movq MEMCPY_SIZE, %rcx |
andq $7, %rcx /* size % 8 */ |
jz 0f |
rep movsb /* copy the rest byte by byte */ |
0: |
ret /* return MEMCPY_SRC, success */ |
memcpy_from_uspace_failover_address: |
memcpy_to_uspace_failover_address: |
xorq %rax, %rax /* return 0, failure */ |
ret |
## Determine CPUID support |
# |
# Return 0 in EAX if CPUID is not support, 1 if supported. |
/kernel/trunk/arch/amd64/src/mm/page.c |
---|
166,7 → 166,7 |
__address page; |
page = read_cr2(); |
if (!as_page_fault(page)) { |
if (as_page_fault(page, istate) == AS_PF_FAULT) { |
print_info_errcode(n, istate); |
printf("Page fault address: %llX\n", page); |
panic("page fault\n"); |
/kernel/trunk/arch/mips32/include/exception.h |
---|
93,6 → 93,11 |
__u32 k1; /* We use it as thread-local pointer */ |
}; |
static inline void istate_set_retaddr(istate_t *istate, __address retaddr) |
{ |
/* TODO */ |
} |
extern void exception(istate_t *istate); |
extern void tlb_refill_entry(void); |
extern void exception_entry(void); |
/kernel/trunk/arch/mips32/src/asm.S |
---|
57,11 → 57,25 |
j _memsetb |
nop |
.global memcpy |
.global memcpy_from_uspace |
.global memcpy_to_uspace |
.global memcpy_from_uspace_failover_address |
.global memcpy_to_uspace_failover_address |
memcpy: |
memcpy_from_uspace: |
memcpy_to_uspace: |
j _memcpy |
nop |
memcpy_from_uspace_failover_address: |
memcpy_to_uspace_failover_address: |
j memcpy_from_uspace_failover_address |
nop |
.macro fpu_gp_save reg ctx |
mfc1 $t0,$\reg |
sw $t0, \reg*4(\ctx) |
/kernel/trunk/arch/mips32/src/mm/tlb.c |
---|
44,7 → 44,7 |
static void tlb_invalid_fail(istate_t *istate); |
static void tlb_modified_fail(istate_t *istate); |
static pte_t *find_mapping_and_check(__address badvaddr); |
static pte_t *find_mapping_and_check(__address badvaddr, istate_t *istate, int *pfrc); |
static void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, __address pfn); |
static void prepare_entry_hi(entry_hi_t *hi, asid_t asid, __address addr); |
91,6 → 91,7 |
asid_t asid; |
__address badvaddr; |
pte_t *pte; |
int pfrc; |
badvaddr = cp0_badvaddr_read(); |
100,9 → 101,23 |
page_table_lock(AS, true); |
pte = find_mapping_and_check(badvaddr); |
if (!pte) |
goto fail; |
pte = find_mapping_and_check(badvaddr, istate, &pfrc); |
if (!pte) { |
switch (pfrc) { |
case AS_PF_FAULT: |
goto fail; |
break; |
case AS_PF_DEFER: |
/* |
* The page fault came during copy_from_uspace() |
* or copy_to_uspace(). |
*/ |
page_table_unlock(AS, true); |
return; |
default: |
panic("unexpected pfrc (%d)\n", pfrc); |
} |
} |
/* |
* Record access to PTE. |
148,6 → 163,7 |
entry_lo_t lo; |
entry_hi_t hi; |
pte_t *pte; |
int pfrc; |
badvaddr = cp0_badvaddr_read(); |
170,9 → 186,23 |
goto fail; |
} |
pte = find_mapping_and_check(badvaddr); |
if (!pte) |
goto fail; |
pte = find_mapping_and_check(badvaddr, istate, &pfrc); |
if (!pte) { |
switch (pfrc) { |
case AS_PF_FAULT: |
goto fail; |
break; |
case AS_PF_DEFER: |
/* |
* The page fault came during copy_from_uspace() |
* or copy_to_uspace(). |
*/ |
page_table_unlock(AS, true); |
return; |
default: |
panic("unexpected pfrc (%d)\n", pfrc); |
} |
} |
/* |
* Read the faulting TLB entry. |
217,6 → 247,7 |
entry_lo_t lo; |
entry_hi_t hi; |
pte_t *pte; |
int pfrc; |
badvaddr = cp0_badvaddr_read(); |
239,9 → 270,23 |
goto fail; |
} |
pte = find_mapping_and_check(badvaddr); |
if (!pte) |
goto fail; |
pte = find_mapping_and_check(badvaddr, istate, &pfrc); |
if (!pte) { |
switch (pfrc) { |
case AS_PF_FAULT: |
goto fail; |
break; |
case AS_PF_DEFER: |
/* |
* The page fault came during copy_from_uspace() |
* or copy_to_uspace(). |
*/ |
page_table_unlock(AS, true); |
return; |
default: |
panic("unexpected pfrc (%d)\n", pfrc); |
} |
} |
/* |
* Fail if the page is not writable. |
321,10 → 366,12 |
* The AS->lock must be held on entry to this function. |
* |
* @param badvaddr Faulting virtual address. |
* @param istate Pointer to interrupted state. |
* @param pfrc Pointer to variable where as_page_fault() return code will be stored. |
* |
* @return PTE on success, NULL otherwise. |
*/ |
pte_t *find_mapping_and_check(__address badvaddr) |
pte_t *find_mapping_and_check(__address badvaddr, istate_t *istate, int *pfrc) |
{ |
entry_hi_t hi; |
pte_t *pte; |
350,12 → 397,15 |
*/ |
return pte; |
} else { |
int rc; |
/* |
* Mapping not found in page tables. |
* Resort to higher-level page fault handler. |
*/ |
page_table_unlock(AS, true); |
if (as_page_fault(badvaddr)) { |
switch (rc = as_page_fault(badvaddr, istate)) { |
case AS_PF_OK: |
/* |
* The higher-level page fault handler succeeded, |
* The mapping ought to be in place. |
364,10 → 414,20 |
pte = page_mapping_find(AS, badvaddr); |
ASSERT(pte && pte->p); |
return pte; |
} else { |
break; |
case AS_PF_DEFER: |
page_table_lock(AS, true); |
*pfrc = AS_PF_DEFER; |
return NULL; |
break; |
case AS_PF_FAULT: |
page_table_lock(AS, true); |
printf("Page fault.\n"); |
*pfrc = AS_PF_FAULT; |
return NULL; |
break; |
default: |
panic("unexpected rc (%d)\n", rc); |
} |
} |
/kernel/trunk/arch/ia32/include/interrupt.h |
---|
83,6 → 83,11 |
__u32 stack[]; |
}; |
static inline void istate_set_retaddr(istate_t *istate, __address retaddr) |
{ |
istate->eip = retaddr; |
} |
extern void (* disable_irqs_function)(__u16 irqmask); |
extern void (* enable_irqs_function)(__u16 irqmask); |
extern void (* eoi_function)(void); |
/kernel/trunk/arch/ia32/src/asm.S |
---|
37,7 → 37,68 |
.global paging_on |
.global enable_l_apic_in_msr |
.global interrupt_handlers |
.global memcpy |
.global memcpy_from_uspace |
.global memcpy_from_uspace_failover_address |
.global memcpy_to_uspace |
.global memcpy_to_uspace_failover_address |
#define MEMCPY_DST 4 |
#define MEMCPY_SRC 8 |
#define MEMCPY_SIZE 12 |
/** Copy memory to/from userspace. |
* |
* This is almost conventional memcpy(). |
* The difference is that there is a failover part |
* to where control is returned from a page fault |
* if the page fault occurs during copy_from_uspace() |
* or copy_to_uspace(). |
* |
* @param MEMCPY_DST(%esp) Destination address. |
* @param MEMCPY_SRC(%esp) Source address. |
* @param MEMCPY_SIZE(%esp) Size. |
* |
* @return MEMCPY_SRC(%esp) on success and 0 on failure. |
*/ |
memcpy: |
memcpy_from_uspace: |
memcpy_to_uspace: |
movl %edi, %edx /* save %edi */ |
movl %esi, %eax /* save %esi */ |
movl MEMCPY_SIZE(%esp), %ecx |
shrl $2, %ecx /* size / 4 */ |
movl MEMCPY_DST(%esp), %edi |
movl MEMCPY_SRC(%esp), %esi |
rep movsl /* copy as much as possible word by word */ |
movl MEMCPY_SIZE(%esp), %ecx |
andl $3, %ecx /* size % 4 */ |
jz 0f |
rep movsb /* copy the rest byte by byte */ |
0: |
movl %edx, %edi |
movl %eax, %esi |
movl MEMCPY_SRC(%esp), %eax /* MEMCPY_SRC(%esp), success */ |
ret |
/* |
* We got here from as_page_fault() after the memory operations |
* above had caused a page fault. |
*/ |
memcpy_from_uspace_failover_address: |
memcpy_to_uspace_failover_address: |
movl %edx, %edi |
movl %eax, %esi |
xorl %eax, %eax /* return 0, failure */ |
ret |
## Turn paging on |
# |
# Enable paging and write-back caching in CR0. |
/kernel/trunk/arch/ia32/src/boot/boot.S |
---|
34,14 → 34,6 |
#define START_STACK (BOOT_OFFSET - BOOT_STACK_SIZE) |
.section K_TEXT_START, "ax" |
KTEXT=8 |
435,12 → 427,8 |
e_vesa_init: |
#endif |
.section K_DATA_START, "aw", @progbits |
.align 4096 |
page_directory: |
.space 4096, 0 |
/kernel/trunk/arch/ia32/src/interrupt.c |
---|
144,7 → 144,7 |
__address page; |
page = read_cr2(); |
if (!as_page_fault(page)) { |
if (as_page_fault(page, istate) == AS_PF_FAULT) { |
PRINT_INFO_ERRCODE(istate); |
printf("page fault address: %#x\n", page); |
panic("page fault\n"); |