Unverified Commit de7766c9 authored by Stefan Lankes's avatar Stefan Lankes Committed by GitHub
Browse files

improve alignment of data between cores (#72)

- avoids false sharing
parent a09ee81e
......@@ -12,6 +12,7 @@ use crate::arch::x86_64::kernel::acpi;
use crate::arch::x86_64::kernel::smp_boot_code::SMP_BOOT_CODE;
use crate::arch::x86_64::mm::paging::{BasePageSize, PageSize, PageTableEntryFlags};
use crate::arch::x86_64::mm::{paging, virtualmem};
use crate::collections::CachePadded;
use crate::config::*;
use crate::environment;
use crate::mm;
......@@ -481,13 +482,19 @@ pub fn init_next_processor_variables(core_id: CoreId) {
// Allocate stack and PerCoreVariables structure for the CPU and pass the addresses.
// Keep the stack executable to possibly support dynamically generated code on the stack (see https://security.stackexchange.com/a/47825).
let stack = mm::allocate(KERNEL_STACK_SIZE, true);
let boxed_percore = Box::new(PerCoreVariables::new(core_id));
let boxed_percore = Box::new(CachePadded::new(PerCoreInnerVariables::new(core_id)));
unsafe {
core::ptr::write_volatile(&mut (*BOOT_INFO).current_stack_address, stack as u64);
core::ptr::write_volatile(
&mut (*BOOT_INFO).current_percore_address,
Box::into_raw(boxed_percore) as u64,
);
trace!(
"Initialize per core data at 0x{:x} (size {} bytes)",
core::ptr::read_volatile(&(*BOOT_INFO).current_percore_address),
mem::size_of::<PerCoreVariables>()
);
}
}
......
......@@ -6,14 +6,17 @@
// copied, modified, or distributed except according to those terms.
use crate::arch::x86_64::kernel::BOOT_INFO;
use crate::collections::CachePadded;
use crate::scheduler::{CoreId, PerCoreScheduler};
use crate::x86::bits64::task::TaskStateSegment;
use crate::x86::msr::*;
use core::ptr;
pub static mut PERCORE: PerCoreVariables = PerCoreVariables::new(0);
pub static mut PERCORE: PerCoreVariables = CachePadded::new(PerCoreInnerVariables::new(0));
pub struct PerCoreVariables {
pub type PerCoreVariables = CachePadded<PerCoreInnerVariables>;
pub struct PerCoreInnerVariables {
/// Sequential ID of this CPU Core.
core_id: PerCoreVariable<CoreId>,
/// Scheduler for this CPU Core.
......@@ -24,7 +27,7 @@ pub struct PerCoreVariables {
pub kernel_stack: PerCoreVariable<u64>,
}
impl PerCoreVariables {
impl PerCoreInnerVariables {
pub const fn new(core_id: CoreId) -> Self {
Self {
core_id: PerCoreVariable::new(core_id),
......
......@@ -8,21 +8,21 @@
//! Kernel Message Buffer for Multi-Kernel mode.
//! Can be read from the Linux side as no serial port is available.
use crate::collections::CachePadded;
use core::sync::atomic::{AtomicUsize, Ordering};
const KMSG_SIZE: usize = 0x1000;
#[repr(align(64))]
#[repr(C)]
struct KmsgSection {
buffer: [u8; KMSG_SIZE + 1],
buffer: CachePadded<[u8; KMSG_SIZE + 1]>,
}
static mut KMSG: KmsgSection = KmsgSection {
buffer: [0; KMSG_SIZE + 1],
buffer: CachePadded::new([0; KMSG_SIZE + 1]),
};
static BUFFER_INDEX: AtomicUsize = AtomicUsize::new(0);
static BUFFER_INDEX: CachePadded<AtomicUsize> = CachePadded::new(AtomicUsize::new(0));
pub fn write_byte(byte: u8) {
let index = BUFFER_INDEX.fetch_add(1, Ordering::SeqCst);
......
......@@ -63,14 +63,14 @@ pub struct PerCoreScheduler {
fpu_owner: Rc<RefCell<Task>>,
/// Queue of tasks, which are ready
ready_queue: PriorityTaskQueue,
/// Queues to handle incoming requests from the other cores
input: SpinlockIrqSave<SchedulerInput>,
/// Queue of tasks, which are finished and can be released
finished_tasks: VecDeque<TaskId>,
/// Queue of blocked tasks, sorted by wakeup time.
blocked_tasks: BlockedTaskQueue,
/// Processor Timer Tick when we last switched the current task.
last_task_switch_tick: u64,
/// Queues to handle incoming requests from the other cores
input: SpinlockIrqSave<SchedulerInput>,
}
impl PerCoreScheduler {
......@@ -531,10 +531,10 @@ pub fn add_current_core() {
idle_task: idle_task.clone(),
fpu_owner: idle_task,
ready_queue: PriorityTaskQueue::new(),
input: SpinlockIrqSave::new(SchedulerInput::new()),
finished_tasks: VecDeque::new(),
blocked_tasks: BlockedTaskQueue::new(),
last_task_switch_tick: 0,
input: SpinlockIrqSave::new(SchedulerInput::new()),
});
let scheduler = Box::into_raw(boxed_scheduler);
......
......@@ -360,7 +360,8 @@ impl PriorityTaskQueue {
}
/// A task control block, which identifies either a process or a thread
#[repr(align(64))]
#[cfg_attr(target_arch = "x86_64", repr(align(128)))]
#[cfg_attr(not(target_arch = "x86_64"), repr(align(64)))]
pub struct Task {
/// The ID of this context
pub id: TaskId,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment