diff --git a/acpi/src/lib.rs b/acpi/src/lib.rs
index 0b254df1..e3a1343b 100644
--- a/acpi/src/lib.rs
+++ b/acpi/src/lib.rs
@@ -72,6 +72,7 @@ pub mod madt;
 pub mod mcfg;
 pub mod rsdp;
 pub mod sdt;
+pub mod slit;
 pub mod spcr;
 
 #[cfg(feature = "allocator_api")]
diff --git a/acpi/src/platform/mod.rs b/acpi/src/platform/mod.rs
index bf4097c3..3d6b96b6 100644
--- a/acpi/src/platform/mod.rs
+++ b/acpi/src/platform/mod.rs
@@ -1,15 +1,7 @@
 pub mod interrupt;
 
 use crate::{
-    address::GenericAddress,
-    fadt::Fadt,
-    madt::{Madt, MadtError, MpProtectedModeWakeupCommand, MultiprocessorWakeupMailbox},
-    AcpiError,
-    AcpiHandler,
-    AcpiResult,
-    AcpiTables,
-    ManagedSlice,
-    PowerProfile,
+    address::GenericAddress, fadt::Fadt, madt::{Madt, MadtError, MpProtectedModeWakeupCommand, MultiprocessorWakeupMailbox}, slit::Slit, AcpiError, AcpiHandler, AcpiResult, AcpiTables, ManagedSlice, PowerProfile
 };
 use core::{alloc::Allocator, mem, ptr};
 use interrupt::InterruptModel;
@@ -64,6 +56,24 @@ where
     }
 }
 
+#[derive(Clone, Debug)]
+pub struct SystemLocalityInfo<'a, A>
+where
+    A: Allocator,
+{
+    pub nr_system_localities: u64,
+    pub distance_matrix: ManagedSlice<'a, ManagedSlice<'a, u8, A>, A>,
+}
+
+impl <'a, A> SystemLocalityInfo<'a, A>
+where
+    A: Allocator,
+{
+    pub(crate) fn new(nr_system_localities: u64, distance_matrix: ManagedSlice<'a, ManagedSlice<'a, u8, A>, A>) -> Self {
+        Self { nr_system_localities, distance_matrix }
+    }
+}
+
 /// Information about the ACPI Power Management Timer (ACPI PM Timer).
 #[derive(Debug, Clone)]
 pub struct PmTimer {
@@ -95,6 +105,7 @@ where
     /// On `x86_64` platforms that support the APIC, the processor topology must also be inferred from the
     /// interrupt model. That information is stored here, if present.
     pub processor_info: Option<ProcessorInfo<'a, A>>,
+    pub system_locality_info: Option<SystemLocalityInfo<'a, A>>,
     pub pm_timer: Option<PmTimer>,
     /*
      * TODO: we could provide a nice view of the hardware register blocks in the FADT here.
@@ -124,12 +135,16 @@ where
 
         let madt = tables.find_table::<Madt>();
         let (interrupt_model, processor_info) = match madt {
-            Ok(madt) => madt.get().parse_interrupt_model_in(allocator)?,
+            Ok(madt) => madt.get().parse_interrupt_model_in(allocator.clone())?,
             Err(_) => (InterruptModel::Unknown, None),
         };
+        let system_locality_info = {
+            let slit = tables.find_table::<Slit>();
+            slit.and_then(|slit| slit.get().parse_system_locality_in(allocator)).ok()
+        };
         let pm_timer = PmTimer::new(&fadt)?;
 
-        Ok(PlatformInfo { power_profile, interrupt_model, processor_info, pm_timer })
+        Ok(PlatformInfo { power_profile, interrupt_model, processor_info, system_locality_info, pm_timer })
     }
 }
 
diff --git a/acpi/src/slit.rs b/acpi/src/slit.rs
new file mode 100644
index 00000000..a51c1d20
--- /dev/null
+++ b/acpi/src/slit.rs
@@ -0,0 +1,84 @@
+use core::{alloc::Allocator, marker::PhantomPinned, pin::Pin};
+
+use crate::{platform::SystemLocalityInfo, sdt::{SdtHeader, Signature}, AcpiResult, AcpiTable};
+
+/// System Locality Information Table (SLIT)
+/// 
+/// This optional table provides a matrix that describes the relative distance 
+/// (memory latency) between all System Localities, which are also referred to 
+/// as Proximity Domains. The value of each Entry[i,j] in the SLIT table, where 
+/// i represents a row of a matrix and j represents a column of a matrix, 
+/// indicates the relative distances from System Locality / Proximity Domain i 
+/// to every other System Locality j in the system (including itself).
+#[repr(C, packed)]
+pub struct Slit {
+    header: SdtHeader,
+    nr_system_localities: u64,
+    _pinned: PhantomPinned,
+}
+
+unsafe impl AcpiTable for Slit {
+    const SIGNATURE: Signature = Signature::SLIT;
+
+    fn header(&self) -> &SdtHeader {
+        &self.header
+    }
+}
+
+impl Slit {
+    #[cfg(feature = "allocator_api")]
+    pub fn parse_system_locality_in<'a, A>(
+        self: Pin<&Self>,
+        allocator: A,
+    ) -> AcpiResult<SystemLocalityInfo<'a, A>>
+    where 
+        A: Allocator + Clone,
+    {
+        use crate::ManagedSlice;
+
+        let (mut row, mut column) = (0, 0);
+        let mut distance_matrix = ManagedSlice::new_in(self.nr_system_localities as usize, allocator.clone())?;
+        for entry in self.entries() {
+            if column == 0 {
+                distance_matrix[row] = ManagedSlice::new_in(self.nr_system_localities as usize, allocator.clone())?;
+            }
+            distance_matrix[row][column] = entry;
+            column += 1;
+            if column == self.nr_system_localities as usize {
+                row += 1;
+                column = 0;
+            }
+        }
+
+        Ok(SystemLocalityInfo::new(self.nr_system_localities, distance_matrix))
+    }
+
+    fn entries(self: Pin<&Self>) -> SlitEntryIter {
+        let ptr = unsafe { Pin::into_inner_unchecked(self) as *const Slit as *const u8 };
+        SlitEntryIter {
+            pointer: unsafe { ptr.add(size_of::<Slit>()) },
+            remaining_length: self.header.length - size_of::<Slit>() as u32,
+        }
+    }   
+}
+
+struct SlitEntryIter {
+    pointer: *const u8,
+    remaining_length: u32,
+}
+
+impl Iterator for SlitEntryIter {
+    type Item = u8;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.remaining_length > 0 {
+            let entry_pointer = self.pointer;
+            self.pointer = unsafe { self.pointer.add(size_of::<Self::Item>()) };
+            self.remaining_length -= size_of::<Self::Item>() as u32;
+            Some(unsafe { *entry_pointer })
+        } else {
+            None
+        }
+    }
+}
+