Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 127 additions & 0 deletions kernel/src/arch/x86_64/interrupt/ipi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
use crate::exception::ipi::{IpiKind, IpiTarget};

extern "C" {
pub fn apic_write_icr(value: u64);
pub fn apic_x2apic_enabled() -> bool;
}

/// IPI的种类(架构相关,指定了向量号)
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[repr(u8)]
pub enum ArchIpiKind {
KickCpu = 200,
FlushTLB = 201,
}

impl From<IpiKind> for ArchIpiKind {
fn from(kind: IpiKind) -> Self {
match kind {
IpiKind::KickCpu => ArchIpiKind::KickCpu,
IpiKind::FlushTLB => ArchIpiKind::FlushTLB,
}
}
}

/// IPI投递目标
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum ArchIpiTarget {
/// 当前CPU
Current,
/// 所有CPU
All,
/// 除了当前CPU以外的所有CPU
Other,
/// 指定的CPU
Specified(usize),
}

impl From<IpiTarget> for ArchIpiTarget {
fn from(target: IpiTarget) -> Self {
match target {
IpiTarget::Current => ArchIpiTarget::Current,
IpiTarget::All => ArchIpiTarget::All,
IpiTarget::Other => ArchIpiTarget::Other,
IpiTarget::Specified(cpu_id) => ArchIpiTarget::Specified(cpu_id),
}
}
}

impl ArchIpiTarget {
pub fn shorthand(&self) -> u8 {
match self {
ArchIpiTarget::Specified(_) => 0,
ArchIpiTarget::Current => 1,
ArchIpiTarget::All => 2,
ArchIpiTarget::Other => 3,
}
}
}

impl Into<x86::apic::DestinationShorthand> for ArchIpiTarget {
fn into(self) -> x86::apic::DestinationShorthand {
match self {
ArchIpiTarget::Specified(_) => x86::apic::DestinationShorthand::NoShorthand,
ArchIpiTarget::Current => x86::apic::DestinationShorthand::Myself,
ArchIpiTarget::All => x86::apic::DestinationShorthand::AllIncludingSelf,
ArchIpiTarget::Other => x86::apic::DestinationShorthand::AllExcludingSelf,
}
}
}

impl Into<x86::apic::ApicId> for ArchIpiTarget {
fn into(self) -> x86::apic::ApicId {
let id = match self {
ArchIpiTarget::Specified(cpu_id) => cpu_id,
_ => 0,
};

if unsafe { apic_x2apic_enabled() } {
return x86::apic::ApicId::X2Apic(id as u32);
} else {
return x86::apic::ApicId::XApic(id as u8);
}
}
}

#[inline(always)]
pub fn send_ipi(kind: IpiKind, target: IpiTarget) {
// kdebug!("send_ipi: {:?} {:?}", kind, target);

let ipi_vec = ArchIpiKind::from(kind) as u8;
let target = ArchIpiTarget::from(target);
let shorthand: x86::apic::DestinationShorthand = target.into();
let destination: x86::apic::ApicId = target.into();
if unsafe { apic_x2apic_enabled() } {
// kdebug!("send_ipi: x2apic");
let icr = x86::apic::Icr::for_x2apic(
ipi_vec,
destination,
shorthand,
x86::apic::DeliveryMode::Fixed,
x86::apic::DestinationMode::Physical,
x86::apic::DeliveryStatus::Idle,
x86::apic::Level::Assert,
x86::apic::TriggerMode::Edge,
);

unsafe {
apic_write_icr(((icr.upper() as u64) << 32) | icr.lower() as u64);
}
} else {
// kdebug!("send_ipi: xapic");
let icr = x86::apic::Icr::for_xapic(
ipi_vec,
destination,
shorthand,
x86::apic::DeliveryMode::Fixed,
x86::apic::DestinationMode::Physical,
x86::apic::DeliveryStatus::Idle,
x86::apic::Level::Assert,
x86::apic::TriggerMode::Edge,
);

unsafe {
apic_write_icr(((icr.upper() as u64) << 32) | icr.lower() as u64);
}
}
}
3 changes: 3 additions & 0 deletions kernel/src/arch/x86_64/interrupt/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#![allow(dead_code)]

pub mod ipi;

use core::{
arch::asm,
sync::atomic::{compiler_fence, Ordering},
Expand Down
5 changes: 1 addition & 4 deletions kernel/src/arch/x86_64/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ use crate::{
syscall::{Syscall, SystemError, SYS_EXECVE, SYS_FORK, SYS_RT_SIGRETURN, SYS_VFORK},
};

use super::{
asm::{ptrace::user_mode},
mm::barrier::mfence,
};
use super::{asm::ptrace::user_mode, mm::barrier::mfence};

extern "C" {
fn do_fork(regs: *mut pt_regs, clone_flags: u64, stack_start: u64, stack_size: u64) -> u64;
Expand Down
60 changes: 48 additions & 12 deletions kernel/src/driver/interrupt/apic/apic.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ void apic_init_ap_core_local_apic()
__local_apic_x2apic_init();
else // 当前为xapic
__local_apic_xapic_init();
barrier();
kdebug("AP-core's local apic initialized.");
barrier();
}

/**
Expand All @@ -160,15 +163,15 @@ static void __local_apic_xapic_init()
uint64_t qword = *(uint64_t *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_SVR);

qword |= (1 << 8);
*(uint64_t *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_SVR) = qword;
qword = *(uint64_t *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_SVR);
*(volatile uint64_t *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_SVR) = qword;
qword = *(volatile uint64_t *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_SVR);
if (qword & 0x100)
kinfo("APIC Software Enabled.");
if (qword & 0x1000)
kinfo("EOI-Broadcast Suppression Enabled.");

barrier();
// 从 Local APIC Version register 获取Local APIC Version
qword = *(uint64_t *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_Version);
qword = *(volatile uint64_t *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_Version);
qword &= 0xffffffff;

local_apic_max_LVT_entries = ((qword >> 16) & 0xff) + 1;
Expand All @@ -188,19 +191,19 @@ static void __local_apic_xapic_init()
// 如果写入这里的话,在有的机器上面会报错
// *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_CMCI) = APIC_LVT_INT_MASKED;
io_mfence();
*(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_TIMER) = APIC_LVT_INT_MASKED;
*(volatile uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_TIMER) = APIC_LVT_INT_MASKED;
io_mfence();

*(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_THERMAL) = APIC_LVT_INT_MASKED;
*(volatile uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_THERMAL) = APIC_LVT_INT_MASKED;
io_mfence();
*(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_PERFORMANCE_MONITOR) =
*(volatile uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_PERFORMANCE_MONITOR) =
APIC_LVT_INT_MASKED;
io_mfence();
*(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_LINT0) = APIC_LVT_INT_MASKED;
*(volatile uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_LINT0) = APIC_LVT_INT_MASKED;
io_mfence();
*(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_LINT1) = APIC_LVT_INT_MASKED;
*(volatile uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_LINT1) = APIC_LVT_INT_MASKED;
io_mfence();
*(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_ERROR) = APIC_LVT_INT_MASKED;
*(volatile uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_ERROR) = APIC_LVT_INT_MASKED;
io_mfence();

kdebug("All LVT Masked");
Expand Down Expand Up @@ -664,8 +667,8 @@ void apic_make_rte_entry(struct apic_IO_APIC_RTE_entry *entry, uint8_t vector, u

/**
* @brief 获取当前处理器的local apic id
*
* @return uint32_t
*
* @return uint32_t
*/
uint32_t apic_get_local_apic_id()
{
Expand All @@ -692,4 +695,37 @@ uint32_t apic_get_local_apic_id()
return x;
}
}

/**
* 写入icr寄存器
*
* @param value 写入的值
*/
void apic_write_icr(uint64_t value)
{
if (flag_support_x2apic)
{
wrmsr(0x830, value);
}
else
{
// kdebug("to write icr: %#018lx", value);
const uint64_t PENDING = 1UL << 12;
while (*(volatile uint32_t *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_ICR_31_0) & PENDING)
;
// kdebug("write icr: %#018lx", value);
*(volatile uint32_t *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_ICR_63_32) = (value >> 32) & 0xffffffff;
*(volatile uint32_t *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_ICR_31_0) = value & 0xffffffff;

while (*(volatile uint32_t *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_ICR_31_0) & PENDING)
;
// kdebug("write icr done");
}
}

// 查询是否启用了x2APIC
bool apic_x2apic_enabled()
{
return flag_support_x2apic;
}
#pragma GCC pop_options
5 changes: 3 additions & 2 deletions kernel/src/driver/interrupt/apic/apic.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#pragma GCC push_options
#pragma GCC optimize("O0")


#define APIC_SUCCESS 0
#define APIC_E_NOTFOUND 1

Expand All @@ -19,7 +18,7 @@
extern uint8_t __apic_enable_state;
#define APIC_XAPIC_ENABLED 0
#define APIC_X2APIC_ENABLED 1
#define CURRENT_APIC_STATE (__apic_enable_state )
#define CURRENT_APIC_STATE (__apic_enable_state)

// ======== local apic 寄存器虚拟地址偏移量表 =======
// 0x00~0x10 Reserved.
Expand Down Expand Up @@ -331,4 +330,6 @@ void apic_make_rte_entry(struct apic_IO_APIC_RTE_entry *entry, uint8_t vector, u
uint8_t deliver_status, uint8_t polarity, uint8_t irr, uint8_t trigger, uint8_t mask, uint8_t dest_apicID);

uint32_t apic_get_local_apic_id();
void apic_write_icr(uint64_t value);
bool apic_x2apic_enabled();
#pragma GCC pop_options
21 changes: 21 additions & 0 deletions kernel/src/exception/ipi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#[allow(dead_code)]
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[repr(u8)]
pub enum IpiKind {
KickCpu,
FlushTLB,
}

/// IPI投递目标
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[allow(dead_code)]
pub enum IpiTarget {
/// 当前CPU
Current,
/// 所有CPU
All,
/// 除了当前CPU以外的所有CPU
Other,
/// 指定的CPU
Specified(usize),
}
1 change: 1 addition & 0 deletions kernel/src/exception/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::arch::CurrentIrqArch;

pub mod ipi;
pub mod softirq;

/// @brief 中断相关的操作
Expand Down
7 changes: 2 additions & 5 deletions kernel/src/filesystem/vfs/syscall.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@

use alloc::{boxed::Box, sync::Arc, vec::Vec};

use crate::{
arch::asm::{current::current_pcb},
arch::asm::current::current_pcb,
filesystem::vfs::file::FileDescriptorVec,
include::bindings::bindings::{
verify_area, AT_REMOVEDIR, PAGE_4K_SIZE, PROC_MAX_FD_NUM,
},
include::bindings::bindings::{verify_area, AT_REMOVEDIR, PAGE_4K_SIZE, PROC_MAX_FD_NUM},
io::SeekFrom,
kerror,
syscall::{Syscall, SystemError},
Expand Down
6 changes: 2 additions & 4 deletions kernel/src/ipc/signal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,10 @@ use crate::{
use super::signal_types::{
si_code_val, sig_is_member, sigaction, sigaction__union_u, sigcontext, sigframe,
sighand_struct, siginfo, signal_struct, sigpending, sigset_clear, sigset_del, sigset_delmask,
sigset_equal, sigset_t, SigQueue, SignalNumber, MAX_SIG_NUM, SA_ALL_FLAGS,
SA_FLAG_DFL, SA_FLAG_IGN, SA_FLAG_IMMUTABLE, SA_FLAG_RESTORER, STACK_ALIGN, _NSIG_U64_CNT,
sigset_equal, sigset_t, SigQueue, SignalNumber, MAX_SIG_NUM, SA_ALL_FLAGS, SA_FLAG_DFL,
SA_FLAG_IGN, SA_FLAG_IMMUTABLE, SA_FLAG_RESTORER, STACK_ALIGN, _NSIG_U64_CNT,
};



/// 默认信号处理程序占位符(用于在sighand结构体中的action数组中占位)
pub static DEFAULT_SIGACTION: sigaction = sigaction {
_u: sigaction__union_u {
Expand Down
Loading