PCI transactions / TLP (transaction layer protocol)

The Transaction Layer is located between the Application Layer and the Data Link Layer.

PCI Express transactions can be grouped into four categories: 1) memory, 2) IO, 3) configuration, and 4) message transactions.

Transactions are defined as a series of one or more packet transmissions required to complete an information transfer …

Introduction to PCI Express Transactions - PCI Express System Architecture [Book]

Chip selection signal

When an engineer needs to connect several devices to the same set of input wires (e.g., a computer bus), but retain the ability to send and receive data or commands to each device independently of the others on the bus, they can use a chip select. When the chip select pin is in:

  • The inactive state, the chip or device is "deaf", and pays no heed to changes in the state of its other input pins;
  • The active state, the chip or device assumes that any input changes it "hears" are meant for it, and responds as if it is the only chip on the bus. Because the other chips have their chip select pins in the inactive state, their outputs are high impedance, allowing the single selected chip to drive its outputs.

Chip select - Wikipedia

QEMU bottom half(bh)

QEMU actually uses a hybrid architecture:

  • Parallel architecture splits work into processes or threads that can execute simultaneously. I will call this threaded architecture.
  • Event-driven architecture reacts to events by running a main loop that dispatches to event handlers. This is commonly implemented using the select(2) or poll(2) family of system calls to wait on multiple file descriptors.

Bottom half 本身就是一种事件循环,并不是用 thread 来实现的。和它在作用上等效的是一个直接 expire 的 timer,区别是 timer 是真的异步,bottom half 是借时间循环来异步。

意义是什么?avoid reentrancy and overflowing the call stack,相当于直接把 call stack 返回了第 0 层。适用于不断调用自己的函数或者调用层级比较多的函数。

深入理解 qemu 事件循环 —— 下半部_享乐主的博客 - CSDN 博客

Stefan Hajnoczi: QEMU Internals: Overall architecture and threading model

pthread_create()

// start_routine: the real thread function need to run
// arg: Arguments need to be passed to "start_routine"
int pthread_create(pthread_t *restrict thread,
                   const pthread_attr_t *restrict attr,
                   void *(*start_routine)(void *),
                   void *restrict arg);

小狼毫/Weasel 调色

Rime西米

Madvise / madvise()

Give (Note: not get) advice about use of memory about the given address range. I.e., use huge page or not.

madvise() only operates on whole page, therefore addr must be page-aligned.

In most cases, the goal of such advice is to improve system or application performance.

MADV_DONTDUMP: Exclude from a core dump those pages in the range specified by addr and length. This is useful in applications that have large areas of memory that are known not to be useful in a core dump.

MADV_DONTFORK: Do not make the pages in this range available to the child after a fork. This is useful to prevent copy-on-write semantics from changing the physical location of a page if the parent writes to it after a fork.

Gdb frame

When your program is started, the stack has only one frame, that of the main(). This is called the initial frame or the outermost frame. Each time a function is called, a new frame is made.

Frames

Mermaid 画时序图

可以用 Gantt 图来画:

Gantt diagrams | Mermaid

如何让 tag (milestone) 不重叠?

Typedef function pointer

typedef void (*myfunc)();
myfunc f;      // compile equally as void (*f)();

c++ - Typedef function pointer? - Stack Overflow

iovec In kernel, scatter/gather IO, readv/writev

为了提高从磁盘读到内存的效率,引入了 struct iovec,主要在 readvwritev 中使用。

// readv:从 fd 中读 count 个数据段到多个 buffers 中,每一个 buffer 是一个 struct iovec,参数 iov 表示这些 iovec。
// iovcnt 表示 iov 中 iovec 的数量,writev 类似。
ssize_t readv(int fd, const struct iovec *iov, int iovcnt);
ssize_t writev(int fd, const struct iovec *iov, int iovcnt);

// Compared to read and write, readv has a higher performance, 
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);

这里有一个简单的性能对比:readv/writev分析 - 知乎

可以看到,主要节省的是系统调用的开销。

struct iovec {
    void *iov_base;	/* Pointer to data.  */
    size_t iov_len;	/* Length of data.  */
};

Userspace use case:

int main() {
	struct iovec iov[3];
	int fd, i;
	
	char *buf[] = {
		"The term buccaneer comes from the word boucan.\n",
		"A boucan is a wooden frame used for cooking meat.\n",
		"Buccaneer is the West Indies name for a pirate.\n" 
	};
	
	fd = open("buccaneer.txt", O_WRONLY | O_CREAT | O_TRUNC);

	for(i = 0; i < 3; i++){
		iov[i].iov_base = buf[i];
		iov[i].iov_len = strlen(buf[i]);
	}
	
	writev(fd, iov, 3);
    close(fd);
	return 0;
}

KVM device framework

struct kvm_device_ops {
	const char *name;
	int (*create)(struct kvm_device *dev, u32 type);
	void (*init)(struct kvm_device *dev);
	void (*destroy)(struct kvm_device *dev);
	void (*release)(struct kvm_device *dev);

	int (*set_attr)(struct kvm_device *dev, struct kvm_device_attr *attr);
	int (*get_attr)(struct kvm_device *dev, struct kvm_device_attr *attr);
	int (*has_attr)(struct kvm_device *dev, struct kvm_device_attr *attr);
	long (*ioctl)(struct kvm_device *dev, unsigned int ioctl,
		      unsigned long arg);
	int (*mmap)(struct kvm_device *dev, struct vm_area_struct *vma);
};

The reason why there is ioctl and set_attr is ioctl callback is used to handle the default operations.

MONITOR/MWAIT Instruction

SSE3 提供的 MONITOR/MWAIT 的目标是供系统软件用于提供更有效的线程同步原件。

OS 可以在其 idle loop(被称为 C0 循环)中使用 MONITORMWAIT 来减少电能消耗。

For a spin lock, a while check loop is performed until the value is changed. This can be enhanced using MONITOR/MWAIT:

  • MONITOR 建立一个有效的寻址范围,用于监视对存储器写的活动;
  • MWAIT 将处理器置于一个优化的状态,直到一次对被监视的地址范围的发生。

引入了 monitormwait 指令后,避免了 hlt 导致的唤醒延迟。

Intel系统编程指南第八章——8.10 空闲和阻塞情况的管理_zenny_chen的博客-CSDN博客

MWAIT: Monitor Wait

Introduction to hlt/pause/monitor/mwait instruction - L

assembly - Uses of the monitor/mwait instructions - Stack Overflow

Anonymous structure/union (unnamed structure/union) in C

struct {
    int a;
    struct {
        int b;
    };
    union {
        int c;
    };
} foo;

You can foo.a, foo.b and foo.c.

Bit field in C

struct date {
    // d has value between 0 and 31, so 5 bits
    // are sufficient
    int d : 5;
    // m has value between 0 and 15, so 4 bits
    // are sufficient
    int m : 4;
    int y;
};

Defconfig

defconfig 一般在 arch/arm64/configs/ 目录下,是一个没有展开的内核配置,需要配合 Kconfig 展开成 .config.

从 defconfig 到.config 不是简单的复制操作,而是 make ARCH=arm64 defconfig

.confg 也不是直接拷贝成 defconfig,而是使用 make ARCH=arm64 savedefconfig

linux kernel: defconfig和.config_defconfig和config_hello_courage的博客-CSDN博客

Merge 2 kernel configs

scripts/kconfig/merge_config.sh -m <base_config> <merge_config>

Get kernel config for currently running system

Make sure CONFIG_IKCONFIG_PROC=y when building the kernel, then:

modprobe configs
cat /proc/config.gz | gunzip > running.config

BMC

Baseboard Management Controller.

BMC 是独立于服务器系统之外的小型操作系统,是一个集成在主板上的芯片。

A baseboard management controller (BMC) is a service processor which is capable of monitoring the physical state of servers, computers or other hardware devices with help of sensors.

What is SeaBIOS and the relationship with OVMF?

SeaBIOS 是 16bit BIOS 的一个实现,是 QEMU 默认使用的。

QEMU, by default, uses a BIOS called SeaBios. It is a pretty good option and most can be used with most bootloaders. And naturally, every guest machine is loaded with the SeaBios and you don't have to do anything. However, you might want, or need, to use UEFI instead. 这个时候就需要用 OVMF 了,其加入了对于 UEFI 的支持。

一句话,能用 OVMF 就用 OVMF。

Vmexit reasons

It is a 32-bit field in VMCS.

Volume 3. SDM APPENDIX C VMX BASIC EXIT REASONS

How to see processor stepping?

BIOS -> Socket Configuration -> Processor BSP Revision

跳线 Jumpers

跳线 - 维基百科,自由的百科全书

Reboot to BIOS/UEFI

systemctl reboot --firmware-setup

"invalid For another…" on Ubuntu

service ntp stop

Configure NTP server by editing /etc/ntp.conf (replace the server with yours):

tinker panic 0
disable monitor
 
restrict <server1> nomodify notrap nopeer noquery
restrict <server2> nomodify notrap nopeer noquery
restrict <server3> nomodify notrap nopeer noquery
 
server <server1> iburst
server <server2> iburst
server <server3> iburst
 
driftfile /var/lib/ntp/drift
 
restrict -4 default kod notrap nomodify nopeer noquery limited
restrict -6 default kod notrap nomodify nopeer noquery limited
 
restrict 127.0.0.1
restrict ::1
 
restrict source notrap nomodify noquery
ntpd -gq
service ntp start

How to create extensions for Thunderbird

A Guide to Extensions - Thunderbird

Why x64 doesn't have r0-r7 registers?

Wrong.

With x86_64 came another doubling of register size, as well as the addition of some new registers. These registers are 64 bits wide and are named (slash used to show alternate register name): RAX/r0, RCX/r1, RDX/r2, RBX/r3, RSP/r4, RBP/r5, RSI/r6, RDI/r7, R8, R9, R10, R11, R12, R13, R14, R15.

assembly - Why did they use numbers for register names in x86-64? - Stack Overflow