//kernel/trunk/generic/src/mm/frame.c |
---|
434,11 → 434,15 |
/** Allocate frame in particular zone |
* |
* Assume zone is locked |
* Panics, if allocation is impossible. |
* Panics if allocation is impossible. |
* |
* @param zone Zone to allocate from. |
* @param order Allocate exactly 2^order frames. |
* |
* @return Frame index in zone |
* |
*/ |
static pfn_t zone_frame_alloc(zone_t *zone,__u8 order) |
static pfn_t zone_frame_alloc(zone_t *zone, __u8 order) |
{ |
pfn_t v; |
link_t *tmp; |
891,13 → 895,15 |
/** Allocate power-of-two frames of physical memory. |
* |
* @param flags Flags for host zone selection and address processing. |
* @param order Allocate exactly 2^order frames. |
* @param pzone Preferred zone |
* @param order Allocate exactly 2^order frames. |
* @param flags Flags for host zone selection and address processing. |
* @param status Allocation status (FRAME_OK on success), unused if NULL. |
* @param pzone Preferred zone |
* |
* @return Allocated frame. |
* |
*/ |
pfn_t frame_alloc_generic(__u8 order, int flags, int * status, int *pzone) |
pfn_t frame_alloc_generic(__u8 order, int flags, int *status, int *pzone) |
{ |
ipl_t ipl; |
int freed; |
906,20 → 912,22 |
loop: |
ipl = interrupts_disable(); |
/* |
* First, find suitable frame zone. |
*/ |
zone = find_free_zone_lock(order,pzone); |
zone = find_free_zone_lock(order, pzone); |
/* If no memory, reclaim some slab memory, |
if it does not help, reclaim all */ |
if (!zone && !(flags & FRAME_NO_RECLAIM)) { |
freed = slab_reclaim(0); |
if (freed) |
zone = find_free_zone_lock(order,pzone); |
zone = find_free_zone_lock(order, pzone); |
if (!zone) { |
freed = slab_reclaim(SLAB_RECLAIM_ALL); |
if (freed) |
zone = find_free_zone_lock(order,pzone); |
zone = find_free_zone_lock(order, pzone); |
} |
} |
if (!zone) { |
941,7 → 949,8 |
panic("Sleep not implemented.\n"); |
goto loop; |
} |
v = zone_frame_alloc(zone,order); |
v = zone_frame_alloc(zone, order); |
v += zone->base; |
spinlock_unlock(&zone->lock); |
//kernel/trunk/arch/ppc32/include/mm/tlb.h |
---|
32,6 → 32,23 |
#include <arch/exception.h> |
#include <typedefs.h> |
extern void pht_refill(istate_t *istate); |
#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/exception.S |
---|
138,7 → 138,8 |
mtlr r3 |
addis sp, sp, 0x8000 |
mr r3, sp |
li r3, 1 |
mr r4, sp |
rfi |
.org 0x400 |
159,7 → 160,8 |
mtlr r3 |
addis sp, sp, 0x8000 |
mr r3, sp |
li r3, 0 |
mr r4, sp |
rfi |
.org 0x500 |
//kernel/trunk/arch/ppc32/src/mm/tlb.c |
---|
29,6 → 29,7 |
#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> |
36,6 → 37,9 |
#include <symtab.h> |
static phte_t *phte; |
/** Initialize Page Hash Table. |
* |
* Setup the Page Hash Table with no entries. |
43,6 → 47,18 |
*/ |
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) |
); |
} |
103,26 → 119,35 |
s = get_symtab_entry(istate->lr); |
if (s) |
sym2 = s; |
panic("%X: PHT Refill Exception at %X(%s<-%s)\n", badvaddr, istate->pc, symbol, sym2); |
panic("%p: PHT Refill Exception at %p (%s<-%s)\n", badvaddr, istate->pc, symbol, sym2); |
} |
/** Process Data Storage Interrupt |
/** Process Instruction/Data Storage Interrupt |
* |
* @param data True if Data Storage Interrupt. |
* @param istate Interrupted register context. |
* |
*/ |
void pht_refill(istate_t *istate) |
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; |
__asm__ volatile ( |
"mfdar %0\n" |
: "=r" (badvaddr) |
); |
if (data) { |
asm volatile ( |
"mfdar %0\n" |
: "=r" (badvaddr) |
); |
} else |
badvaddr = istate->pc; |
spinlock_lock(&AS->lock); |
asid = AS->asid; |
spinlock_unlock(&AS->lock); |
133,13 → 158,40 |
if (!pte) |
goto fail; |
/* |
* Record access to PTE. |
*/ |
/* Record access to PTE */ |
pte->a = 1; |
// FIXME: Insert entry into PHT |
page = ADDR2PFN(badvaddr); |
api = (badvaddr >> 22) & 0x3f; |
asm volatile ( |
"mfsrin %0, %1\n" |
: "=r" (vsid) |
: "r" (badvaddr >> 28) |
); |
/* 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; |
//kernel/trunk/arch/ppc32/src/drivers/cuda.c |
---|
71,6 → 71,10 |
void cpu_halt(void) { |
#ifdef CONFIG_POWEROFF |
cuda_packet(CUDA_POWERDOWN); |
#else |
asm volatile ( |
"b 0\n" |
); |
#endif |
cpu_sleep(); |
} |