Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

move bottle and populateChild to user/ipc.d; move types to user/types.d

  • Loading branch information...
commit 5c4e054d0636cc2c396630a5f42aa7d86478438f 1 parent 1f5f727
@wolfwood wolfwood authored
Showing with 222 additions and 212 deletions.
  1. +1 −1  user/c/Makefile
  2. +4 −211 user/environment.d
  3. +168 −0 user/ipc.d
  4. +49 −0 user/types.d
View
2  user/c/Makefile
@@ -8,7 +8,7 @@ syscall.a: clean
ldc ${DFLAGS} -c ../../libos/fs/minfs.d
ldc ${DFLAGS} -c ../nativecall.d
# these meet dependencies of drt0.a
- ldc ${DFLAGS} -c ../../libos/libdeepmajik/threadscheduler.d ../../libos/libdeepmajik/umm.d ../../user/environment.d ../../libos/keyboard.d
+ ldc ${DFLAGS} -c ../../libos/libdeepmajik/threadscheduler.d ../../libos/libdeepmajik/umm.d ../../user/environment.d ../../user/ipc.d ../../libos/keyboard.d
mkdir -p lib
ar rcs lib/syscall.a *.o
# console.o csyscall.o entry.o nativecall.o pretexttrampoline.o syscall.o threadscheduler.o umm.o
View
215 user/environment.d
@@ -3,228 +3,21 @@ module user.environment;
import user.util;
import Syscall = user.syscall;
+public import user.ipc;
+public import user.types;
+
version(KERNEL){
import kernel.mem.pageallocator;
}else{
import libos.console;
}
-typedef ubyte* AddressSpace;
-typedef ubyte* PhysicalAddress;
-alias ulong AddressFragment;
+// --- Constants ---
const ulong oneGB = 1024*1024*1024UL;
const PageLevel!(4)* root = cast(PageLevel!(4)*)0xFFFFFF7F_BFDFE000;
-// XXX make this a ulong alligned with PTE bits?
-enum AccessMode : uint {
- Read = 0,
-
- // bits that get encoded in the available bits
- Global = 1,
- AllocOnAccess = 2,
-
- MapOnce = 4,
- CopyOnWrite = 8,
-
- PrivilegedGlobal = 16,
- PrivilegedExecutable = 32,
-
- // use Indicators
- Segment = 64,
- RootPageTable = 128,
- Device = 256, // good enough for isTTY?
-
- // Permissions
- Delete = 512,
- // bits that are encoded in hardware defined PTE bits
- Writable = 1 << 14,
- User = 1 << 15,
- Executable = 1 << 16,
-
- // Size? - could be encoded w/ paging trick on address
-
- // Default policies
- DefaultUser = Writable | AllocOnAccess | User,
- DefaultKernel = Writable | AllocOnAccess,
-
- // flags that are always permitted in syscalls
- SyscallStrictMask = Global | AllocOnAccess | MapOnce | CopyOnWrite | Writable
- | User | Executable,
-
- // Flags that go in the available bits
- AvailableMask = Global | AllocOnAccess | MapOnce | CopyOnWrite |
- PrivilegedGlobal | PrivilegedExecutable | Segment | RootPageTable |
- Device | Delete
-}
-
-
-// place to store values that must be communicated to the child process from the parent
-struct MessageInAbottle {
- ubyte[] stdin;
- ubyte[] stdout;
- bool stdinIsTTY, stdoutIsTTY;
- char[][] argv;
-
- int exitCode;
-
- // assumes alloc on write beyond end of exe
- void setArgv(char[][] parentArgv, ubyte[] to = (cast(ubyte*)oneGB)[0..oneGB]){
- // assumes allocation on write region exists immediately following bottle
-
- // allocate argv's array reference array first, since we know how long it is
- argv = (cast(char[]*)this + MessageInAbottle.sizeof)[0..parentArgv.length];
-
- // this will be a sliding window for the strngs themselves, allocated after the argv array reference array
- char[] storage = (cast(char*)argv[length..length].ptr)[0..0];
-
- foreach(i, str; parentArgv){
- storage = storage[length..length].ptr[0..(str.length+1)]; // allocate an extra space for null terminator
-
- storage[0..(str.length)] = str[];
-
- storage[(str.length)] = '\0'; // stick on null terminator
-
- argv[i] = storage[0..(str.length)];
- }
-
- // adjust pointers
- adjustArgvPointers(to);
- }
-
- void setArgv(char[] parentArgv, ubyte[] to = (cast(ubyte*)oneGB)[0..oneGB]){
-
- // allocate strings first, since we know how long they are
- char[] storage = (cast(char*)this + MessageInAbottle.sizeof)[0..(parentArgv.length +1)];
-
- storage[0..($-1)] = parentArgv[];
-
- // determine length of array reference array
- int substrings = 1;
-
- foreach(ch; storage){
- if(ch == ' '){
- substrings++;
- }
- }
-
- storage[($-1)] = '\0';
-
- // allocate array reference array
- argv = (cast(char[]*)storage[length..length].ptr)[0..substrings];
-
- char* arg = storage.ptr;
- int len, i;
-
- foreach(ref ch; storage){
- if(ch == ' '){
- ch = '\0';
- argv[i] = arg[0..len];
- len++;
- len++;
- arg = arg[len..len].ptr;
- len = 0;
- i++;
- }else{
- len++;
- }
- }//end foreach
-
- // final sub array isn't (hopefully) followed by a space, so it
- // will bot get assigned in loop, and we must do it here instead
-
- argv[i] = (arg)[0..len];
-
- adjustArgvPointers(to);
- }
-
-private:
- void adjustArgvPointers(ubyte[] to){
- // exploits fact that all argv pointers are intra-segment, so it
- // is enought to mod (mask) by the segment size and then add the
- // new segment base address
-
- foreach(ref str; argv){
- str = (cast(char*)(to.ptr + (cast(ulong)str.ptr & (to.length -1) )))[0..str.length];
- }
-
- argv = (cast(char[]*)(to.ptr + (cast(ulong)argv.ptr & (to.length -1) )))[0..argv.length];
- }
-
- public static:
- MessageInAbottle* getBottleForSegment(ubyte* seg){
- return cast(MessageInAbottle*)(seg + (oneGB - 4096));
- }
-
- MessageInAbottle* getMyBottle(){
- return getBottleForSegment(cast(ubyte*) oneGB);
- }
-}
-
-template populateChild(T){
- void populateChild(T argv, AddressSpace child, ubyte[] f, ubyte[] stdin = null, ubyte[] stdout = null){
- // XXX: restrict T to char[] and char[][]
-
- // map executable to default (kernel hardcoded) location in the child address space
- ubyte* dest = cast(ubyte*)oneGB;
-
- assert(child !is null && f !is null && dest !is null, "NULLS!!!!!\n");
-
- version(KERNEL){
- // kernel only executes init once, so its OK not to copy
- }else{
- ubyte* g = findFreeSegment(false).ptr;
-
- Syscall.create(g, oneGB, AccessMode.Writable|AccessMode.User|AccessMode.Executable|AccessMode.AllocOnAccess);
-
- // XXX: instead of copying the whole thing we should only be duping the r/w data section
- uint len = *(cast(ulong*)f.ptr) + ulong.sizeof;
- g[0..len] = f.ptr[0..len];
-
- f = g[0..f.length];
- }
-
- Syscall.map(child, f, dest, AccessMode.Writable|AccessMode.User|AccessMode.Executable|AccessMode.AllocOnAccess);
-
- // bottle to bottle transfer of stdin/out isthe default case
- MessageInAbottle* bottle = MessageInAbottle.getMyBottle();
- MessageInAbottle* childBottle = MessageInAbottle.getBottleForSegment(f.ptr);
-
-
- childBottle.stdoutIsTTY = false;
- childBottle.stdinIsTTY = false;
-
- childBottle.setArgv(argv);
-
- AccessMode stdoutMode = AccessMode.Writable|AccessMode.User;
-
- // if no stdin/out is specified, us the same buffer as parent
- if(stdout is null){
- stdout = bottle.stdout;
- childBottle.stdoutIsTTY = bottle.stdoutIsTTY;
- }
-
- if(!childBottle.stdoutIsTTY){
- stdoutMode |= AccessMode.AllocOnAccess;
- }
-
- if(stdin is null){
- stdin = bottle.stdin;
- childBottle.stdinIsTTY = bottle.stdinIsTTY;
- }
-
- // XXX: use findFreeSemgent to pick gib locations in child
- childBottle.stdout = (cast(ubyte*)(2*oneGB))[0..stdout.length];
- childBottle.stdin = (cast(ubyte*)(3*oneGB))[0..stdin.length];
-
- // map stdin/out into child process
- Syscall.map(child, stdout, childBottle.stdout.ptr, stdoutMode);
- Syscall.map(child, stdin, childBottle.stdin.ptr, AccessMode.Writable|AccessMode.User);
- }
-}
-
-
// --- Paging Structures ---
// The x86 implements a four level page table.
View
168 user/ipc.d
@@ -0,0 +1,168 @@
+module user.ipc;
+
+import user.environment;
+
+// place to store values that must be communicated to the child process from the parent
+struct MessageInAbottle {
+ ubyte[] stdin;
+ ubyte[] stdout;
+ bool stdinIsTTY, stdoutIsTTY;
+ char[][] argv;
+
+ int exitCode;
+
+ // assumes alloc on write beyond end of exe
+ void setArgv(char[][] parentArgv, ubyte[] to = (cast(ubyte*)oneGB)[0..oneGB]){
+ // assumes allocation on write region exists immediately following bottle
+
+ // allocate argv's array reference array first, since we know how long it is
+ argv = (cast(char[]*)this + MessageInAbottle.sizeof)[0..parentArgv.length];
+
+ // this will be a sliding window for the strngs themselves, allocated after the argv array reference array
+ char[] storage = (cast(char*)argv[length..length].ptr)[0..0];
+
+ foreach(i, str; parentArgv){
+ storage = storage[length..length].ptr[0..(str.length+1)]; // allocate an extra space for null terminator
+
+ storage[0..(str.length)] = str[];
+
+ storage[(str.length)] = '\0'; // stick on null terminator
+
+ argv[i] = storage[0..(str.length)];
+ }
+
+ // adjust pointers
+ adjustArgvPointers(to);
+ }
+
+ void setArgv(char[] parentArgv, ubyte[] to = (cast(ubyte*)oneGB)[0..oneGB]){
+
+ // allocate strings first, since we know how long they are
+ char[] storage = (cast(char*)this + MessageInAbottle.sizeof)[0..(parentArgv.length +1)];
+
+ storage[0..($-1)] = parentArgv[];
+
+ // determine length of array reference array
+ int substrings = 1;
+
+ foreach(ch; storage){
+ if(ch == ' '){
+ substrings++;
+ }
+ }
+
+ storage[($-1)] = '\0';
+
+ // allocate array reference array
+ argv = (cast(char[]*)storage[length..length].ptr)[0..substrings];
+
+ char* arg = storage.ptr;
+ int len, i;
+
+ foreach(ref ch; storage){
+ if(ch == ' '){
+ ch = '\0';
+ argv[i] = arg[0..len];
+ len++;
+ len++;
+ arg = arg[len..len].ptr;
+ len = 0;
+ i++;
+ }else{
+ len++;
+ }
+ }//end foreach
+
+ // final sub array isn't (hopefully) followed by a space, so it
+ // will bot get assigned in loop, and we must do it here instead
+
+ argv[i] = (arg)[0..len];
+
+ adjustArgvPointers(to);
+ }
+
+private:
+ void adjustArgvPointers(ubyte[] to){
+ // exploits fact that all argv pointers are intra-segment, so it
+ // is enought to mod (mask) by the segment size and then add the
+ // new segment base address
+
+ foreach(ref str; argv){
+ str = (cast(char*)(to.ptr + (cast(ulong)str.ptr & (to.length -1) )))[0..str.length];
+ }
+
+ argv = (cast(char[]*)(to.ptr + (cast(ulong)argv.ptr & (to.length -1) )))[0..argv.length];
+ }
+
+ public static:
+ MessageInAbottle* getBottleForSegment(ubyte* seg){
+ return cast(MessageInAbottle*)(seg + (oneGB - 4096));
+ }
+
+ MessageInAbottle* getMyBottle(){
+ return getBottleForSegment(cast(ubyte*) oneGB);
+ }
+}
+
+
+template populateChild(T){
+ void populateChild(T argv, AddressSpace child, ubyte[] f, ubyte[] stdin = null, ubyte[] stdout = null){
+ // XXX: restrict T to char[] and char[][]
+
+ // map executable to default (kernel hardcoded) location in the child address space
+ ubyte* dest = cast(ubyte*)oneGB;
+
+ assert(child !is null && f !is null && dest !is null, "NULLS!!!!!\n");
+
+ version(KERNEL){
+ // kernel only executes init once, so its OK not to copy
+ }else{
+ ubyte* g = findFreeSegment(false).ptr;
+
+ Syscall.create(g, oneGB, AccessMode.Writable|AccessMode.User|AccessMode.Executable|AccessMode.AllocOnAccess);
+
+ // XXX: instead of copying the whole thing we should only be duping the r/w data section
+ uint len = *(cast(ulong*)f.ptr) + ulong.sizeof;
+ g[0..len] = f.ptr[0..len];
+
+ f = g[0..f.length];
+ }
+
+ Syscall.map(child, f, dest, AccessMode.Writable|AccessMode.User|AccessMode.Executable|AccessMode.AllocOnAccess);
+
+ // bottle to bottle transfer of stdin/out isthe default case
+ MessageInAbottle* bottle = MessageInAbottle.getMyBottle();
+ MessageInAbottle* childBottle = MessageInAbottle.getBottleForSegment(f.ptr);
+
+
+ childBottle.stdoutIsTTY = false;
+ childBottle.stdinIsTTY = false;
+
+ childBottle.setArgv(argv);
+
+ AccessMode stdoutMode = AccessMode.Writable|AccessMode.User;
+
+ // if no stdin/out is specified, us the same buffer as parent
+ if(stdout is null){
+ stdout = bottle.stdout;
+ childBottle.stdoutIsTTY = bottle.stdoutIsTTY;
+ }
+
+ if(!childBottle.stdoutIsTTY){
+ stdoutMode |= AccessMode.AllocOnAccess;
+ }
+
+ if(stdin is null){
+ stdin = bottle.stdin;
+ childBottle.stdinIsTTY = bottle.stdinIsTTY;
+ }
+
+ // XXX: use findFreeSemgent to pick gib locations in child
+ childBottle.stdout = (cast(ubyte*)(2*oneGB))[0..stdout.length];
+ childBottle.stdin = (cast(ubyte*)(3*oneGB))[0..stdin.length];
+
+ // map stdin/out into child process
+ Syscall.map(child, stdout, childBottle.stdout.ptr, stdoutMode);
+ Syscall.map(child, stdin, childBottle.stdin.ptr, AccessMode.Writable|AccessMode.User);
+ }
+}
View
49 user/types.d
@@ -0,0 +1,49 @@
+module user.types;
+
+
+typedef ubyte* AddressSpace;
+typedef ubyte* PhysicalAddress;
+alias ulong AddressFragment;
+
+
+// XXX: make this a ulong aligned with PTE bits?
+enum AccessMode : uint {
+ Read = 0,
+
+ // bits that get encoded in the available bits
+ Global = 1,
+ AllocOnAccess = 2,
+
+ MapOnce = 4,
+ CopyOnWrite = 8,
+
+ PrivilegedGlobal = 16,
+ PrivilegedExecutable = 32,
+
+ // use Indicators
+ Segment = 64,
+ RootPageTable = 128,
+ Device = 256, // good enough for isTTY?
+
+ // Permissions
+ Delete = 512,
+ // bits that are encoded in hardware defined PTE bits
+ Writable = 1 << 14,
+ User = 1 << 15,
+ Executable = 1 << 16,
+
+ // Size?
+
+ // Default policies
+ DefaultUser = Writable | AllocOnAccess | User,
+ DefaultKernel = Writable | AllocOnAccess,
+
+ // flags that are always permitted in syscalls
+ SyscallStrictMask = Global | AllocOnAccess | MapOnce | CopyOnWrite | Writable
+ | User | Executable,
+
+ // Flags that go in the available bits
+ AvailableMask = Global | AllocOnAccess | MapOnce | CopyOnWrite |
+ PrivilegedGlobal | PrivilegedExecutable | Segment | RootPageTable |
+ Device | Delete
+}
Please sign in to comment.
Something went wrong with that request. Please try again.