/kernel/trunk/arch/ppc32/_link.ld.in |
---|
11,7 → 11,7 |
ENTRY(kernel_image_start) |
SECTIONS { |
.image 0x80000000: AT (0x80000000) { |
.image 0x800000: AT (0x800000) { |
ktext_start = .; |
*(K_TEXT_START) |
*(.text); |
30,7 → 30,7 |
hardcoded_kdata_size = .; |
LONG(kdata_end - kdata_start); |
hardcoded_load_address = .; |
LONG(0x80000000); |
LONG(0x800000); |
*(.bss); /* uninitialized static variables */ |
*(COMMON); /* global variables */ |
/kernel/trunk/arch/ppc32/include/asm/spr.h |
---|
0,0 → 1,41 |
/* |
* Copyright (C) 2006 Ondrej Palkovsky |
* 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. |
*/ |
#ifndef __ppc32_SPR_H__ |
#define __ppc32_SPR_H__ |
#define MSR_DR (1<<27) |
#define MSR_IR (1<<26) |
#define SPRN_SRR0 0x1a |
#define SPRN_SRR1 0x1b |
/* Works for PPC32 */ |
#define L1_CACHE_BYTES (1 << 5) |
#endif |
/kernel/trunk/arch/ppc32/include/console.h |
---|
29,6 → 29,6 |
#ifndef __ppc32_CONSOLE_H__ |
#define __ppc32_CONSOLE_H__ |
extern void ofw_ppc32_console_init(void); |
extern void ppc32_console_init(void); |
#endif |
/kernel/trunk/arch/ppc32/include/mm/memory_init.h |
---|
32,5 → 32,7 |
#include <config.h> |
size_t get_memory_size(void); |
void preboot_read_config(void); |
void ppc_init_zones(void); |
#endif |
/kernel/trunk/arch/ppc32/include/mm/page.h |
---|
36,8 → 36,8 |
#define PAGE_WIDTH FRAME_WIDTH |
#define PAGE_SIZE FRAME_SIZE |
#define KA2PA(x) (((__address) (x)) - 0x80000000) |
#define PA2KA(x) (((__address) (x)) + 0x80000000) |
#define KA2PA(x) ((__address)(x)) |
#define PA2KA(x) ((__address)(x)) |
#define PTL0_ENTRIES_ARCH 0 |
#define PTL1_ENTRIES_ARCH 0 |
/kernel/trunk/arch/ppc32/src/console.c |
---|
30,24 → 30,12 |
#include <genarch/ofw/ofw.h> |
#include <console/chardev.h> |
#include <console/console.h> |
#include <genarch/fb/fb.h> |
/** Print one character. |
* |
* @param ch Character to be printed. |
*/ |
static void ofw_ppc32_putchar(chardev_t *d, const char ch) |
{ |
ofw_putchar(ch); |
} |
static chardev_t ofw_ppc32_console; |
static chardev_operations_t ofw_ppc32_console_ops = { |
.write = ofw_ppc32_putchar |
}; |
/** Initialize console to use ofw output */ |
void ofw_ppc32_console_init(void) |
void ppc32_console_init(void) |
{ |
chardev_initialize("ofw_out", &ofw_ppc32_console, &ofw_ppc32_console_ops); |
stdout = &ofw_ppc32_console; |
/* TODO: PCI detection etc. etc. - this is fine in PearPC for now */ |
fb_init(0x84000000,800,600,4); |
} |
/kernel/trunk/arch/ppc32/src/ppc32.c |
---|
31,7 → 31,7 |
void arch_pre_mm_init(void) |
{ |
ofw_ppc32_console_init(); |
ppc32_console_init(); |
} |
void arch_post_mm_init(void) |
/kernel/trunk/arch/ppc32/src/mm/frame.c |
---|
27,6 → 27,7 |
*/ |
#include <arch/mm/frame.h> |
#include <arch/mm/memory_init.h> |
#include <mm/frame.h> |
#include <config.h> |
#include <panic.h> |
33,9 → 34,7 |
void frame_arch_init(void) |
{ |
/* First page is exception vector, |
* second is 'implementation specific', evade it too |
*/ |
zone_create(0, SIZE2FRAMES(config.memory_size), 2, 0); |
ppc_init_zones(); |
/* First is exception vector, second is 'implementation specific' */ |
frame_mark_unavailable(0, 2); |
} |
/kernel/trunk/arch/ppc32/src/mm/memory_init.c |
---|
29,6 → 29,8 |
#include <arch/mm/memory_init.h> |
#include <genarch/ofw/ofw.h> |
#include <panic.h> |
#include <mm/frame.h> |
#include <align.h> |
#define MEMMAP_MAX_RECORDS 32 |
37,25 → 39,52 |
__u32 size; |
} memmap_t; |
size_t get_memory_size(void) |
static memmap_t memmap[MEMMAP_MAX_RECORDS]; |
size_t total_mem = 0; |
static void init_memmap(void) |
{ |
int i; |
phandle handle = ofw_find_device("/memory"); |
if (handle == -1) |
panic("No RAM\n"); |
memmap_t memmap[MEMMAP_MAX_RECORDS]; |
size_t ret = ofw_get_property(handle, "reg", &memmap, sizeof(memmap)); |
if (ret == -1) |
panic("Device /memory has no reg property\n"); |
size_t total = 0; |
int i; |
for (i = 0; i < MEMMAP_MAX_RECORDS; i++) { |
if (memmap[i].size == 0) |
break; |
total += memmap[i].size; |
total_mem += memmap[i].size; |
} |
} |
return total; |
void preboot_read_config(void) |
{ |
init_memmap(); |
} |
size_t get_memory_size(void) |
{ |
return total_mem; |
} |
void ppc_init_zones(void) |
{ |
int i; |
pfn_t confdata; |
for (i = 0; i < MEMMAP_MAX_RECORDS; i++) { |
if (memmap[i].size == 0) |
break; |
confdata = ADDR2PFN(memmap[i].start); |
if (confdata == 0) |
confdata = 2; |
zone_create(ADDR2PFN(memmap[i].start), |
SIZE2FRAMES(ALIGN_DOWN(memmap[i].size,PAGE_SIZE)), |
confdata, 0); |
} |
} |
/kernel/trunk/arch/ppc32/src/start.S |
---|
27,16 → 27,71 |
# |
#include <arch/asm/macro.h> |
#include <arch/asm/spr.h> |
.section K_TEXT_START |
.global kernel_image_start |
.org 0x0 |
/* 256 bytes of some data */ |
/* exception table - must use 'ba' instructions for branches, |
* because it is elsewhere than the linker thinks |
*/ |
.space 4096 |
kernel_image_start: |
/* Initialize OFW, might be needed before relocate_kernel? */ |
lis r4, ofw@ha |
addi r4, r4, ofw@l |
stw r5, 0(r4) |
bl ofw_init |
bl preboot_read_config |
bl relocate_kernel |
__after_reloc: |
/* Set stack to some more meaningful value */ |
/* TODO: This is hardcoded for PearPC, must be changed later */ |
lis r1, 0x70 |
b main_bsp |
relocate_kernel: |
/* TODO: We _know_ that pearpc loads it to 8MB, and |
* but it should be really generic |
*/ |
lis r4, 0x80 /* r4 is where data was loaded - 8MB */ |
bl to_real_mode |
/* Now we are in real mode, copy first block and jump to it, |
* we are running in the loaded kernel now |
* We still have in r3 physical load kernel address |
*/ |
b __after_reloc /* We know in pearpc we are ok, so return, |
* otherwise we should relocate kernel |
* here |
*/ |
/* Turn off page translation |
* - assume that physical-loaded address is in r4 |
*/ |
to_real_mode: |
mflr r0 |
lis r5, ktext_start@ha // Expected start of kernel |
addi r5, r5, ktext_start@l |
add r0, r4, r0 |
sub r0, r0, r5 // r0 now contains physical return address |
mfmsr r3 |
andis. r3, r3, (~MSR_DR | MSR_IR) >> 16 |
mtspr SPRN_SRR0, r0 |
mtspr SPRN_SRR1, r3 |
sync // Really needed? RFI should do it as well? |
RFI |