mirror of
https://github.com/xenia-project/xell-rs.git
synced 2024-11-23 11:29:43 +00:00
Latest updates
This commit is contained in:
parent
e64f5006ca
commit
91291912ae
@ -2,10 +2,11 @@
|
|||||||
[build]
|
[build]
|
||||||
target = "powerpc64-unknown-linux-gnu"
|
target = "powerpc64-unknown-linux-gnu"
|
||||||
|
|
||||||
[profile]
|
[profile.release]
|
||||||
incremental = false
|
incremental = false
|
||||||
opt-level = "z"
|
opt-level = "z"
|
||||||
lto = true
|
lto = true
|
||||||
|
|
||||||
[target.powerpc64-unknown-linux-gnu]
|
[target.powerpc64-unknown-linux-gnu]
|
||||||
linker = "rust-lld"
|
linker = "rust-lld"
|
||||||
|
rustflags = ["-C", "relocation-model=static"]
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
|
.vscode/
|
||||||
**/target
|
**/target
|
||||||
|
15
.vscode/tasks.json
vendored
15
.vscode/tasks.json
vendored
@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"version": "2.0.0",
|
|
||||||
"tasks": [
|
|
||||||
{
|
|
||||||
"type": "cargo",
|
|
||||||
"command": "build",
|
|
||||||
"args": ["-Zextra-link-arg"],
|
|
||||||
"problemMatcher": [
|
|
||||||
"$rustc"
|
|
||||||
],
|
|
||||||
"group": "build",
|
|
||||||
"label": "rust: cargo build"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
13
Cargo.lock
generated
13
Cargo.lock
generated
@ -79,11 +79,24 @@ name = "stage1"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"core_reqs",
|
"core_reqs",
|
||||||
|
"xenon-cpu",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "volatile"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e4c2dbd44eb8b53973357e6e207e370f0c1059990df850aca1eca8947cf464f0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "xenon-cpu"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "xenon-enet"
|
name = "xenon-enet"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"smoltcp",
|
"smoltcp",
|
||||||
|
"volatile",
|
||||||
|
"xenon-cpu",
|
||||||
]
|
]
|
||||||
|
@ -5,6 +5,7 @@ members = [
|
|||||||
"boot/stage1",
|
"boot/stage1",
|
||||||
"shared/core_reqs",
|
"shared/core_reqs",
|
||||||
"shared/display",
|
"shared/display",
|
||||||
|
"shared/xenon-cpu",
|
||||||
"shared/xenon-enet",
|
"shared/xenon-enet",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -7,8 +7,13 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
core_reqs = { path = "../../shared/core_reqs" }
|
core_reqs = { path = "../../shared/core_reqs" }
|
||||||
|
xenon-cpu = { path = "../../shared/xenon-cpu" }
|
||||||
|
|
||||||
|
[profile.dev]
|
||||||
|
panic = "abort"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
|
panic = "abort"
|
||||||
opt-level = "s"
|
opt-level = "s"
|
||||||
lto = true
|
lto = true
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ SECTIONS
|
|||||||
{
|
{
|
||||||
. = 0x800000001c000000;
|
. = 0x800000001c000000;
|
||||||
|
|
||||||
.text : {
|
.text 0x800000001c000000 : {
|
||||||
KEEP(*(.text.startup));
|
KEEP(*(.text.startup));
|
||||||
*(.text .text.*);
|
*(.text .text.*);
|
||||||
}
|
}
|
||||||
@ -12,6 +12,15 @@ SECTIONS
|
|||||||
.sdata : { *(.sdata) }
|
.sdata : { *(.sdata) }
|
||||||
.rodata : { *(.rodata) }
|
.rodata : { *(.rodata) }
|
||||||
|
|
||||||
|
.dynsym : { *(.dynsym) }
|
||||||
|
.gnu.hash : { *(.gnu.hash) }
|
||||||
|
.hash : { *(.hash) }
|
||||||
|
.dynstr : { *(.dynstr) }
|
||||||
|
.rela.dyn : { *(.rela.dyn) }
|
||||||
|
.rela.opd : { *(.rela.opd) }
|
||||||
|
.eh_frame_hdr : { *(.eh_frame_hdr) }
|
||||||
|
.eh_frame : { *(.eh_frame) }
|
||||||
|
|
||||||
.got : {
|
.got : {
|
||||||
__toc_start = .;
|
__toc_start = .;
|
||||||
|
|
||||||
@ -21,7 +30,7 @@ SECTIONS
|
|||||||
|
|
||||||
. = ALIGN(256);
|
. = ALIGN(256);
|
||||||
__bss_start = .;
|
__bss_start = .;
|
||||||
.bss : { *(.bss .bss.*) }
|
.bss (NOLOAD) : { *(.bss .bss.*) }
|
||||||
.sbss : { *(.sbss .sbss.*) }
|
.sbss : { *(.sbss .sbss.*) }
|
||||||
__bss_end = .;
|
__bss_end = .;
|
||||||
}
|
}
|
||||||
|
189
boot/stage1/src/except.rs
Normal file
189
boot/stage1/src/except.rs
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
//! This module defines exception handlers.
|
||||||
|
|
||||||
|
use crate::iic::Iic;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[repr(u32)]
|
||||||
|
enum ExceptionType {
|
||||||
|
Reset = 1,
|
||||||
|
MachineCheck = 2,
|
||||||
|
Dsi = 3,
|
||||||
|
Isi = 4,
|
||||||
|
ExternalInterrupt = 5,
|
||||||
|
Alignment = 6,
|
||||||
|
Program = 7,
|
||||||
|
Decrementer = 9,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C, align(4096))]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
struct CpuContext {
|
||||||
|
r: [u64; 32],
|
||||||
|
lr: u64,
|
||||||
|
ctr: u64,
|
||||||
|
srr0: u64,
|
||||||
|
srr1: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CpuContext {
|
||||||
|
const fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
r: [0u64; 32],
|
||||||
|
lr: 0,
|
||||||
|
ctr: 0,
|
||||||
|
srr0: 0,
|
||||||
|
srr1: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
static mut EXCEPTION_SAVE_AREA: [CpuContext; 6] = [CpuContext::new(); 6];
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn except(id: ExceptionType, save_area: &mut CpuContext) {
|
||||||
|
match id {
|
||||||
|
ExceptionType::ExternalInterrupt => {
|
||||||
|
let iic = unsafe { Iic::local() };
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => loop {}
|
||||||
|
}
|
||||||
|
|
||||||
|
load_context(save_area);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_context(ctx: &CpuContext) -> ! {
|
||||||
|
unsafe {
|
||||||
|
asm!(
|
||||||
|
"ld %r0, 256(%r4)",
|
||||||
|
"mtlr %r0",
|
||||||
|
"ld %r0, 264(%r4)",
|
||||||
|
"mtctr %r0",
|
||||||
|
"ld %r0, 272(%r4)",
|
||||||
|
"mtsrr0 %r0",
|
||||||
|
"ld %r0, 280(%r4)",
|
||||||
|
"mtsrr1 %r0",
|
||||||
|
"ld %r0, 0(%r4)",
|
||||||
|
"ld %r1, 8(%r4)",
|
||||||
|
"ld %r2, 16(%r4)",
|
||||||
|
"ld %r3, 24(%r4)",
|
||||||
|
"ld %r4, 32(%r4)",
|
||||||
|
"ld %r5, 40(%r4)",
|
||||||
|
"ld %r6, 48(%r4)",
|
||||||
|
"ld %r7, 56(%r4)",
|
||||||
|
"ld %r8, 64(%r4)",
|
||||||
|
"ld %r9, 72(%r4)",
|
||||||
|
"ld %r10, 80(%r4)",
|
||||||
|
"ld %r11, 88(%r4)",
|
||||||
|
"ld %r12, 96(%r4)",
|
||||||
|
"ld %r13, 104(%r4)",
|
||||||
|
"ld %r14, 112(%r4)",
|
||||||
|
"ld %r15, 120(%r4)",
|
||||||
|
"ld %r16, 128(%r4)",
|
||||||
|
"ld %r17, 136(%r4)",
|
||||||
|
"ld %r18, 144(%r4)",
|
||||||
|
"ld %r19, 152(%r4)",
|
||||||
|
"ld %r20, 160(%r4)",
|
||||||
|
"ld %r21, 168(%r4)",
|
||||||
|
"ld %r22, 176(%r4)",
|
||||||
|
"ld %r23, 184(%r4)",
|
||||||
|
"ld %r24, 192(%r4)",
|
||||||
|
"ld %r25, 200(%r4)",
|
||||||
|
"ld %r26, 208(%r4)",
|
||||||
|
"ld %r27, 216(%r4)",
|
||||||
|
"ld %r28, 224(%r4)",
|
||||||
|
"ld %r29, 232(%r4)",
|
||||||
|
"ld %r30, 240(%r4)",
|
||||||
|
"ld %r31, 248(%r4)",
|
||||||
|
"rfid",
|
||||||
|
in("4") ctx,
|
||||||
|
options(noreturn),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[naked]
|
||||||
|
unsafe extern "C" fn except_thunk() {
|
||||||
|
asm!(
|
||||||
|
"mtctr %r4", // Reload CTR with original value
|
||||||
|
"mfspr %r4, 1023", // r4 = PIR
|
||||||
|
"sldi %r4, %r4, 32 + 12",
|
||||||
|
"oris %r4, %r4, EXCEPTION_SAVE_AREA@highest",
|
||||||
|
"ori %r4, %r4, EXCEPTION_SAVE_AREA@higher",
|
||||||
|
"rldicr %r4, %r4, 32, 63",
|
||||||
|
"oris %r4, %r4, EXCEPTION_SAVE_AREA@high",
|
||||||
|
"ori %r4, %r4, EXCEPTION_SAVE_AREA@l",
|
||||||
|
// Now save registers.
|
||||||
|
"std %r0, 0(%r4)",
|
||||||
|
"std %r1, 8(%r4)",
|
||||||
|
"subi %r1, %r1, 0x100", // HACK: Subtract 0x100 bytes from r1 to reuse the stack.
|
||||||
|
"std %r2, 16(%r4)",
|
||||||
|
"mfspr %r0, 304", // Reload R3, which was saved in HPSRG0.
|
||||||
|
"std %r0, 24(%r4)",
|
||||||
|
"mfspr %r0, 305", // Reload R4, which was saved in HSPRG1.
|
||||||
|
"std %r0, 32(%r4)",
|
||||||
|
"std %r5, 40(%r4)",
|
||||||
|
"std %r6, 48(%r4)",
|
||||||
|
"std %r7, 56(%r4)",
|
||||||
|
"std %r8, 64(%r4)",
|
||||||
|
"std %r9, 72(%r4)",
|
||||||
|
"std %r10, 80(%r4)",
|
||||||
|
"std %r11, 88(%r4)",
|
||||||
|
"std %r12, 96(%r4)",
|
||||||
|
"std %r13, 104(%r4)",
|
||||||
|
"std %r14, 112(%r4)",
|
||||||
|
"std %r15, 120(%r4)",
|
||||||
|
"std %r16, 128(%r4)",
|
||||||
|
"std %r17, 136(%r4)",
|
||||||
|
"std %r18, 144(%r4)",
|
||||||
|
"std %r19, 152(%r4)",
|
||||||
|
"std %r20, 160(%r4)",
|
||||||
|
"std %r21, 168(%r4)",
|
||||||
|
"std %r22, 176(%r4)",
|
||||||
|
"std %r23, 184(%r4)",
|
||||||
|
"std %r24, 192(%r4)",
|
||||||
|
"std %r25, 200(%r4)",
|
||||||
|
"std %r26, 208(%r4)",
|
||||||
|
"std %r27, 212(%r4)",
|
||||||
|
"std %r28, 220(%r4)",
|
||||||
|
"std %r29, 228(%r4)",
|
||||||
|
"std %r30, 236(%r4)",
|
||||||
|
"std %r31, 244(%r4)",
|
||||||
|
"mflr %r0",
|
||||||
|
"std %r0, 252(%r4)",
|
||||||
|
"mfctr %r0",
|
||||||
|
"std %r0, 260(%r4)",
|
||||||
|
"mfsrr0 %r0",
|
||||||
|
"std %r0, 268(%r4)",
|
||||||
|
"mfsrr1 %r0",
|
||||||
|
"std %r0, 276(%r4)",
|
||||||
|
"bl except",
|
||||||
|
options(noreturn)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a longjmp for an exception vector.
|
||||||
|
/// This will preverse r3/r4 in HSPRG0 and HSPRG1, respectively.
|
||||||
|
/// r3 will be loaded with the constant specified in the `id` parameter.
|
||||||
|
/// r4 will be loaded with the value of CTR.
|
||||||
|
const fn make_longjmp_exc(id: u16, target: usize) -> [u32; 11] {
|
||||||
|
[
|
||||||
|
0x7C704BA6, // mtspr HSPRG0, %r3
|
||||||
|
0x7C914BA6, // mtspr HSPRG1, %r4
|
||||||
|
(0x3C600000 | ((target >> 48) & 0xFFFF)) as u32, // lis %r3, target[64:48]
|
||||||
|
(0x60630000 | ((target >> 32) & 0xFFFF)) as u32, // ori %r3, %r3, target[48:32]
|
||||||
|
0x786307C6, // rldicr %r3, %r3, 32, 31
|
||||||
|
(0x64630000 | ((target >> 16) & 0xFFFF)) as u32, // oris %r3, %r3, target[32:16]
|
||||||
|
(0x60630000 | ((target >> 00) & 0xFFFF)) as u32, // ori %r3, %r3, target[16:0]
|
||||||
|
0x7C8902A6, // mfctr %r4
|
||||||
|
(0x38600000 | (id as u32)), // li %r3, id
|
||||||
|
0x7C6903A6, // mtctr %r3
|
||||||
|
0x4E800420, // bctr
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn init_except() {
|
||||||
|
let buf = make_longjmp_exc(5, except_thunk as usize);
|
||||||
|
core::ptr::copy_nonoverlapping(buf.as_ptr(), 0x00000500 as *mut u32, buf.len());
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
const IIC_BASE: usize = 0x80000200_00050000;
|
|
||||||
|
|
||||||
//! Integrated Interrupt Controller (IIC)
|
//! Integrated Interrupt Controller (IIC)
|
||||||
|
|
||||||
|
const IIC_BASE: u64 = 0x80000200_00050000;
|
||||||
|
|
||||||
#[repr(usize)]
|
#[repr(usize)]
|
||||||
enum Register {
|
enum Register {
|
||||||
WhoAmI = 0x00,
|
WhoAmI = 0x00,
|
||||||
@ -14,3 +15,59 @@ enum Register {
|
|||||||
Unk70 = 0x70,
|
Unk70 = 0x70,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(u8)]
|
||||||
|
enum Interrupt {
|
||||||
|
Ipi4 = 2,
|
||||||
|
Ipi3 = 4,
|
||||||
|
Smm = 5,
|
||||||
|
Sfcx = 6,
|
||||||
|
SataHdd = 8,
|
||||||
|
SataCdrom = 9,
|
||||||
|
Ohci0 = 11,
|
||||||
|
Ehci0 = 12,
|
||||||
|
Ohci1 = 13,
|
||||||
|
Ehci1 = 14,
|
||||||
|
Xma = 16,
|
||||||
|
Audio = 17,
|
||||||
|
Enet = 19,
|
||||||
|
Xps = 21,
|
||||||
|
Graphics = 22,
|
||||||
|
Profiler = 24,
|
||||||
|
Biu = 25,
|
||||||
|
Ioc = 26,
|
||||||
|
Fsb = 27,
|
||||||
|
Ipi2 = 28,
|
||||||
|
Clock = 29,
|
||||||
|
Ipi1 = 30,
|
||||||
|
None = 31,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Iic {
|
||||||
|
mmio: &'static mut [u8],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iic {
|
||||||
|
pub fn local() -> Self {
|
||||||
|
let id = xenon_cpu::intrin::pir();
|
||||||
|
let base = IIC_BASE + (0x1000 * id);
|
||||||
|
|
||||||
|
// SAFETY: It should always be safe to get a pointer to the current CPU's
|
||||||
|
// interrupt controller.
|
||||||
|
Self {
|
||||||
|
mmio: unsafe { core::slice::from_raw_parts_mut(base as *mut _, 0x1000) },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write<T>(&self, reg: Register, val: T) {
|
||||||
|
unsafe { core::ptr::write_volatile(&self.mmio[reg as usize] as *const _ as *mut T, val); }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read<T>(&self, reg: Register) -> T {
|
||||||
|
unsafe { core::ptr::read_volatile(&self.mmio[reg as usize] as *const _ as *mut T) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_priority(&self, prio: Interrupt) {
|
||||||
|
self.write(Register::CurrentTaskPriority, ((prio as u64) << 2));
|
||||||
|
self.read::<u64>(Register::CurrentTaskPriority);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -9,13 +9,16 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use core::{sync::atomic::{AtomicU32, AtomicUsize, Ordering}};
|
use core::sync::atomic::{AtomicU32, AtomicUsize, Ordering};
|
||||||
|
|
||||||
global_asm!(include_str!("startup.s"));
|
global_asm!(include_str!("startup.s"));
|
||||||
|
|
||||||
extern crate core_reqs;
|
extern crate core_reqs;
|
||||||
|
|
||||||
|
mod except;
|
||||||
|
mod iic;
|
||||||
mod panic;
|
mod panic;
|
||||||
|
mod smc;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn start_from_libxenon() -> !;
|
fn start_from_libxenon() -> !;
|
||||||
@ -65,6 +68,8 @@ const fn make_reljump(address: usize, target: usize) -> u32 {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[link_section = ".text.startup"]
|
#[link_section = ".text.startup"]
|
||||||
pub extern "C" fn __start_rust(pir: u32, _hrmor: u32, _pvr: u32, src: u32) -> ! {
|
pub extern "C" fn __start_rust(pir: u32, _hrmor: u32, _pvr: u32, src: u32) -> ! {
|
||||||
|
unsafe { smc::set_led(1, 0xF0); }
|
||||||
|
|
||||||
PROCESSORS.fetch_or(1 << pir, Ordering::Relaxed);
|
PROCESSORS.fetch_or(1 << pir, Ordering::Relaxed);
|
||||||
if pir != 0 {
|
if pir != 0 {
|
||||||
loop {
|
loop {
|
||||||
@ -91,7 +96,11 @@ pub extern "C" fn __start_rust(pir: u32, _hrmor: u32, _pvr: u32, src: u32) -> !
|
|||||||
let jmpbuf = make_longjmp(start_from_libxenon as usize);
|
let jmpbuf = make_longjmp(start_from_libxenon as usize);
|
||||||
|
|
||||||
// Copy the jump buffer to some unused bytes at the beginning of the hypervisor.
|
// Copy the jump buffer to some unused bytes at the beginning of the hypervisor.
|
||||||
core::ptr::copy_nonoverlapping(jmpbuf.as_ptr(), 0x000000A0 as *mut u32, jmpbuf.len());
|
core::ptr::copy_nonoverlapping(
|
||||||
|
jmpbuf.as_ptr(),
|
||||||
|
0x000000A0 as *mut u32,
|
||||||
|
jmpbuf.len(),
|
||||||
|
);
|
||||||
|
|
||||||
// Ensure the compiler does not reorder instructions.
|
// Ensure the compiler does not reorder instructions.
|
||||||
core::sync::atomic::compiler_fence(Ordering::SeqCst);
|
core::sync::atomic::compiler_fence(Ordering::SeqCst);
|
||||||
@ -115,15 +124,20 @@ pub extern "C" fn __start_rust(pir: u32, _hrmor: u32, _pvr: u32, src: u32) -> !
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Loop...
|
// Loop...
|
||||||
while PROCESSORS.load(Ordering::Relaxed) != 0x3F {}
|
while PROCESSORS.load(Ordering::Relaxed) != 0x3F {
|
||||||
|
unsafe { smc::set_led(1, PROCESSORS.load(Ordering::Relaxed) as u8); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shouldn't hit this case.
|
// Shouldn't hit this case.
|
||||||
_ => loop {}
|
_ => loop {},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now the system is in a defined state. All secondary processors are captured,
|
// Now the system is in a defined state. All secondary processors are captured,
|
||||||
// and we are free to modify the system.
|
// and we are free to modify the system.
|
||||||
|
unsafe { except::init_except() };
|
||||||
|
|
||||||
|
unsafe { smc::set_led(1, 0xF0) };
|
||||||
|
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use core::panic::PanicInfo;
|
use core::{ffi::c_void, panic::PanicInfo};
|
||||||
|
|
||||||
#[lang = "eh_personality"]
|
#[lang = "eh_personality"]
|
||||||
extern fn rust_eh_personality() {}
|
extern fn rust_eh_personality() {}
|
||||||
@ -8,3 +8,9 @@ extern fn rust_eh_personality() {}
|
|||||||
pub fn panic(_info: &PanicInfo) -> ! {
|
pub fn panic(_info: &PanicInfo) -> ! {
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn _Unwind_Resume(_exception: *mut c_void) -> ! {
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
24
boot/stage1/src/smc.rs
Normal file
24
boot/stage1/src/smc.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
//! This file includes routines to communicate with the SMC.
|
||||||
|
const SMC_ADDRESS: *mut u32 = 0x8000_0200_EA00_1000 as *mut u32;
|
||||||
|
|
||||||
|
pub unsafe fn send_message(msg: &[u32; 4]) {
|
||||||
|
while (core::ptr::read_volatile(SMC_ADDRESS.offset(33)) & 0x04000000) == 0 {}
|
||||||
|
|
||||||
|
core::ptr::write_volatile::<u32>(SMC_ADDRESS.offset(33), 0x04000000);
|
||||||
|
core::ptr::write_volatile::<u32>(SMC_ADDRESS.offset(32), msg[0]);
|
||||||
|
core::ptr::write_volatile::<u32>(SMC_ADDRESS.offset(32), msg[1]);
|
||||||
|
core::ptr::write_volatile::<u32>(SMC_ADDRESS.offset(32), msg[2]);
|
||||||
|
core::ptr::write_volatile::<u32>(SMC_ADDRESS.offset(32), msg[3]);
|
||||||
|
core::ptr::write_volatile::<u32>(SMC_ADDRESS.offset(33), 0x00000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn set_led(override_val: u8, value: u8) {
|
||||||
|
let buf: [u32; 4] = [
|
||||||
|
0x99000000 | ((override_val as u32) << 16) | ((value as u32) << 8),
|
||||||
|
0x00000000,
|
||||||
|
0x00000000,
|
||||||
|
0x00000000,
|
||||||
|
];
|
||||||
|
|
||||||
|
send_message(&buf);
|
||||||
|
}
|
@ -4,6 +4,7 @@
|
|||||||
#define ctrlrd 136
|
#define ctrlrd 136
|
||||||
#define ctrlwr 152
|
#define ctrlwr 152
|
||||||
#define pvr 287
|
#define pvr 287
|
||||||
|
#define sprg0 272
|
||||||
#define hsprg0 304
|
#define hsprg0 304
|
||||||
#define hsprg1 305
|
#define hsprg1 305
|
||||||
#define hdsisr 306
|
#define hdsisr 306
|
||||||
@ -124,60 +125,25 @@ start_common:
|
|||||||
mtspr lpcr, %r10
|
mtspr lpcr, %r10
|
||||||
isync
|
isync
|
||||||
|
|
||||||
// set stack
|
|
||||||
// R1 = 0x80000000_1E000000
|
|
||||||
li %r1, 0
|
|
||||||
oris %r1, %r1, 0x8000
|
|
||||||
rldicr %r1, %r1, 32,31
|
|
||||||
oris %r1, %r1, 0x1e00
|
|
||||||
|
|
||||||
1:
|
|
||||||
slwi %r3, %r3, 16 // 64k stack per thread
|
|
||||||
sub %r1, %r1, %r3
|
|
||||||
subi %r1, %r1, 0x80
|
|
||||||
|
|
||||||
// lis %r3, 0x8000
|
// lis %r3, 0x8000
|
||||||
// rldicr %r3, %r3, 32,31
|
// rldicr %r3, %r3, 32,31
|
||||||
// oris %r3, %r3, start@high
|
// oris %r3, %r3, start@high
|
||||||
// ori %r3, %r3, start@l
|
// ori %r3, %r3, start@l
|
||||||
// ld %r2, 8(%r3)
|
// ld %r2, 8(%r3)
|
||||||
|
|
||||||
// Set the high bit for PC.
|
bl branch_high
|
||||||
bl 1f
|
|
||||||
1:
|
|
||||||
mflr %r10
|
|
||||||
|
|
||||||
lis %r3, 0x8000
|
|
||||||
sldi %r3, %r3, 32
|
|
||||||
or %r3, %r3, %r10
|
|
||||||
addi %r3, %r3, (1f - 1b)
|
|
||||||
mtctr %r3
|
|
||||||
bctr
|
|
||||||
|
|
||||||
1:
|
|
||||||
bl load_toc
|
bl load_toc
|
||||||
|
|
||||||
|
mfspr %r3, pir
|
||||||
|
bl load_stack
|
||||||
|
|
||||||
mfspr %r3, pir
|
mfspr %r3, pir
|
||||||
cmplwi %r3, 0
|
cmplwi %r3, 0
|
||||||
bne 1f
|
bne 1f
|
||||||
|
|
||||||
// Initialize BSS.
|
// Initialize BSS on processor 0 only.
|
||||||
ld %r10, __bss_start@got(%r2)
|
bl init_bss
|
||||||
ld %r11, __bss_end@got(%r2)
|
|
||||||
sub %r11, %r11, %r10
|
|
||||||
srdi %r11, %r11, 2
|
|
||||||
subi %r10, %r10, 1
|
|
||||||
cmplwi %r11, 0
|
|
||||||
beq 1f
|
|
||||||
|
|
||||||
mtctr %r11
|
|
||||||
li %r11, 0
|
|
||||||
|
|
||||||
.bss_loop:
|
|
||||||
stwu %r11, 4(%r10)
|
|
||||||
bdnz .bss_loop
|
|
||||||
|
|
||||||
1:
|
|
||||||
// Relocate startup source.
|
// Relocate startup source.
|
||||||
mr %r6, %r4
|
mr %r6, %r4
|
||||||
|
|
||||||
@ -185,11 +151,7 @@ start_common:
|
|||||||
mfspr %r4, hrmor
|
mfspr %r4, hrmor
|
||||||
mfpvr %r5
|
mfpvr %r5
|
||||||
|
|
||||||
// Branch to start_rust via 64-bit ELF ABI.
|
bl __start_rust
|
||||||
ld %r0, __start_rust@got(%r2)
|
|
||||||
ld %r0, 0(%r0)
|
|
||||||
mtctr %r0
|
|
||||||
bctrl
|
|
||||||
nop
|
nop
|
||||||
|
|
||||||
b .
|
b .
|
||||||
@ -297,6 +259,57 @@ init_regs:
|
|||||||
|
|
||||||
blr
|
blr
|
||||||
|
|
||||||
|
// Initialize BSS
|
||||||
|
// R10 = clobber
|
||||||
|
// R11 = clobber
|
||||||
|
// CTR = clobber
|
||||||
|
init_bss:
|
||||||
|
ld %r10, __bss_start@got(%r2)
|
||||||
|
ld %r11, __bss_end@got(%r2)
|
||||||
|
sub %r11, %r11, %r10
|
||||||
|
srdi %r11, %r11, 2
|
||||||
|
subi %r10, %r10, 1
|
||||||
|
cmplwi %r11, 0
|
||||||
|
beq 1f
|
||||||
|
|
||||||
|
mtctr %r11
|
||||||
|
li %r11, 0
|
||||||
|
|
||||||
|
.bss_loop:
|
||||||
|
stwu %r11, 4(%r10)
|
||||||
|
bdnz .bss_loop
|
||||||
|
|
||||||
|
1:
|
||||||
|
blr
|
||||||
|
|
||||||
|
// Sets the high bit in PC.
|
||||||
|
// R3 = clobber
|
||||||
|
// R10 = clobber
|
||||||
|
branch_high:
|
||||||
|
mflr %r10
|
||||||
|
|
||||||
|
lis %r3, 0x8000
|
||||||
|
sldi %r3, %r3, 32
|
||||||
|
or %r3, %r3, %r10
|
||||||
|
|
||||||
|
mtlr %r3
|
||||||
|
blr
|
||||||
|
|
||||||
|
// Sets up the stack.
|
||||||
|
// R1(out) = stack
|
||||||
|
// R3(in/out) = pir / clobber
|
||||||
|
load_stack:
|
||||||
|
// set stack
|
||||||
|
// R1 = 0x80000000_1E000000
|
||||||
|
lis %r1, 0x8000
|
||||||
|
rldicr %r1, %r1, 32,31
|
||||||
|
oris %r1, %r1, 0x1e00
|
||||||
|
|
||||||
|
slwi %r3, %r3, 16 // 64k stack per thread
|
||||||
|
sub %r1, %r1, %r3
|
||||||
|
subi %r1, %r1, 0x80
|
||||||
|
blr
|
||||||
|
|
||||||
// Loads the table of contents pointer into R2.
|
// Loads the table of contents pointer into R2.
|
||||||
// R0 = clobber
|
// R0 = clobber
|
||||||
// R2 = TOC
|
// R2 = TOC
|
||||||
|
8
shared/xenon-cpu/Cargo.toml
Normal file
8
shared/xenon-cpu/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "xenon-cpu"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
19
shared/xenon-cpu/src/intrin.rs
Normal file
19
shared/xenon-cpu/src/intrin.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#[inline]
|
||||||
|
pub fn mftb() -> u64 {
|
||||||
|
let tb;
|
||||||
|
unsafe {
|
||||||
|
asm!("mftb {}", out(reg) tb);
|
||||||
|
}
|
||||||
|
|
||||||
|
tb
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn pir() -> u64 {
|
||||||
|
let pir;
|
||||||
|
unsafe {
|
||||||
|
asm!("mfspr {}, 1023", out(reg) pir);
|
||||||
|
}
|
||||||
|
|
||||||
|
pir
|
||||||
|
}
|
5
shared/xenon-cpu/src/lib.rs
Normal file
5
shared/xenon-cpu/src/lib.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#![feature(asm)]
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
pub mod intrin;
|
||||||
|
pub mod time;
|
13
shared/xenon-cpu/src/time.rs
Normal file
13
shared/xenon-cpu/src/time.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
const TIMEBASE_FREQ: u64 = 3192000000 / 64;
|
||||||
|
|
||||||
|
use crate::intrin::mftb;
|
||||||
|
use core::time::Duration;
|
||||||
|
|
||||||
|
fn tdelay(time: u128) {
|
||||||
|
let tgt = time.saturating_add(mftb() as u128) as u64;
|
||||||
|
while mftb() < tgt {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn delay(length: Duration) {
|
||||||
|
tdelay((length.as_micros() * TIMEBASE_FREQ as u128) / 1000000);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user