Skip to content
This repository was archived by the owner on Jul 17, 2025. It is now read-only.

Commit 19e49c3

Browse files
committed
ivshmem interrupts working
1 parent a9bd768 commit 19e49c3

File tree

16 files changed

+481
-128
lines changed

16 files changed

+481
-128
lines changed

Cargo.lock

Lines changed: 2 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

kernel/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ vmxnet3 = { path = "../lib/vmxnet3" }
2323
bootloader_shared = { path = "../lib/bootloader_shared" }
2424
x86 = { version = "0.52", features = ["unstable"] }
2525
klogger = "0.0.16"
26-
driverkit = "0.21"
26+
driverkit = { git = "https://github.com/hunhoffe/rust-driverkit.git", branch = "msix" }
2727
spin = "0.9.1"
2828
elfloader = "0.14"
2929
slabmalloc = "0.10"
@@ -123,3 +123,5 @@ cause-gpfault-early = []
123123
cause-double-fault = []
124124
# test-timer: print something on a timer interrupt.
125125
test-timer = []
126+
# test-shmem: print something on a shmem interrupt.
127+
test-shmem = []

kernel/run.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -407,16 +407,11 @@ def run_qemu(args):
407407
'isa-debug-exit,iobase=0xf4,iosize=0x04']
408408

409409
if args.qemu_ivshmem:
410-
if not args.qemu_shmem_path:
411-
print("Provide path to the shared memory file.")
412-
sys.exit(errno.EINVAL)
413-
410+
qemu_default_args += ['-device', 'ivshmem-doorbell,vectors=2,chardev=id']
414411
qemu_default_args += [
415-
'-object',
416-
'memory-backend-file,size={}M,mem-path={},share=on,id=HMB'.format(
417-
args.qemu_ivshmem, args.qemu_shmem_path)
412+
'-chardev',
413+
'socket,path={},id=id'.format(args.qemu_shmem_path)
418414
]
419-
qemu_default_args += ['-device', 'ivshmem-plain,memdev=HMB']
420415

421416
# Enable networking:
422417
mac, tap = NETWORK_CONFIG[args.tap]['mac'], args.tap

kernel/src/arch/x86_64/irq.rs

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ use super::memory::{PAddr, VAddr, BASE_PAGE_SIZE, KERNEL_BASE};
6060
use super::process::{Ring0Resumer, Ring3Process, Ring3Resumer};
6161
use super::{debug, gdb, timer};
6262

63+
// TODO(hunhoffe): probably not the right place for this but transport/shmem isn't always included.
64+
pub(crate) const SHMEM_VECTOR: u8 = 249;
65+
6366
/// The x2APIC driver of the current core.
6467
#[thread_local]
6568
pub(crate) static LOCAL_APIC: RefCell<X2APICDriver> = RefCell::new(X2APICDriver::new());
@@ -180,8 +183,11 @@ impl Default for IdtTable {
180183
idt_set!(table.0, 46, isr_handler46, 0);
181184
idt_set!(table.0, 47, isr_handler47, 0);
182185

183-
idt_set!(table.0, TLB_WORK_PENDING as usize, isr_handler251, 0);
186+
// shmem interrupt
187+
idt_set!(table.0, SHMEM_VECTOR as usize, isr_handler249, 0);
188+
184189
idt_set!(table.0, MLNR_GC_INIT as usize, isr_handler250, 0);
190+
idt_set!(table.0, TLB_WORK_PENDING as usize, isr_handler251, 0);
185191
idt_set!(table.0, apic::TSC_TIMER_VECTOR as usize, isr_handler252, 0);
186192

187193
table
@@ -230,9 +236,8 @@ impl IdtTable {
230236
idt_set!(table.0, SIMD_FLOATING_POINT_VECTOR, isr_handler_early19, 0);
231237
idt_set!(table.0, VIRTUALIZATION_VECTOR, isr_handler_early20, 0);
232238

233-
idt_set!(table.0, TLB_WORK_PENDING as usize, isr_handler_early251, 0);
234-
235239
idt_set!(table.0, MLNR_GC_INIT as usize, isr_handler_early250, 0);
240+
idt_set!(table.0, TLB_WORK_PENDING as usize, isr_handler_early251, 0);
236241
idt_set!(
237242
table.0,
238243
apic::TSC_TIMER_VECTOR as usize,
@@ -491,7 +496,7 @@ unsafe fn timer_handler(_a: &ExceptionArguments) {
491496
#[cfg(feature = "test-timer")]
492497
{
493498
// Don't change this print stmt. without changing
494-
// `s01_timer` in integration-tests.rs:
499+
// `s01_timer` in tests/s01_kernel_low_tests.rs:
495500
sprintln!("Got a timer interrupt");
496501
debug::shutdown(ExitReason::Ok);
497502
}
@@ -544,6 +549,30 @@ unsafe fn timer_handler(_a: &ExceptionArguments) {
544549
}
545550
}
546551

552+
/// Handler for the shmem interrupt.
553+
///
554+
/// We currently use it to check for work from the controller
555+
/// or other nodes in the rackscale architecture.
556+
unsafe fn shmem_handler(_a: &ExceptionArguments) {
557+
#[cfg(feature = "test-shmem")]
558+
{
559+
// Don't change this print stmt. without changing
560+
// `s03_ivshmem_interrupt` in tests/s03_kernel_high_tests.rs:
561+
sprintln!("Got a shmem interrupt");
562+
debug::shutdown(ExitReason::Ok);
563+
}
564+
565+
if super::process::has_executor() {
566+
// Return immediately
567+
let kcb = get_kcb();
568+
let r = kcb_iret_handle(kcb);
569+
r.resume()
570+
} else {
571+
// Go to scheduler instead
572+
crate::scheduler::schedule()
573+
}
574+
}
575+
547576
/// Handler for a general protection exception.
548577
///
549578
/// TODO: Right now we terminate kernel.
@@ -681,8 +710,8 @@ pub extern "C" fn handle_generic_exception(a: ExceptionArguments) -> ! {
681710
// If we have an active process we should do scheduler activations:
682711
// TODO(scheduling): do proper masking based on some VCPU mask
683712
// TODO(scheduling): Currently don't deliver interrupts to process not currently running
684-
if a.vector > 30 && a.vector < 250 && a.vector != debug::GDB_REMOTE_IRQ_VECTOR.into() {
685-
trace!("handle_generic_exception {:?}", a);
713+
if a.vector > 30 && a.vector < 249 && a.vector != debug::GDB_REMOTE_IRQ_VECTOR.into() {
714+
log::info!("handle_generic_exception {:?}", a);
686715

687716
let mut pborrow = super::process::CURRENT_EXECUTOR.borrow_mut();
688717
let p = pborrow.as_mut().unwrap();
@@ -760,6 +789,8 @@ pub extern "C" fn handle_generic_exception(a: ExceptionArguments) -> ! {
760789
}
761790
} else if a.vector == apic::TSC_TIMER_VECTOR.into() {
762791
timer_handler(&a);
792+
} else if a.vector == SHMEM_VECTOR.into() {
793+
shmem_handler(&a);
763794
}
764795

765796
unhandled_irq(&a);

kernel/src/arch/x86_64/isr.S

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,9 @@ isr_handler 45
229229
isr_handler 46
230230
isr_handler 47
231231

232+
/* qemu shmem interrupt, may (or may not) be used */
233+
isr_handler 249
234+
232235
/* The MLNR gc interrupt */
233236
isr_handler 250
234237
/* TLB work-queue trigger IPI */

kernel/src/arch/x86_64/rackscale/client.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::arch::rackscale::processops::request_core::request_core_work;
1515
use crate::cmdline::Transport;
1616
use crate::error::KError;
1717
use crate::fs::NrLock;
18-
use crate::transport::shmem::SHMEM_REGION;
18+
use crate::transport::shmem::SHMEM_DEVICE;
1919

2020
/// A handle to an RPC client
2121
///
@@ -28,7 +28,7 @@ pub(crate) static ref RPC_CLIENT: Arc<Mutex<Box<Client>>> =
2828
.map_or(false, |c| c.transport == Transport::Ethernet)
2929
{
3030
// To support alloc_phys, client needs shared memory to be mapped
31-
lazy_static::initialize(&SHMEM_REGION);
31+
lazy_static::initialize(&SHMEM_DEVICE);
3232

3333
Arc::new(Mutex::new(
3434
crate::transport::ethernet::init_ethernet_rpc(

kernel/src/arch/x86_64/rackscale/processops/allocate_physical.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use crate::fs::fd::FileDescriptor;
1919
use crate::memory::backends::PhysicalPageProvider;
2020
use crate::memory::{Frame, PAddr, BASE_PAGE_SIZE};
2121
use crate::nrproc::NrProcess;
22-
use crate::transport::shmem::SHMEM_REGION;
22+
use crate::transport::shmem::SHMEM_DEVICE;
2323

2424
use super::super::dcm::resource_alloc::dcm_resource_alloc;
2525
use super::super::dcm::DCM_INTERFACE;
@@ -68,9 +68,9 @@ pub(crate) fn rpc_allocate_physical(
6868
debug!(
6969
"AllocatePhysical() mapping base from {:x?} to {:x?}",
7070
frame_base,
71-
frame_base + SHMEM_REGION.base_addr
71+
frame_base + SHMEM_DEVICE.mem_addr
7272
);
73-
let frame_base = frame_base + SHMEM_REGION.base_addr;
73+
let frame_base = frame_base + SHMEM_DEVICE.mem_addr;
7474
let frame = Frame::new(PAddr::from(frame_base), size as usize, affinity as usize);
7575
let fid = NrProcess::<Ring3Process>::allocate_frame_to_process(pid, frame)?;
7676

kernel/src/arch/x86_64/rackscale/processops/release_physical.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ use crate::arch::process::current_pid;
2323
use crate::arch::process::Ring3Process;
2424
use crate::arch::rackscale::client::{get_frame_as, FRAME_MAP};
2525
use crate::arch::rackscale::controller::{get_local_pid, SHMEM_MANAGERS};
26-
use crate::transport::shmem::SHMEM_REGION;
2726

2827
#[derive(Debug)]
2928
pub(crate) struct ReleasePhysicalReq {

kernel/src/integration_tests.rs

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::ExitReason;
1111
type MainFn = fn();
1212

1313
#[cfg(feature = "integration-test")]
14-
const INTEGRATION_TESTS: [(&str, MainFn); 27] = [
14+
const INTEGRATION_TESTS: [(&str, MainFn); 29] = [
1515
("exit", just_exit_ok),
1616
("wrgsbase", wrgsbase),
1717
("pfault-early", just_exit_fail),
@@ -39,6 +39,8 @@ const INTEGRATION_TESTS: [(&str, MainFn); 27] = [
3939
("vmxnet-smoltcp", vmxnet_smoltcp),
4040
("cxl-read", cxl_read),
4141
("cxl-write", cxl_write),
42+
("shmem-interruptor", shmem_interruptor),
43+
("shmem-interruptee", shmem_interruptee),
4244
];
4345

4446
#[cfg(feature = "integration-test")]
@@ -770,11 +772,12 @@ pub(crate) const BUFFER_CONTENT: u8 = 0xb;
770772
#[cfg(all(feature = "integration-test", target_arch = "x86_64"))]
771773
pub(crate) fn cxl_write() {
772774
use crate::memory::KERNEL_BASE;
773-
use crate::transport::shmem::init_shmem_device;
775+
use crate::transport::shmem::SHMEM_DEVICE;
774776

775-
let (base_paddr, size) = init_shmem_device().expect("Can't init shmem device");
776-
for i in 0..size {
777-
let region = (base_paddr + KERNEL_BASE + i as u64) as *mut u8;
777+
lazy_static::initialize(&SHMEM_DEVICE);
778+
779+
for i in 0..SHMEM_DEVICE.mem_size {
780+
let region = (SHMEM_DEVICE.mem_addr + KERNEL_BASE + i as u64) as *mut u8;
778781
unsafe { core::ptr::write(region, BUFFER_CONTENT) };
779782
}
780783

@@ -785,18 +788,63 @@ pub(crate) fn cxl_write() {
785788
#[cfg(all(feature = "integration-test", target_arch = "x86_64"))]
786789
pub(crate) fn cxl_read() {
787790
use crate::memory::KERNEL_BASE;
788-
use crate::transport::shmem::init_shmem_device;
791+
use crate::transport::shmem::SHMEM_DEVICE;
792+
793+
lazy_static::initialize(&SHMEM_DEVICE);
789794

790-
let (base_paddr, size) = init_shmem_device().expect("Can't init shmem device");
791-
for i in 0..size {
792-
let region = (base_paddr + KERNEL_BASE + i as u64) as *mut u8;
795+
for i in 0..SHMEM_DEVICE.mem_size {
796+
let region = (SHMEM_DEVICE.mem_addr + KERNEL_BASE + i as u64) as *mut u8;
793797
let read = unsafe { core::ptr::read(region) };
794798
assert_eq!(read, BUFFER_CONTENT);
795799
}
796800

797801
shutdown(ExitReason::Ok);
798802
}
799803

804+
/// Test cxl device in the kernel.
805+
#[cfg(all(feature = "integration-test", target_arch = "x86_64"))]
806+
pub(crate) fn shmem_interruptor() {
807+
use crate::transport::shmem::SHMEM_DEVICE;
808+
809+
lazy_static::initialize(&SHMEM_DEVICE);
810+
{
811+
// The ivshmem server allocates IDs consecutively, so we'll assume interruptee is
812+
// current_id - 1
813+
log::info!(
814+
"Sending shmem interrupt to: {:?} on vector {:?}",
815+
SHMEM_DEVICE.id - 1,
816+
1
817+
);
818+
SHMEM_DEVICE.set_doorbell(1, SHMEM_DEVICE.id - 1);
819+
}
820+
shutdown(ExitReason::Ok);
821+
}
822+
823+
/// Test cxl device in the kernel.
824+
#[cfg(all(feature = "integration-test", target_arch = "x86_64"))]
825+
pub(crate) fn shmem_interruptee() {
826+
use core::hint::spin_loop;
827+
use core::time::Duration;
828+
829+
use crate::arch::irq::SHMEM_VECTOR;
830+
use crate::transport::shmem::SHMEM_DEVICE;
831+
832+
lazy_static::initialize(&SHMEM_DEVICE);
833+
834+
SHMEM_DEVICE.enable_msix_vector(0, 0, SHMEM_VECTOR);
835+
SHMEM_DEVICE.enable_msix_vector(1, 0, SHMEM_VECTOR);
836+
837+
let start = rawtime::Instant::now();
838+
crate::arch::irq::enable();
839+
while start.elapsed() < Duration::from_secs(60) {
840+
spin_loop();
841+
}
842+
crate::arch::irq::disable();
843+
let _done = start.elapsed().as_nanos();
844+
845+
shutdown(ExitReason::Ok);
846+
}
847+
800848
/// Test shootdown facilities in the kernel.
801849
#[cfg(all(feature = "integration-test", target_arch = "x86_64"))]
802850
fn shootdown_simple() {

0 commit comments

Comments
 (0)