70 lines
3.0 KiB
Go
70 lines
3.0 KiB
Go
// Copyright 2016 The Periph Authors. All rights reserved.
|
|
// Use of this source code is governed under the Apache License, Version 2.0
|
|
// that can be found in the LICENSE file.
|
|
|
|
// Package pmem implements handling of physical memory for user space programs.
|
|
//
|
|
// To make things confusing, a modern computer has many view of the memory
|
|
// (address spaces):
|
|
//
|
|
// User
|
|
//
|
|
// User mode address space is the virtual address space that an application
|
|
// runs in. It is generally a tad less than half the addressable memory, so on
|
|
// a 32 bits system, the addressable range is 1.9Gb. For 64 bits OS, it depends
|
|
// but it usually at least 3.5Gb. The memory is virtual and can be flushed to
|
|
// disk in the swap file unless individual pages are locked.
|
|
//
|
|
// Kernel
|
|
//
|
|
// Kernel address space is the virtual address space the kernel sees. It often
|
|
// can see the currently active user space program on the current CPU core in
|
|
// addition to all the memory the kernel sees. The kernel memory pages that are
|
|
// not mlock()'ed are 'virtual' and can be flushed to disk in the swap file
|
|
// when there's not enough RAM available. On linux systems, the kernel
|
|
// addressed memory can be mapped in user space via `/dev/kmem`.
|
|
//
|
|
// Physical
|
|
//
|
|
// Physical memory address space is the actual address of each page in the DRAM
|
|
// chip and anything connected to the memory controller. The mapping may be
|
|
// different depending on what controller looks at the bus, like with IOMMU. So
|
|
// a peripheral (GPU, DMA controller) may have a different view of the physical
|
|
// memory than the host CPU. On linux systems, this memory can be mapped in
|
|
// user space via `/dev/mem`.
|
|
//
|
|
// CPU
|
|
//
|
|
// The CPU or its subsystems may memory map registers (for example, to control
|
|
// GPIO pins, clock speed, etc). This is not "real" memory, this is a view of
|
|
// registers but it still follows "mostly" the same semantic as DRAM backed
|
|
// physical memory.
|
|
//
|
|
// Some CPU memory may have very special semantic where the mere fact of
|
|
// reading has side effects. For example reading a specific register may
|
|
// latches another.
|
|
//
|
|
// CPU memory accesses are layered with multiple caches, usually named L1, L2
|
|
// and optionally L3. Some controllers (DMA) can see some cache levels (L2) but
|
|
// not others (L1) on some CPU architecture (bcm283x). This means that a user
|
|
// space program writing data to a memory page and immediately asking the DMA
|
|
// controller to read it may cause stale data to be read!
|
|
//
|
|
// Hypervisor
|
|
//
|
|
// Hypervisor can change the complete memory mapping as seen by the kernel.
|
|
// This is outside the scope of this project. :)
|
|
//
|
|
// Summary
|
|
//
|
|
// In practice, the semantics change between CPU manufacturers (Broadcom vs
|
|
// Allwinner) and between architectures (ARM vs x86). The most tricky one is to
|
|
// understand cached memory and how it affects coherence and performance.
|
|
// Uncached memory is extremely slow so it must only be used when necessary.
|
|
//
|
|
// References
|
|
//
|
|
// Overview of IOMMU:
|
|
// https://en.wikipedia.org/wiki/Input-output_memory_management_unit
|
|
package pmem
|