Subversion Repositories HelenOS-historic

Compare Revisions

Ignore whitespace Rev 1373 → Rev 1374

/kernel/trunk/arch/ppc32/include/console.h
File deleted
/kernel/trunk/arch/ppc32/include/asm/regname.h
189,6 → 189,22
#define sprg2 274
#define sprg3 275
#define prv 287
#define ibat0u 528
#define ibat0l 529
#define ibat1u 530
#define ibat1l 531
#define ibat2u 532
#define ibat2l 533
#define ibat3u 534
#define ibat3l 535
#define dbat0u 536
#define dbat0l 537
#define dbat1u 538
#define dbat1l 539
#define dbat2u 540
#define dbat2l 541
#define dbat3u 542
#define dbat3l 543
#define hid0 1008
 
/* MSR bits */
/kernel/trunk/arch/ppc32/include/types.h
52,6 → 52,7
typedef struct {
unsigned p : 1; /**< Present bit. */
unsigned a : 1; /**< Accessed bit. */
unsigned g : 1; /**< Global bit. */
unsigned valid : 1; /**< Valid content even if not present. */
unsigned pfn : 20; /**< Physical frame number. */
} pte_t;
/kernel/trunk/arch/ppc32/include/asm.h
140,6 → 140,7
 
void cpu_halt(void);
void asm_delay_loop(__u32 t);
void invalidate_bat(void);
 
extern void userspace_asm(__address uspace_uarg, __address stack, __address entry);
 
/kernel/trunk/arch/ppc32/include/mm/frame.h
35,6 → 35,10
#ifdef KERNEL
#ifndef __ASM__
 
#include <arch/types.h>
 
extern __address last_frame;
 
extern void frame_arch_init(void);
 
#endif /* __ASM__ */
/kernel/trunk/arch/ppc32/include/mm/page.h
108,7 → 108,8
(1 << PAGE_USER_SHIFT) |
(1 << PAGE_READ_SHIFT) |
(1 << PAGE_WRITE_SHIFT) |
(1 << PAGE_EXEC_SHIFT)
(1 << PAGE_EXEC_SHIFT) |
(p->g << PAGE_GLOBAL_SHIFT)
);
}
 
117,11 → 118,32
pte_t *p = &pt[i];
p->p = !(flags & PAGE_NOT_PRESENT);
p->g = (flags & PAGE_GLOBAL) != 0;
p->valid = 1;
}
 
extern void page_arch_init(void);
 
#define PHT_BITS 16
#define PHT_ORDER 4
 
typedef struct {
unsigned v : 1; /**< Valid */
unsigned vsid : 24; /**< Virtual Segment ID */
unsigned h : 1; /**< Primary/secondary hash */
unsigned api : 6; /**< Abbreviated Page Index */
unsigned rpn : 20; /**< Real Page Number */
unsigned reserved0 : 3;
unsigned r : 1; /**< Reference */
unsigned c : 1; /**< Change */
unsigned wimg : 4; /**< Access control */
unsigned reserved1 : 1;
unsigned pp : 2; /**< Page protection */
} phte_t;
 
extern void pht_refill(bool data, istate_t *istate);
extern void pht_init(void);
 
#endif /* __ASM__ */
 
#endif /* KERNEL */
/kernel/trunk/arch/ppc32/include/mm/tlb.h
29,26 → 29,5
#ifndef __ppc32_TLB_H__
#define __ppc32_TLB_H__
 
#include <arch/exception.h>
#include <typedefs.h>
 
#define PHT_BITS 16
#define PHT_ORDER 4
 
typedef struct {
unsigned v : 1; /**< Valid */
unsigned vsid : 24; /**< Virtual Segment ID */
unsigned h : 1; /**< Primary/secondary hash */
unsigned api : 6; /**< Abbreviated Page Index */
unsigned rpn : 20; /**< Real Page Number */
unsigned reserved0 : 3;
unsigned r : 1; /**< Reference */
unsigned c : 1; /**< Change */
unsigned wimg : 4; /**< Access control */
unsigned reserved1 : 1;
unsigned pp : 2; /**< Page protection */
} phte_t;
 
extern void pht_refill(bool data, istate_t *istate);
 
#endif
/kernel/trunk/arch/ppc32/src/asm.S
33,6 → 33,7
.global userspace_asm
.global iret
.global iret_syscall
.global invalidate_bat
.global memsetb
.global memcpy
.global memcpy_from_uspace
193,6 → 194,38
 
rfi
invalidate_bat:
# invalidate block address translation registers
li r14, 0
mtspr ibat0u, r14
mtspr ibat0l, r14
mtspr ibat1u, r14
mtspr ibat1l, r14
mtspr ibat2u, r14
mtspr ibat2l, r14
mtspr ibat3u, r14
mtspr ibat3l, r14
mtspr dbat0u, r14
mtspr dbat0l, r14
mtspr dbat1u, r14
mtspr dbat1l, r14
mtspr dbat2u, r14
mtspr dbat2l, r14
mtspr dbat3u, r14
mtspr dbat3l, r14
blr
memsetb:
rlwimi r5, r5, 8, 16, 23
rlwimi r5, r5, 16, 0, 15
/kernel/trunk/arch/ppc32/src/proc/scheduler.c
40,7 → 40,7
/** Perform ppc32 specific tasks needed before the new thread is scheduled. */
void before_thread_runs_arch(void)
{
tlb_invalidate_all();
pht_init();
asm volatile (
"mtsprg0 %0\n"
:
/kernel/trunk/arch/ppc32/src/ppc32.c
28,10 → 28,10
 
#include <arch.h>
#include <arch/boot/boot.h>
#include <arch/console.h>
#include <arch/drivers/cuda.h>
#include <arch/mm/memory_init.h>
#include <arch/interrupt.h>
#include <genarch/fb/fb.h>
#include <userspace.h>
#include <proc/uarg.h>
 
67,8 → 67,6
/* Merge all zones to 1 big zone */
zone_merge_all();
ppc32_console_register();
}
}
 
/kernel/trunk/arch/ppc32/src/mm/tlb.c
26,20 → 26,9
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <arch/mm/tlb.h>
#include <arch/types.h>
#include <mm/tlb.h>
#include <mm/frame.h>
#include <mm/page.h>
#include <mm/as.h>
#include <arch.h>
#include <print.h>
#include <symtab.h>
 
 
static phte_t *phte;
 
 
/** Initialize Page Hash Table.
*
* Setup the Page Hash Table with no entries.
47,198 → 36,14
*/
void tlb_arch_init(void)
{
phte_t *physical_phte = (phte_t *) PFN2ADDR(frame_alloc(PHT_ORDER, FRAME_KA | FRAME_PANIC));
phte =(phte_t *) PA2KA((__address) physical_phte);
ASSERT((__address) physical_phte % (1 << PHT_BITS) == 0);
memsetb((__address) phte, 1 << PHT_BITS, 0);
asm volatile (
"mtsdr1 %0\n"
:
: "r" ((__address) physical_phte)
"tlbia\n"
);
}
 
 
/** Try to find PTE for faulting address
*
* Try to find PTE for faulting address.
* 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, istate_t *istate, int *pfcr)
{
/*
* Check if the mapping exists in page tables.
*/
pte_t *pte = page_mapping_find(AS, badvaddr);
if ((pte) && (pte->p)) {
/*
* Mapping found in page tables.
* Immediately succeed.
*/
return pte;
} else {
int rc;
/*
* Mapping not found in page tables.
* Resort to higher-level page fault handler.
*/
page_table_unlock(AS, true);
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.
*/
page_table_lock(AS, true);
pte = page_mapping_find(AS, badvaddr);
ASSERT((pte) && (pte->p));
return pte;
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;
}
}
}
 
 
static void pht_refill_fail(__address badvaddr, istate_t *istate)
{
char *symbol = "";
char *sym2 = "";
 
char *s = get_symtab_entry(istate->pc);
if (s)
symbol = s;
s = get_symtab_entry(istate->lr);
if (s)
sym2 = s;
panic("%p: PHT Refill Exception at %p (%s<-%s)\n", badvaddr, istate->pc, symbol, sym2);
}
 
 
/** Process Instruction/Data Storage Interrupt
*
* @param data True if Data Storage Interrupt.
* @param istate Interrupted register context.
*
*/
void pht_refill(bool data, istate_t *istate)
{
asid_t asid;
__address badvaddr;
pte_t *pte;
__u32 page;
__u32 api;
__u32 vsid;
__u32 hash;
__u32 i;
int pfcr;
if (data) {
asm volatile (
"mfdar %0\n"
: "=r" (badvaddr)
);
} else
badvaddr = istate->pc;
spinlock_lock(&AS->lock);
asid = AS->asid;
spinlock_unlock(&AS->lock);
page_table_lock(AS, true);
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;
page = (badvaddr >> 12) & 0xffff;
api = (badvaddr >> 22) & 0x3f;
asm volatile (
"mfsrin %0, %1\n"
: "=r" (vsid)
: "r" (badvaddr)
);
/* Primary hash (xor) */
hash = ((vsid ^ page) & 0x3ff) << 3;
/* Find invalid PTE in PTEG */
for (i = 0; i < 8; i++) {
if (!phte[hash + i].v)
break;
}
// TODO: Check access/change bits, secondary hash
if (i == 8)
i = page % 8;
phte[hash + i].v = 1;
phte[hash + i].vsid = vsid;
phte[hash + i].h = 0;
phte[hash + i].api = api;
phte[hash + i].rpn = pte->pfn;
phte[hash + i].r = 0;
phte[hash + i].c = 0;
phte[hash + i].pp = 2; // FIXME
page_table_unlock(AS, true);
return;
fail:
page_table_unlock(AS, true);
pht_refill_fail(badvaddr, istate);
}
 
 
void tlb_invalidate_all(void)
{
ipl_t ipl;
 
ipl = interrupts_disable();
memsetb((__address) phte, 1 << PHT_BITS, 0);
interrupts_restore(ipl);
}
 
 
/kernel/trunk/arch/ppc32/src/mm/page.c
29,11 → 29,236
#include <arch/mm/page.h>
#include <genarch/mm/page_pt.h>
#include <arch/mm/frame.h>
#include <arch/asm.h>
#include <mm/frame.h>
#include <mm/page.h>
#include <mm/as.h>
#include <arch.h>
#include <arch/types.h>
#include <arch/exception.h>
#include <config.h>
#include <print.h>
#include <symtab.h>
 
static phte_t *phte;
 
 
/** Try to find PTE for faulting address
*
* Try to find PTE for faulting address.
* 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, istate_t *istate, int *pfcr)
{
/*
* Check if the mapping exists in page tables.
*/
pte_t *pte = page_mapping_find(AS, badvaddr);
if ((pte) && (pte->p)) {
/*
* Mapping found in page tables.
* Immediately succeed.
*/
return pte;
} else {
int rc;
/*
* Mapping not found in page tables.
* Resort to higher-level page fault handler.
*/
page_table_unlock(AS, true);
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.
*/
page_table_lock(AS, true);
pte = page_mapping_find(AS, badvaddr);
ASSERT((pte) && (pte->p));
return pte;
case AS_PF_DEFER:
page_table_lock(AS, true);
*pfcr = rc;
return NULL;
case AS_PF_FAULT:
page_table_lock(AS, true);
printf("Page fault.\n");
*pfcr = rc;
return NULL;
default:
panic("unexpected rc (%d)\n", rc);
}
}
}
 
 
static void pht_refill_fail(__address badvaddr, istate_t *istate)
{
char *symbol = "";
char *sym2 = "";
 
char *s = get_symtab_entry(istate->pc);
if (s)
symbol = s;
s = get_symtab_entry(istate->lr);
if (s)
sym2 = s;
panic("%p: PHT Refill Exception at %p (%s<-%s)\n", badvaddr, istate->pc, symbol, sym2);
}
 
static void pht_insert(const __address vaddr, const pfn_t pfn)
{
__u32 page = (vaddr >> 12) & 0xffff;
__u32 api = (vaddr >> 22) & 0x3f;
__u32 vsid;
asm volatile (
"mfsrin %0, %1\n"
: "=r" (vsid)
: "r" (vaddr)
);
/* Primary hash (xor) */
__u32 hash = ((vsid ^ page) & 0x3ff) << 3;
__u32 i;
/* Find unused PTE in PTEG */
for (i = 0; i < 8; i++) {
if (!phte[hash + i].v)
break;
}
// TODO: Check access/change bits, secondary hash
if (i == 8)
i = page % 8;
phte[hash + i].v = 1;
phte[hash + i].vsid = vsid;
phte[hash + i].h = 0;
phte[hash + i].api = api;
phte[hash + i].rpn = pfn;
phte[hash + i].r = 0;
phte[hash + i].c = 0;
phte[hash + i].pp = 2; // FIXME
}
 
 
/** Process Instruction/Data Storage Interrupt
*
* @param data True if Data Storage Interrupt.
* @param istate Interrupted register context.
*
*/
void pht_refill(bool data, istate_t *istate)
{
asid_t asid;
__address badvaddr;
pte_t *pte;
int pfcr;
if (data) {
asm volatile (
"mfdar %0\n"
: "=r" (badvaddr)
);
} else
badvaddr = istate->pc;
spinlock_lock(&AS->lock);
asid = AS->asid;
spinlock_unlock(&AS->lock);
page_table_lock(AS, true);
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;
}
}
pte->a = 1; /* Record access to PTE */
pht_insert(badvaddr, pte->pfn);
page_table_unlock(AS, true);
return;
fail:
page_table_unlock(AS, true);
pht_refill_fail(badvaddr, istate);
}
 
 
void pht_init(void)
{
memsetb((__address) phte, 1 << PHT_BITS, 0);
/* Insert global kernel mapping */
__address cur;
for (cur = 0; cur < last_frame; cur += FRAME_SIZE) {
pte_t *pte = page_mapping_find(AS_KERNEL, PA2KA(cur));
if ((pte) && (pte->p) && (pte->g))
pht_insert(PA2KA(cur), pte->pfn);
}
}
 
 
void page_arch_init(void)
{
page_mapping_operations = &pt_mapping_operations;
if (config.cpu_active == 1) {
page_mapping_operations = &pt_mapping_operations;
/*
* PA2KA(identity) mapping for all frames until last_frame.
*/
__address cur;
int flags;
for (cur = 0; cur < last_frame; cur += FRAME_SIZE) {
flags = PAGE_CACHEABLE;
if ((PA2KA(cur) >= config.base) && (PA2KA(cur) < config.base + config.kernel_size))
flags |= PAGE_GLOBAL;
page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, flags);
}
/* Allocate page hash table */
phte_t *physical_phte = (phte_t *) PFN2ADDR(frame_alloc(PHT_ORDER, FRAME_KA | FRAME_PANIC));
phte = (phte_t *) PA2KA((__address) physical_phte);
ASSERT((__address) physical_phte % (1 << PHT_BITS) == 0);
pht_init();
asm volatile (
"mtsdr1 %0\n"
:
: "r" ((__address) physical_phte)
);
/* Invalidate block address translation registers,
thus remove the temporary mapping */
// invalidate_bat();
}
}