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

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

parent 4f5303fa
Branches
No related tags found
No related merge requests found
...@@ -168,20 +168,30 @@ pandoc-latex-fontsize: ...@@ -168,20 +168,30 @@ pandoc-latex-fontsize:
\vspace{.3cm} \vspace{.3cm}
```{.c .verysmall} ```{.c .verysmall}
int kvmfd = open("/dev/kvm", O_RDWR | O_CLOEXEC); 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); int version = ioctl(kvmfd, KVM_GET_API_VERSION, NULL);
if (version < 0) err(1, "KVM_GET_API_VERSION"); if (version < 0) err(1, "KVM_GET_API_VERSION failed: ");
if (version != KVM_API_VERSION) err(1, "Unsupported version of the KVM API"); 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 ## (2) Create a VM
- To obtain a file descriptor (here, `vmfd`) on a newly created VM: - To obtain a file descriptor (here, `vmfd`) on a newly created VM:
```{.c .verysmall} ```{.c .verysmall}
int vmfd = ioctl(kvmfd, KVM_CREATE_VM, 0); #define MACHINE_TYPE 0
if (vmfd < 0) err(1, "KVM_CREATE_VM"); 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: - This file descriptor allows us to:
- defines the VM's memory address space - defines the VM's memory address space
...@@ -206,7 +216,7 @@ pandoc-latex-fontsize: ...@@ -206,7 +216,7 @@ pandoc-latex-fontsize:
// Alloc 4KB for the guest // Alloc 4KB for the guest
u_int ram_size = 4096; u_int ram_size = 4096;
uint8_t *mem = mmap(NULL, ram_size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); 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: ...@@ -224,7 +234,7 @@ pandoc-latex-fontsize:
.userspace_addr = (uint64_t)mem, .userspace_addr = (uint64_t)mem,
.flags = 0 .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: ...@@ -245,7 +255,7 @@ pandoc-latex-fontsize:
.userspace_addr = (uint64_t)mmio, .userspace_addr = (uint64_t)mmio,
.flags = KVM_MEM_READONLY // Mandatory for 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: ...@@ -269,14 +279,14 @@ pandoc-latex-fontsize:
\vspace{.3cm} \vspace{.3cm}
```{.c .tiny} ```{.c .tiny}
int vcpufd = ioctl(vmfd, KVM_CREATE_VCPU, 0); 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); 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 < 0) err(1, "Error: 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 < 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); 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: ...@@ -286,12 +296,12 @@ pandoc-latex-fontsize:
\vspace{.3cm} \vspace{.3cm}
```{.c .verysmall} ```{.c .verysmall}
struct kvm_sregs sregs; 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.cs.base = 0; sregs.cs.selector = 0;
sregs.ds.base = 0; sregs.ds.selector = 0; sregs.ds.base = 0; sregs.ds.selector = 0;
sregs.es.base = 0; sregs.es.selector = 0; sregs.es.base = 0; sregs.es.selector = 0;
sregs.ss.base = 0; sregs.ss.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: ...@@ -307,7 +317,7 @@ pandoc-latex-fontsize:
regs.rip = 0; regs.rip = 0;
regs.rsp = ram_size; regs.rsp = ram_size;
regs.rflags = 0x2; 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: ...@@ -322,7 +332,7 @@ pandoc-latex-fontsize:
bool done = false; bool done = false;
while (!done) { while (!done) {
// Runs the vCPU until encoutering a VM_EXIT (blocking call) // 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" switch (run->exit_reason) { // See struct kvm_run in "(6) Create a vCPU"
case KVM_EXIT_IO: // Encountered a PMIO VMexit case KVM_EXIT_IO: // Encountered a PMIO VMexit
break; // This VMexit should be handled here... break; // This VMexit should be handled here...
...@@ -1097,11 +1107,12 @@ outb(0x3C5, 0x0F); ...@@ -1097,11 +1107,12 @@ outb(0x3C5, 0x0F);
## Why hardware interrupts? ## Why hardware interrupts?
- To avoid constantly polling devices - To avoid constantly polling devices
- Polling must be avoided: - Polling should be avoided:
- polling frequently: low latency, but high CPU usage - polling frequently: low latency, but high CPU usage
- polling infrequently: low CPU usage, but high latency - polling infrequently: low CPU usage, but high latency
- To handle timers - To handle timers
- A timer offers a time base independent of the CPU frequency - A timer offers a time base independent of the CPU frequency
- necessary to mesure time accurately
- necessary to implement `sleep` or similar functionalities - necessary to implement `sleep` or similar functionalities
[//]: # ---------------------------------------------------------------- [//]: # ----------------------------------------------------------------
...@@ -1158,11 +1169,13 @@ A Programmable Interrupt Controller (PIC) is created by using the following `ioc ...@@ -1158,11 +1169,13 @@ A Programmable Interrupt Controller (PIC) is created by using the following `ioc
\vspace{.3cm} \vspace{.3cm}
```{.verysmall .c} ```{.verysmall .c}
if (ioctl(vmfd, KVM_CREATE_IRQCHIP, 0) < 0) { if (ioctl(vmfd, KVM_CREATE_IRQCHIP, NULL) < 0) {
// Error... // Error...
} }
``` ```
Make sure to create it **\textcolor{myred}{before}** creating any vCPU!
[//]: # ---------------------------------------------------------------- [//]: # ----------------------------------------------------------------
## Injection VMM side: (2) configure virtual PIC ## Injection VMM side: (2) configure virtual PIC
...@@ -1231,7 +1244,7 @@ Create a file descriptor for event notification by using the `eventfd` function: ...@@ -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 // Create a file descriptor for event (hardware interrupts) notification
int fd = eventfd(0, 0); int fd = eventfd(0, 0);
if (fd == -1) { if (fd == -1) {
err(1, "eventfd failed"); err(1, "eventfd failed: ");
} }
``` ```
...@@ -1250,7 +1263,7 @@ if (fd == -1) { ...@@ -1250,7 +1263,7 @@ if (fd == -1) {
}; };
if (ioctl(vm->vmfd, KVM_IRQFD, &irqfd) < 0) { 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]: ...@@ -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 - implement ISRs for all potential hardware interrupts that may be triggered
1. Unmask hardware interrupts so that they will be received 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 [^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