summaryrefslogtreecommitdiff
path: root/kernel/user.c
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2025-03-27 11:39:12 -0400
committerFreya Murphy <freya@freyacat.org>2025-03-27 11:39:12 -0400
commit0ff301cda68669c59351e5854ce98f2cf460543f (patch)
treecfe8f976261962420ada64b821559b9da0a56841 /kernel/user.c
parentadd compile_flags.txt for clangd lsp (diff)
downloadcomus-0ff301cda68669c59351e5854ce98f2cf460543f.tar.gz
comus-0ff301cda68669c59351e5854ce98f2cf460543f.tar.bz2
comus-0ff301cda68669c59351e5854ce98f2cf460543f.zip
pull upstream changes, add auto formatting
Diffstat (limited to 'kernel/user.c')
-rw-r--r--kernel/user.c604
1 files changed, 352 insertions, 252 deletions
diff --git a/kernel/user.c b/kernel/user.c
index 2d32157..a019430 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -6,7 +6,7 @@
** @brief User-level code manipulation routines
*/
-#define KERNEL_SRC
+#define KERNEL_SRC
#include <common.h>
@@ -39,12 +39,12 @@
**
** These are visible so that the startup code can find them.
*/
-uint16_t user_offset; // byte offset from the segment base
-uint16_t user_segment; // segment base address
-uint16_t user_sectors; // number of 512-byte sectors it occupies
+uint16_t user_offset; // byte offset from the segment base
+uint16_t user_segment; // segment base address
+uint16_t user_sectors; // number of 512-byte sectors it occupies
-header_t *user_header; // filled in by the user_init routine
-prog_t *prog_table; // filled in by the user_init routine
+header_t *user_header; // filled in by the user_init routine
+prog_t *prog_table; // filled in by the user_init routine
/*
** PRIVATE FUNCTIONS
@@ -65,78 +65,117 @@ static char ebuf[16];
*/
// interpret the file class
-static const char *fh_eclass( e32_si class ) {
- switch( class ) {
- case ELF_CLASS_NONE: return( "None" ); break;
- case ELF_CLASS_32: return( "EC32" ); break;
- case ELF_CLASS_64: return( "EC64" ); break;
+static const char *fh_eclass(e32_si class)
+{
+ switch (class) {
+ case ELF_CLASS_NONE:
+ return ("None");
+ break;
+ case ELF_CLASS_32:
+ return ("EC32");
+ break;
+ case ELF_CLASS_64:
+ return ("EC64");
+ break;
}
- return( "????" );
+ return ("????");
}
// interpret the data encoding
-static const char *fh_edata( e32_si data ) {
- switch( data ) {
- case ELF_DATA_NONE: return( "Invd" ); break;
- case ELF_DATA_2LSB: return( "2CLE" ); break;
- case ELF_DATA_2MSB: return( "2CBE" ); break;
+static const char *fh_edata(e32_si data)
+{
+ switch (data) {
+ case ELF_DATA_NONE:
+ return ("Invd");
+ break;
+ case ELF_DATA_2LSB:
+ return ("2CLE");
+ break;
+ case ELF_DATA_2MSB:
+ return ("2CBE");
+ break;
}
- return( "????" );
+ return ("????");
}
// interpret the file type
-static const char *fh_htype( e32_h type ) {
- switch( type ) {
- case ET_NONE: return( "none" ); break;
- case ET_REL: return( "rel" ); break;
- case ET_EXEC: return( "exec" ); break;
- case ET_DYN: return( "dyn" ); break;
- case ET_CORE: return( "core" ); break;
+static const char *fh_htype(e32_h type)
+{
+ switch (type) {
+ case ET_NONE:
+ return ("none");
+ break;
+ case ET_REL:
+ return ("rel");
+ break;
+ case ET_EXEC:
+ return ("exec");
+ break;
+ case ET_DYN:
+ return ("dyn");
+ break;
+ case ET_CORE:
+ return ("core");
+ break;
default:
- if( type >= ET_LO_OS && type <= ET_HI_OS )
- return( "OSsp" );
- else if( type >= ET_LO_CP && type <= ET_HI_CP )
- return( "CPsp" );
+ if (type >= ET_LO_OS && type <= ET_HI_OS)
+ return ("OSsp");
+ else if (type >= ET_LO_CP && type <= ET_HI_CP)
+ return ("CPsp");
}
- sprint( ebuf, "0x%04x", type );
- return( (const char *) ebuf );
+ sprint(ebuf, "0x%04x", type);
+ return ((const char *)ebuf);
}
// interpret the machine type
-static const char *fh_mtype( e32_h machine ) {
- switch( machine ) {
- case EM_NONE: return( "None" ); break;
- case EM_386: return( "386" ); break;
- case EM_ARM: return( "ARM" ); break;
- case EM_X86_64: return( "AMD64" ); break;
- case EM_AARCH64: return( "AARCH64" ); break;
- case EM_RISCV: return( "RISC-V" ); break;
+static const char *fh_mtype(e32_h machine)
+{
+ switch (machine) {
+ case EM_NONE:
+ return ("None");
+ break;
+ case EM_386:
+ return ("386");
+ break;
+ case EM_ARM:
+ return ("ARM");
+ break;
+ case EM_X86_64:
+ return ("AMD64");
+ break;
+ case EM_AARCH64:
+ return ("AARCH64");
+ break;
+ case EM_RISCV:
+ return ("RISC-V");
+ break;
}
- return( "Other" );
+ return ("Other");
}
// dump the program header
-static void dump_fhdr( elfhdr_t *hdr ) {
- cio_puts( "File header: magic " );
- for( int i = EI_MAG0; i <= EI_MAG3; ++i )
- put_char_or_code( hdr->e_ident.bytes[i] );
- cio_printf( " class %s", fh_eclass(hdr->e_ident.f.class) );
- cio_printf( " enc %s", fh_edata(hdr->e_ident.f.data) );
- cio_printf( " ver %u\n", hdr->e_ident.f.version );
- cio_printf( " type %s", fh_htype(hdr->e_type) );
- cio_printf( " mach %s", fh_mtype(hdr->e_machine) );
- cio_printf( " vers %d", hdr->e_version );
- cio_printf( " entr %08x\n", hdr->e_entry );
+static void dump_fhdr(elfhdr_t *hdr)
+{
+ cio_puts("File header: magic ");
+ for (int i = EI_MAG0; i <= EI_MAG3; ++i)
+ put_char_or_code(hdr->e_ident.bytes[i]);
+ cio_printf(" class %s", fh_eclass(hdr->e_ident.f.class));
+ cio_printf(" enc %s", fh_edata(hdr->e_ident.f.data));
+ cio_printf(" ver %u\n", hdr->e_ident.f.version);
+ cio_printf(" type %s", fh_htype(hdr->e_type));
+ cio_printf(" mach %s", fh_mtype(hdr->e_machine));
+ cio_printf(" vers %d", hdr->e_version);
+ cio_printf(" entr %08x\n", hdr->e_entry);
- cio_printf( " phoff %08x", hdr->e_phoff );
- cio_printf( " shoff %08x", hdr->e_shoff );
- cio_printf( " flags %08x", (uint32_t) hdr->e_flags );
- cio_printf( " ehsize %u\n", hdr->e_ehsize );
- cio_printf( " phentsize %u", hdr->e_phentsize );
- cio_printf( " phnum %u", hdr->e_phnum );
- cio_printf( " shentsize %u", hdr->e_shentsize );
- cio_printf( " shnum %u", hdr->e_shnum );
- cio_printf( " shstrndx %u\n", hdr->e_shstrndx );
+ cio_printf(" phoff %08x", hdr->e_phoff);
+ cio_printf(" shoff %08x", hdr->e_shoff);
+ cio_printf(" flags %08x", (uint32_t)hdr->e_flags);
+ cio_printf(" ehsize %u\n", hdr->e_ehsize);
+ cio_printf(" phentsize %u", hdr->e_phentsize);
+ cio_printf(" phnum %u", hdr->e_phnum);
+ cio_printf(" shentsize %u", hdr->e_shentsize);
+ cio_printf(" shnum %u", hdr->e_shnum);
+ cio_printf(" shstrndx %u\n", hdr->e_shstrndx);
}
/*
@@ -144,45 +183,67 @@ static void dump_fhdr( elfhdr_t *hdr ) {
*/
// categorize the header type
-static const char *ph_type( e32_w type ) {
- switch( type ) {
- case PT_NULL: return( "Unused" ); break;
- case PT_LOAD: return( "Load" ); break;
- case PT_DYNAMIC: return( "DLI" ); break;
- case PT_INTERP: return( "Interp" ); break;
- case PT_NOTE: return( "Aux" ); break;
- case PT_SHLIB: return( "RSVD" ); break;
- case PT_PHDR: return( "PTentry" ); break;
- case PT_TLS: return( "TLS" ); break;
+static const char *ph_type(e32_w type)
+{
+ switch (type) {
+ case PT_NULL:
+ return ("Unused");
+ break;
+ case PT_LOAD:
+ return ("Load");
+ break;
+ case PT_DYNAMIC:
+ return ("DLI");
+ break;
+ case PT_INTERP:
+ return ("Interp");
+ break;
+ case PT_NOTE:
+ return ("Aux");
+ break;
+ case PT_SHLIB:
+ return ("RSVD");
+ break;
+ case PT_PHDR:
+ return ("PTentry");
+ break;
+ case PT_TLS:
+ return ("TLS");
+ break;
default:
- if( type >= PT_LO_OS && type <= PT_HI_OS )
- return( "OSsp" );
- else if( type >= PT_LO_CP && type <= PT_HI_CP )
- return( "CPsp" );
+ if (type >= PT_LO_OS && type <= PT_HI_OS)
+ return ("OSsp");
+ else if (type >= PT_LO_CP && type <= PT_HI_CP)
+ return ("CPsp");
}
- sprint( ebuf, "0x%08x", type );
- return( (const char *) ebuf );
+ sprint(ebuf, "0x%08x", type);
+ return ((const char *)ebuf);
}
// report the individual flags
-static void ph_flags( e32_w flags ) {
- if( (flags & PF_R) != 0 ) cio_putchar( 'R' );
- if( (flags & PF_W) != 0 ) cio_putchar( 'W' );
- if( (flags & PF_E) != 0 ) cio_putchar( 'X' );
+static void ph_flags(e32_w flags)
+{
+ if ((flags & PF_R) != 0)
+ cio_putchar('R');
+ if ((flags & PF_W) != 0)
+ cio_putchar('W');
+ if ((flags & PF_E) != 0)
+ cio_putchar('X');
}
// dump a program header
-static void dump_phdr( elfproghdr_t *hdr, int n ) {
- cio_printf( "Prog header %d, type %s\n", n, ph_type(hdr->p_type) );
- cio_printf( " offset %08x", hdr->p_offset );
- cio_printf( " va %08x", hdr->p_va );
- cio_printf( " pa %08x\n", hdr->p_pa );
- cio_printf( " filesz %08x", hdr->p_filesz );
- cio_printf( " memsz %08x", hdr->p_memsz );
- cio_puts( " flags " );
- ph_flags( hdr->p_flags );
- cio_printf( " align %08x", hdr->p_align );
- cio_putchar( '\n' );
+static void dump_phdr(elfproghdr_t *hdr, int n)
+{
+ cio_printf("Prog header %d, type %s\n", n, ph_type(hdr->p_type));
+ cio_printf(" offset %08x", hdr->p_offset);
+ cio_printf(" va %08x", hdr->p_va);
+ cio_printf(" pa %08x\n", hdr->p_pa);
+ cio_printf(" filesz %08x", hdr->p_filesz);
+ cio_printf(" memsz %08x", hdr->p_memsz);
+ cio_puts(" flags ");
+ ph_flags(hdr->p_flags);
+ cio_printf(" align %08x", hdr->p_align);
+ cio_putchar('\n');
}
/*
@@ -190,58 +251,95 @@ static void dump_phdr( elfproghdr_t *hdr, int n ) {
*/
// interpret the header type
-static const char *sh_type( e32_w type ) {
- switch( type ) {
- case SHT_NULL: return( "Unused" ); break;
- case SHT_PROGBITS: return( "Progbits" ); break;
- case SHT_SYMTAB: return( "Symtab" ); break;
- case SHT_STRTAB: return( "Strtab" ); break;
- case SHT_RELA: return( "Rela" ); break;
- case SHT_HASH: return( "Hash" ); break;
- case SHT_DYNAMIC: return( "Dynamic" ); break;
- case SHT_NOTE: return( "Note" ); break;
- case SHT_NOBITS: return( "Nobits" ); break;
- case SHT_REL: return( "Rel" ); break;
- case SHT_SHLIB: return( "Shlib" ); break;
- case SHT_DYNSYM: return( "Dynsym" ); break;
+static const char *sh_type(e32_w type)
+{
+ switch (type) {
+ case SHT_NULL:
+ return ("Unused");
+ break;
+ case SHT_PROGBITS:
+ return ("Progbits");
+ break;
+ case SHT_SYMTAB:
+ return ("Symtab");
+ break;
+ case SHT_STRTAB:
+ return ("Strtab");
+ break;
+ case SHT_RELA:
+ return ("Rela");
+ break;
+ case SHT_HASH:
+ return ("Hash");
+ break;
+ case SHT_DYNAMIC:
+ return ("Dynamic");
+ break;
+ case SHT_NOTE:
+ return ("Note");
+ break;
+ case SHT_NOBITS:
+ return ("Nobits");
+ break;
+ case SHT_REL:
+ return ("Rel");
+ break;
+ case SHT_SHLIB:
+ return ("Shlib");
+ break;
+ case SHT_DYNSYM:
+ return ("Dynsym");
+ break;
default:
- if( type >= SHT_LO_CP && type <= SHT_HI_CP )
- return( "CCsp" );
- else if( type >= SHT_LO_US && type <= SHT_HI_US )
- return( "User" );
+ if (type >= SHT_LO_CP && type <= SHT_HI_CP)
+ return ("CCsp");
+ else if (type >= SHT_LO_US && type <= SHT_HI_US)
+ return ("User");
}
- sprint( ebuf, "0x%08x", type );
- return( (const char *) ebuf );
+ sprint(ebuf, "0x%08x", type);
+ return ((const char *)ebuf);
}
// report the various flags
-static void sh_flags( unsigned int flags ) {
- if( (flags & SHF_WRITE) != 0 ) cio_putchar( 'W' );
- if( (flags & SHF_ALLOC) != 0 ) cio_putchar( 'A' );
- if( (flags & SHF_EXECINSTR) != 0 ) cio_putchar( 'X' );
- if( (flags & SHF_MERGE) != 0 ) cio_putchar( 'M' );
- if( (flags & SHF_STRINGS) != 0 ) cio_putchar( 'S' );
- if( (flags & SHF_INFO_LINK) != 0 ) cio_putchar( 'L' );
- if( (flags & SHF_LINK_ORDER) != 0 ) cio_putchar( 'o' );
- if( (flags & SHF_OS_NONCON) != 0 ) cio_putchar( 'n' );
- if( (flags & SHF_GROUP) != 0 ) cio_putchar( 'g' );
- if( (flags & SHF_TLS) != 0 ) cio_putchar( 't' );
+static void sh_flags(unsigned int flags)
+{
+ if ((flags & SHF_WRITE) != 0)
+ cio_putchar('W');
+ if ((flags & SHF_ALLOC) != 0)
+ cio_putchar('A');
+ if ((flags & SHF_EXECINSTR) != 0)
+ cio_putchar('X');
+ if ((flags & SHF_MERGE) != 0)
+ cio_putchar('M');
+ if ((flags & SHF_STRINGS) != 0)
+ cio_putchar('S');
+ if ((flags & SHF_INFO_LINK) != 0)
+ cio_putchar('L');
+ if ((flags & SHF_LINK_ORDER) != 0)
+ cio_putchar('o');
+ if ((flags & SHF_OS_NONCON) != 0)
+ cio_putchar('n');
+ if ((flags & SHF_GROUP) != 0)
+ cio_putchar('g');
+ if ((flags & SHF_TLS) != 0)
+ cio_putchar('t');
}
// dump a section header
-__attribute__((__unused__))
-static void dump_shdr( elfsecthdr_t *hdr, int n ) {
- cio_printf( "Sect header %d, type %d (%s), name %s\n",
- n, hdr->sh_type, sh_type(hdr->sh_type) );
- cio_printf( " flags %08x ", (uint32_t) hdr->sh_flags );
- sh_flags( hdr->sh_flags );
- cio_printf( " addr %08x", hdr->sh_addr );
- cio_printf( " offset %08x", hdr->sh_offset );
- cio_printf( " size %08x\n", hdr->sh_size );
- cio_printf( " link %08x", hdr->sh_link );
- cio_printf( " info %08x", hdr->sh_info );
- cio_printf( " align %08x", hdr->sh_addralign );
- cio_printf( " entsz %08x\n", hdr->sh_entsize );
+ATTR_UNUSED
+static void dump_shdr(elfsecthdr_t *hdr, int n)
+{
+ cio_printf("Sect header %d, type %d (%s), name %s\n", n, hdr->sh_type,
+ sh_type(hdr->sh_type));
+ cio_printf(" flags %08x ", (uint32_t)hdr->sh_flags);
+ sh_flags(hdr->sh_flags);
+ cio_printf(" addr %08x", hdr->sh_addr);
+ cio_printf(" offset %08x", hdr->sh_offset);
+ cio_printf(" size %08x\n", hdr->sh_size);
+ cio_printf(" link %08x", hdr->sh_link);
+ cio_printf(" info %08x", hdr->sh_info);
+ cio_printf(" align %08x", hdr->sh_addralign);
+ cio_printf(" entsz %08x\n", hdr->sh_entsize);
}
#endif
@@ -258,51 +356,51 @@ static void dump_shdr( elfsecthdr_t *hdr, int n ) {
** E_LOAD_LIMIT more than N_LOADABLE PT_LOAD sections
** other status returned from vm_add()
*/
-static int read_phdrs( elfhdr_t *hdr, pcb_t *pcb ) {
-
+static int read_phdrs(elfhdr_t *hdr, pcb_t *pcb)
+{
// sanity check
- assert1( hdr != NULL );
- assert2( pcb != NULL );
+ assert1(hdr != NULL);
+ assert2(pcb != NULL);
#if TRACING_USER
- cio_printf( "read_phdrs(%08x,%08x)\n", (uint32_t) hdr, (uint32_t) pcb );
+ cio_printf("read_phdrs(%08x,%08x)\n", (uint32_t)hdr, (uint32_t)pcb);
#endif
// iterate through the program headers
uint_t nhdrs = hdr->e_phnum;
// pointer to the first header table entry
- elfproghdr_t *curr = (elfproghdr_t *) ((uint32_t) hdr + hdr->e_phoff);
+ elfproghdr_t *curr = (elfproghdr_t *)((uint32_t)hdr + hdr->e_phoff);
// process them all
int loaded = 0;
- for( uint_t i = 0; i < nhdrs; ++i, ++curr ) {
-
+ for (uint_t i = 0; i < nhdrs; ++i, ++curr) {
#if TRACING_ELF
- dump_phdr( curr, i );
+ dump_phdr(curr, i);
#endif
- if( curr->p_type != PT_LOAD ) {
+ if (curr->p_type != PT_LOAD) {
// not loadable --> we'll skip it
continue;
}
- if( loaded >= N_LOADABLE ) {
+ if (loaded >= N_LOADABLE) {
#if TRACING_USER
- cio_puts( " LIMIT\n" );
+ cio_puts(" LIMIT\n");
#endif
return E_LOAD_LIMIT;
}
// set a pointer to the bytes within the object file
- char *data = (char *) (((uint32_t)hdr) + curr->p_offset);
+ char *data = (char *)(((uint32_t)hdr) + curr->p_offset);
#if TRACING_USER
- cio_printf( " data @ %08x", (uint32_t) data );
+ cio_printf(" data @ %08x", (uint32_t)data);
#endif
// copy the pages into memory
- int stat = vm_add( pcb->pdir, curr->p_flags & PF_W, false,
- (char *) curr->p_va, curr->p_memsz, data, curr->p_filesz );
- if( stat != SUCCESS ) {
+ int stat = vm_add(pcb->pdir, curr->p_flags & PF_W, false,
+ (char *)curr->p_va, curr->p_memsz, data,
+ curr->p_filesz);
+ if (stat != SUCCESS) {
// TODO what else should we do here? check for memory leak?
return stat;
}
@@ -311,8 +409,8 @@ static int read_phdrs( elfhdr_t *hdr, pcb_t *pcb ) {
pcb->sects[loaded].length = curr->p_memsz;
pcb->sects[loaded].addr = curr->p_va;
#if TRACING_USER
- cio_printf( " loaded %u @ %08x\n",
- pcb->sects[loaded].length, pcb->sects[loaded].addr );
+ cio_printf(" loaded %u @ %08x\n", pcb->sects[loaded].length,
+ pcb->sects[loaded].addr);
#endif
++loaded;
}
@@ -331,8 +429,8 @@ static int read_phdrs( elfhdr_t *hdr, pcb_t *pcb ) {
**
** @return A pointer to the context_t on the stack, or NULL
*/
-static context_t *stack_setup( pcb_t *pcb, uint32_t entry, const char **args ) {
-
+static context_t *stack_setup(pcb_t *pcb, uint32_t entry, const char **args)
+{
/*
** First, we need to count the space we'll need for the argument
** vector and strings.
@@ -341,10 +439,10 @@ static context_t *stack_setup( pcb_t *pcb, uint32_t entry, const char **args ) {
int argbytes = 0;
int argc = 0;
- while( args[argc] != NULL ) {
- int n = strlen( args[argc] ) + 1;
+ while (args[argc] != NULL) {
+ int n = strlen(args[argc]) + 1;
// can't go over one page in size
- if( (argbytes + n) > SZ_PAGE ) {
+ if ((argbytes + n) > SZ_PAGE) {
// oops - ignore this and any others
break;
}
@@ -376,20 +474,20 @@ static context_t *stack_setup( pcb_t *pcb, uint32_t entry, const char **args ) {
** annoyance.
*/
- char argstrings[ argbytes ];
- char *argv[ argc + 1 ];
+ char argstrings[argbytes];
+ char *argv[argc + 1];
- CLEAR( argstrings );
- CLEAR( argv );
+ CLEAR(argstrings);
+ CLEAR(argv);
// Next, duplicate the argument strings, and create pointers to
// each one in our argv.
char *tmp = argstrings;
- for( int i = 0; i < argc; ++i ) {
+ for (int i = 0; i < argc; ++i) {
int nb = strlen(args[i]) + 1; // bytes (incl. NUL) in this string
- strcpy( tmp, args[i] ); // add to our buffer
- argv[i] = tmp; // remember where it was
- tmp += nb; // move on
+ strcpy(tmp, args[i]); // add to our buffer
+ argv[i] = tmp; // remember where it was
+ tmp += nb; // move on
}
// trailing NULL pointer
@@ -421,7 +519,7 @@ static context_t *stack_setup( pcb_t *pcb, uint32_t entry, const char **args ) {
** see below for more information.
*/
- // Pointer to the last word in stack. We get this from the
+ // Pointer to the last word in stack. We get this from the
// VM hierarchy. Get the PDE entry for the user address space.
pde_t stack_pde = pcb->pdir[USER_PDE];
@@ -431,19 +529,18 @@ static context_t *stack_setup( pcb_t *pcb, uint32_t entry, const char **args ) {
// OK, now we have the PTE. The frame address of the last page is
// in this PTE. Find the address immediately after that.
- uint32_t *ptr = (uint32_t *)
- ((uint32_t)(stack_pte & MOD4K_MASK) + SZ_PAGE);
+ uint32_t *ptr = (uint32_t *)((uint32_t)(stack_pte & MOD4K_MASK) + SZ_PAGE);
// Pointer to where the arg strings should be filled in.
- char *strings = (char *) ( (uint32_t) ptr - argbytes );
+ char *strings = (char *)((uint32_t)ptr - argbytes);
// back the pointer up to the nearest word boundary; because we're
// moving toward location 0, the nearest word boundary is just the
// next smaller address whose low-order two bits are zeroes
- strings = (char *) ((uint32_t) strings & MOD4_MASK);
+ strings = (char *)((uint32_t)strings & MOD4_MASK);
// Copy over the argv strings.
- memcpy( (void *)strings, argstrings, argbytes );
+ memcpy((void *)strings, argstrings, argbytes);
/*
** Next, we need to copy over the argv pointers. Start by
@@ -469,7 +566,7 @@ static context_t *stack_setup( pcb_t *pcb, uint32_t entry, const char **args ) {
*/
int nwords = argc + 3;
- uint32_t *acptr = ((uint32_t *) strings) - nwords;
+ uint32_t *acptr = ((uint32_t *)strings) - nwords;
/*
** Next, back up until we're at a multiple-of-16 address. Because we
@@ -478,7 +575,7 @@ static context_t *stack_setup( pcb_t *pcb, uint32_t entry, const char **args ) {
** AND to just turn off the lower four bits.
*/
- acptr = (uint32_t *) ( ((uint32_t)acptr) & MOD16_MASK );
+ acptr = (uint32_t *)(((uint32_t)acptr) & MOD16_MASK);
// copy in 'argc'
*acptr = argc;
@@ -486,17 +583,17 @@ static context_t *stack_setup( pcb_t *pcb, uint32_t entry, const char **args ) {
// next, 'argv', which follows 'argc'; 'argv' points to the
// word that follows it in the stack
uint32_t *avptr = acptr + 2;
- *(acptr+1) = (uint32_t) avptr;
+ *(acptr + 1) = (uint32_t)avptr;
/*
** Next, we copy in all argc+1 pointers.
*/
// Adjust and copy the string pointers.
- for( int i = 0; i <= argc; ++i ) {
- if( argv[i] != NULL ) {
+ for (int i = 0; i <= argc; ++i) {
+ if (argv[i] != NULL) {
// an actual pointer - adjust it and copy it in
- *avptr = (uint32_t) strings;
+ *avptr = (uint32_t)strings;
// skip to the next entry in the array
strings += strlen(argv[i]) + 1;
} else {
@@ -517,7 +614,7 @@ static context_t *stack_setup( pcb_t *pcb, uint32_t entry, const char **args ) {
*/
// Locate the context save area on the stack.
- context_t *ctx = ((context_t *) avptr) - 1;
+ context_t *ctx = ((context_t *)avptr) - 1;
/*
** We cleared the entire stack earlier, so all the context
@@ -525,9 +622,9 @@ static context_t *stack_setup( pcb_t *pcb, uint32_t entry, const char **args ) {
** all the important fields.
*/
- ctx->eflags = DEFAULT_EFLAGS; // IE enabled, PPL 0
- ctx->eip = entry; // initial EIP
- ctx->cs = GDT_CODE; // segment registers
+ ctx->eflags = DEFAULT_EFLAGS; // IE enabled, PPL 0
+ ctx->eip = entry; // initial EIP
+ ctx->cs = GDT_CODE; // segment registers
ctx->ss = GDT_STACK;
ctx->ds = ctx->es = ctx->fs = ctx->gs = GDT_DATA;
@@ -535,8 +632,8 @@ static context_t *stack_setup( pcb_t *pcb, uint32_t entry, const char **args ) {
** Return the new context pointer to the caller. It will be our
** caller's responsibility to schedule this process.
*/
-
- return( ctx );
+
+ return (ctx);
}
/*
@@ -548,39 +645,36 @@ static context_t *stack_setup( pcb_t *pcb, uint32_t entry, const char **args ) {
**
** Initializes the user support module.
*/
-void user_init( void ) {
-
+void user_init(void)
+{
#if TRACING_INIT
- cio_puts( " User" );
-#endif
+ cio_puts(" User");
+#endif
// This is gross, but we need to get this information somehow.
// Access the "user blob" data in the second bootstrap sector
- uint16_t *blobdata = (uint16_t *) USER_BLOB_DATA;
- user_offset = *blobdata++;
+ uint16_t *blobdata = (uint16_t *)USER_BLOB_DATA;
+ user_offset = *blobdata++;
user_segment = *blobdata++;
user_sectors = *blobdata++;
#if TRACING_USER
- cio_printf( "\nUser blob: %u sectors @ %04x:%04x", user_sectors,
- user_segment, user_offset );
+ cio_printf("\nUser blob: %u sectors @ %04x:%04x", user_sectors,
+ user_segment, user_offset);
#endif
// calculate the location of the user blob
- if( user_sectors > 0 ) {
-
+ if (user_sectors > 0) {
// calculate the address of the header
- user_header = (header_t *)
- ( KERN_BASE +
- ( (((uint_t)user_segment) << 4) + ((uint_t)user_offset) )
- );
+ user_header = (header_t *)(KERN_BASE + ((((uint_t)user_segment) << 4) +
+ ((uint_t)user_offset)));
// the program table immediate follows the blob header
- prog_table = (prog_t *) (user_header + 1);
+ prog_table = (prog_t *)(user_header + 1);
#if TRACING_USER
- cio_printf( ", hdr %08x, %u progs, tbl %08x\n", (uint32_t) user_header,
- user_header->num, (uint32_t) prog_table );
+ cio_printf(", hdr %08x, %u progs, tbl %08x\n", (uint32_t)user_header,
+ user_header->num, (uint32_t)prog_table);
#endif
} else {
@@ -588,7 +682,7 @@ void user_init( void ) {
user_header = NULL;
prog_table = NULL;
#if TRACING_USER
- cio_putchar( '\n' );
+ cio_putchar('\n');
#endif
}
}
@@ -602,15 +696,15 @@ void user_init( void ) {
**
** @return pointer to the program table entry in the code archive, or NULL
*/
-prog_t *user_locate( uint_t what ) {
-
+prog_t *user_locate(uint_t what)
+{
// no programs if there is no blob!
- if( user_header == NULL ) {
+ if (user_header == NULL) {
return NULL;
}
// make sure this is a reasonable program to request
- if( what >= user_header->num ) {
+ if (what >= user_header->num) {
// no such program!
return NULL;
}
@@ -619,7 +713,7 @@ prog_t *user_locate( uint_t what ) {
prog_t *prog = &prog_table[what];
// if there are no bytes, it's useless
- if( prog->size < 1 ) {
+ if (prog->size < 1) {
return NULL;
}
@@ -637,8 +731,8 @@ prog_t *user_locate( uint_t what ) {
**
** @return the status of the duplicate attempt
*/
-int user_duplicate( pcb_t *new, pcb_t *old ) {
-
+int user_duplicate(pcb_t *new, pcb_t *old)
+{
// We need to do a recursive duplication of the process address
// space of the current process. First, we create a new user
// page directory. Next, we'll duplicate the USER_PDE page
@@ -647,39 +741,45 @@ int user_duplicate( pcb_t *new, pcb_t *old ) {
// create the initial VM hierarchy
pde_t *pdir = vm_mkuvm();
- if( pdir == NULL ) {
+ if (pdir == NULL) {
return E_NO_MEMORY;
}
new->pdir = pdir;
- // next, add a USER_PDE page table that's a duplicate of the
+ // Next, add a USER_PDE page table that's a duplicate of the
// current process' page table
- if( !vm_uvmdup(old->pdir,new->pdir) ) {
+ if (!vm_uvmdup(old->pdir, new->pdir)) {
// check for memory leak?
return E_NO_MEMORY;
}
- // now, iterate through the entries, replacing the frame
- // numbers with duplicate frames
+ // We don't do copy-on-write, so we must duplicate all the
+ // individual page frames. Iterate through all the user-level
+ // PDE entries, and replace the existing frames with duplicates.
//
// NOTE: we only deal with pdir[0] here, as we are limiting
- // the user address space to the first 4MB
- pte_t *pt = (pte_t *) (pdir[USER_PDE]);
+ // the user address space to the first 4MB. If the size of
+ // the address space goes up, this code will need to be
+ // modified to loop over the larger space.
+
+ // pointer to the PMT for the user
+ pte_t *pt = (pte_t *)(pdir[USER_PDE]);
+ assert(pt != NULL);
- for( int i = 0; i < N_PTE; ++i ) {
+ for (int i = 0; i < N_PTE; ++i) {
+ // get the current entry from the PMT
+ pte_t entry = *pt;
// if this entry is present,
- if( IS_PRESENT(*pt) ) {
+ if (IS_PRESENT(entry)) {
+ // duplicate the frame pointed to by this PTE
+ void *tmp = vm_pagedup((void *)PTE_ADDR(entry));
- // duplicate the page
- void *tmp = vm_pagedup( (void *) (*pt & FRAME_MASK) );
// replace the old frame number with the new one
- *pt = (pte_t) (((uint32_t)tmp) | (*pt & PERM_MASK));
+ *pt = (pte_t)(((uint32_t)tmp) | PERMS(entry));
} else {
-
*pt = 0;
-
}
++pt;
}
@@ -699,57 +799,57 @@ int user_duplicate( pcb_t *new, pcb_t *old ) {
**
** @return the status of the load attempt
*/
-int user_load( prog_t *ptab, pcb_t *pcb, const char **args ) {
-
+int user_load(prog_t *ptab, pcb_t *pcb, const char **args)
+{
// NULL pointers are bad!
- assert1( ptab != NULL );
- assert1( pcb != NULL );
- assert1( args != NULL );
+ assert1(ptab != NULL);
+ assert1(pcb != NULL);
+ assert1(args != NULL);
// locate the ELF binary
- elfhdr_t *hdr = (elfhdr_t *) ((uint32_t)user_header + ptab->offset);
+ elfhdr_t *hdr = (elfhdr_t *)((uint32_t)user_header + ptab->offset);
#if TRACING_ELF
- cio_printf( "Load: ptab %08x: '%s', off %08x, size %08x, flags %08x\n",
- (uint32_t) ptab, ptab->name, ptab->offset, ptab->size,
- ptab->flags );
- cio_printf( " args %08x:", (uint32_t) args );
- for( int i = 0; args[i] != NULL; ++i ) {
- cio_printf( " [%d] %s", i, args[i] );
+ cio_printf("Load: ptab %08x: '%s', off %08x, size %08x, flags %08x\n",
+ (uint32_t)ptab, ptab->name, ptab->offset, ptab->size,
+ ptab->flags);
+ cio_printf(" args %08x:", (uint32_t)args);
+ for (int i = 0; args[i] != NULL; ++i) {
+ cio_printf(" [%d] %s", i, args[i]);
}
- cio_printf( "\n pcb %08x (pid %u)\n", (uint32_t) pcb, pcb->pid );
- dump_fhdr( hdr );
+ cio_printf("\n pcb %08x (pid %u)\n", (uint32_t)pcb, pcb->pid);
+ dump_fhdr(hdr);
#endif
// verify the ELF header
- if( hdr->e_ident.f.magic != ELF_MAGIC ) {
+ if (hdr->e_ident.f.magic != ELF_MAGIC) {
return E_BAD_PARAM;
}
// allocate a page directory
pcb->pdir = vm_mkuvm();
- if( pcb->pdir == NULL ) {
+ if (pcb->pdir == NULL) {
return E_NO_MEMORY;
}
// read all the program headers
- int stat = read_phdrs( hdr, pcb );
- if( stat != SUCCESS ) {
+ int stat = read_phdrs(hdr, pcb);
+ if (stat != SUCCESS) {
// TODO figure out a better way to deal with this
- PANIC( 0, "user_load: phdr read failed" );
+ PANIC(0, "user_load: phdr read failed");
}
// next, set up the runtime stack - just like setting up loadable
// sections, except nothing to copy
- stat = vm_add( pcb->pdir, true, false, (void *) USER_STACK,
- SZ_USTACK, NULL, 0 );
- if( stat != SUCCESS ) {
+ stat =
+ vm_add(pcb->pdir, true, false, (void *)USER_STACK, SZ_USTACK, NULL, 0);
+ if (stat != SUCCESS) {
// TODO yadda yadda...
- PANIC( 0, "user_load: vm_add failed" );
+ PANIC(0, "user_load: vm_add failed");
}
// set up the command-line arguments
- pcb->context = stack_setup( pcb, hdr->e_entry, args );
+ pcb->context = stack_setup(pcb, hdr->e_entry, args);
return SUCCESS;
}
@@ -762,13 +862,13 @@ int user_load( prog_t *ptab, pcb_t *pcb, const char **args ) {
**
** @param pcb The PCB of the program to be unloaded
*/
-void user_cleanup( pcb_t *pcb ) {
-
- if( pcb == NULL ) {
+void user_cleanup(pcb_t *pcb)
+{
+ if (pcb == NULL) {
// should this be an error?
return;
}
- vm_free( pcb->pdir );
+ vm_free(pcb->pdir);
pcb->pdir = NULL;
}