diff --git a/unikernel-demo/.gitignore b/unikernel-demo/.gitignore new file mode 100644 index 00000000..31d45ec5 --- /dev/null +++ b/unikernel-demo/.gitignore @@ -0,0 +1,3 @@ +*.cmd +*.img +*.o diff --git a/unikernel-demo/Makefile b/unikernel-demo/Makefile new file mode 100644 index 00000000..6257935c --- /dev/null +++ b/unikernel-demo/Makefile @@ -0,0 +1,23 @@ +all: + $(MAKE) -C ../../../whiterose/ UKL=$(CURDIR) bzImage + +../../disk.img: + qemu-img create ../../disk.img 0g + mkfs.ext2 ../../disk.img + mkdir tmp_mnt + sudo mount -o loop ../../disk.img tmp_mnt + sudo debootstrap --arch amd64 jessie tmp_mnt + sudo umount tmp_mnt + rmdir tmp_mnt + +qemu: ../../disk.img + qemu-system-x86_64 -enable-kvm -s -m 1G -nographic -cpu host\ + -kernel ../../../whiterose/arch/x86/boot/bzImage\ + -append "console=ttyS0 ukl-hybrid quiet root=/dev/sda"\ + -hda ../../disk.img + +qemu-ukl: ../../disk.img + qemu-system-x86_64 -enable-kvm -s -m 1G -nographic -cpu host\ + -kernel ../../../whiterose/arch/x86/boot/bzImage\ + -append "console=ttyS0 ukl quiet root=/dev/sda"\ + -hda ../../disk.img diff --git a/unikernel-demo/README.md b/unikernel-demo/README.md new file mode 100644 index 00000000..0f5e9dfe --- /dev/null +++ b/unikernel-demo/README.md @@ -0,0 +1,35 @@ +# unikernel-demo + +### setup + +##### Requirements +- qemu +- debootstrap + +##### Clone & Configure the kernel +``` +git clone https://github.com/ne02ptzero/whiterose +cd whiterose && make defconfig +``` + +It will apply the default of the linux kernel, with UKL support. If you're +trying to run this on exotic hardware, now is a good time to change the +configuration. As long as you keep `CONFIG_UKL_LINUX` to `true`, you should be +fine. + +##### Clone && Running the examples +``` +git clone https://github.com/jzck/unikernel-demo +cd unikernel-demo +``` + +Each example come with a Makefile. For example, if you want to run the unistd +example, simply do: +``` +make -C fs1/unistd all qemu +``` + +Or stdio: +``` +make -C fs1/stdio all qemu +``` diff --git a/unikernel-demo/fs1/stat/Makefile b/unikernel-demo/fs1/stat/Makefile new file mode 100644 index 00000000..ecd636b7 --- /dev/null +++ b/unikernel-demo/fs1/stat/Makefile @@ -0,0 +1,3 @@ +export ukl-obj-m := main.o + +include ../../Makefile diff --git a/unikernel-demo/fs1/stat/main.c b/unikernel-demo/fs1/stat/main.c new file mode 100644 index 00000000..abb3da10 --- /dev/null +++ b/unikernel-demo/fs1/stat/main.c @@ -0,0 +1,20 @@ +#include +#include + +#ifndef USERSPACE +#define main ukl_main +#endif + +int main(void) +{ + struct stat st = { 0 }; + + if (stat("/etc/passwd", &st) != 0) + { + fprintf(stderr, "Cannot stat() /etc/passwd\n"); + return 1; + } + + printf("Size of /etc/passwd: %zu bytes\n", st.st_size); + return 0; +} diff --git a/unikernel-demo/fs1/stdio/Makefile b/unikernel-demo/fs1/stdio/Makefile new file mode 100644 index 00000000..ecd636b7 --- /dev/null +++ b/unikernel-demo/fs1/stdio/Makefile @@ -0,0 +1,3 @@ +export ukl-obj-m := main.o + +include ../../Makefile diff --git a/unikernel-demo/fs1/stdio/main.c b/unikernel-demo/fs1/stdio/main.c new file mode 100644 index 00000000..cee94583 --- /dev/null +++ b/unikernel-demo/fs1/stdio/main.c @@ -0,0 +1,26 @@ +#include + +#include +#include + +#ifndef USERSPACE +#define main ukl_main +#endif + +int main(void) { + FILE *f = fopen("/etc/passwd", "r"); + ssize_t ret; + char buf[256] = { 0 }; + + if (f == NULL) + { + fputs("Cannot open /etc/passwd\n", stderr); + return 1; + } + + while ((ret = fread(buf, 1, sizeof(buf), f))) + fwrite(buf, ret, 1, stdout); + + fclose(f); + return 0; +} diff --git a/unikernel-demo/fs1/unistd/Makefile b/unikernel-demo/fs1/unistd/Makefile new file mode 100644 index 00000000..ecd636b7 --- /dev/null +++ b/unikernel-demo/fs1/unistd/Makefile @@ -0,0 +1,3 @@ +export ukl-obj-m := main.o + +include ../../Makefile diff --git a/unikernel-demo/fs1/unistd/main.c b/unikernel-demo/fs1/unistd/main.c new file mode 100644 index 00000000..6f0a7a52 --- /dev/null +++ b/unikernel-demo/fs1/unistd/main.c @@ -0,0 +1,25 @@ +#include +#include + +#ifndef USERSPACE +# define main ukl_main +#endif + +int main(void) { + char buf[256] = { 0 }; + int fd = open("/etc/passwd", O_RDONLY); + ssize_t ret; + + if (fd == -1) + return 1; + + while ((ret = read(fd, buf, sizeof(buf)))) + { + buf[ret] = 0; + write(1, buf, ret); + } + + close(fd); + + return 0; +} diff --git a/unikernel-demo/io1/printf/Makefile b/unikernel-demo/io1/printf/Makefile new file mode 100644 index 00000000..ecd636b7 --- /dev/null +++ b/unikernel-demo/io1/printf/Makefile @@ -0,0 +1,3 @@ +export ukl-obj-m := main.o + +include ../../Makefile diff --git a/unikernel-demo/io1/printf/main.c b/unikernel-demo/io1/printf/main.c new file mode 100644 index 00000000..ea0d990c --- /dev/null +++ b/unikernel-demo/io1/printf/main.c @@ -0,0 +1,25 @@ +#include + +#ifndef USERSPACE +#define main ukl_main +#endif + +typedef struct { + char a; + char *b; + int c; +} test_t; + +int main(void) { + char str[250]; + test_t test = { + .a = 'a', + .b = "Hello!", + .c = 10 + }; + + printf("a = %c, b = %s, c = %d\n", test.a, test.b, test.c); + snprintf(str, sizeof(str), "a = %c, b = %s, c = %d\n", test.a, test.b, test.c); + puts(str); + return 0; +} diff --git a/unikernel-demo/network1/Makefile b/unikernel-demo/network1/Makefile new file mode 100644 index 00000000..4e60eb44 --- /dev/null +++ b/unikernel-demo/network1/Makefile @@ -0,0 +1,26 @@ +PACKAGES = bash coreutils iputils net-tools strace util-linux iproute pciutils +TARGET = min-initrd.d +SMD = supermin.d +bzImage = ../../whiterose/x86/boot/bzImage + +export ukl-obj-m := main.o + +all: $(target)/root + $(MAKE) -C ../../whiterose/ UKL=$(PWD) bzImage + +supermin.d/packages: + supermin --prepare $(PACKAGES) -o $(SMD) + +supermin.d/init.tar.gz: init + tar zcf $@ $^ + +$(TARGET)/root: supermin.d/packages supermin.d/init.tar.gz + supermin --build -v -v -v --size 8G --if-newer --format ext2 supermin.d -o ${@D} + +qemu: + qemu-system-x86_64 -enable-kvm -s -m 1G -nographic -cpu host\ + -kernel $(bzImage)\ + -initrd min-initrd.d/initrd\ + -hda min-initrd.d/root\ + -append "console=ttyS0 ukl quiet"\ + --device virtio-net,netdev=usernet -netdev user,id=usernet,hostfwd=tcp::5555-:5555 diff --git a/unikernel-demo/network1/main.c b/unikernel-demo/network1/main.c new file mode 100644 index 00000000..a1d2a9cf --- /dev/null +++ b/unikernel-demo/network1/main.c @@ -0,0 +1,49 @@ +// https://github.com/mafintosh/echo-servers.c/blob/master/tcp-echo-server.c + +#include +#include +#include +#include +#include +#include +#include + +#define BUFFER_SIZE 1024 + +int main(int argc, char *argv[]) { + + int port = 5555; + + int server_fd, client_fd, err; + struct sockaddr_in server, client; + char buf[BUFFER_SIZE]; + + server_fd = socket(AF_INET, SOCK_STREAM, 0); // ukl_socket + + server.sin_family = AF_INET; + server.sin_port = __builtin_bswap16 (port); + server.sin_addr.s_addr = (uint32_t) 0x00000000; + + int opt_val = 1; + setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt_val, sizeof opt_val); // ukl_ + + err = bind(server_fd, (struct sockaddr *) &server, sizeof(server)); + + err = listen(server_fd, 128); + + while (1) { + socklen_t client_len = sizeof(client); + client_fd = accept(server_fd, (struct sockaddr *) &client, &client_len); // ukl_accept + + while (1) { + int read = recv(client_fd, buf, BUFFER_SIZE, 0); // (recvfrom, fd, buf, len, flags, NULL, NULL); + + if (!read) break; + + err = send(client_fd, buf, read, 0); // (sendto, fd, buf, len, flags, NULL, 0); + + } + } + + return 0; +}