Skip to content
Snippets Groups Projects
Commit d6d9ef6b authored by Florent Gluck's avatar Florent Gluck
Browse files

Added new slide about err vs errx, minor improvements throughout the slides

parent e8cbeebd
No related branches found
No related tags found
No related merge requests found
......@@ -168,20 +168,30 @@ pandoc-latex-fontsize:
\vspace{.3cm}
```{.c .verysmall}
int kvmfd = open("/dev/kvm", O_RDWR | O_CLOEXEC);
if (kvmfd < 0) err(1, "%s", "/dev/kvm");
if (kvmfd < 0) err(1, "Failed opening kvm device: ");
int version = ioctl(kvmfd, KVM_GET_API_VERSION, NULL);
if (version < 0) err(1, "KVM_GET_API_VERSION");
if (version != KVM_API_VERSION) err(1, "Unsupported version of the KVM API");
if (version < 0) err(1, "KVM_GET_API_VERSION failed: ");
if (version != KVM_API_VERSION) errx(1, "Error: KVM_GET_API_VERSION %d, expected %d!", version, KVM_API_VERSION);
```
[//]: # ----------------------------------------------------------------
## Abort handling: err vs errx
- Both `err` and `errx` functions print an error message to `stderr` and abort the current process
- `err` must be used when the function that fails sets `errno` (typically a system call)
- `err` appends an error message (based on `errno`) to the text passed in argument
- `errx` must be used when the function that fails does not set `errno`
- Both functions accept variable parameters (like `printf`)
[//]: # ----------------------------------------------------------------
## (2) Create a VM
- To obtain a file descriptor (here, `vmfd`) on a newly created VM:
```{.c .verysmall}
int vmfd = ioctl(kvmfd, KVM_CREATE_VM, 0);
if (vmfd < 0) err(1, "KVM_CREATE_VM");
#define MACHINE_TYPE 0
int vmfd = ioctl(kvmfd, KVM_CREATE_VM, MACHINE_TYPE);
if (vmfd < 0) err(1, "Error: KVM_CREATE_VM failed: ");
```
- This file descriptor allows us to:
- defines the VM's memory address space
......@@ -206,7 +216,7 @@ pandoc-latex-fontsize:
// Alloc 4KB for the guest
u_int ram_size = 4096;
uint8_t *mem = mmap(NULL, ram_size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
if (!mem) err(1, "Allocating guest memory");
if (!mem) err(1, "Error: failed allocating guest memory: ");
```
[//]: # ----------------------------------------------------------------
......@@ -224,7 +234,7 @@ pandoc-latex-fontsize:
.userspace_addr = (uint64_t)mem,
.flags = 0
};
if (ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &memreg) < 0) err(1, "KVM_SET_USER_MEMORY_REGION");
if (ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &memreg) < 0) err(1, "Error: KVM_SET_USER_MEMORY_REGION: ");
```
<!--
......@@ -245,7 +255,7 @@ pandoc-latex-fontsize:
.userspace_addr = (uint64_t)mmio,
.flags = KVM_MEM_READONLY // Mandatory for MMIO!
};
if (ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &memreg) < 0) err(1, "KVM_SET_USER_MEMORY_REGION");
if (ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &memreg) < 0) err(1, "Error: KVM_SET_USER_MEMORY_REGION: ");
```
-->
......@@ -269,14 +279,14 @@ pandoc-latex-fontsize:
\vspace{.3cm}
```{.c .tiny}
int vcpufd = ioctl(vmfd, KVM_CREATE_VCPU, 0);
if (vcpufd < 0) err(1, "KVM_CREATE_VCPU");
if (vcpufd < 0) err(1, "Error: KVM_CREATE_VCPU: ");
int vcpu_mmap_sz = ioctl(kvmfd, KVM_GET_VCPU_MMAP_SIZE, NULL);
if (vcpu_mmap_sz < 0) err(1, "KVM_GET_VCPU_MMAP_SIZE");
if (vcpu_mmap_sz < sizeof(struct kvm_run)) err(1, "KVM_GET_VCPU_MMAP_SIZE unexpectedly small");
if (vcpu_mmap_sz < 0) err(1, "Error: KVM_GET_VCPU_MMAP_SIZE: ");
if (vcpu_mmap_sz < sizeof(struct kvm_run)) err(1, "Error: KVM_GET_VCPU_MMAP_SIZE unexpectedly small: ");
struct kvm_run *run = mmap(NULL, vcpu_mmap_sz, PROT_READ | PROT_WRITE, MAP_SHARED, vcpufd, 0);
if (!run) err(1, "mmap vcpu");
if (!run) err(1, "Error: Failed to mmap vCPU: ");
```
[//]: # ----------------------------------------------------------------
......@@ -286,12 +296,12 @@ pandoc-latex-fontsize:
\vspace{.3cm}
```{.c .verysmall}
struct kvm_sregs sregs;
if (ioctl(vcpufd, KVM_GET_SREGS, &sregs) < 0) err(1, "KVM_GET_SREGS");
if (ioctl(vcpufd, KVM_GET_SREGS, &sregs) < 0) err(1, "Error: KVM_GET_SREGS: ");
sregs.cs.base = 0; sregs.cs.selector = 0;
sregs.ds.base = 0; sregs.ds.selector = 0;
sregs.es.base = 0; sregs.es.selector = 0;
sregs.ss.base = 0; sregs.ss.selector = 0;
if (ioctl(vcpufd, KVM_SET_SREGS, &sregs) < 0) err(1, "KVM_SET_SREGS");
if (ioctl(vcpufd, KVM_SET_SREGS, &sregs) < 0) err(1, "Error: KVM_SET_SREGS: ");
```
[//]: # ----------------------------------------------------------------
......@@ -307,7 +317,7 @@ pandoc-latex-fontsize:
regs.rip = 0;
regs.rsp = ram_size;
regs.rflags = 0x2;
if (ioctl(vcpufd, KVM_SET_REGS, &regs) < 0) err(1, "KVM_SET_REGS");
if (ioctl(vcpufd, KVM_SET_REGS, &regs) < 0) err(1, "Error: KVM_SET_REGS: ");
```
[//]: # ----------------------------------------------------------------
......@@ -322,7 +332,7 @@ pandoc-latex-fontsize:
bool done = false;
while (!done) {
// Runs the vCPU until encoutering a VM_EXIT (blocking call)
if (ioctl(vcpufd, KVM_RUN, NULL) < 0) err(1, "KVM_RUN");
if (ioctl(vcpufd, KVM_RUN, NULL) < 0) err(1, "Error: KVM_RUN: ");
switch (run->exit_reason) { // See struct kvm_run in "(6) Create a vCPU"
case KVM_EXIT_IO: // Encountered a PMIO VMexit
break; // This VMexit should be handled here...
......@@ -1097,11 +1107,12 @@ outb(0x3C5, 0x0F);
## Why hardware interrupts?
- To avoid constantly polling devices
- Polling must be avoided:
- Polling should be avoided:
- polling frequently: low latency, but high CPU usage
- polling infrequently: low CPU usage, but high latency
- To handle timers
- A timer offers a time base independent of the CPU frequency
- necessary to mesure time accurately
- necessary to implement `sleep` or similar functionalities
[//]: # ----------------------------------------------------------------
......@@ -1158,11 +1169,13 @@ A Programmable Interrupt Controller (PIC) is created by using the following `ioc
\vspace{.3cm}
```{.verysmall .c}
if (ioctl(vmfd, KVM_CREATE_IRQCHIP, 0) < 0) {
if (ioctl(vmfd, KVM_CREATE_IRQCHIP, NULL) < 0) {
// Error...
}
```
Make sure to create it **\textcolor{myred}{before}** creating any vCPU!
[//]: # ----------------------------------------------------------------
## Injection VMM side: (2) configure virtual PIC
......@@ -1231,7 +1244,7 @@ Create a file descriptor for event notification by using the `eventfd` function:
// Create a file descriptor for event (hardware interrupts) notification
int fd = eventfd(0, 0);
if (fd == -1) {
err(1, "eventfd failed");
err(1, "eventfd failed: ");
}
```
......@@ -1250,7 +1263,7 @@ if (fd == -1) {
};
if (ioctl(vm->vmfd, KVM_IRQFD, &irqfd) < 0) {
err(1, "KVM_IRQFD error");
err(1, "KVM_IRQFD error: ");
}
```
......@@ -1276,7 +1289,7 @@ Perform the same steps as on a real physical system[^4]:
- implement ISRs for all potential hardware interrupts that may be triggered
1. Unmask hardware interrupts so that they will be received
\textcolor{myred}{Receiving a hardware interrupts for which there is no properly initialized IVT entry will result in a shutdown/reboot of the guest (as it would on a physical machine)}
\textcolor{myred}{Receiving a hardware interrupts for which there is no properly initialized IVT entry will result in a reboot of the guest (as it would on a physical machine)}
[^4]: \scriptsize With one exception: in the ISR, no need to send an EOI command to the PIC
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment