‫Talking with the colonel from the land.
‫Communication with the colonel from a process starts with the use of program calling it interrupt,
‫this interrupt is created by the colonel and it's designed by us in such a way that it allows to use
‫a program to talk with the colonel when they use the program.
‫Calls the interrupt the colonel interrupt routine is executed.
‫The routine extracts arguments pushed by the use the program, for example, in the case of some sort
‫of print message, some print function, the argument extracted will be the address of the message to
‫print.
‫Finally, the colonel interpreting returns.
‫The result.
‫This is usually returned in the register.
‫OK, we're going to break the entire problem down.
‫Let's pretend that we have a colonel operation that's represented by code one.
‫Code one simply means to print a message to the screen.
‫So you can think of all these codes in the colonel.
‫We have codes to exit the application.
‫We have codes to open file handles and so on.
‫OK, so let's pretend we have code one, which means that we want to print a message to the screen.
‫So to tell the colonel to print is easy from New Zealand.
‫We simply start by setting the X register to one.
‫This is the Colonel Operation Code for print operations.
‫In case you haven't gathered already, the X register will be used to hold that Colonel Operation Code
‫or Colonel Command, I should say.
‫The next step.
‫The use program pushes the address of the message that should be printed to the screen, so it pushes
‫that to the stack.
‫They use a program, then issues an interest to the colonel.
‫This number can be almost anything but we will use interest zero 18 for all colonel commands in our
‫hypothetical colonel implementation.
‫So we will be doing this in reality in later lectures.
‫But let's just pretend we've all done it now because it's going to be easier for me to explain that
‫to you.
‫So in our hypothetical colonel implementation, we've decided to use you for handling commands to the
‫colonel and we will use the same interruption later on, as I said.
‫So this is how the code would look for printing from New Zealand.
‫So we have assembly function here called print and the prototype in C will look like this, right?
‫Voiceprint Canstar message.
‫The assembly for that will be very simple.
‫We push the base pointer and so on by setting up our stack and we set up our stack frame here.
‫We set the X register to one, which means come on, one print.
‫We set the SBX register to the string to print, which is the constant message pastors here.
‫We then push that register to the stack and we issued and it's eighty when we issue and it's 80, the
‫colonel will be called a will extract the message you post here and we'll will print the message.
‫OK, so from user land, it's very easy to do this.
‫Col sounds more complicated.
‫We have to do a lot of things to get this implementation working properly.
‫So before we continue, what I want to let you know is when we issue interrupt from the use the land,
‫the processor pushes the same information that we push to get into use land in the first place.
‫So it's pushing the stack select or stack segment.
‫It's pushing the stack point up.
‫It's pushing the flags, OK?
‫It's pushing the code segment and the return address, OK, which will be the IP in this case.
‫So it's pushing a lot of things to the stack.
‫OK, you need to be aware of that because after we finish our interpreting, all we have to do is issue.
‫And I read and that'll take us straight back into use the land.
‫And I want you to understand why and why we don't have to do this again.
‫And the reason for that is because the processor itself pushes all of these things that we that we pushed
‫here to enter use land in the first place.
‫But it won't push the exact values.
‫It'll push the values as they are during the interrupt in the user land and the values being the registers.
‫OK, so now explain that we can continue this.
‫OK, so we've just issued and it's zero eight from UCLA and what happens next?
‫Well, the colonel insert routine is executed, so the interruption at routine begins execution.
‫So we save all of the usual registers ready for when we handle the interim handle.
‫So we do that using the push add function here.
‫OK.
‫OK, so that'll save the use land registers.
‫Some of the things have already been pushed to the stack.
‫As I explained in the previous slide here where the processor pushes the same information we push to
‫get to use the land in the first place.
‫So so that information's already pushed.
‫We then just pushed to the general purpose registers so that X, X and so on.
‫OK, OK, so once we've done that, we push the stack point as it currently is.
‫OK, and we also push the command.
‫OK, so the stack point and we plushie that will point to the interim frame which we'll discuss in a
‫moment, because at this point in time that's where the stacks pointing, OK.
‫That's why we pushed ESP the frame is all these general-purpose registers and all of the the registers
‫pushed by the process of force automatically upon entering the interrupt.
‫OK, so we then push the command by here pushbacks.
‫We now call the ISO 88 Shangela.
‫OK, now the ISO 80 Hans-Olaf.
‫Explain more about that in a minute.
‫But essentially that will return a value in X and we will take that value.
‫We will store it in a memory address temporarily.
‫And then once we're done with our Interop, we'll set the X register back to it.
‫OK, that that's important because we use the X X register on these next few lines.
‫OK, but essentially that is how it's returning values back to use the land.
‫The interest handler is returning it in the X register.
‫OK, in case you didn't know when you would turn a integer value or point of value from a C function,
‫it is setting the register.
‫So I just want to make that clear in case you didn't know that.
‫So that's if you're returning from a C function.
‫OK, so here you can see the frame.
‫This is the C structure that represents everything that we described here where we push the add we all
‫of the registers that were automatically pushed that I explained all of that that is represented by
‫the interim frame, OK?
‫And the interim frame is pushed here because we just pushed the stack pointer, as I just explained.
‫So the frame contains all the general purpose registers and some segment registers as well.
‫All the ones that we care about that is.
‫So let's now explain the ISI, the handler that gets called, as you saw in the assembly code, we come
‫in here.
‫We first switched to the colonel page because at this moment in time, the paging is still pointing
‫to the page directory of the task.
‫We don't want that.
‫So we switched to the colonel page.
‫OK.
‫We then constant currency states and we pass in the frame, so this will just save the registers in
‫the frame that I showed here.
‫It'll save all of those into the task.
‫OK, that's what I do into the contest that's running with an issue.
‫Izadi Handle Command.
‫This is responsible for handling a interrupt command, a COL command, I should say, because remember,
‫all the commands are specified in the X register.
‫We pick a command number and we set the X register from New Zealand issue and it's your Zaidee.
‫OK, so that's what that command number is stored here in the command variable.
‫So we call a chain of command.
‫We pass the command and the frame that then handles the command.
‫OK, finally, when we leave this function, we switch back to the tasks page of the current task,
‫OK, because obviously we don't want to return to use the land while the page directory is pointing
‫to the COL page, that would be disaster.
‫Right?
‫So we switch back to the current tasks page directory.
‫OK, by calling Task Page and then we just return the results from Izadi Hands Handler Command.
‫OK, and then returns the result to the use of process, by the way.
‫OK, so when we call Izadi Chains of Command that finds the correct command handler to call, in our
‫case, it's the command handler.
‫So this function gets called Isaw 8H Command one print.
‫Now this is responsible for printing to the screen.
‫So let me explain this to you.
‫We get the current stack item from the stack.
‫We pass in zero there and that gets us the first element that they pushed.
‫OK, they pushed us one one argument and that was the message.
‫They pushed that to us.
‫So we access that element here by index.
‫And then once we do that.
‫The variable conolan right now on the Col Stack message userspace address is equal to the virtual address
‫of the message that the user process provided to us when they called the kernel to print this message.
‫OK, so that's equal to that.
‫However, we can't just call, text, print and pass in the message userspace address.
‫The reason for that is because it's a virtual address.
‫Because it's a virtual address and it points to zero x 400000 and we're currently in the kernel page,
‫this address points nowhere to us.
‫Well, it does point some way, points to address some 400000 physical address because the Colonel Page
‫directory is my Berlinale.
‫However, we all know because I've explained paging to you.
‫So we all know that that message in dress code X 400000, 15 or whatever, we all know that the message
‫stored there is not actually stored there is stored in the process memory that we allocated when we
‫loaded the process.
‫Right.
‫So access in message userspace address was the kernel, whilst the paging directory said to the kernel
‫page directory will give us different results.
‫It won't give us the message, which is unfortunate.
‫So what we can do to get around this problem, we can create a function called Copy's String from task,
‫which is responsible for going into the actual task memory, copying it to the kernel, and then and
‫then copying it to the buffer that we created on the kernel.
‫OK, and that'll work.
‫It's a little complicated to explain.
‫So we will explain this function another time.
‫So it's more complicated to explain.
‫Essentially we we share the pages temporarily and copy the data to the kernel buffer, but more will
‫be explained on that later.
‫Anyway, let's carry on.
‫So once we finally copy the string from the task into a buffer, we then do task printing, which prints
‫out that message.
‫OK.
‫And there we go, we would see.
‫Hello.
‫Well, this isn't this isn't an actual colonel output.
‫I just made a little image just to demonstrate that.
‫So the messages I put it to the screen, the colonel command return zero.
‫You can see that happening here, return zero.
‫You'll notice the return type is a very pintor.
‫We can still return and charges.
‫That's no, that's no problem.
‫If your print command returns and just find just return.
‫The integer doesn't have to be a pointer.
‫It's the type has to be a pointer, but the actual value returned can be anything.
‫It's no problem.
‫So the kind of comparison zero the X registers populate with the return result upon returning from interrupts
‫your 80.
‫So we are now actually in New Zealand again, just after our call to the colonel, the ex registrar
‫is equal to zero as the routine return zero.
‫So let's just have a brief overview of calling the colonel from New Zealand.
‫So the process of pushing the same information we push to get into use land in the first place to the
‫stack.
‫OK, this is important so that when we issue and I read it will immediately take us back to the USA
‫program and continue where it was executing.
‫Entraps you 80 kind of routine begins execution, the command number is extracted from the register.
‫So, yes, you noticed that when we pushed the command to the stack in the assembly code of the routine,
‫we then call the CI A. Penzler for 060.
‫The task that executed the incorrupt has its state saved.
‫All the rest for that task are saved in the tasks register structure.
‫We extract these from the interrupt frame.
‫Execution flows pass to the correct handler for the command number that was provided to the colonel
‫in the register.
‫The colonel does the action that it was instructed to do from the use of land, for example, printing
‫to the screen, accessing a bite from the keyboard, the kind of command handler then returns a value.
‫Execution continues after the user lands, interrupts your instruction.
‫The rest is populated with the return result from the kernel.
‫So, yes, essentially, guys, when we return from our kernel handler, we're running back in the process
‫again just after the interview to USA.
‫The instruction and the process is now in a restricted state.
‫Again, it's in a user land state to keep a ring.
‫Three state and Sunnis.
‫As as soon as that's happened, we return from that interpretation in the colonel.
‫The register contains the return result from the colonel.
‫So these are examples system commands.
‫You know, you can have system command, exit system, command, print, get key, get kernel info,
‫Mallak, invoke sleep and so on.
‫We represent these with an enum in this exam.
‫In this image example, you can also use definitions.
‫It's good to keep your kernel very structured and clean, so it's wise to have a function for registering
‫all of our commands.
‫So we do Izadi register all and then we have an isolated register command which will pass the ID and
‫the function pointer that that ID links to.
‫You see, having function pointis is much cleaner than having some gyne switch statement with 2000 commands,
‫you know what I mean?
‫So what we can do is we can have an array of function pointers and do it that way and it's much cleaner.
‫This is the function for registering commands so it checks if the command ideas in bounds, it checks
‫that the array of commands does not already have that command taken with the command ID provided.
‫If that's completely fine, then it sets it.
‫You'll notice we panic.
‫That's because an operation like that is very bad and we shouldn't even continue.
‫If there was an error like that, some sort of inbounds error or the command being taken.
‫So this is what the function pointer looks like for ISIS.
‫Come on, as you can see, we return a void point and we accept an entire frame.
‫So this is our ISIS handle command function that you saw earlier in the ISIS handler and in the file.
‫So you can see that just basically just checks that the command that's being called exists.
‫And if it does, then we we basically make a function pointer here so that command in the array and
‫we just go command function to basically call it.
‫So we're calling the function point of here and the results returned.
‫Access in the stack can be a little complicated.
‫So I'll try and explain it the best I can here.
‫Look at this image once again and pay very close attention to the task and get stack item function.
‫So we grab the address from the stack of the task.
‫Essentially, as you know, the use the land they pushed the HelloWallet string.
‫Well, not the string itself, the address, the string weight grabbing that here.
‫OK, I was setting message userspace address to that.
‫OK, that's the message they want to print.
‫We set that to the address that they pushed to us.
‫We need to know the address that they pushed because we need to know the message to print.
‫So we need functions to access the tasks stack.
‫So this is how you access the task stack?
‫It's not too difficult.
‫We set the stack point to the task registers stack pointer.
‫That's the very first thing.
‫OK, and now we call task page task.
‫We haven't created that function yet.
‫And what this will do, it will switch the page directory in the kernel to point to the tasks page directory
‫that we provided here.
‫OK, so at this point in time the processor sees the tasks stack because we've just switched the entire
‫page directory to the tasks page directory so we can access that point that we created here.
‫Hesp pointer.
‫We can access that right here.
‫Results equals ASCII pointer index.
‫OK, so then we can get the result from the stack here and then we switch back to the kernel page because
‫obviously we've basically just changed the entire mapping in memory just then address you x 400000 and
‫onwards is now pointing to the tasks memory.
‫We don't want that.
‫So we have to switch back to the kernel page so that we see only the kernel memory again and then we
‫return the results.
‫It's that easy.
‫So I know some questions that you might have, and I'm sure I'm reading your mind right now.
‫I'm just going to go out there because I know that I want to use thinking this.
‫When we switch to the tasks page, how do we still access the COL stack?
‫Well, how that works is because the entire tasks memory is linear, apart from where it was loaded.
‫Address Eurex 400000 and it's all the way to its to its size.
‫So that memory is taken OK, that memory is mapped differently.
‫All the other memory is mapped exactly the same as the kernel memory is mapped.
‫OK, now because we are missing zero and we have a supervisor, we can access this memory.
‫OK, so the task itself might not be able to access memory.
‫If if the supervisor bit in the page is is wrong, it won't be able to access this memory.
‫But because the colonel's in a supervisor state ring zero, we can access this memory.
‫So, yes, there's a potential problem where the program you're loading may be so big that it may span
‫over the memory here.
‫OK, now, if that happens, then then yes, that could be a bug of some kind.
‫But you can you can solve those problems by loading your colonel in appropriate places and so on.
‫So this is what the task page function looks like, OK?
‫And the task page tax tasks function.
‫So we call user registers, as you know, that switches all the second registers.
‫OK, we program that earlier.
‫We call paging switch and we pass in the page directory.
‫So I hope that explains how tasks communicate with the colonel.
‫As you've noticed, access in the task stack can be somewhat complicated.
‫I didn't explain everything in this presentation because I don't want to overwhelm you.
‫Copy and string's is much more difficult so that we'll have to wait for another lecture.
‫However, we will now soon be getting on with implementing communication from use of programs to the
‫colonel.