Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tasks: Add support for task context switching #50

Closed
wants to merge 9 commits into from
19 changes: 19 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ doctest = false
bitflags = "1.3.2"
gdbstub = { version = "0.6.6", default-features = false, optional = true }
gdbstub_arch = { version = "0.2.4", optional = true }
intrusive-collections = "0.9"
log = { version = "0.4.17", features = ["max_level_info", "release_max_level_info"] }
packit = { git = "https://github.com/coconut-svsm/packit", version = "0.1.0" }

Expand Down
10 changes: 5 additions & 5 deletions src/cpu/extable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ extern "C" {
pub static exception_table_end: u8;
}

use super::idt::X86ExceptionContext;
use crate::address::{Address, VirtAddr};
use crate::cpu::X86Regs;
use core::mem;

#[repr(C, packed)]
Expand Down Expand Up @@ -67,14 +67,14 @@ pub fn dump_exception_table() {
}
}

pub fn handle_exception_table(regs: &mut X86Regs) -> bool {
let ex_rip = VirtAddr::from(regs.rip);
pub fn handle_exception_table(ctx: &mut X86ExceptionContext) -> bool {
let ex_rip = VirtAddr::from(ctx.frame.rip);
let new_rip = check_exception_table(ex_rip);

// If an exception hit in an area covered by the exception table, set rcx to -1
if new_rip != ex_rip {
regs.rcx = !0usize;
regs.rip = new_rip.bits();
ctx.regs.rcx = !0usize;
ctx.frame.rip = new_rip.bits();
return true;
}

Expand Down
65 changes: 24 additions & 41 deletions src/cpu/idt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use super::control_regs::read_cr2;
use super::tss::IST_DF;
use super::vc::handle_vc_exception;
use super::{X86GeneralRegs, X86InterruptFrame};
use crate::address::{Address, VirtAddr};
use crate::cpu::extable::handle_exception_table;
use crate::debug::gdbstub::svsm_gdbstub::handle_bp_exception;
Expand Down Expand Up @@ -39,29 +40,11 @@ pub const VC_VECTOR: usize = 29;
pub const _SX_VECTOR: usize = 30;

#[repr(C, packed)]
pub struct X86Regs {
pub r15: usize,
pub r14: usize,
pub r13: usize,
pub r12: usize,
pub r11: usize,
pub r10: usize,
pub r9: usize,
pub r8: usize,
pub rbp: usize,
pub rdi: usize,
pub rsi: usize,
pub rdx: usize,
pub rcx: usize,
pub rbx: usize,
pub rax: usize,
pub struct X86ExceptionContext {
pub regs: X86GeneralRegs,
pub vector: usize,
pub error_code: usize,
pub rip: usize,
pub cs: usize,
pub flags: usize,
pub rsp: usize,
pub ss: usize,
pub frame: X86InterruptFrame,
}

#[derive(Copy, Clone)]
Expand Down Expand Up @@ -178,46 +161,46 @@ pub fn idt_init() {
}

#[no_mangle]
fn generic_idt_handler(regs: &mut X86Regs) {
if regs.vector == DF_VECTOR {
fn generic_idt_handler(ctx: &mut X86ExceptionContext) {
if ctx.vector == DF_VECTOR {
let cr2 = read_cr2();
let rip = regs.rip;
let rsp = regs.rsp;
let rip = ctx.frame.rip;
let rsp = ctx.frame.rsp;
panic!(
"Double-Fault at RIP {:#018x} RSP: {:#018x} CR2: {:#018x}",
rip, rsp, cr2
);
} else if regs.vector == GP_VECTOR {
let rip = regs.rip;
let err = regs.error_code;
} else if ctx.vector == GP_VECTOR {
let rip = ctx.frame.rip;
let err = ctx.error_code;

if !handle_exception_table(regs) {
if !handle_exception_table(ctx) {
panic!(
"Unhandled General-Protection-Fault at RIP {:#018x} error code: {:#018x}",
rip, err
);
}
} else if regs.vector == PF_VECTOR {
} else if ctx.vector == PF_VECTOR {
let cr2 = read_cr2();
let rip = regs.rip;
let err = regs.error_code;
let rip = ctx.frame.rip;
let err = ctx.error_code;

if !handle_exception_table(regs) {
if !handle_exception_table(ctx) {
panic!(
"Unhandled Page-Fault at RIP {:#018x} CR2: {:#018x} error code: {:#018x}",
rip, cr2, err
);
}
} else if regs.vector == VC_VECTOR {
handle_vc_exception(regs);
} else if regs.vector == BP_VECTOR {
handle_bp_exception(regs);
} else if ctx.vector == VC_VECTOR {
handle_vc_exception(ctx);
} else if ctx.vector == BP_VECTOR {
handle_bp_exception(ctx);
} else {
let err = regs.error_code;
let vec = regs.vector;
let rip = regs.rip;
let err = ctx.error_code;
let vec = ctx.vector;
let rip = ctx.frame.rip;

if !handle_exception_table(regs) {
if !handle_exception_table(ctx) {
panic!(
"Unhandled exception {} RIP {:#018x} error code: {:#018x}",
vec, rip, err
Expand Down
4 changes: 3 additions & 1 deletion src/cpu/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ pub mod gdt;
pub mod idt;
pub mod msr;
pub mod percpu;
pub mod registers;
pub mod smp;
pub mod tlb;
pub mod tss;
pub mod vc;
pub mod vmsa;

pub use idt::X86Regs;
pub use idt::X86ExceptionContext;
pub use registers::{X86GeneralRegs, X86InterruptFrame, X86SegmentRegs};
pub use tlb::*;
27 changes: 27 additions & 0 deletions src/cpu/msr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,30 @@ pub fn write_msr(msr: u32, val: u64) {
options(att_syntax));
}
}

pub fn rdtsc() -> u64 {
let eax: u32;
let edx: u32;

unsafe {
asm!("rdtsc",
out("eax") eax,
out("edx") edx,
options(att_syntax));
}
(eax as u64) | (edx as u64) << 32
}

pub fn read_flags() -> u64 {
let rax: u64;
unsafe {
asm!(
r#"
pushfq
pop %rax
"#,
out("rax") rax,
options(att_syntax));
}
rax
}
4 changes: 4 additions & 0 deletions src/cpu/percpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use crate::mm::{
use crate::sev::ghcb::GHCB;
use crate::sev::utils::RMPFlags;
use crate::sev::vmsa::{allocate_new_vmsa, VMSASegment, VMSA};
use crate::task::TaskPointer;
use crate::types::{PAGE_SHIFT, PAGE_SHIFT_2M, PAGE_SIZE, PAGE_SIZE_2M, SVSM_TR_FLAGS, SVSM_TSS};
use alloc::vec::Vec;
use core::cell::UnsafeCell;
Expand Down Expand Up @@ -187,6 +188,8 @@ pub struct PerCpu {
pub vrange_4k: VirtualRange,
/// Address allocator for per-cpu 2m temporary mappings
pub vrange_2m: VirtualRange,

pub current_task: Option<TaskPointer>,
}

impl PerCpu {
Expand All @@ -204,6 +207,7 @@ impl PerCpu {
reset_ip: 0xffff_fff0u64,
vrange_4k: VirtualRange::new(),
vrange_2m: VirtualRange::new(),
current_task: None,
}
}

Expand Down
45 changes: 45 additions & 0 deletions src/cpu/registers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2022-2023 SUSE LLC
//
// Author: Roy Hopkins <rhopkins@suse.de>

#[repr(C, packed)]
#[derive(Default, Debug)]
pub struct X86GeneralRegs {
pub r15: usize,
pub r14: usize,
pub r13: usize,
pub r12: usize,
pub r11: usize,
pub r10: usize,
pub r9: usize,
pub r8: usize,
pub rbp: usize,
pub rdi: usize,
pub rsi: usize,
pub rdx: usize,
pub rcx: usize,
pub rbx: usize,
pub rax: usize,
}

#[repr(C, packed)]
#[derive(Default, Debug)]
pub struct X86SegmentRegs {
pub cs: usize,
pub ds: usize,
pub es: usize,
pub fs: usize,
pub gs: usize,
pub ss: usize,
}

#[repr(C, packed)]
pub struct X86InterruptFrame {
pub rip: usize,
pub cs: usize,
pub flags: usize,
pub rsp: usize,
pub ss: usize,
}
18 changes: 14 additions & 4 deletions src/cpu/smp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
extern crate alloc;

use crate::acpi::tables::ACPICPUInfo;
use crate::cpu::percpu::{this_cpu_mut, PerCpu};
use crate::cpu::percpu::{this_cpu, this_cpu_mut, PerCpu};
use crate::cpu::vmsa::init_svsm_vmsa;
use crate::requests::request_loop;
use crate::task::{create_initial_task, TASK_FLAG_SHARE_PT};

fn start_cpu(apic_id: u32) {
unsafe {
Expand Down Expand Up @@ -51,7 +52,7 @@ pub fn start_secondary_cpus(cpus: &[ACPICPUInfo]) {
start_cpu(c.apic_id);
count += 1;
}
log::info!("Brough {} AP(s) online", count);
log::info!("Brought {} AP(s) online", count);
}

#[no_mangle]
Expand All @@ -66,8 +67,17 @@ fn start_ap() {
// Set CPU online so that BSP can proceed
this_cpu_mut().set_online();

// Loop for now
request_loop();
// Create the task making sure the task only runs on this new AP
create_initial_task(
ap_request_loop,
TASK_FLAG_SHARE_PT,
Some(this_cpu().get_apic_id()),
)
.expect("Failed to create AP initial task");
}

#[no_mangle]
pub extern "C" fn ap_request_loop() {
request_loop();
panic!("Returned from request_loop!");
}
20 changes: 20 additions & 0 deletions src/cpu/tsc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2022-2023 SUSE LLC
//
// Author: Roy Hopkins <rhopkins@suse.de>

use core::arch::asm;

pub fn rdtsc() -> u64 {
roy-hopkins marked this conversation as resolved.
Show resolved Hide resolved
let eax: u32;
let edx: u32;

unsafe {
asm!("rdtsc",
out("eax") eax,
out("edx") edx,
options(att_syntax));
}
(eax as u64) | (edx as u64) << 32
}
12 changes: 6 additions & 6 deletions src/cpu/vc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,25 @@
//
// Author: Joerg Roedel <jroedel@suse.de>

use super::idt::X86Regs;
use super::idt::X86ExceptionContext;
use crate::cpu::extable::handle_exception_table;
use crate::debug::gdbstub::svsm_gdbstub::handle_db_exception;

pub const SVM_EXIT_EXCP_BASE: usize = 0x40;
pub const X86_TRAP_DB: usize = 0x01;

pub fn handle_vc_exception(regs: &mut X86Regs) {
let err = regs.error_code;
let rip = regs.rip;
pub fn handle_vc_exception(ctx: &mut X86ExceptionContext) {
let err = ctx.error_code;
let rip = ctx.frame.rip;

// If the debugger is enabled then handle the DB exception
// by directly invoking the exception hander
if err == (SVM_EXIT_EXCP_BASE + X86_TRAP_DB) {
handle_db_exception(regs);
handle_db_exception(ctx);
return;
}

if !handle_exception_table(regs) {
if !handle_exception_table(ctx) {
panic!(
"Unhandled #VC exception RIP {:#018x} error code: {:#018x}",
rip, err
Expand Down
Loading
Loading