diff options
author | Freya Murphy <freya@freyacat.org> | 2025-03-27 11:39:12 -0400 |
---|---|---|
committer | Freya Murphy <freya@freyacat.org> | 2025-03-27 11:39:12 -0400 |
commit | 0ff301cda68669c59351e5854ce98f2cf460543f (patch) | |
tree | cfe8f976261962420ada64b821559b9da0a56841 /kernel/user.c | |
parent | add compile_flags.txt for clangd lsp (diff) | |
download | comus-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.c | 604 |
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; } |