diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.seq | 26 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aicasm.c | 482 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aicasm.h | 68 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aicasm_gram.y | 1304 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aicasm_scan.l | 243 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aicasm_symbol.c | 451 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aicasm_symbol.h | 144 | ||||
-rw-r--r-- | sys/i386/include/asm.h | 201 | ||||
-rw-r--r-- | sys/i386/include/vmparam.h | 5 | ||||
-rw-r--r-- | sys/i386/scsi/aic7xxx.c | 26 | ||||
-rw-r--r-- | sys/miscfs/procfs/procfs_map.c | 6 | ||||
-rw-r--r-- | sys/scsi/scsi_base.c | 4 | ||||
-rw-r--r-- | sys/vm/vm_extern.h | 3 | ||||
-rw-r--r-- | sys/vm/vm_fault.c | 73 | ||||
-rw-r--r-- | sys/vm/vm_glue.c | 18 | ||||
-rw-r--r-- | sys/vm/vm_kern.c | 32 | ||||
-rw-r--r-- | sys/vm/vm_map.c | 413 | ||||
-rw-r--r-- | sys/vm/vm_map.h | 24 | ||||
-rw-r--r-- | sys/vm/vm_meter.c | 4 | ||||
-rw-r--r-- | sys/vm/vm_mmap.c | 33 | ||||
-rw-r--r-- | sys/vm/vm_object.c | 72 | ||||
-rw-r--r-- | sys/vm/vm_page.c | 55 | ||||
-rw-r--r-- | sys/vm/vm_pageout.c | 26 | ||||
-rw-r--r-- | sys/vm/vm_pageout.h | 35 | ||||
-rw-r--r-- | sys/vm/vnode_pager.c | 4 |
25 files changed, 541 insertions, 3211 deletions
diff --git a/sys/dev/aic7xxx/aic7xxx.seq b/sys/dev/aic7xxx/aic7xxx.seq index 5077ef0092d0f..572586588dd99 100644 --- a/sys/dev/aic7xxx/aic7xxx.seq +++ b/sys/dev/aic7xxx/aic7xxx.seq @@ -1039,7 +1039,18 @@ dma_scb: mov DFCNTRL, DMAPARAMS; test DMAPARAMS, DIRECTION jnz dma_scb_fromhost; /* Fill it with the SCB data */ - call copy_scb_tofifo; +copy_scb_tofifo: + mvi SINDEX, SCB_CONTROL; + add A, 28, SINDEX; +copy_scb_tofifo_loop: + mov DFDAT,SINDIR; + mov DFDAT,SINDIR; + mov DFDAT,SINDIR; + mov DFDAT,SINDIR; + mov DFDAT,SINDIR; + mov DFDAT,SINDIR; + mov DFDAT,SINDIR; + cmp SINDEX, A jne copy_scb_tofifo_loop; or DFCNTRL, HDMAEN|FIFOFLUSH; dma_scb_fromhost: call dma_finish; @@ -1060,19 +1071,6 @@ dfdat_in_7_continued: mov DINDIR,DFDAT; mov DINDIR,DFDAT ret; -copy_scb_tofifo: - mvi SCB_CONTROL call dfdat_out_7; - call dfdat_out_7; - call dfdat_out_7; -dfdat_out_7: - mov DFDAT,SINDIR; - mov DFDAT,SINDIR; - mov DFDAT,SINDIR; - mov DFDAT,SINDIR; - mov DFDAT,SINDIR; - mov DFDAT,SINDIR; - mov DFDAT,SINDIR ret; - /* * Wait for DMA from host memory to data FIFO to complete, then disable * DMA and wait for it to acknowledge that it's off. diff --git a/sys/dev/aic7xxx/aicasm.c b/sys/dev/aic7xxx/aicasm.c deleted file mode 100644 index 4251af1a383ea..0000000000000 --- a/sys/dev/aic7xxx/aicasm.c +++ /dev/null @@ -1,482 +0,0 @@ -/* - * Aic7xxx SCSI host adapter firmware asssembler - * - * Copyright (c) 1997 Justin T. Gibbs. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice immediately at the beginning of the file, without modification, - * this list of conditions, and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: aic7xxx_asm.c,v 1.12.6.1 1997/03/16 07:21:30 gibbs Exp $ - */ -#include <sys/types.h> -#include <sys/mman.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sysexits.h> -#include <unistd.h> - -#include "aic7xxx_asm.h" -#include "symbol.h" -#include "sequencer.h" - -static void usage __P((void)); -static void back_patch __P((void)); -static void output_code __P((FILE *ofile)); -static void output_listing __P((FILE *listfile, char *ifilename, - char *options)); -static struct patch *next_patch __P((struct patch *cur_patch, int options, - int instrptr)); - -struct path_list search_path; -int includes_search_curdir; -char *appname; -FILE *ofile; -char *ofilename; - -static STAILQ_HEAD(,instruction) seq_program; -static STAILQ_HEAD(, patch) patch_list; -symlist_t patch_options; - -#if DEBUG -extern int yy_flex_debug; -extern int yydebug; -#endif -extern FILE *yyin; -extern int yyparse __P((void)); - -int -main(argc, argv) - int argc; - char *argv[]; -{ - extern char *optarg; - extern int optind; - int ch; - int retval; - char *inputfilename; - char *regfilename; - FILE *regfile; - char *listfilename; - FILE *listfile; - char *options; - - SLIST_INIT(&search_path); - STAILQ_INIT(&seq_program); - STAILQ_INIT(&patch_list); - SLIST_INIT(&patch_options); - includes_search_curdir = 1; - appname = *argv; - regfile = NULL; - listfile = NULL; - options = NULL; -#if DEBUG - yy_flex_debug = 0; -#endif - while ((ch = getopt(argc, argv, "d:l:n:o:r:I:O:")) != EOF) { - switch(ch) { - case 'd': -#if DEBUG - if (strcmp(optarg, "s") == 0) - yy_flex_debug = 1; - else if (strcmp(optarg, "p") == 0) - yydebug = 1; -#else - stop("-d: Assembler not built with debugging " - "information", EX_SOFTWARE); -#endif - break; - case 'l': - /* Create a program listing */ - if ((listfile = fopen(optarg, "w")) == NULL) { - perror(optarg); - stop(NULL, EX_CANTCREAT); - } - listfilename = optarg; - break; - case 'n': - /* Don't complain about the -nostdinc directrive */ - if (strcmp(optarg, "ostdinc")) { - fprintf(stderr, "%s: Unknown option -%c%s\n", - appname, ch, optarg); - usage(); - /* NOTREACHED */ - } - break; - case 'o': - if ((ofile = fopen(optarg, "w")) == NULL) { - perror(optarg); - stop(NULL, EX_CANTCREAT); - } - ofilename = optarg; - break; - case 'O': - /* Patches to include in the listing */ - options = optarg; - break; - case 'r': - if ((regfile = fopen(optarg, "w")) == NULL) { - perror(optarg); - stop(NULL, EX_CANTCREAT); - } - regfilename = optarg; - break; - case 'I': - { - path_entry_t include_dir; - - if (strcmp(optarg, "-") == 0) { - if (includes_search_curdir == 0) { - fprintf(stderr, "%s: Warning - '-I-' " - "specified multiple " - "times\n", appname); - } - includes_search_curdir = 0; - for (include_dir = search_path.slh_first; - include_dir != NULL; - include_dir = include_dir->links.sle_next) - /* - * All entries before a '-I-' only - * apply to includes specified with - * quotes instead of "<>". - */ - include_dir->quoted_includes_only = 1; - } else { - include_dir = - (path_entry_t)malloc(sizeof(*include_dir)); - if (include_dir == NULL) { - perror(optarg); - stop(NULL, EX_OSERR); - } - include_dir->directory = strdup(optarg); - if (include_dir->directory == NULL) { - perror(optarg); - stop(NULL, EX_OSERR); - } - include_dir->quoted_includes_only = 0; - SLIST_INSERT_HEAD(&search_path, include_dir, - links); - } - break; - } - case '?': - default: - usage(); - /* NOTREACHED */ - } - } - argc -= optind; - argv += optind; - - if (argc != 1) { - fprintf(stderr, "%s: No input file specifiled\n", appname); - usage(); - /* NOTREACHED */ - } - - symtable_open(); - inputfilename = *argv; - include_file(*argv, SOURCE_FILE); - retval = yyparse(); - if (retval == 0) { - back_patch(); - if (ofile != NULL) - output_code(ofile); - if (regfile != NULL) - symtable_dump(regfile); - if (listfile != NULL) - output_listing(listfile, inputfilename, options); - } - - stop(NULL, 0); - /* NOTREACHED */ - return (0); -} - -static void -usage() -{ - - (void)fprintf(stderr, -"usage: %-16s [-nostdinc] [-I-] [-I directory] [-o output_file] - [-r register_output_file] [-l program_list_file] - [-O option_name[|options_name2]] input_file\n", - appname); - exit(EX_USAGE); -} - -static void -back_patch() -{ - struct instruction *cur_instr; - - for(cur_instr = seq_program.stqh_first; - cur_instr != NULL; - cur_instr = cur_instr->links.stqe_next) { - if (cur_instr->patch_label != NULL) { - struct ins_format3 *f3_instr; - u_int address; - - if (cur_instr->patch_label->type != LABEL) { - char buf[255]; - - snprintf(buf, sizeof(buf), - "Undefined label %s", - cur_instr->patch_label->name); - stop(buf, EX_DATAERR); - /* NOTREACHED */ - } - f3_instr = &cur_instr->format.format3; - address = ((f3_instr->opcode_addr & ADDR_HIGH_BIT) << 8) - | f3_instr->address; - address += cur_instr->patch_label->info.linfo->address; - f3_instr->opcode_addr &= ~ADDR_HIGH_BIT; - f3_instr->opcode_addr |= (address >> 8) & ADDR_HIGH_BIT; - f3_instr->address = address & 0xFF; - } - } -} - -static void -output_code(ofile) - FILE *ofile; -{ - struct instruction *cur_instr; - patch_t *cur_patch; - symbol_node_t *cur_node; - int instrcount; - - instrcount = 0; - fprintf(ofile, -"/* - * DO NOT EDIT - This file is automatically generated. - */\n"); - - fprintf(ofile, "static u_int8_t seqprog[] = {\n"); - for(cur_instr = seq_program.stqh_first; - cur_instr != NULL; - cur_instr = cur_instr->links.stqe_next) { - fprintf(ofile, "\t0x%02x, 0x%02x, 0x%02x, 0x%02x,\n", - cur_instr->format.bytes[0], - cur_instr->format.bytes[1], - cur_instr->format.bytes[2], - cur_instr->format.bytes[3]); - instrcount++; - } - fprintf(ofile, "};\n"); - - /* - * Output the patch list, option definitions first. - */ - for(cur_node = patch_options.slh_first; - cur_node != NULL; - cur_node = cur_node->links.sle_next) { - fprintf(ofile, "#define\t%-16s\t0x%x\n", cur_node->symbol->name, - cur_node->symbol->info.condinfo->value); - } - - fprintf(ofile, -"struct patch { - int options; - int negative; - int begin; - int end; -} patches[] = {\n"); - - for(cur_patch = patch_list.stqh_first; - cur_patch != NULL; - cur_patch = cur_patch->links.stqe_next) - - fprintf(ofile, "\t{ 0x%08x, %d, 0x%03x, 0x%03x },\n", - cur_patch->options, cur_patch->negative, cur_patch->begin, - cur_patch->end); - - fprintf(ofile, "\t{ 0x%08x, %d, 0x%03x, 0x%03x }\n};\n", - 0, 0, 0, 0); - - fprintf(stderr, "%s: %d instructions used\n", appname, instrcount); -} - -void -output_listing(listfile, ifilename, patches) - FILE *listfile; - char *ifilename; - char *patches; -{ - FILE *ifile; - int line; - struct instruction *cur_instr; - int instrcount; - int instrptr; - char buf[1024]; - patch_t *cur_patch; - char *option_spec; - int options; - - instrcount = 0; - instrptr = 0; - line = 1; - options = 1; /* All code outside of patch blocks */ - if ((ifile = fopen(ifilename, "r")) == NULL) { - perror(ifilename); - stop(NULL, EX_DATAERR); - } - - /* - * Determine which options to apply to this listing. - */ - while ((option_spec = strsep(&patches, "|")) != NULL) { - symbol_t *symbol; - - symbol = symtable_get(option_spec); - if (symbol->type != CONDITIONAL) { - stop("Invalid option specified in patch list for " - "program listing", EX_USAGE); - /* NOTREACHED */ - } - options |= symbol->info.condinfo->value; - } - - cur_patch = patch_list.stqh_first; - for(cur_instr = seq_program.stqh_first; - cur_instr != NULL; - cur_instr = cur_instr->links.stqe_next,instrcount++) { - - cur_patch = next_patch(cur_patch, options, instrcount); - if (cur_patch - && cur_patch->begin <= instrcount - && cur_patch->end > instrcount) - /* Don't count this instruction as it is in a patch - * that was removed. - */ - continue; - - while (line < cur_instr->srcline) { - fgets(buf, sizeof(buf), ifile); - fprintf(listfile, "\t\t%s", buf); - line++; - } - fprintf(listfile, "%03x %02x%02x%02x%02x", instrptr, - cur_instr->format.bytes[0], - cur_instr->format.bytes[1], - cur_instr->format.bytes[2], - cur_instr->format.bytes[3]); - fgets(buf, sizeof(buf), ifile); - fprintf(listfile, "\t%s", buf); - line++; - instrptr++; - } - /* Dump the remainder of the file */ - while(fgets(buf, sizeof(buf), ifile) != NULL) - fprintf(listfile, "\t\t%s", buf); - - fclose(ifile); -} - -static struct patch * -next_patch(cur_patch, options, instrptr) - struct patch *cur_patch; - int options; - int instrptr; -{ - while(cur_patch != NULL) { - if (((cur_patch->options & options) != 0 - && cur_patch->negative == FALSE) - || ((cur_patch->options & options) == 0 - && cur_patch->negative == TRUE) - || (instrptr >= cur_patch->end)) { - /* - * Either we want to keep this section of code, - * or we have consumed this patch. Skip to the - * next patch. - */ - cur_patch = cur_patch->links.stqe_next; - } else - /* Found an okay patch */ - break; - } - return (cur_patch); -} - -/* - * Print out error information if appropriate, and clean up before - * terminating the program. - */ -void -stop(string, err_code) - const char *string; - int err_code; -{ - if (string != NULL) { - fprintf(stderr, "%s: ", appname); - if (yyfilename != NULL) { - fprintf(stderr, "Stopped at file %s, line %d - ", - yyfilename, yylineno); - } - fprintf(stderr, "%s\n", string); - } - - if (ofile != NULL) { - fclose(ofile); - if (err_code != 0) { - fprintf(stderr, "%s: Removing %s due to error\n", - appname, ofilename); - unlink(ofilename); - } - } - - symlist_free(&patch_options); - symtable_close(); - - exit(err_code); -} - -struct instruction * -seq_alloc() -{ - struct instruction *new_instr; - - new_instr = (struct instruction *)malloc(sizeof(struct instruction)); - if (new_instr == NULL) - stop("Unable to malloc instruction object", EX_SOFTWARE); - memset(new_instr, 0, sizeof(*new_instr)); - STAILQ_INSERT_TAIL(&seq_program, new_instr, links); - new_instr->srcline = yylineno; - return new_instr; -} - -patch_t * -patch_alloc() -{ - patch_t *new_patch; - - new_patch = (patch_t *)malloc(sizeof(patch_t)); - if (new_patch == NULL) - stop("Unable to malloc patch object", EX_SOFTWARE); - memset(new_patch, 0, sizeof(*new_patch)); - STAILQ_INSERT_TAIL(&patch_list, new_patch, links); - return new_patch; -} diff --git a/sys/dev/aic7xxx/aicasm.h b/sys/dev/aic7xxx/aicasm.h deleted file mode 100644 index 185d807f6788d..0000000000000 --- a/sys/dev/aic7xxx/aicasm.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Assembler for the sequencer program downloaded to Aic7xxx SCSI host adapters - * - * Copyright (c) 1997 Justin T. Gibbs. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice immediately at the beginning of the file, without modification, - * this list of conditions, and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id$ - */ - -#include <sys/queue.h> - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - -typedef struct path_entry { - char *directory; - int quoted_includes_only; - SLIST_ENTRY(path_entry) links; -} *path_entry_t; - -typedef enum { - QUOTED_INCLUDE, - BRACKETED_INCLUDE, - SOURCE_FILE -} include_type; - -SLIST_HEAD(path_list, path_entry); - -extern struct path_list search_path; -extern struct symlist patch_options; -extern int includes_search_curdir; /* False if we've seen -I- */ -extern char *appname; -extern int yylineno; -extern char *yyfilename; - -void stop __P((const char *errstring, int err_code)); -void include_file __P((char *file_name, include_type type)); -struct instruction *seq_alloc __P((void)); -struct patch *patch_alloc __P((void)); diff --git a/sys/dev/aic7xxx/aicasm_gram.y b/sys/dev/aic7xxx/aicasm_gram.y deleted file mode 100644 index 0c75edca3b3ee..0000000000000 --- a/sys/dev/aic7xxx/aicasm_gram.y +++ /dev/null @@ -1,1304 +0,0 @@ -%{ -/* - * Parser for the Aic7xxx SCSI Host adapter sequencer assembler. - * - * Copyright (c) 1997 Justin T. Gibbs. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice immediately at the beginning of the file, without modification, - * this list of conditions, and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id$ - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sysexits.h> - -#include <sys/types.h> -#include <sys/queue.h> - -#include "aic7xxx_asm.h" -#include "symbol.h" -#include "sequencer.h" - -int yylineno; -char *yyfilename; -static symbol_t *cur_symbol; -static symtype cur_symtype; -static symbol_t *accumulator; -static symbol_ref_t allones; -static symbol_ref_t allzeros; -static symbol_ref_t none; -static symbol_ref_t sindex; -static int instruction_ptr; -static int sram_or_scb_offset; -static patch_t *cur_patch; - -static void process_bitmask __P((int mask_type, symbol_t *sym, int mask)); -static void initialize_symbol __P((symbol_t *symbol)); -static void process_register __P((symbol_t **p_symbol)); -static void format_1_instr __P((int opcode, symbol_ref_t *dest, - expression_t *immed, symbol_ref_t *src, - int ret)); -static void format_2_instr __P((int opcode, symbol_ref_t *dest, - expression_t *places, symbol_ref_t *src, - int ret)); -static void format_3_instr __P((int opcode, symbol_ref_t *src, - expression_t *immed, symbol_ref_t *address)); -static void test_readable_symbol __P((symbol_t *symbol)); -static void test_writable_symbol __P((symbol_t *symbol)); -static void type_check __P((symbol_t *symbol, expression_t *expression, - int and_op)); -static void make_expression __P((expression_t *immed, int value)); -static void add_conditional __P((symbol_t *symbol)); - -#define YYDEBUG 1 -#define SRAM_SYMNAME "SRAM_BASE" -#define SCB_SYMNAME "SCB_BASE" -%} - -%union { - int value; - char *str; - symbol_t *sym; - symbol_ref_t sym_ref; - expression_t expression; -} - -%token T_REGISTER - -%token <value> T_CONST - -%token T_SCB - -%token T_SRAM - -%token T_ALIAS - -%token T_SIZE - -%token <value> T_ADDRESS - -%token T_ACCESS_MODE - -%token <value> T_MODE - -%token T_BIT - -%token T_MASK - -%token <value> T_NUMBER - -%token <str> T_PATH - -%token T_EOF T_INCLUDE - -%token <value> T_SHR T_SHL T_ROR T_ROL - -%token <value> T_MVI T_MOV T_CLR - -%token <value> T_JMP T_JC T_JNC T_JE T_JNE T_JNZ T_JZ T_CALL - -%token <value> T_ADD T_ADC - -%token <value> T_INC T_DEC - -%token <value> T_STC T_CLC - -%token <value> T_CMP T_XOR - -%token <value> T_TEST T_AND - -%token <value> T_OR - -%token T_RET - -%token T_NOP - -%token T_ACCUM T_ALLONES T_ALLZEROS T_NONE T_SINDEX - -%token T_A - -%token <sym> T_SYMBOL - -%token T_NL - -%token T_IF T_ELSE T_ENDIF - -%type <sym_ref> reg_symbol address destination source opt_source - -%type <expression> expression immediate immediate_or_a - -%type <value> ret f1_opcode f2_opcode jmp_jc_jnc_call jz_jnz je_jne - -%left '|' -%left '&' -%left '+' '-' -%right '~' -%nonassoc UMINUS -%% - -program: - include -| program include -| register -| program register -| constant -| program constant -| scratch_ram -| program scratch_ram -| scb -| program scb -| label -| program label -| conditional -| program conditional -| code -| program code -; - -include: - T_INCLUDE '<' T_PATH '>' - { include_file($3, BRACKETED_INCLUDE); } -| T_INCLUDE '"' T_PATH '"' - { include_file($3, QUOTED_INCLUDE); } -; - -register: - T_REGISTER { cur_symtype = REGISTER; } reg_definition -; - -reg_definition: - T_SYMBOL '{' - { - if ($1->type != UNINITIALIZED) { - stop("Register multiply defined", EX_DATAERR); - /* NOTREACHED */ - } - cur_symbol = $1; - cur_symbol->type = cur_symtype; - initialize_symbol(cur_symbol); - } - reg_attribute_list - '}' - { - /* - * Default to allowing everything in for registers - * with no bit or mask definitions. - */ - if (cur_symbol->info.rinfo->valid_bitmask == 0) - cur_symbol->info.rinfo->valid_bitmask = 0xFF; - - if (cur_symbol->info.rinfo->size == 0) - cur_symbol->info.rinfo->size = 1; - - /* - * This might be useful for registers too. - */ - if (cur_symbol->type != REGISTER) { - if (cur_symbol->info.rinfo->address == 0) - cur_symbol->info.rinfo->address = - sram_or_scb_offset; - sram_or_scb_offset += - cur_symbol->info.rinfo->size; - } - cur_symbol = NULL; - } -; - -reg_attribute_list: - reg_attribute -| reg_attribute_list reg_attribute -; - -reg_attribute: - reg_address -| size -| access_mode -| bit_defn -| mask_defn -| alias -| accumulator -| allones -| allzeros -| none -| sindex -; - -reg_address: - T_ADDRESS T_NUMBER - { - cur_symbol->info.rinfo->address = $2; - } -; - -size: - T_SIZE T_NUMBER - { - cur_symbol->info.rinfo->size = $2; - } -; - -access_mode: - T_ACCESS_MODE T_MODE - { - cur_symbol->info.rinfo->mode = $2; - } -; - -bit_defn: - T_BIT T_SYMBOL T_NUMBER - { - process_bitmask(BIT, $2, $3); - } -; - -mask_defn: - T_MASK T_SYMBOL expression - { - process_bitmask(MASK, $2, $3.value); - } -; - -alias: - T_ALIAS T_SYMBOL - { - if ($2->type != UNINITIALIZED) { - stop("Re-definition of register alias", - EX_DATAERR); - /* NOTREACHED */ - } - $2->type = ALIAS; - initialize_symbol($2); - $2->info.ainfo->parent = cur_symbol; - } -; - -accumulator: - T_ACCUM - { - if (accumulator != NULL) { - stop("Only one accumulator definition allowed", - EX_DATAERR); - /* NOTREACHED */ - } - accumulator = cur_symbol; - } -; - -allones: - T_ALLONES - { - if (allones.symbol != NULL) { - stop("Only one definition of allones allowed", - EX_DATAERR); - /* NOTREACHED */ - } - allones.symbol = cur_symbol; - } -; - -allzeros: - T_ALLZEROS - { - if (allzeros.symbol != NULL) { - stop("Only one definition of allzeros allowed", - EX_DATAERR); - /* NOTREACHED */ - } - allzeros.symbol = cur_symbol; - } -; - -none: - T_NONE - { - if (none.symbol != NULL) { - stop("Only one definition of none allowed", - EX_DATAERR); - /* NOTREACHED */ - } - none.symbol = cur_symbol; - } -; - -sindex: - T_SINDEX - { - if (sindex.symbol != NULL) { - stop("Only one definition of sindex allowed", - EX_DATAERR); - /* NOTREACHED */ - } - sindex.symbol = cur_symbol; - } -; - -expression: - expression '|' expression - { - $$.value = $1.value | $3.value; - symlist_merge(&$$.referenced_syms, - &$1.referenced_syms, - &$3.referenced_syms); - } -| expression '&' expression - { - $$.value = $1.value & $3.value; - symlist_merge(&$$.referenced_syms, - &$1.referenced_syms, - &$3.referenced_syms); - } -| expression '+' expression - { - $$.value = $1.value + $3.value; - symlist_merge(&$$.referenced_syms, - &$1.referenced_syms, - &$3.referenced_syms); - } -| expression '-' expression - { - $$.value = $1.value - $3.value; - symlist_merge(&($$.referenced_syms), - &($1.referenced_syms), - &($3.referenced_syms)); - } -| '(' expression ')' - { - $$ = $2; - } -| '~' expression - { - $$ = $2; - $$.value = (~$$.value) & 0xFF; - } -| '-' expression %prec UMINUS - { - $$ = $2; - $$.value = -$$.value; - } -| T_NUMBER - { - $$.value = $1; - SLIST_INIT(&$$.referenced_syms); - } -| T_SYMBOL - { - symbol_t *symbol; - - symbol = $1; - switch (symbol->type) { - case ALIAS: - symbol = $1->info.ainfo->parent; - case REGISTER: - case SCBLOC: - case SRAMLOC: - $$.value = symbol->info.rinfo->address; - break; - case MASK: - case BIT: - $$.value = symbol->info.minfo->mask; - break; - case CONST: - $$.value = symbol->info.cinfo->value; - break; - case UNINITIALIZED: - default: - { - char buf[255]; - - snprintf(buf, sizeof(buf), - "Undefined symbol %s referenced", - symbol->name); - stop(buf, EX_DATAERR); - /* NOTREACHED */ - break; - } - } - SLIST_INIT(&$$.referenced_syms); - symlist_add(&$$.referenced_syms, symbol, SYMLIST_INSERT_HEAD); - } -; - -constant: - T_CONST T_SYMBOL T_NUMBER - { - if ($2->type != UNINITIALIZED) { - stop("Re-definition of constant variable", - EX_DATAERR); - /* NOTREACHED */ - } - $2->type = CONST; - initialize_symbol($2); - $2->info.cinfo->value = $3; - $2->info.cinfo->define = $1; - } -; - -scratch_ram: - T_SRAM '{' - { - cur_symbol = symtable_get(SRAM_SYMNAME); - cur_symtype = SRAMLOC; - if (cur_symbol->type != UNINITIALIZED) { - stop("Only one SRAM definition allowed", - EX_DATAERR); - /* NOTREACHED */ - } - cur_symbol->type = SRAMLOC; - initialize_symbol(cur_symbol); - } - reg_address - { - sram_or_scb_offset = cur_symbol->info.rinfo->address; - } - scb_or_sram_reg_list - '}' - { - cur_symbol = NULL; - } -; - -scb: - T_SCB '{' - { - cur_symbol = symtable_get(SCB_SYMNAME); - cur_symtype = SCBLOC; - if (cur_symbol->type != UNINITIALIZED) { - stop("Only one SRAM definition allowed", - EX_SOFTWARE); - /* NOTREACHED */ - } - cur_symbol->type = SCBLOC; - initialize_symbol(cur_symbol); - } - reg_address - { - sram_or_scb_offset = cur_symbol->info.rinfo->address; - } - scb_or_sram_reg_list - '}' - { - cur_symbol = NULL; - } -; - -scb_or_sram_reg_list: - reg_definition -| scb_or_sram_reg_list reg_definition -; - -reg_symbol: - T_SYMBOL - { - process_register(&$1); - $$.symbol = $1; - $$.offset = 0; - } -| T_SYMBOL '[' T_NUMBER ']' - { - process_register(&$1); - if (($3 + 1) > $1->info.rinfo->size) { - stop("Accessing offset beyond range of register", - EX_DATAERR); - /* NOTREACHED */ - } - $$.symbol = $1; - $$.offset = $3; - } -| T_A - { - if (accumulator == NULL) { - stop("No accumulator has been defined", EX_DATAERR); - /* NOTREACHED */ - } - $$.symbol = accumulator; - $$.offset = 0; - } -; - -destination: - reg_symbol - { - test_writable_symbol($1.symbol); - $$ = $1; - } -; - -immediate: - expression - { $$ = $1; } -; - -immediate_or_a: - expression - { - $$ = $1; - } -| T_A - { - SLIST_INIT(&$$.referenced_syms); - $$.value = 0; - } -; - -source: - reg_symbol - { - test_readable_symbol($1.symbol); - $$ = $1; - } -; - -opt_source: - { - $$.symbol = NULL; - $$.offset = 0; - } -| ',' source - { $$ = $2; } -; - -ret: - { $$ = 0; } -| T_RET - { $$ = 1; } -; - -label: - T_SYMBOL ':' - { - if ($1->type != UNINITIALIZED) { - stop("Program label multiply defined", EX_DATAERR); - /* NOTREACHED */ - } - $1->type = LABEL; - initialize_symbol($1); - $1->info.linfo->address = instruction_ptr; - } -; - -address: - T_SYMBOL - { - $$.symbol = $1; - $$.offset = 0; - } -| T_SYMBOL '+' T_NUMBER - { - $$.symbol = $1; - $$.offset = $3; - } -| T_SYMBOL '-' T_NUMBER - { - $$.symbol = $1; - $$.offset = -$3; - } -| '.' - { - $$.symbol = NULL; - $$.offset = 0; - } -| '.' '+' T_NUMBER - { - $$.symbol = NULL; - $$.offset = $3; - } -| '.' '-' T_NUMBER - { - $$.symbol = NULL; - $$.offset = -$3; - } -; - -conditional: - T_IF - { - if (cur_patch != NULL) { - stop("Nested .if directive", EX_DATAERR); - /* NOTREACHED */ - } - cur_patch = patch_alloc(); - cur_patch->begin = instruction_ptr; - } - option_list -; - -conditional: - T_ELSE - { - patch_t *next_patch; - - if (cur_patch == NULL) { - stop(".else outsize of .if", EX_DATAERR); - /* NOTREACHED */ - } - cur_patch->end = instruction_ptr; - next_patch = patch_alloc(); - next_patch->options = cur_patch->options; - next_patch->negative = cur_patch->negative ? FALSE : TRUE; - cur_patch = next_patch; - cur_patch->begin = instruction_ptr; - } -; - -conditional: - T_ENDIF - { - if (cur_patch == NULL) { - stop(".endif outsize of .if", EX_DATAERR); - /* NOTREACHED */ - } - cur_patch->end = instruction_ptr; - cur_patch = NULL; - } -; - -option_list: - '(' option_symbol_list ')' -| '!' option_list - { - cur_patch->negative = cur_patch->negative ? FALSE : TRUE; - } -; - -option_symbol_list: - T_SYMBOL - { - add_conditional($1); - } -| option_list '|' T_SYMBOL - { - add_conditional($3); - } -; - -f1_opcode: - T_AND { $$ = AIC_OP_AND; } -| T_XOR { $$ = AIC_OP_XOR; } -| T_ADD { $$ = AIC_OP_ADD; } -| T_ADC { $$ = AIC_OP_ADC; } -; - -code: - f1_opcode destination ',' immediate_or_a opt_source ret ';' - { - format_1_instr($1, &$2, &$4, &$5, $6); - } -; - -code: - T_OR reg_symbol ',' immediate_or_a opt_source ret ';' - { - format_1_instr(AIC_OP_OR, &$2, &$4, &$5, $6); - } -; - -code: - T_INC destination opt_source ret ';' - { - expression_t immed; - - make_expression(&immed, 1); - format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4); - } -; - -code: - T_DEC destination opt_source ret ';' - { - expression_t immed; - - make_expression(&immed, -1); - format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4); - } -; - -code: - T_CLC ret ';' - { - expression_t immed; - - make_expression(&immed, -1); - format_1_instr(AIC_OP_ADD, &none, &immed, &allzeros, $2); - } -| T_CLC T_MVI destination ',' immediate_or_a ret ';' - { - format_1_instr(AIC_OP_ADD, &$3, &$5, &allzeros, $6); - } -; - -code: - T_STC ret ';' - { - expression_t immed; - - make_expression(&immed, 1); - format_1_instr(AIC_OP_ADD, &none, &immed, &allones, $2); - } -| T_STC destination ret ';' - { - expression_t immed; - - make_expression(&immed, 1); - format_1_instr(AIC_OP_ADD, &$2, &immed, &allones, $3); - } -; - -code: - T_MOV destination ',' source ret ';' - { - expression_t immed; - - make_expression(&immed, 0xff); - format_1_instr(AIC_OP_AND, &$2, &immed, &$4, $5); - } -; - -code: - T_MVI destination ',' immediate_or_a ret ';' - { - format_1_instr(AIC_OP_OR, &$2, &$4, &allzeros, $5); - } -; - -code: - T_CLR destination ret ';' - { - expression_t immed; - - make_expression(&immed, 0xff); - format_1_instr(AIC_OP_AND, &$2, &immed, &allzeros, $3); - } -; - -code: - T_NOP ';' - { - expression_t immed; - - make_expression(&immed, 0xff); - format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, FALSE); - } -; - -code: - T_RET ';' - { - expression_t immed; - - make_expression(&immed, 0xff); - format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, TRUE); - } -; - - /* - * This grammer differs from the one in the aic7xxx - * reference manual since the grammer listed there is - * ambiguous and causes a shift/reduce conflict. - * It also seems more logical as the "immediate" - * argument is listed as the second arg like the - * other formats. - */ - -f2_opcode: - T_SHL { $$ = AIC_OP_SHL; } -| T_SHR { $$ = AIC_OP_SHR; } -| T_ROL { $$ = AIC_OP_ROL; } -| T_ROR { $$ = AIC_OP_ROR; } -; - -code: - f2_opcode destination ',' expression opt_source ret ';' - { - format_2_instr($1, &$2, &$4, &$5, $6); - } -; - -jmp_jc_jnc_call: - T_JMP { $$ = AIC_OP_JMP; } -| T_JC { $$ = AIC_OP_JC; } -| T_JNC { $$ = AIC_OP_JNC; } -| T_CALL { $$ = AIC_OP_CALL; } -; - -jz_jnz: - T_JZ { $$ = AIC_OP_JZ; } -| T_JNZ { $$ = AIC_OP_JNZ; } -; - -je_jne: - T_JE { $$ = AIC_OP_JE; } -| T_JNE { $$ = AIC_OP_JNE; } -; - -code: - jmp_jc_jnc_call address ';' - { - expression_t immed; - - make_expression(&immed, 0); - format_3_instr($1, &sindex, &immed, &$2); - } -; - -code: - T_OR reg_symbol ',' immediate jmp_jc_jnc_call address ';' - { - format_3_instr($5, &$2, &$4, &$6); - } -; - -code: - T_TEST source ',' immediate_or_a jz_jnz address ';' - { - format_3_instr($5, &$2, &$4, &$6); - } -; - -code: - T_CMP source ',' immediate_or_a je_jne address ';' - { - format_3_instr($5, &$2, &$4, &$6); - } -; - -code: - T_MOV source jmp_jc_jnc_call address ';' - { - expression_t immed; - - make_expression(&immed, 0); - format_3_instr($3, &$2, &immed, &$4); - } -; - -code: - T_MVI immediate jmp_jc_jnc_call address ';' - { - format_3_instr($3, &allzeros, &$2, &$4); - } -; - -%% - -static void -process_bitmask(mask_type, sym, mask) - int mask_type; - symbol_t *sym; - int mask; -{ - /* - * Add the current register to its - * symbol list, if it already exists, - * warn if we are setting it to a - * different value, or in the bit to - * the "allowed bits" of this register. - */ - if (sym->type == UNINITIALIZED) { - sym->type = mask_type; - initialize_symbol(sym); - if (mask_type == BIT) { - if (mask == 0) { - stop("Bitmask with no bits set", EX_DATAERR); - /* NOTREACHED */ - } - if ((mask & ~(0x01 << (ffs(mask) - 1))) != 0) { - stop("Bitmask with more than one bit set", - EX_DATAERR); - /* NOTREACHED */ - } - } - sym->info.minfo->mask = mask; - } else if (sym->type != mask_type) { - stop("Bit definition mirrors a definition of the same " - " name, but a different type", EX_DATAERR); - /* NOTREACHED */ - } else if (mask != sym->info.minfo->mask) { - stop("Bitmask redefined with a conflicting value", EX_DATAERR); - /* NOTREACHED */ - } - /* Fail if this symbol is already listed */ - if (symlist_search(&(sym->info.minfo->symrefs), - cur_symbol->name) != NULL) { - stop("Bitmask defined multiple times for register", EX_DATAERR); - /* NOTREACHED */ - } - symlist_add(&(sym->info.minfo->symrefs), cur_symbol, - SYMLIST_INSERT_HEAD); - cur_symbol->info.rinfo->valid_bitmask |= mask; - cur_symbol->info.rinfo->typecheck_masks = TRUE; -} - -static void -initialize_symbol(symbol) - symbol_t *symbol; -{ - switch (symbol->type) { - case UNINITIALIZED: - stop("Call to initialize_symbol with type field unset", - EX_SOFTWARE); - /* NOTREACHED */ - break; - case REGISTER: - case SRAMLOC: - case SCBLOC: - symbol->info.rinfo = - (struct reg_info *)malloc(sizeof(struct reg_info)); - if (symbol->info.rinfo == NULL) { - stop("Can't create register info", EX_SOFTWARE); - /* NOTREACHED */ - } - memset(symbol->info.rinfo, 0, - sizeof(struct reg_info)); - break; - case ALIAS: - symbol->info.ainfo = - (struct alias_info *)malloc(sizeof(struct alias_info)); - if (symbol->info.ainfo == NULL) { - stop("Can't create alias info", EX_SOFTWARE); - /* NOTREACHED */ - } - memset(symbol->info.ainfo, 0, - sizeof(struct alias_info)); - break; - case MASK: - case BIT: - symbol->info.minfo = - (struct mask_info *)malloc(sizeof(struct mask_info)); - if (symbol->info.minfo == NULL) { - stop("Can't create bitmask info", EX_SOFTWARE); - /* NOTREACHED */ - } - memset(symbol->info.minfo, 0, sizeof(struct mask_info)); - SLIST_INIT(&(symbol->info.minfo->symrefs)); - break; - case CONST: - symbol->info.cinfo = - (struct const_info *)malloc(sizeof(struct const_info)); - if (symbol->info.cinfo == NULL) { - stop("Can't create alias info", EX_SOFTWARE); - /* NOTREACHED */ - } - memset(symbol->info.cinfo, 0, - sizeof(struct const_info)); - break; - case LABEL: - symbol->info.linfo = - (struct label_info *)malloc(sizeof(struct label_info)); - if (symbol->info.linfo == NULL) { - stop("Can't create label info", EX_SOFTWARE); - /* NOTREACHED */ - } - memset(symbol->info.linfo, 0, - sizeof(struct label_info)); - break; - case CONDITIONAL: - symbol->info.condinfo = - (struct cond_info *)malloc(sizeof(struct cond_info)); - if (symbol->info.condinfo == NULL) { - stop("Can't create conditional info", EX_SOFTWARE); - /* NOTREACHED */ - } - memset(symbol->info.condinfo, 0, - sizeof(struct cond_info)); - break; - default: - stop("Call to initialize_symbol with invalid symbol type", - EX_SOFTWARE); - /* NOTREACHED */ - break; - } -} - -static void -process_register(p_symbol) - symbol_t **p_symbol; -{ - char buf[255]; - symbol_t *symbol = *p_symbol; - - if (symbol->type == UNINITIALIZED) { - snprintf(buf, sizeof(buf), "Undefined register %s", - symbol->name); - stop(buf, EX_DATAERR); - /* NOTREACHED */ - } else if (symbol->type == ALIAS) { - *p_symbol = symbol->info.ainfo->parent; - } else if ((symbol->type != REGISTER) - && (symbol->type != SCBLOC) - && (symbol->type != SRAMLOC)) { - snprintf(buf, sizeof(buf), - "Specified symbol %s is not a register", - symbol->name); - stop(buf, EX_DATAERR); - } -} - -static void -format_1_instr(opcode, dest, immed, src, ret) - int opcode; - symbol_ref_t *dest; - expression_t *immed; - symbol_ref_t *src; - int ret; -{ - struct instruction *instr; - struct ins_format1 *f1_instr; - - if (src->symbol == NULL) - src = dest; - - /* Test register permissions */ - test_writable_symbol(dest->symbol); - test_readable_symbol(src->symbol); - - /* Ensure that immediate makes sense for this destination */ - type_check(dest->symbol, immed, opcode); - - /* Allocate sequencer space for the instruction and fill it out */ - instr = seq_alloc(); - f1_instr = &instr->format.format1; - f1_instr->opcode_ret = (opcode << 1) | (ret ? RETURN_BIT : 0); - f1_instr->destination = dest->symbol->info.rinfo->address - + dest->offset; - f1_instr->source = src->symbol->info.rinfo->address - + src->offset; - f1_instr->immediate = immed->value; - symlist_free(&immed->referenced_syms); - instruction_ptr++; -} - -static void -format_2_instr(opcode, dest, places, src, ret) - int opcode; - symbol_ref_t *dest; - expression_t *places; - symbol_ref_t *src; - int ret; -{ - struct instruction *instr; - struct ins_format2 *f2_instr; - u_int8_t shift_control; - - if (src->symbol == NULL) - src = dest; - - /* Test register permissions */ - test_writable_symbol(dest->symbol); - test_readable_symbol(src->symbol); - - /* Allocate sequencer space for the instruction and fill it out */ - instr = seq_alloc(); - f2_instr = &instr->format.format2; - f2_instr->opcode_ret = (AIC_OP_ROL << 1) | (ret ? RETURN_BIT : 0); - f2_instr->destination = dest->symbol->info.rinfo->address - + dest->offset; - f2_instr->source = src->symbol->info.rinfo->address - + src->offset; - if (places->value > 8 || places->value <= 0) { - stop("illegal shift value", EX_DATAERR); - /* NOTREACHED */ - } - switch (opcode) { - case AIC_OP_SHL: - if (places->value == 8) - shift_control = 0xf0; - else - shift_control = (places->value << 4) | places->value; - break; - case AIC_OP_SHR: - if (places->value == 8) { - shift_control = 0xf8; - } else { - shift_control = (places->value << 4) - | (8 - places->value) - | 0x08; - } - break; - case AIC_OP_ROL: - shift_control = places->value & 0x7; - break; - case AIC_OP_ROR: - shift_control = (8 - places->value) | 0x08; - break; - default: - shift_control = 0; /* Quiet Compiler */ - stop("Invalid shift operation specified", EX_SOFTWARE); - /* NOTREACHED */ - break; - }; - f2_instr->shift_control = shift_control; - symlist_free(&places->referenced_syms); - instruction_ptr++; -} - -static void -format_3_instr(opcode, src, immed, address) - int opcode; - symbol_ref_t *src; - expression_t *immed; - symbol_ref_t *address; -{ - struct instruction *instr; - struct ins_format3 *f3_instr; - int addr; - - /* Test register permissions */ - test_readable_symbol(src->symbol); - - /* Ensure that immediate makes sense for this source */ - type_check(src->symbol, immed, opcode); - - /* Allocate sequencer space for the instruction and fill it out */ - instr = seq_alloc(); - f3_instr = &instr->format.format3; - if (address->symbol == NULL) { - /* 'dot' referrence. Use the current instruction pointer */ - addr = instruction_ptr + address->offset; - } else if (address->symbol->type == UNINITIALIZED) { - /* forward reference */ - addr = address->offset; - instr->patch_label = address->symbol; - } else - addr = address->symbol->info.linfo->address + address->offset; - f3_instr->opcode_addr = (opcode << 1) - | ((addr >> 8) & 0x01); - f3_instr->address = addr & 0xff; - f3_instr->source = src->symbol->info.rinfo->address - + src->offset; - f3_instr->immediate = immed->value; - symlist_free(&immed->referenced_syms); - instruction_ptr++; -} - -static void -test_readable_symbol(symbol) - symbol_t *symbol; -{ - if (symbol->info.rinfo->mode == WO) { - stop("Write Only register specified as source", - EX_DATAERR); - /* NOTREACHED */ - } -} - -static void -test_writable_symbol(symbol) - symbol_t *symbol; -{ - if (symbol->info.rinfo->mode == RO) { - stop("Read Only register specified as destination", - EX_DATAERR); - /* NOTREACHED */ - } -} - -static void -type_check(symbol, expression, opcode) - symbol_t *symbol; - expression_t *expression; - int opcode; -{ - symbol_node_t *node; - int and_op; - char buf[255]; - - and_op = FALSE; - if (opcode == AIC_OP_AND || opcode == AIC_OP_JNZ || AIC_OP_JZ) - and_op = TRUE; - /* - * Make sure that we aren't attempting to write something - * that hasn't been defined. If this is an and operation, - * this is a mask, so "undefined" bits are okay. - */ - if (and_op == FALSE - && (expression->value & ~symbol->info.rinfo->valid_bitmask) != 0) { - snprintf(buf, sizeof(buf), - "Invalid bit(s) 0x%x in immediate written to %s", - expression->value & ~symbol->info.rinfo->valid_bitmask, - symbol->name); - stop(buf, EX_DATAERR); - /* NOTREACHED */ - } - - /* - * Now make sure that all of the symbols referenced by the - * expression are defined for this register. - */ - if(symbol->info.rinfo->typecheck_masks != FALSE) { - for(node = expression->referenced_syms.slh_first; - node != NULL; - node = node->links.sle_next) { - if ((node->symbol->type == MASK - || node->symbol->type == BIT) - && symlist_search(&node->symbol->info.minfo->symrefs, - symbol->name) == NULL) { - snprintf(buf, sizeof(buf), - "Invalid bit or mask %s " - "for register %s", - node->symbol->name, symbol->name); - stop(buf, EX_DATAERR); - /* NOTREACHED */ - } - } - } -} - -static void -make_expression(immed, value) - expression_t *immed; - int value; -{ - SLIST_INIT(&immed->referenced_syms); - immed->value = value & 0xff; -} - -static void -add_conditional(symbol) - symbol_t *symbol; -{ - static int numoptions = 1; - - if (symbol->type == UNINITIALIZED) { - symbol->type = CONDITIONAL; - initialize_symbol(symbol); - symbol->info.condinfo->value = 0x01 << numoptions++; - symlist_add(&patch_options, symbol, SYMLIST_INSERT_HEAD); - } else if (symbol->type != CONDITIONAL) { - stop("Conditional symbol mirrors other symbol", - EX_DATAERR); - /* NOTREACHED */ - } - cur_patch->options |= symbol->info.condinfo->value; -} - -void -yyerror(string) - const char *string; -{ - stop(string, EX_DATAERR); -} diff --git a/sys/dev/aic7xxx/aicasm_scan.l b/sys/dev/aic7xxx/aicasm_scan.l deleted file mode 100644 index 0caf46a8d7db2..0000000000000 --- a/sys/dev/aic7xxx/aicasm_scan.l +++ /dev/null @@ -1,243 +0,0 @@ -%{ -/* - * Lexical Analyzer for the Aic7xxx SCSI Host adapter sequencer assembler. - * - * Copyright (c) 1997 Justin T. Gibbs. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice immediately at the beginning of the file, without modification, - * this list of conditions, and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: scan.l,v 1.1 1997/03/16 07:08:17 gibbs Exp $ - */ - -#include <limits.h> -#include <stdio.h> -#include <string.h> -#include <sysexits.h> -#include <sys/queue.h> -#include <sys/types.h> - -#include "aic7xxx_asm.h" -#include "symbol.h" -#include "y.tab.h" -%} - -PATH [-/A-Za-z0-9_.]*[./][-/A-Za-z0-9_.]* -WORD [A-Za-z_][-A-Za-z_0-9]* -SPACE [ \t]+ - -%x COMMENT - -%% -\n { ++yylineno; } -"/*" { BEGIN COMMENT; /* Enter comment eating state */ } -<COMMENT>"/*" { fprintf(stderr, "Warning! Comment within comment."); } -<COMMENT>\n { ++yylineno; } -<COMMENT>[^*/\n]* ; -<COMMENT>"*"+[^*/\n]* ; -<COMMENT>"/"+[^*/\n]* ; -<COMMENT>"*"+"/" { BEGIN INITIAL; } - -{SPACE} ; - - /* Register/SCB/SRAM definition keywords */ -register { return T_REGISTER; } -const { yylval.value = FALSE; return T_CONST; } -address { return T_ADDRESS; } -access_mode { return T_ACCESS_MODE; } -RW|RO|WO { - if (strcmp(yytext, "RW") == 0) - yylval.value = RW; - else if (strcmp(yytext, "RO") == 0) - yylval.value = RO; - else - yylval.value = WO; - return T_MODE; - } -bit { return T_BIT; } -mask { return T_MASK; } -alias { return T_ALIAS; } -size { return T_SIZE; } -scb { return T_SCB; } -scratch_ram { return T_SRAM; } -accumulator { return T_ACCUM; } -allones { return T_ALLONES; } -allzeros { return T_ALLZEROS; } -none { return T_NONE; } -sindex { return T_SINDEX; } -A { return T_A; } - - /* Opcodes */ -shl { return T_SHL; } -shr { return T_SHR; } -ror { return T_ROR; } -rol { return T_ROL; } -mvi { return T_MVI; } -mov { return T_MOV; } -clr { return T_CLR; } -jmp { return T_JMP; } -jc { return T_JC; } -jnc { return T_JNC; } -je { return T_JE; } -jne { return T_JNE; } -jz { return T_JZ; } -jnz { return T_JNZ; } -call { return T_CALL; } -add { return T_ADD; } -adc { return T_ADC; } -inc { return T_INC; } -dec { return T_DEC; } -stc { return T_STC; } -clc { return T_CLC; } -cmp { return T_CMP; } -xor { return T_XOR; } -test { return T_TEST;} -and { return T_AND; } -or { return T_OR; } -ret { return T_RET; } -nop { return T_NOP; } -.if { return T_IF; } -.else { return T_ELSE; } -.endif { return T_ENDIF; } - - /* Allowed Symbols */ -[-+,:()~|&."{};<>[\]!] { return yytext[0]; } - - /* Number processing */ -0[0-7]* { - yylval.value = strtol(yytext, NULL, 8); - return T_NUMBER; - } - -0[xX][0-9a-fA-F]+ { - yylval.value = strtoul(yytext + 2, NULL, 16); - return T_NUMBER; - } - -[1-9][0-9]* { - yylval.value = strtol(yytext, NULL, 10); - return T_NUMBER; - } - - /* Include Files */ -#include { return T_INCLUDE; } - - /* For parsing C include files with #define foo */ -#define { yylval.value = TRUE; return T_CONST; } - /* Throw away macros */ -#define[^\n]*[()]+[^\n]* ; -{PATH} { yylval.str = strdup(yytext); return T_PATH; } - -{WORD} { yylval.sym = symtable_get(yytext); return T_SYMBOL; } - -. { - char buf[255]; - - snprintf(buf, sizeof(buf), "Invalid character " - "'%c'", yytext[0]); - stop(buf, EX_DATAERR); - } -%% - -typedef struct include { - YY_BUFFER_STATE buffer; - int lineno; - char *filename; - SLIST_ENTRY(include) links; -}include_t; - -SLIST_HEAD(, include) include_stack; - -void -include_file(file_name, type) - char *file_name; - include_type type; -{ - FILE *newfile; - include_t *include; - - newfile = NULL; - /* Try the current directory first */ - if (includes_search_curdir != 0 || type == SOURCE_FILE) - newfile = fopen(file_name, "r"); - - if (newfile == NULL && type != SOURCE_FILE) { - path_entry_t include_dir; - for (include_dir = search_path.slh_first; - include_dir != NULL; - include_dir = include_dir->links.sle_next) { - char fullname[PATH_MAX]; - - if ((include_dir->quoted_includes_only == TRUE) - && (type != QUOTED_INCLUDE)) - continue; - - snprintf(fullname, sizeof(fullname), - "%s/%s", include_dir->directory, file_name); - - if ((newfile = fopen(fullname, "r")) != NULL) - break; - } - } - - if (newfile == NULL) { - perror(file_name); - stop("Unable to open input file", EX_SOFTWARE); - /* NOTREACHED */ - } - include = (include_t *)malloc(sizeof(include_t)); - if (include == NULL) { - stop("Unable to allocate include stack entry", EX_SOFTWARE); - /* NOTREACHED */ - } - include->buffer = YY_CURRENT_BUFFER; - include->lineno = yylineno; - include->filename = yyfilename; - SLIST_INSERT_HEAD(&include_stack, include, links); - yy_switch_to_buffer(yy_create_buffer(newfile, YY_BUF_SIZE)); - yylineno = 1; - yyfilename = strdup(file_name); -} - -int -yywrap() -{ - include_t *include; - - yy_delete_buffer(YY_CURRENT_BUFFER); - (void)fclose(yyin); - if (yyfilename != NULL) - free(yyfilename); - include = include_stack.slh_first; - if (include != NULL) { - yy_switch_to_buffer(include->buffer); - yylineno = include->lineno; - yyfilename = include->filename; - SLIST_REMOVE_HEAD(&include_stack, links); - free(include); - return (0); - } - return (1); -} diff --git a/sys/dev/aic7xxx/aicasm_symbol.c b/sys/dev/aic7xxx/aicasm_symbol.c deleted file mode 100644 index e2b93efbd2ee1..0000000000000 --- a/sys/dev/aic7xxx/aicasm_symbol.c +++ /dev/null @@ -1,451 +0,0 @@ -/* - * Aic7xxx SCSI host adapter firmware asssembler symbol table implementation - * - * Copyright (c) 1997 Justin T. Gibbs. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice immediately at the beginning of the file, without modification, - * this list of conditions, and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id$ - */ - - -#include <sys/types.h> - -#include <db.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sysexits.h> - -#include "symbol.h" -#include "aic7xxx_asm.h" - -static DB *symtable; - -symbol_t * -symbol_create(name) - char *name; -{ - symbol_t *new_symbol; - - new_symbol = (symbol_t *)malloc(sizeof(symbol_t)); - if (new_symbol == NULL) { - perror("Unable to create new symbol"); - exit(EX_SOFTWARE); - } - memset(new_symbol, 0, sizeof(*new_symbol)); - new_symbol->name = strdup(name); - new_symbol->type = UNINITIALIZED; - return (new_symbol); -} - -void -symbol_delete(symbol) - symbol_t *symbol; -{ - if (symtable != NULL) { - DBT key; - - key.data = symbol->name; - key.size = strlen(symbol->name); - symtable->del(symtable, &key, /*flags*/0); - } - switch(symbol->type) { - case SCBLOC: - case SRAMLOC: - case REGISTER: - if (symbol->info.rinfo != NULL) - free(symbol->info.rinfo); - break; - case ALIAS: - if (symbol->info.ainfo != NULL) - free(symbol->info.ainfo); - break; - case MASK: - case BIT: - if (symbol->info.minfo != NULL) { - symlist_free(&symbol->info.minfo->symrefs); - free(symbol->info.minfo); - } - break; - case CONST: - if (symbol->info.cinfo != NULL) - free(symbol->info.cinfo); - break; - case LABEL: - if (symbol->info.linfo != NULL) - free(symbol->info.linfo); - break; - case UNINITIALIZED: - default: - break; - } - free(symbol->name); - free(symbol); -} - -void -symtable_open() -{ - symtable = dbopen(/*filename*/NULL, - O_CREAT | O_NONBLOCK | O_RDWR, /*mode*/0, DB_HASH, - /*openinfo*/NULL); - - if (symtable == NULL) { - perror("Symbol table creation failed"); - exit(EX_SOFTWARE); - /* NOTREACHED */ - } -} - -void -symtable_close() -{ - if (symtable != NULL) { - DBT key; - DBT data; - - while (symtable->seq(symtable, &key, &data, R_FIRST) == 0) { - symbol_t *cursym; - - cursym = *(symbol_t **)data.data; - symbol_delete(cursym); - } - symtable->close(symtable); - } -} - -/* - * The semantics of get is to return an uninitialized symbol entry - * if a lookup fails. - */ -symbol_t * -symtable_get(name) - char *name; -{ - DBT key; - DBT data; - int retval; - - key.data = (void *)name; - key.size = strlen(name); - - if ((retval = symtable->get(symtable, &key, &data, /*flags*/0)) != 0) { - if (retval == -1) { - perror("Symbol table get operation failed"); - exit(EX_SOFTWARE); - /* NOTREACHED */ - } else if (retval == 1) { - /* Symbol wasn't found, so create a new one */ - symbol_t *new_symbol; - - new_symbol = symbol_create(name); - data.data = &new_symbol; - data.size = sizeof(new_symbol); - if (symtable->put(symtable, &key, &data, - /*flags*/0) !=0) { - perror("Symtable put failed"); - exit(EX_SOFTWARE); - } - return (new_symbol); - } else { - perror("Unexpected return value from db get routine"); - exit(EX_SOFTWARE); - /* NOTREACHED */ - } - } - return (*(symbol_t **)data.data); -} - -symbol_node_t * -symlist_search(symlist, symname) - symlist_t *symlist; - char *symname; -{ - symbol_node_t *curnode; - - curnode = symlist->slh_first; - while(curnode != NULL) { - if (strcmp(symname, curnode->symbol->name) == 0) - break; - curnode = curnode->links.sle_next; - } - return (curnode); -} - -void -symlist_add(symlist, symbol, how) - symlist_t *symlist; - symbol_t *symbol; - int how; -{ - symbol_node_t *newnode; - - newnode = (symbol_node_t *)malloc(sizeof(symbol_node_t)); - if (newnode == NULL) { - stop("symlist_add: Unable to malloc symbol_node", EX_SOFTWARE); - /* NOTREACHED */ - } - newnode->symbol = symbol; - if (how == SYMLIST_SORT) { - symbol_node_t *curnode; - int mask; - - mask = FALSE; - switch(symbol->type) { - case REGISTER: - case SCBLOC: - case SRAMLOC: - break; - case BIT: - case MASK: - mask = TRUE; - break; - default: - stop("symlist_add: Invalid symbol type for sorting", - EX_SOFTWARE); - /* NOTREACHED */ - } - - curnode = symlist->slh_first; - if (curnode == NULL - || (mask && (curnode->symbol->info.minfo->mask > - newnode->symbol->info.minfo->mask)) - || (!mask && (curnode->symbol->info.rinfo->address > - newnode->symbol->info.rinfo->address))) { - SLIST_INSERT_HEAD(symlist, newnode, links); - return; - } - - while (1) { - if (curnode->links.sle_next == NULL) { - SLIST_INSERT_AFTER(curnode, newnode, - links); - break; - } else { - symbol_t *cursymbol; - - cursymbol = curnode->links.sle_next->symbol; - if ((mask && (cursymbol->info.minfo->mask > - symbol->info.minfo->mask)) - || (!mask &&(cursymbol->info.rinfo->address > - symbol->info.rinfo->address))){ - SLIST_INSERT_AFTER(curnode, newnode, - links); - break; - } - } - curnode = curnode->links.sle_next; - } - } else { - SLIST_INSERT_HEAD(symlist, newnode, links); - } -} - -void -symlist_free(symlist) - symlist_t *symlist; -{ - symbol_node_t *node1, *node2; - - node1 = symlist->slh_first; - while (node1 != NULL) { - node2 = node1->links.sle_next; - free(node1); - node1 = node2; - } - SLIST_INIT(symlist); -} - -void -symlist_merge(symlist_dest, symlist_src1, symlist_src2) - symlist_t *symlist_dest; - symlist_t *symlist_src1; - symlist_t *symlist_src2; -{ - symbol_node_t *node; - - *symlist_dest = *symlist_src1; - while((node = symlist_src2->slh_first) != NULL) { - SLIST_REMOVE_HEAD(symlist_src2, links); - SLIST_INSERT_HEAD(symlist_dest, node, links); - } - - /* These are now empty */ - SLIST_INIT(symlist_src1); - SLIST_INIT(symlist_src2); -} - -void -symtable_dump(ofile) - FILE *ofile; -{ - /* - * Sort the registers by address with a simple insertion sort. - * Put bitmasks next to the first register that defines them. - * Put constants at the end. - */ - symlist_t registers; - symlist_t masks; - symlist_t constants; - symlist_t aliases; - - SLIST_INIT(®isters); - SLIST_INIT(&masks); - SLIST_INIT(&constants); - SLIST_INIT(&aliases); - - if (symtable != NULL) { - DBT key; - DBT data; - int flag = R_FIRST; - - while (symtable->seq(symtable, &key, &data, flag) == 0) { - symbol_t *cursym; - - cursym = *(symbol_t **)data.data; - switch(cursym->type) { - case REGISTER: - case SCBLOC: - case SRAMLOC: - symlist_add(®isters, cursym, SYMLIST_SORT); - break; - case MASK: - case BIT: - symlist_add(&masks, cursym, SYMLIST_SORT); - break; - case CONST: - if (cursym->info.cinfo->define == FALSE) { - symlist_add(&constants, cursym, - SYMLIST_INSERT_HEAD); - } - break; - case ALIAS: - symlist_add(&aliases, cursym, - SYMLIST_INSERT_HEAD); - default: - break; - } - flag = R_NEXT; - } - - /* Put in the masks and bits */ - while (masks.slh_first != NULL) { - symbol_node_t *curnode; - symbol_node_t *regnode; - char *regname; - - curnode = masks.slh_first; - SLIST_REMOVE_HEAD(&masks, links); - - regnode = - curnode->symbol->info.minfo->symrefs.slh_first; - regname = regnode->symbol->name; - regnode = symlist_search(®isters, regname); - SLIST_INSERT_AFTER(regnode, curnode, links); - } - - /* Add the aliases */ - while (aliases.slh_first != NULL) { - symbol_node_t *curnode; - symbol_node_t *regnode; - char *regname; - - curnode = aliases.slh_first; - SLIST_REMOVE_HEAD(&aliases, links); - - regname = curnode->symbol->info.ainfo->parent->name; - regnode = symlist_search(®isters, regname); - SLIST_INSERT_AFTER(regnode, curnode, links); - } - - /* Output what we have */ - fprintf(ofile, -"/* - * DO NOT EDIT - This file is automatically generated. - */\n"); - while (registers.slh_first != NULL) { - symbol_node_t *curnode; - u_int8_t value; - char *tab_str; - char *tab_str2; - - curnode = registers.slh_first; - SLIST_REMOVE_HEAD(®isters, links); - switch(curnode->symbol->type) { - case REGISTER: - case SCBLOC: - case SRAMLOC: - fprintf(ofile, "\n"); - value = curnode->symbol->info.rinfo->address; - tab_str = "\t"; - tab_str2 = "\t\t"; - break; - case ALIAS: - { - symbol_t *parent; - - parent = curnode->symbol->info.ainfo->parent; - value = parent->info.rinfo->address; - tab_str = "\t"; - tab_str2 = "\t\t"; - break; - } - case MASK: - case BIT: - value = curnode->symbol->info.minfo->mask; - tab_str = "\t\t"; - tab_str2 = "\t"; - break; - default: - value = 0; /* Quiet compiler */ - tab_str = NULL; - tab_str2 = NULL; - stop("symtable_dump: Invalid symbol type " - "encountered", EX_SOFTWARE); - break; - } - fprintf(ofile, "#define%s%-16s%s0x%02x\n", - tab_str, curnode->symbol->name, tab_str2, - value); - free(curnode); - } - fprintf(ofile, "\n\n"); - - while (constants.slh_first != NULL) { - symbol_node_t *curnode; - - curnode = constants.slh_first; - SLIST_REMOVE_HEAD(&constants, links); - fprintf(ofile, "#define\t%-8s\t0x%02x\n", - curnode->symbol->name, - curnode->symbol->info.cinfo->value); - free(curnode); - } - } -} - diff --git a/sys/dev/aic7xxx/aicasm_symbol.h b/sys/dev/aic7xxx/aicasm_symbol.h deleted file mode 100644 index cf8fa0071225a..0000000000000 --- a/sys/dev/aic7xxx/aicasm_symbol.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Aic7xxx SCSI host adapter firmware asssembler symbol table definitions - * - * Copyright (c) 1997 Justin T. Gibbs. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice immediately at the beginning of the file, without modification, - * this list of conditions, and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id$ - */ - -#include <sys/queue.h> - -typedef enum { - UNINITIALIZED, - REGISTER, - ALIAS, - SCBLOC, - SRAMLOC, - MASK, - BIT, - CONST, - LABEL, - CONDITIONAL -}symtype; - -typedef enum { - RO = 0x01, - WO = 0x02, - RW = 0x03 -}amode_t; - -struct reg_info { - u_int8_t address; - int size; - amode_t mode; - u_int8_t valid_bitmask; - int typecheck_masks; -}; - -typedef SLIST_HEAD(symlist, symbol_node) symlist_t; - -struct mask_info { - symlist_t symrefs; - u_int8_t mask; -}; - -struct const_info { - u_int8_t value; - int define; -}; - -struct alias_info { - struct symbol *parent; -}; - -struct label_info { - int address; -}; - -struct cond_info { - int value; -}; - -typedef struct expression_info { - symlist_t referenced_syms; - int value; -} expression_t; - -typedef struct symbol { - char *name; - symtype type; - union { - struct reg_info *rinfo; - struct mask_info *minfo; - struct const_info *cinfo; - struct alias_info *ainfo; - struct label_info *linfo; - struct cond_info *condinfo; - }info; -} symbol_t; - -typedef struct symbol_ref { - symbol_t *symbol; - int offset; -} symbol_ref_t; - -typedef struct symbol_node { - SLIST_ENTRY(symbol_node) links; - symbol_t *symbol; -}symbol_node_t; - -typedef struct patch { - STAILQ_ENTRY(patch) links; - int negative; - int begin; - int end; - int options; -} patch_t; - -void symbol_delete __P((symbol_t *symbol)); - -void symtable_open __P((void)); - -void symtable_close __P((void)); - -symbol_t * - symtable_get __P((char *name)); - -symbol_node_t * - symlist_search __P((symlist_t *symlist, char *symname)); - -void - symlist_add __P((symlist_t *symlist, symbol_t *symbol, int how)); -#define SYMLIST_INSERT_HEAD 0x00 -#define SYMLIST_SORT 0x01 - -void symlist_free __P((symlist_t *symlist)); - -void symlist_merge __P((symlist_t *symlist_dest, symlist_t *symlist_src1, - symlist_t *symlist_src2)); -void symtable_dump __P((FILE *ofile)); diff --git a/sys/i386/include/asm.h b/sys/i386/include/asm.h deleted file mode 100644 index d700579696a4e..0000000000000 --- a/sys/i386/include/asm.h +++ /dev/null @@ -1,201 +0,0 @@ -/*- - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * William Jolitz. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)DEFS.h 5.1 (Berkeley) 4/23/90 - * $Id: asm.h,v 1.1 1997/03/09 10:39:15 bde Exp $ - */ - -#include <sys/cdefs.h> - -#ifdef PIC -#define PIC_PROLOGUE \ - pushl %ebx; \ - call 1f; \ -1: \ - popl %ebx; \ - addl $_GLOBAL_OFFSET_TABLE_+[.-1b],%ebx -#define PIC_EPILOGUE \ - popl %ebx -#define PIC_PLT(x) x@PLT -#define PIC_GOT(x) x@GOT(%ebx) -#define PIC_GOTOFF(x) x@GOTOFF(%ebx) -#else -#define PIC_PROLOGUE -#define PIC_EPILOGUE -#define PIC_PLT(x) x -#define PIC_GOT(x) x -#define PIC_GOTOFF(x) x -#endif - -/* - * CNAME and HIDENAME manage the relationship between symbol names in C - * and the equivalent assembly language names. CNAME is given a name as - * it would be used in a C program. It expands to the equivalent assembly - * language name. HIDENAME is given an assembly-language name, and expands - * to a possibly-modified form that will be invisible to C programs. - */ -#if defined(__ELF__) /* { */ -#define CNAME(csym) csym -#define HIDENAME(asmsym) __CONCAT(.,asmsym) -#else /* } { */ -#define CNAME(csym) __CONCAT(_,csym) -#define HIDENAME(asmsym) asmsym -#endif /* } */ - - -/* XXX should use align 4,0x90 for -m486. */ -#define _START_ENTRY .text; .align 2,0x90; -#if 0 -/* Data is not used, except perhaps by non-g prof, which we don't support. */ -#define _MID_ENTRY .data; .align 2; 8:; .long 0; \ - .text; lea 8b,%eax; -#else -#define _MID_ENTRY -#endif - -#ifdef PROF - -#define ALTENTRY(x) _START_ENTRY \ - .globl CNAME(x); .type CNAME(x),@function; CNAME(x):; \ - _MID_ENTRY \ - call HIDENAME(mcount); jmp 9f - -#define ENTRY(x) _START_ENTRY \ - .globl CNAME(x); .type CNAME(x),@function; CNAME(x):; \ - _MID_ENTRY \ - call HIDENAME(mcount); 9: - - -#define ALTASENTRY(x) _START_ENTRY \ - .globl x; .type x,@function; x:; \ - _MID_ENTRY \ - call HIDENAME(mcount); jmp 9f - -#define ASENTRY(x) _START_ENTRY \ - .globl x; .type x,@function; x:; \ - _MID_ENTRY \ - call HIDENAME(mcount); 9: - -#else /* !PROF */ - -#define ENTRY(x) _START_ENTRY .globl CNAME(x); .type CNAME(x),@function; \ - CNAME(x): -#define ALTENTRY(x) ENTRY(x) - -#define ASENTRY(x) _START_ENTRY .globl x; .type x,@function; x: -#define ALTASENTRY(x) ASENTRY(x) - -#endif - -/* - * This header is currently only used in lib/msun/i387. - * Use it to generate code to select between the generic math functions - * and the i387 ones. - */ -#undef ENTRY -#define ANAME(x) CNAME(__CONCAT(__i387_,x)) -#define ASELNAME(x) CNAME(__CONCAT(__arch_select_,x)) -#define AVECNAME(x) CNAME(__CONCAT(__arch_,x)) -#define GNAME(x) CNAME(__CONCAT(__generic_,x)) - -/* Don't bother profiling this. */ -#ifdef PIC -#define ARCH_DISPATCH(x) \ - _START_ENTRY; \ - .globl CNAME(x); .type CNAME(x),@function; CNAME(x): ; \ - PIC_PROLOGUE; \ - movl PIC_GOT(AVECNAME(x)),%eax; \ - PIC_EPILOGUE; \ - jmpl *(%eax) - -#define ARCH_SELECT(x) _START_ENTRY; \ - .type ASELNAME(x),@function; \ - ASELNAME(x): \ - PIC_PROLOGUE; \ - call PIC_PLT(CNAME(__get_hw_float)); \ - testl %eax,%eax; \ - movl PIC_GOT(ANAME(x)),%eax; \ - jne 8f; \ - movl PIC_GOT(GNAME(x)),%eax; \ - 8: \ - movl PIC_GOT(AVECNAME(x)),%edx; \ - movl %eax,(%edx); \ - PIC_EPILOGUE; \ - jmpl *%eax -#else /* !PIC */ -#define ARCH_DISPATCH(x) \ - _START_ENTRY; \ - .globl CNAME(x); .type CNAME(x),@function; CNAME(x): ; \ - jmpl *AVECNAME(x) - -#define ARCH_SELECT(x) _START_ENTRY; \ - .type ASELNAME(x),@function; \ - ASELNAME(x): \ - call CNAME(__get_hw_float); \ - testl %eax,%eax; \ - movl $ANAME(x),%eax; \ - jne 8f; \ - movl $GNAME(x),%eax; \ - 8: \ - movl %eax,AVECNAME(x); \ - jmpl *%eax -#endif /* PIC */ - -#define ARCH_VECTOR(x) .data; .align 2; \ - .globl AVECNAME(x); \ - .type AVECNAME(x),@object; \ - .size AVECNAME(x),4; \ - AVECNAME(x): .long ASELNAME(x) - -#ifdef PROF - -#define ALTENTRY(x) ENTRY(x); jmp 9f -#define ENTRY(x) ARCH_VECTOR(x); ARCH_SELECT(x); ARCH_DISPATCH(x); \ - _START_ENTRY; \ - .globl ANAME(x); .type ANAME(x),@function; ANAME(x):; \ - call HIDENAME(mcount); 9: - -#else /* !PROF */ - -#define ALTENTRY(x) ENTRY(x) -#define ENTRY(x) ARCH_VECTOR(x); ARCH_SELECT(x); ARCH_DISPATCH(x); \ - _START_ENTRY; \ - .globl ANAME(x); .type ANAME(x),@function; ANAME(x): - -#endif /* PROF */ - -#ifndef RCSID -#define RCSID(a) -#endif diff --git a/sys/i386/include/vmparam.h b/sys/i386/include/vmparam.h index 48b570dd0232a..d26b1c6d43ab3 100644 --- a/sys/i386/include/vmparam.h +++ b/sys/i386/include/vmparam.h @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * from: @(#)vmparam.h 5.9 (Berkeley) 5/12/91 - * $Id: vmparam.h,v 1.20 1996/04/30 12:02:12 phk Exp $ + * $Id: vmparam.h,v 1.21 1996/05/02 14:20:07 phk Exp $ */ @@ -116,4 +116,7 @@ /* virtual sizes (bytes) for various kernel submaps */ #define VM_KMEM_SIZE (32 * 1024 * 1024) +/* read and exec are the same thing */ +#define VM_PROT_READ_IS_EXEC + #endif /* _MACHINE_VMPARAM_H_ */ diff --git a/sys/i386/scsi/aic7xxx.c b/sys/i386/scsi/aic7xxx.c index bb61ea4a9c292..ed0eb8eb675bf 100644 --- a/sys/i386/scsi/aic7xxx.c +++ b/sys/i386/scsi/aic7xxx.c @@ -32,7 +32,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: aic7xxx.c,v 1.81.2.14 1997/03/01 06:53:35 gibbs Exp $ + * $Id: aic7xxx.c,v 1.81.2.16 1997/03/24 05:11:03 gibbs Exp $ */ /* * TODO: @@ -812,8 +812,7 @@ ahc_intr(arg) scb->xs->error); ahc_run_done_queue(ahc); } - if (scb->hscb->status != SCSI_QUEUE_FULL) - ahc_done(ahc, scb); + ahc_done(ahc, scb); } ahc_outb(ahc, CLRINT, CLRCMDINT); int_cleared++; @@ -1334,13 +1333,8 @@ ahc_handle_seqint(ahc, intstat) /* * XXX requeue this unconditionally. */ - STAILQ_INSERT_TAIL(&ahc->waiting_scbs, scb, - links); - scb->flags |= SCB_WAITINGQ; - /* Give the command a new lease on life */ - untimeout(ahc_timeout, (caddr_t)scb); - timeout(ahc_timeout, (caddr_t)scb, - (scb->xs->timeout * hz) / 1000); + scb->xs->retries++; + scb->xs->error = XS_BUSY; break; } /* Else treat as if it is a BUSY condition */ @@ -2566,7 +2560,12 @@ ahc_run_waiting_queue(ahc) { struct scb *scb; - pause_sequencer(ahc); + /* + * On aic78X0 chips, we rely on Auto Access Pause (AAP) + * instead of doing an explicit pause/unpause. + */ + if ((ahc->type & AHC_AIC78X0) == 0) + pause_sequencer(ahc); while ((scb = ahc->waiting_scbs.stqh_first) != NULL) { @@ -2588,7 +2587,8 @@ ahc_run_waiting_queue(ahc) */ ahc->curqincnt++; } - unpause_sequencer(ahc, /*Unpause always*/FALSE); + if ((ahc->type & AHC_AIC78X0) == 0) + unpause_sequencer(ahc, /*Unpause always*/FALSE); } /* @@ -3185,7 +3185,7 @@ ahc_find_scb(ahc, scb) break; } ahc_outb(ahc, SCBPTR, saved_scbptr); - if (curindex > ahc->scb_data->maxhscbs) + if (curindex >= ahc->scb_data->maxhscbs) curindex = SCB_LIST_NULL; return curindex; diff --git a/sys/miscfs/procfs/procfs_map.c b/sys/miscfs/procfs/procfs_map.c index b3d6c9bd73b55..d9bbe180852aa 100644 --- a/sys/miscfs/procfs/procfs_map.c +++ b/sys/miscfs/procfs/procfs_map.c @@ -36,7 +36,7 @@ * * @(#)procfs_status.c 8.3 (Berkeley) 2/17/94 * - * $Id: procfs_map.c,v 1.4 1996/07/27 19:47:04 dyson Exp $ + * $Id: procfs_map.c,v 1.6 1996/10/30 03:52:57 dyson Exp $ */ #include <sys/param.h> @@ -113,7 +113,7 @@ procfs_domap(curp, p, pfs, uio) int resident, privateresident; char *type; - if (entry->is_a_map || entry->is_sub_map) + if (entry->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP)) continue; obj = entry->object.vm_object; @@ -163,7 +163,7 @@ case OBJT_DEVICE: (entry->protection & VM_PROT_READ)?"r":"-", (entry->protection & VM_PROT_WRITE)?"w":"-", (entry->protection & VM_PROT_EXECUTE)?"x":"-", - entry->copy_on_write?"COW":" ", + (entry->eflags & MAP_ENTRY_COW)?"COW":" ", type); len = strlen(mebuffer); diff --git a/sys/scsi/scsi_base.c b/sys/scsi/scsi_base.c index 2b8eeacd8f099..b4147611536c7 100644 --- a/sys/scsi/scsi_base.c +++ b/sys/scsi/scsi_base.c @@ -8,7 +8,7 @@ * file. * * Written by Julian Elischer (julian@dialix.oz.au) - * $Id: scsi_base.c,v 1.39.4.1 1997/01/12 22:09:53 joerg Exp $ + * $Id: scsi_base.c,v 1.39.4.2 1997/01/30 22:49:29 joerg Exp $ */ #include "opt_bounce.h" @@ -615,7 +615,9 @@ retry: * check if anyone else needs to be started up. */ bad: + s = splbio(); free_xs(xs, sc_link, flags); /* includes the 'start' op */ + splx(s); if (bp && retval) { bp->b_error = retval; bp->b_flags |= B_ERROR; diff --git a/sys/vm/vm_extern.h b/sys/vm/vm_extern.h index 5a706917de747..3d5a335278528 100644 --- a/sys/vm/vm_extern.h +++ b/sys/vm/vm_extern.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)vm_extern.h 8.2 (Berkeley) 1/12/94 - * $Id: vm_extern.h,v 1.26 1996/09/14 11:54:54 bde Exp $ + * $Id: vm_extern.h,v 1.27 1996/09/15 11:24:21 bde Exp $ */ #ifndef _VM_EXTERN_H_ @@ -80,6 +80,7 @@ int vm_fault __P((vm_map_t, vm_offset_t, vm_prot_t, boolean_t)); void vm_fault_copy_entry __P((vm_map_t, vm_map_t, vm_map_entry_t, vm_map_entry_t)); void vm_fault_unwire __P((vm_map_t, vm_offset_t, vm_offset_t)); int vm_fault_wire __P((vm_map_t, vm_offset_t, vm_offset_t)); +int vm_fault_user_wire __P((vm_map_t, vm_offset_t, vm_offset_t)); int vm_fork __P((struct proc *, struct proc *)); int vm_mmap __P((vm_map_t, vm_offset_t *, vm_size_t, vm_prot_t, vm_prot_t, int, caddr_t, vm_ooffset_t)); vm_offset_t vm_page_alloc_contig __P((vm_offset_t, vm_offset_t, vm_offset_t, vm_offset_t)); diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index e7fdd373e34bf..561b496b4ffcd 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -66,7 +66,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_fault.c,v 1.57 1996/09/08 20:44:37 dyson Exp $ + * $Id: vm_fault.c,v 1.57.2.1 1996/12/15 09:57:11 davidg Exp $ */ /* @@ -197,11 +197,37 @@ RetryFault:; return (result); } - if (entry->nofault) { + if (entry->eflags & MAP_ENTRY_NOFAULT) { panic("vm_fault: fault on nofault entry, addr: %lx", vaddr); } + /* + * If we are user-wiring a r/w segment, and it is COW, then + * we need to do the COW operation. Note that we don't COW + * currently RO sections now, because it is NOT desirable + * to COW .text. We simply keep .text from ever being COW'ed + * and take the heat that one cannot debug wired .text sections. + */ + if ((change_wiring == VM_FAULT_USER_WIRE) && (entry->eflags & MAP_ENTRY_NEEDS_COPY)) { + if(entry->protection & VM_PROT_WRITE) { + int tresult; + vm_map_lookup_done(map, entry); + + tresult = vm_map_lookup(&map, vaddr, VM_PROT_READ|VM_PROT_WRITE, + &entry, &first_object, &first_pindex, &prot, &wired, &su); + if (tresult != KERN_SUCCESS) + return tresult; + } else { + /* + * If we don't COW now, on a user wire, the user will never + * be able to write to the mapping. If we don't make this + * restriction, the bookkeeping would be nearly impossible. + */ + entry->max_protection &= ~VM_PROT_WRITE; + } + } + vp = vnode_pager_lock(first_object); lookup_still_valid = TRUE; @@ -839,7 +865,48 @@ vm_fault_wire(map, start, end) */ for (va = start; va < end; va += PAGE_SIZE) { - rv = vm_fault(map, va, VM_PROT_READ|VM_PROT_WRITE, TRUE); + rv = vm_fault(map, va, VM_PROT_READ|VM_PROT_WRITE, + VM_FAULT_CHANGE_WIRING); + if (rv) { + if (va != start) + vm_fault_unwire(map, start, va); + return (rv); + } + } + return (KERN_SUCCESS); +} + +/* + * vm_fault_user_wire: + * + * Wire down a range of virtual addresses in a map. This + * is for user mode though, so we only ask for read access + * on currently read only sections. + */ +int +vm_fault_user_wire(map, start, end) + vm_map_t map; + vm_offset_t start, end; +{ + + register vm_offset_t va; + register pmap_t pmap; + int rv; + + pmap = vm_map_pmap(map); + + /* + * Inform the physical mapping system that the range of addresses may + * not fault, so that page tables and such can be locked down as well. + */ + pmap_pageable(pmap, start, end, FALSE); + + /* + * We simulate a fault to get the page and enter it in the physical + * map. + */ + for (va = start; va < end; va += PAGE_SIZE) { + rv = vm_fault(map, va, VM_PROT_READ, VM_FAULT_USER_WIRE); if (rv) { if (va != start) vm_fault_unwire(map, start, va); diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c index 22091d772737f..71bcb7c67c4b4 100644 --- a/sys/vm/vm_glue.c +++ b/sys/vm/vm_glue.c @@ -59,7 +59,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_glue.c,v 1.55.2.1 1996/12/22 23:21:25 joerg Exp $ + * $Id: vm_glue.c,v 1.55.2.2 1997/02/13 08:17:31 bde Exp $ */ #include "opt_rlimit.h" @@ -126,7 +126,9 @@ kernacc(addr, len, rw) saddr = trunc_page(addr); eaddr = round_page(addr + len); + vm_map_lock_read(kernel_map); rv = vm_map_check_protection(kernel_map, saddr, eaddr, prot); + vm_map_unlock_read(kernel_map); return (rv == TRUE); } @@ -137,6 +139,8 @@ useracc(addr, len, rw) { boolean_t rv; vm_prot_t prot = rw == B_READ ? VM_PROT_READ : VM_PROT_WRITE; + vm_map_t map; + vm_map_entry_t save_hint; /* * XXX - check separately to disallow access to user area and user @@ -151,8 +155,18 @@ useracc(addr, len, rw) || (vm_offset_t) addr + len < (vm_offset_t) addr) { return (FALSE); } - rv = vm_map_check_protection(&curproc->p_vmspace->vm_map, + map = &curproc->p_vmspace->vm_map; + vm_map_lock_read(map); + /* + * We save the map hint, and restore it. Useracc appears to distort + * the map hint unnecessarily. + */ + save_hint = map->hint; + rv = vm_map_check_protection(map, trunc_page(addr), round_page(addr + len), prot); + map->hint = save_hint; + vm_map_unlock_read(map); + return (rv == TRUE); } diff --git a/sys/vm/vm_kern.c b/sys/vm/vm_kern.c index 21939f6e4da97..c5096cb5c93c8 100644 --- a/sys/vm/vm_kern.c +++ b/sys/vm/vm_kern.c @@ -61,7 +61,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_kern.c,v 1.27 1996/07/02 02:08:02 dyson Exp $ + * $Id: vm_kern.c,v 1.27.2.1 1997/01/17 19:28:38 davidg Exp $ */ /* @@ -89,17 +89,17 @@ #include <vm/vm_kern.h> #include <vm/vm_extern.h> -vm_map_t buffer_map; -vm_map_t kernel_map; -vm_map_t kmem_map; -vm_map_t mb_map; -int mb_map_full; -vm_map_t io_map; -vm_map_t clean_map; -vm_map_t phys_map; -vm_map_t exec_map; -vm_map_t exech_map; -vm_map_t u_map; +vm_map_t kernel_map=0; +vm_map_t kmem_map=0; +vm_map_t exec_map=0; +vm_map_t exech_map=0; +vm_map_t clean_map=0; +vm_map_t u_map=0; +vm_map_t buffer_map=0; +vm_map_t mb_map=0; +int mb_map_full=0; +vm_map_t io_map=0; +vm_map_t phys_map=0; /* * kmem_alloc_pageable: @@ -199,11 +199,6 @@ kmem_alloc(map, size) (void) vm_map_pageable(map, (vm_offset_t) addr, addr + size, FALSE); - /* - * Try to coalesce the map - */ - vm_map_simplify(map, addr); - return (addr); } @@ -362,6 +357,8 @@ retry: panic("kmem_malloc: entry not found or misaligned"); entry->wired_count++; + vm_map_simplify_entry(map, entry); + /* * Loop thru pages, entering them in the pmap. (We cannot add them to * the wired count without wrapping the vm_page_queue_lock in @@ -377,7 +374,6 @@ retry: } vm_map_unlock(map); - vm_map_simplify(map, addr); return (addr); } diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index b66b770110fd9..2ec6926b5baf8 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -61,7 +61,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_map.c,v 1.57.2.2 1997/01/26 03:14:59 dyson Exp $ + * $Id: vm_map.c,v 1.57.2.3 1997/01/31 04:17:20 dyson Exp $ */ /* @@ -153,6 +153,7 @@ vm_size_t kentry_data_size; static vm_map_entry_t kentry_free; static vm_map_t kmap_free; extern char kstack[]; +extern int inmprotect; static int kentry_count; static vm_offset_t mapvm_start, mapvm, mapvmmax; @@ -170,7 +171,6 @@ static void vm_map_entry_dispose __P((vm_map_t, vm_map_entry_t)); static void vm_map_entry_unwire __P((vm_map_t, vm_map_entry_t)); static void vm_map_copy_entry __P((vm_map_t, vm_map_t, vm_map_entry_t, vm_map_entry_t)); -static void vm_map_simplify_entry __P((vm_map_t, vm_map_entry_t)); void vm_map_startup() @@ -606,6 +606,7 @@ vm_map_insert(map, object, offset, start, end, prot, max, cow) register vm_map_entry_t prev_entry; vm_map_entry_t temp_entry; vm_object_t prev_object; + u_char protoeflags; if ((object != NULL) && (cow & MAP_NOFAULT)) { panic("vm_map_insert: paradoxical MAP_NOFAULT request"); @@ -637,48 +638,61 @@ vm_map_insert(map, object, offset, start, end, prot, max, cow) (prev_entry->next->start < end)) return (KERN_NO_SPACE); - if ((prev_entry != &map->header) && - (prev_entry->end == start) && - (object == NULL) && - (prev_entry->is_a_map == FALSE) && - (prev_entry->is_sub_map == FALSE) && - (prev_entry->inheritance == VM_INHERIT_DEFAULT) && - (prev_entry->protection == prot) && - (prev_entry->max_protection == max) && - (prev_entry->wired_count == 0)) { + protoeflags = 0; + if (cow & MAP_COPY_NEEDED) + protoeflags |= MAP_ENTRY_NEEDS_COPY; + + if (cow & MAP_COPY_ON_WRITE) + protoeflags |= MAP_ENTRY_COW; + + if (cow & MAP_NOFAULT) + protoeflags |= MAP_ENTRY_NOFAULT; - /* * See if we can avoid creating a new entry by extending one of our - * neighbors. + * neighbors. Or at least extend the object. */ - u_char needs_copy = (cow & MAP_COPY_NEEDED) != 0; - u_char copy_on_write = (cow & MAP_COPY_ON_WRITE) != 0; - u_char nofault = (cow & MAP_NOFAULT) != 0; - - if ((needs_copy == prev_entry->needs_copy) && - (copy_on_write == prev_entry->copy_on_write) && - (nofault == prev_entry->nofault) && - (nofault || vm_object_coalesce(prev_entry->object.vm_object, - OFF_TO_IDX(prev_entry->offset), - (vm_size_t) (prev_entry->end - - prev_entry->start), - (vm_size_t) (end - prev_entry->end)))) { - /* - * Coalesced the two objects - can extend the - * previous map entry to include the new - * range. - */ + if ((object == NULL) && + (prev_entry != &map->header) && + (( prev_entry->eflags & (MAP_ENTRY_IS_A_MAP | MAP_ENTRY_IS_SUB_MAP)) == 0) && + (prev_entry->end == start) && + (prev_entry->wired_count == 0)) { + + + if ((protoeflags == prev_entry->eflags) && + ((cow & MAP_NOFAULT) || + vm_object_coalesce(prev_entry->object.vm_object, + OFF_TO_IDX(prev_entry->offset), + (vm_size_t) (prev_entry->end - prev_entry->start), + (vm_size_t) (end - prev_entry->end)))) { + + /* + * Coalesced the two objects. Can we extend the + * previous map entry to include the new range? + */ + if ((prev_entry->inheritance == VM_INHERIT_DEFAULT) && + (prev_entry->protection == prot) && + (prev_entry->max_protection == max)) { + map->size += (end - prev_entry->end); prev_entry->end = end; - if (!nofault) { + if ((cow & MAP_NOFAULT) == 0) { prev_object = prev_entry->object.vm_object; default_pager_convert_to_swapq(prev_object); } return (KERN_SUCCESS); } + else { + object = prev_entry->object.vm_object; + offset = prev_entry->offset + (prev_entry->end - + prev_entry->start); + + vm_object_reference(object); + } + } } + /* * Create a new entry */ @@ -687,26 +701,10 @@ vm_map_insert(map, object, offset, start, end, prot, max, cow) new_entry->start = start; new_entry->end = end; - new_entry->is_a_map = FALSE; - new_entry->is_sub_map = FALSE; + new_entry->eflags = protoeflags; new_entry->object.vm_object = object; new_entry->offset = offset; - if (cow & MAP_COPY_NEEDED) - new_entry->needs_copy = TRUE; - else - new_entry->needs_copy = FALSE; - - if (cow & MAP_COPY_ON_WRITE) - new_entry->copy_on_write = TRUE; - else - new_entry->copy_on_write = FALSE; - - if (cow & MAP_NOFAULT) - new_entry->nofault = TRUE; - else - new_entry->nofault = FALSE; - if (map->is_main_map) { new_entry->inheritance = VM_INHERIT_DEFAULT; new_entry->protection = prot; @@ -838,28 +836,19 @@ vm_map_find(map, object, offset, addr, length, find_space, prot, max, cow) } /* - * vm_map_simplify_entry: [ internal use only ] + * vm_map_simplify_entry: * - * Simplify the given map entry by: - * removing extra sharing maps - * [XXX maybe later] merging with a neighbor + * Simplify the given map entry by merging with either neighbor. */ -static void +void vm_map_simplify_entry(map, entry) vm_map_t map; vm_map_entry_t entry; { vm_map_entry_t next, prev; - vm_size_t nextsize, prevsize, esize; - - /* - * If this entry corresponds to a sharing map, then see if we can - * remove the level of indirection. If it's not a sharing map, then it - * points to a VM object, so see if we can merge with either of our - * neighbors. - */ + vm_size_t prevsize, esize; - if (entry->is_sub_map || entry->is_a_map || entry->wired_count) + if (entry->eflags & (MAP_ENTRY_IS_SUB_MAP|MAP_ENTRY_IS_A_MAP)) return; prev = entry->prev; @@ -870,14 +859,11 @@ vm_map_simplify_entry(map, entry) (!prev->object.vm_object || (prev->object.vm_object->behavior == entry->object.vm_object->behavior)) && (!prev->object.vm_object || (prev->offset + prevsize == entry->offset)) && - (prev->needs_copy == entry->needs_copy) && - (prev->copy_on_write == entry->copy_on_write) && + (prev->eflags == entry->eflags) && (prev->protection == entry->protection) && (prev->max_protection == entry->max_protection) && (prev->inheritance == entry->inheritance) && - (prev->is_a_map == FALSE) && - (prev->is_sub_map == FALSE) && - (prev->wired_count == 0)) { + (prev->wired_count == entry->wired_count)) { if (map->first_free == prev) map->first_free = entry; if (map->hint == prev) @@ -893,21 +879,17 @@ vm_map_simplify_entry(map, entry) next = entry->next; if (next != &map->header) { - nextsize = next->end - next->start; esize = entry->end - entry->start; if ((entry->end == next->start) && (next->object.vm_object == entry->object.vm_object) && (!next->object.vm_object || (next->object.vm_object->behavior == entry->object.vm_object->behavior)) && (!entry->object.vm_object || (entry->offset + esize == next->offset)) && - (next->needs_copy == entry->needs_copy) && - (next->copy_on_write == entry->copy_on_write) && + (next->eflags == entry->eflags) && (next->protection == entry->protection) && (next->max_protection == entry->max_protection) && (next->inheritance == entry->inheritance) && - (next->is_a_map == FALSE) && - (next->is_sub_map == FALSE) && - (next->wired_count == 0)) { + (next->wired_count == entry->wired_count)) { if (map->first_free == next) map->first_free = entry; if (map->hint == next) @@ -962,7 +944,7 @@ _vm_map_clip_start(map, entry, start) vm_map_entry_link(map, entry->prev, new_entry); - if (entry->is_a_map || entry->is_sub_map) + if (entry->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP)) vm_map_reference(new_entry->object.share_map); else vm_object_reference(new_entry->object.vm_object); @@ -1006,7 +988,7 @@ _vm_map_clip_end(map, entry, end) vm_map_entry_link(map, entry, new_entry); - if (entry->is_a_map || entry->is_sub_map) + if (entry->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP)) vm_map_reference(new_entry->object.share_map); else vm_object_reference(new_entry->object.vm_object); @@ -1068,11 +1050,9 @@ vm_map_submap(map, start, end, submap) vm_map_clip_end(map, entry, end); if ((entry->start == start) && (entry->end == end) && - (!entry->is_a_map) && - (entry->object.vm_object == NULL) && - (!entry->copy_on_write)) { - entry->is_a_map = FALSE; - entry->is_sub_map = TRUE; + ((entry->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_COW)) == 0) && + (entry->object.vm_object == NULL)) { + entry->eflags |= MAP_ENTRY_IS_SUB_MAP; vm_map_reference(entry->object.sub_map = submap); result = KERN_SUCCESS; } @@ -1106,8 +1086,9 @@ vm_map_protect(map, start, end, new_prot, set_max) if (vm_map_lookup_entry(map, start, &entry)) { vm_map_clip_start(map, entry, start); - } else + } else { entry = entry->next; + } /* * Make a first pass to check for protection violations. @@ -1115,7 +1096,7 @@ vm_map_protect(map, start, end, new_prot, set_max) current = entry; while ((current != &map->header) && (current->start < end)) { - if (current->is_sub_map) { + if (current->eflags & MAP_ENTRY_IS_SUB_MAP) { vm_map_unlock(map); return (KERN_INVALID_ARGUMENT); } @@ -1152,11 +1133,11 @@ vm_map_protect(map, start, end, new_prot, set_max) */ if (current->protection != old_prot) { -#define MASK(entry) ((entry)->copy_on_write ? ~VM_PROT_WRITE : \ +#define MASK(entry) (((entry)->eflags & MAP_ENTRY_COW) ? ~VM_PROT_WRITE : \ VM_PROT_ALL) #define max(a,b) ((a) > (b) ? (a) : (b)) - if (current->is_a_map) { + if (current->eflags & MAP_ENTRY_IS_A_MAP) { vm_map_entry_t share_entry; vm_offset_t share_end; @@ -1229,9 +1210,22 @@ vm_map_madvise(map, pmap, start, end, advise) for(current = entry; (current != &map->header) && (current->start < end); current = current->next) { - if (current->is_a_map || current->is_sub_map) { + vm_size_t size = current->end - current->start; + + if (current->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP)) { continue; } + + /* + * Create an object if needed + */ + if (current->object.vm_object == NULL) { + vm_object_t object; + object = vm_object_allocate(OBJT_DEFAULT, OFF_TO_IDX(size)); + current->object.vm_object = object; + current->offset = 0; + } + vm_map_clip_end(map, current, end); switch (advise) { case MADV_NORMAL: @@ -1252,7 +1246,7 @@ vm_map_madvise(map, pmap, start, end, advise) { vm_pindex_t pindex; int count; - vm_size_t size = current->end - current->start; + size = current->end - current->start; pindex = OFF_TO_IDX(entry->offset); count = OFF_TO_IDX(size); /* @@ -1268,7 +1262,7 @@ vm_map_madvise(map, pmap, start, end, advise) { vm_pindex_t pindex; int count; - vm_size_t size = current->end - current->start; + size = current->end - current->start; pindex = OFF_TO_IDX(current->offset); count = OFF_TO_IDX(size); vm_object_madvise(current->object.vm_object, @@ -1341,6 +1335,137 @@ vm_map_inherit(map, start, end, new_inheritance) } /* + * Implement the semantics of mlock + */ +int +vm_map_user_pageable(map, start, end, new_pageable) + register vm_map_t map; + register vm_offset_t start; + register vm_offset_t end; + register boolean_t new_pageable; +{ + register vm_map_entry_t entry; + vm_map_entry_t start_entry; + register vm_offset_t failed = 0; + int rv; + + vm_map_lock(map); + VM_MAP_RANGE_CHECK(map, start, end); + + if (vm_map_lookup_entry(map, start, &start_entry) == FALSE) { + vm_map_unlock(map); + return (KERN_INVALID_ADDRESS); + } + + if (new_pageable) { + + entry = start_entry; + vm_map_clip_start(map, entry, start); + + /* + * Now decrement the wiring count for each region. If a region + * becomes completely unwired, unwire its physical pages and + * mappings. + */ + lock_set_recursive(&map->lock); + + entry = start_entry; + while ((entry != &map->header) && (entry->start < end)) { + if (entry->eflags & MAP_ENTRY_USER_WIRED) { + vm_map_clip_end(map, entry, end); + entry->eflags &= ~MAP_ENTRY_USER_WIRED; + entry->wired_count--; + if (entry->wired_count == 0) + vm_fault_unwire(map, entry->start, entry->end); + } + entry = entry->next; + } + vm_map_simplify_entry(map, start_entry); + lock_clear_recursive(&map->lock); + } else { + + /* + * Because of the possiblity of blocking, etc. We restart + * through the process's map entries from beginning so that + * we don't end up depending on a map entry that could have + * changed. + */ + rescan: + + entry = start_entry; + + while ((entry != &map->header) && (entry->start < end)) { + + if (entry->eflags & MAP_ENTRY_USER_WIRED) { + entry = entry->next; + continue; + } + + if (entry->wired_count != 0) { + entry->wired_count++; + entry->eflags |= MAP_ENTRY_USER_WIRED; + entry = entry->next; + continue; + } + + /* Here on entry being newly wired */ + + if ((entry->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP)) == 0) { + int copyflag = entry->eflags & MAP_ENTRY_NEEDS_COPY; + if (copyflag && ((entry->protection & VM_PROT_WRITE) != 0)) { + + vm_object_shadow(&entry->object.vm_object, + &entry->offset, + OFF_TO_IDX(entry->end + - entry->start)); + entry->eflags &= ~MAP_ENTRY_NEEDS_COPY; + + } else if (entry->object.vm_object == NULL) { + + entry->object.vm_object = + vm_object_allocate(OBJT_DEFAULT, + OFF_TO_IDX(entry->end - entry->start)); + entry->offset = (vm_offset_t) 0; + + } + default_pager_convert_to_swapq(entry->object.vm_object); + } + + vm_map_clip_start(map, entry, start); + vm_map_clip_end(map, entry, end); + + entry->wired_count++; + entry->eflags |= MAP_ENTRY_USER_WIRED; + + /* First we need to allow map modifications */ + lock_set_recursive(&map->lock); + lock_write_to_read(&map->lock); + + rv = vm_fault_user_wire(map, entry->start, entry->end); + if (rv) { + + entry->wired_count--; + entry->eflags &= ~MAP_ENTRY_USER_WIRED; + + lock_clear_recursive(&map->lock); + vm_map_unlock(map); + + (void) vm_map_user_pageable(map, start, entry->start, TRUE); + return rv; + } + + lock_clear_recursive(&map->lock); + vm_map_unlock(map); + vm_map_lock(map); + + goto rescan; + } + } + vm_map_unlock(map); + return KERN_SUCCESS; +} + +/* * vm_map_pageable: * * Sets the pageability of the specified address @@ -1467,8 +1592,8 @@ vm_map_pageable(map, start, end, new_pageable) * point to sharing maps, because we won't * hold the lock on the sharing map. */ - if (!entry->is_a_map && !entry->is_sub_map) { - int copyflag = entry->needs_copy; + if ((entry->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP)) == 0) { + int copyflag = entry->eflags & MAP_ENTRY_NEEDS_COPY; if (copyflag && ((entry->protection & VM_PROT_WRITE) != 0)) { @@ -1476,7 +1601,7 @@ vm_map_pageable(map, start, end, new_pageable) &entry->offset, OFF_TO_IDX(entry->end - entry->start)); - entry->needs_copy = FALSE; + entry->eflags &= ~MAP_ENTRY_NEEDS_COPY; } else if (entry->object.vm_object == NULL) { entry->object.vm_object = vm_object_allocate(OBJT_DEFAULT, @@ -1568,6 +1693,7 @@ vm_map_pageable(map, start, end, new_pageable) (void) vm_map_pageable(map, start, failed, TRUE); return (rv); } + vm_map_simplify_entry(map, start_entry); } vm_map_unlock(map); @@ -1608,7 +1734,7 @@ vm_map_clean(map, start, end, syncio, invalidate) * Make a first pass to check for holes. */ for (current = entry; current->start < end; current = current->next) { - if (current->is_sub_map) { + if (current->eflags & MAP_ENTRY_IS_SUB_MAP) { vm_map_unlock_read(map); return (KERN_INVALID_ARGUMENT); } @@ -1627,7 +1753,7 @@ vm_map_clean(map, start, end, syncio, invalidate) for (current = entry; current->start < end; current = current->next) { offset = current->offset + (start - current->start); size = (end <= current->end ? end : current->end) - start; - if (current->is_a_map || current->is_sub_map) { + if (current->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP)) { register vm_map_t smap; vm_map_entry_t tentry; vm_size_t tsize; @@ -1718,7 +1844,7 @@ vm_map_entry_delete(map, entry) vm_map_entry_unlink(map, entry); map->size -= entry->end - entry->start; - if (entry->is_a_map || entry->is_sub_map) { + if (entry->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP)) { vm_map_deallocate(entry->object.share_map); } else { vm_object_deallocate(entry->object.vm_object); @@ -1915,7 +2041,8 @@ vm_map_copy_entry(src_map, dst_map, src_entry, dst_entry) vm_map_t src_map, dst_map; register vm_map_entry_t src_entry, dst_entry; { - if (src_entry->is_sub_map || dst_entry->is_sub_map) + if ((dst_entry->eflags|src_entry->eflags) & + (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP)) return; if (src_entry->wired_count == 0) { @@ -1924,7 +2051,7 @@ vm_map_copy_entry(src_map, dst_map, src_entry, dst_entry) * If the source entry is marked needs_copy, it is already * write-protected. */ - if (!src_entry->needs_copy) { + if ((src_entry->eflags & MAP_ENTRY_NEEDS_COPY) == 0) { boolean_t su; @@ -1957,11 +2084,8 @@ vm_map_copy_entry(src_map, dst_map, src_entry, dst_entry) src_entry->object.vm_object->type == OBJT_SWAP)) vm_object_collapse(src_entry->object.vm_object); ++src_entry->object.vm_object->ref_count; - src_entry->copy_on_write = TRUE; - src_entry->needs_copy = TRUE; - - dst_entry->needs_copy = TRUE; - dst_entry->copy_on_write = TRUE; + src_entry->eflags |= (MAP_ENTRY_COW|MAP_ENTRY_NEEDS_COPY); + dst_entry->eflags |= (MAP_ENTRY_COW|MAP_ENTRY_NEEDS_COPY); dst_entry->object.vm_object = src_entry->object.vm_object; dst_entry->offset = src_entry->offset; @@ -2015,14 +2139,14 @@ vmspace_fork(vm1) old_entry = old_map->header.next; while (old_entry != &old_map->header) { - if (old_entry->is_sub_map) + if (old_entry->eflags & MAP_ENTRY_IS_SUB_MAP) panic("vm_map_fork: encountered a submap"); switch (old_entry->inheritance) { case VM_INHERIT_NONE: break; - case VM_INHERIT_SHARE: + case VM_INHERIT_SHARE: /* * Clone the entry, creating the shared object if necessary. */ @@ -2033,13 +2157,13 @@ vmspace_fork(vm1) old_entry->start)); old_entry->object.vm_object = object; old_entry->offset = (vm_offset_t) 0; - } else if (old_entry->needs_copy) { + } else if (old_entry->eflags & MAP_ENTRY_NEEDS_COPY) { vm_object_shadow(&old_entry->object.vm_object, &old_entry->offset, OFF_TO_IDX(old_entry->end - - old_entry->start)); + old_entry->start)); - old_entry->needs_copy = 0; + old_entry->eflags &= ~MAP_ENTRY_NEEDS_COPY; object = old_entry->object.vm_object; } @@ -2077,7 +2201,7 @@ vmspace_fork(vm1) *new_entry = *old_entry; new_entry->wired_count = 0; new_entry->object.vm_object = NULL; - new_entry->is_a_map = FALSE; + new_entry->eflags &= ~MAP_ENTRY_IS_A_MAP; vm_map_entry_link(new_map, new_map->header.prev, new_entry); vm_map_copy_entry(old_map, new_map, old_entry, @@ -2173,11 +2297,12 @@ RetryLookup:; entry = tmp_entry; *out_entry = entry; } + /* * Handle submaps. */ - if (entry->is_sub_map) { + if (entry->eflags & MAP_ENTRY_IS_SUB_MAP) { vm_map_t old_map = map; *var_map = map = entry->object.sub_map; @@ -2205,7 +2330,7 @@ RetryLookup:; * If we don't already have a VM object, track it down. */ - su = !entry->is_a_map; + su = (entry->eflags & MAP_ENTRY_IS_A_MAP) == 0; if (su) { share_map = map; share_offset = vaddr; @@ -2237,7 +2362,7 @@ RetryLookup:; * If the entry was copy-on-write, we either ... */ - if (entry->needs_copy) { + if (entry->eflags & MAP_ENTRY_NEEDS_COPY) { /* * If we want to write the page, we may as well handle that * now since we've got the sharing map locked. @@ -2264,7 +2389,7 @@ RetryLookup:; &entry->offset, OFF_TO_IDX(entry->end - entry->start)); - entry->needs_copy = FALSE; + entry->eflags &= ~MAP_ENTRY_NEEDS_COPY; lock_write_to_read(&share_map->lock); } else { @@ -2333,7 +2458,7 @@ vm_map_lookup_done(map, entry) * If this entry references a map, unlock it first. */ - if (entry->is_a_map) + if (entry->eflags & MAP_ENTRY_IS_A_MAP) vm_map_unlock_read(entry->object.share_map); /* @@ -2343,62 +2468,6 @@ vm_map_lookup_done(map, entry) vm_map_unlock_read(map); } -/* - * Routine: vm_map_simplify - * Purpose: - * Attempt to simplify the map representation in - * the vicinity of the given starting address. - * Note: - * This routine is intended primarily to keep the - * kernel maps more compact -- they generally don't - * benefit from the "expand a map entry" technology - * at allocation time because the adjacent entry - * is often wired down. - */ -void -vm_map_simplify(map, start) - vm_map_t map; - vm_offset_t start; -{ - vm_map_entry_t this_entry; - vm_map_entry_t prev_entry; - - vm_map_lock(map); - if ((vm_map_lookup_entry(map, start, &this_entry)) && - ((prev_entry = this_entry->prev) != &map->header) && - (prev_entry->end == start) && - (prev_entry->object.vm_object == this_entry->object.vm_object) && - ((prev_entry->offset + (prev_entry->end - prev_entry->start)) - == this_entry->offset) && - - (map->is_main_map) && - - (prev_entry->is_a_map == FALSE) && - (prev_entry->is_sub_map == FALSE) && - - (this_entry->is_a_map == FALSE) && - (this_entry->is_sub_map == FALSE) && - - (prev_entry->inheritance == this_entry->inheritance) && - (prev_entry->protection == this_entry->protection) && - (prev_entry->max_protection == this_entry->max_protection) && - (prev_entry->wired_count == this_entry->wired_count) && - - (prev_entry->copy_on_write == this_entry->copy_on_write) && - (prev_entry->needs_copy == this_entry->needs_copy)) { - if (map->first_free == this_entry) - map->first_free = prev_entry; - if (map->hint == this_entry) - SAVE_HINT(map, prev_entry); - vm_map_entry_unlink(map, this_entry); - prev_entry->end = this_entry->end; - if (this_entry->object.vm_object) - vm_object_deallocate(this_entry->object.vm_object); - vm_map_entry_dispose(map, this_entry); - } - vm_map_unlock(map); -} - #include "opt_ddb.h" #ifdef DDB #include <sys/kernel.h> @@ -2440,12 +2509,12 @@ DB_SHOW_COMMAND(map, vm_map_print) if (entry->wired_count != 0) db_printf("wired, "); } - if (entry->is_a_map || entry->is_sub_map) { + if (entry->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP)) { db_printf("share=0x%x, offset=0x%x\n", (int) entry->object.share_map, (int) entry->offset); if ((entry->prev == &map->header) || - (!entry->prev->is_a_map) || + ((entry->prev->eflags & MAP_ENTRY_IS_A_MAP) == 0) || (entry->prev->object.share_map != entry->object.share_map)) { db_indent += 2; @@ -2457,13 +2526,13 @@ DB_SHOW_COMMAND(map, vm_map_print) db_printf("object=0x%x, offset=0x%x", (int) entry->object.vm_object, (int) entry->offset); - if (entry->copy_on_write) + if (entry->eflags & MAP_ENTRY_COW) db_printf(", copy (%s)", - entry->needs_copy ? "needed" : "done"); + (entry->eflags & MAP_ENTRY_NEEDS_COPY) ? "needed" : "done"); db_printf("\n"); if ((entry->prev == &map->header) || - (entry->prev->is_a_map) || + (entry->prev->eflags & MAP_ENTRY_IS_A_MAP) || (entry->prev->object.vm_object != entry->object.vm_object)) { db_indent += 2; diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h index e0fde407aa8c4..5c745e7c4459a 100644 --- a/sys/vm/vm_map.h +++ b/sys/vm/vm_map.h @@ -61,7 +61,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_map.h,v 1.15 1996/07/30 03:08:11 dyson Exp $ + * $Id: vm_map.h,v 1.15.2.1 1996/12/15 09:57:14 davidg Exp $ */ /* @@ -104,11 +104,7 @@ struct vm_map_entry { vm_offset_t end; /* end address */ union vm_map_object object; /* object I point to */ vm_ooffset_t offset; /* offset into object */ - u_char is_a_map:1, /* Is "object" a map? */ - is_sub_map:1, /* Is "object" a submap? */ - copy_on_write:1, /* is data copy-on-write */ - needs_copy:1, /* does object need to be copied */ - nofault:1; /* should never fault */ + u_char eflags; /* map entry flags */ /* Only in task maps: */ vm_prot_t protection; /* protection code */ vm_prot_t max_protection; /* maximum protection */ @@ -116,6 +112,13 @@ struct vm_map_entry { int wired_count; /* can be paged if = 0 */ }; +#define MAP_ENTRY_IS_A_MAP 0x1 +#define MAP_ENTRY_IS_SUB_MAP 0x2 +#define MAP_ENTRY_COW 0x4 +#define MAP_ENTRY_NEEDS_COPY 0x8 +#define MAP_ENTRY_NOFAULT 0x10 +#define MAP_ENTRY_USER_WIRED 0x20 + /* * Maps are doubly-linked lists of map entries, kept sorted * by address. A single hint is provided to start @@ -210,6 +213,13 @@ typedef struct { #define MAP_COPY_ON_WRITE 0x2 #define MAP_NOFAULT 0x4 +/* + * vm_fault option flags + */ +#define VM_FAULT_NORMAL 0 +#define VM_FAULT_CHANGE_WIRING 1 +#define VM_FAULT_USER_WIRE 2 + #ifdef KERNEL extern vm_offset_t kentry_data; extern vm_size_t kentry_data_size; @@ -230,6 +240,7 @@ int vm_map_lookup __P((vm_map_t *, vm_offset_t, vm_prot_t, vm_map_entry_t *, vm_ void vm_map_lookup_done __P((vm_map_t, vm_map_entry_t)); boolean_t vm_map_lookup_entry __P((vm_map_t, vm_offset_t, vm_map_entry_t *)); int vm_map_pageable __P((vm_map_t, vm_offset_t, vm_offset_t, boolean_t)); +int vm_map_user_pageable __P((vm_map_t, vm_offset_t, vm_offset_t, boolean_t)); int vm_map_clean __P((vm_map_t, vm_offset_t, vm_offset_t, boolean_t, boolean_t)); int vm_map_protect __P((vm_map_t, vm_offset_t, vm_offset_t, vm_prot_t, boolean_t)); void vm_map_reference __P((vm_map_t)); @@ -238,6 +249,7 @@ void vm_map_simplify __P((vm_map_t, vm_offset_t)); void vm_map_startup __P((void)); int vm_map_submap __P((vm_map_t, vm_offset_t, vm_offset_t, vm_map_t)); void vm_map_madvise __P((vm_map_t, pmap_t, vm_offset_t, vm_offset_t, int)); +void vm_map_simplify_entry __P((vm_map_t, vm_map_entry_t)); #endif #endif /* _VM_MAP_ */ diff --git a/sys/vm/vm_meter.c b/sys/vm/vm_meter.c index faed27f801346..54d66789c4180 100644 --- a/sys/vm/vm_meter.c +++ b/sys/vm/vm_meter.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)vm_meter.c 8.4 (Berkeley) 1/4/94 - * $Id: vm_meter.c,v 1.15 1996/05/18 03:37:47 dyson Exp $ + * $Id: vm_meter.c,v 1.16 1996/09/08 20:44:39 dyson Exp $ */ #include <sys/param.h> @@ -179,7 +179,7 @@ vmtotal SYSCTL_HANDLER_ARGS paging = 0; for (map = &p->p_vmspace->vm_map, entry = map->header.next; entry != &map->header; entry = entry->next) { - if (entry->is_a_map || entry->is_sub_map || + if ((entry->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP)) || entry->object.vm_object == NULL) continue; entry->object.vm_object->flags |= OBJ_ACTIVE; diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index 16a0dfbbce1b0..6d2b9a6a65a50 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -38,7 +38,7 @@ * from: Utah $Hdr: vm_mmap.c 1.6 91/10/21$ * * @(#)vm_mmap.c 8.4 (Berkeley) 1/12/94 - * $Id: vm_mmap.c,v 1.53 1996/10/29 22:07:11 dyson Exp $ + * $Id: vm_mmap.c,v 1.53.2.1 1996/12/22 23:21:26 joerg Exp $ */ /* @@ -475,6 +475,10 @@ mprotect(p, uap, retval) addr = (vm_offset_t) uap->addr; size = uap->len; prot = uap->prot & VM_PROT_ALL; +#if defined(VM_PROT_READ_IS_EXEC) + if (prot & VM_PROT_READ) + prot |= VM_PROT_EXECUTE; +#endif pageoff = (addr & PAGE_MASK); addr -= pageoff; @@ -648,7 +652,7 @@ mincore(p, uap, retval) /* * ignore submaps (for now) or null objects */ - if (current->is_a_map || current->is_sub_map || + if ((current->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP)) || current->object.vm_object == NULL) continue; @@ -787,7 +791,7 @@ mlock(p, uap, retval) return (error); #endif - error = vm_map_pageable(&p->p_vmspace->vm_map, addr, addr + size, FALSE); + error = vm_map_user_pageable(&p->p_vmspace->vm_map, addr, addr + size, FALSE); return (error == KERN_SUCCESS ? 0 : ENOMEM); } @@ -825,7 +829,7 @@ munlock(p, uap, retval) return (error); #endif - error = vm_map_pageable(&p->p_vmspace->vm_map, addr, addr + size, TRUE); + error = vm_map_user_pageable(&p->p_vmspace->vm_map, addr, addr + size, TRUE); return (error == KERN_SUCCESS ? 0 : ENOMEM); } @@ -905,9 +909,14 @@ vm_mmap(map, addr, size, prot, maxprot, flags, handle, foff) type = OBJT_VNODE; } } - object = vm_pager_allocate(type, handle, OFF_TO_IDX(objsize), prot, foff); - if (object == NULL) - return (type == OBJT_DEVICE ? EINVAL : ENOMEM); + + if (handle == NULL) { + object = NULL; + } else { + object = vm_pager_allocate(type, handle, OFF_TO_IDX(objsize), prot, foff); + if (object == NULL) + return (type == OBJT_DEVICE ? EINVAL : ENOMEM); + } /* * Force device mappings to be shared. @@ -922,6 +931,14 @@ vm_mmap(map, addr, size, prot, maxprot, flags, handle, foff) docow = MAP_COPY_ON_WRITE | MAP_COPY_NEEDED; } +#if defined(VM_PROT_READ_IS_EXEC) + if (prot & VM_PROT_READ) + prot |= VM_PROT_EXECUTE; + + if (maxprot & VM_PROT_READ) + maxprot |= VM_PROT_EXECUTE; +#endif + rv = vm_map_find(map, object, foff, addr, size, fitit, prot, maxprot, docow); @@ -939,7 +956,7 @@ vm_mmap(map, addr, size, prot, maxprot, flags, handle, foff) /* * "Pre-fault" resident pages. */ - if ((type == OBJT_VNODE) && (map->pmap != NULL)) { + if ((type == OBJT_VNODE) && (map->pmap != NULL) && (object != NULL)) { pmap_object_init_pt(map->pmap, *addr, object, (vm_pindex_t) OFF_TO_IDX(foff), size, 1); } diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index 3c6ceeb437db7..133d0edcba11e 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -61,7 +61,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_object.c,v 1.81 1996/09/14 11:54:57 bde Exp $ + * $Id: vm_object.c,v 1.82 1996/09/28 03:33:26 dyson Exp $ */ /* @@ -681,6 +681,8 @@ vm_object_pmap_remove(object, start, end) if (p->pindex >= start && p->pindex < end) vm_page_protect(p, VM_PROT_NONE); } + if ((start == 0) && (object->size == end)) + object->flags &= ~OBJ_WRITEABLE; } /* @@ -695,7 +697,9 @@ vm_object_madvise(object, pindex, count, advise) int count; int advise; { - vm_pindex_t end; + int s; + vm_pindex_t end, tpindex; + vm_object_t tobject; vm_page_t m; if (object == NULL) @@ -704,34 +708,60 @@ vm_object_madvise(object, pindex, count, advise) end = pindex + count; for (; pindex < end; pindex += 1) { - m = vm_page_lookup(object, pindex); + +relookup: + tobject = object; + tpindex = pindex; +shadowlookup: + m = vm_page_lookup(tobject, tpindex); + if (m == NULL) { + if (tobject->type != OBJT_DEFAULT) { + continue; + } + + tobject = tobject->backing_object; + if ((tobject == NULL) || (tobject->ref_count != 1)) { + continue; + } + tpindex += OFF_TO_IDX(tobject->backing_object_offset); + goto shadowlookup; + } /* * If the page is busy or not in a normal active state, * we skip it. Things can break if we mess with pages * in any of the below states. */ - if (m == NULL || m->busy || (m->flags & PG_BUSY) || - m->hold_count || m->wire_count || - m->valid != VM_PAGE_BITS_ALL) + if (m->hold_count || m->wire_count || + m->valid != VM_PAGE_BITS_ALL) { continue; + } + + if (m->busy || (m->flags & PG_BUSY)) { + s = splvm(); + if (m->busy || (m->flags & PG_BUSY)) { + m->flags |= PG_WANTED; + tsleep(m, PVM, "madvpw", 0); + } + splx(s); + goto relookup; + } if (advise == MADV_WILLNEED) { if (m->queue != PQ_ACTIVE) vm_page_activate(m); - } else if ((advise == MADV_DONTNEED) || - ((advise == MADV_FREE) && - ((object->type != OBJT_DEFAULT) && - (object->type != OBJT_SWAP)))) { + } else if (advise == MADV_DONTNEED) { vm_page_deactivate(m); } else if (advise == MADV_FREE) { + pmap_clear_modify(VM_PAGE_TO_PHYS(m)); + m->dirty = 0; /* - * Force a demand-zero on next ref + * Force a demand zero if attempt to read from swap. + * We currently don't handle vnode files correctly, + * and will reread stale contents unnecessarily. */ if (object->type == OBJT_SWAP) - swap_pager_dmzspace(object, m->pindex, 1); - vm_page_protect(m, VM_PROT_NONE); - vm_page_free(m); + swap_pager_dmzspace(tobject, m->pindex, 1); } } } @@ -853,6 +883,7 @@ vm_object_qcollapse(object) swap_pager_freespace(backing_object, backing_object_paging_offset_index + p->pindex, 1); vm_page_rename(p, object, new_pindex); + vm_page_protect(p, VM_PROT_NONE); p->dirty = VM_PAGE_BITS_ALL; } } @@ -968,7 +999,9 @@ vm_object_collapse(object) PAGE_WAKEUP(p); vm_page_free(p); } else { + vm_page_protect(p, VM_PROT_NONE); vm_page_rename(p, object, new_pindex); + p->dirty = VM_PAGE_BITS_ALL; } } } @@ -1299,13 +1332,18 @@ vm_object_coalesce(prev_object, prev_pindex, prev_size, next_size) * pages not mapped to prev_entry may be in use anyway) */ - if (prev_object->ref_count > 1 || - prev_object->backing_object != NULL) { + if (prev_object->backing_object != NULL) { return (FALSE); } prev_size >>= PAGE_SHIFT; next_size >>= PAGE_SHIFT; + + if ((prev_object->ref_count > 1) && + (prev_object->size != prev_pindex + prev_size)) { + return (FALSE); + } + /* * Remove any pages that may still be in the object from a previous * deallocation. @@ -1360,7 +1398,7 @@ _vm_object_in_map(map, object, entry) } tmpe = tmpe->next; } - } else if (entry->is_sub_map || entry->is_a_map) { + } else if (entry->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP)) { tmpm = entry->object.share_map; tmpe = tmpm->header.next; entcount = tmpm->nentries; diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index d768359259bb4..0c4a001390cd0 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)vm_page.c 7.4 (Berkeley) 5/7/91 - * $Id: vm_page.c,v 1.69.2.1 1996/11/09 21:16:08 phk Exp $ + * $Id: vm_page.c,v 1.69.2.2 1996/11/12 09:10:16 phk Exp $ */ /* @@ -98,16 +98,16 @@ static struct pglist *vm_page_buckets; /* Array of buckets */ static int vm_page_bucket_count; /* How big is array? */ static int vm_page_hash_mask; /* Mask for hash function */ -struct pglist vm_page_queue_free[PQ_L2_SIZE]; -struct pglist vm_page_queue_zero[PQ_L2_SIZE]; -struct pglist vm_page_queue_active; -struct pglist vm_page_queue_inactive; -struct pglist vm_page_queue_cache[PQ_L2_SIZE]; +struct pglist vm_page_queue_free[PQ_L2_SIZE] = {0}; +struct pglist vm_page_queue_zero[PQ_L2_SIZE] = {0}; +struct pglist vm_page_queue_active = {0}; +struct pglist vm_page_queue_inactive = {0}; +struct pglist vm_page_queue_cache[PQ_L2_SIZE] = {0}; -int no_queue; +int no_queue=0; -struct vpgqueues vm_page_queues[PQ_COUNT]; -int pqcnt[PQ_COUNT]; +struct vpgqueues vm_page_queues[PQ_COUNT] = {0}; +int pqcnt[PQ_COUNT] = {0}; static void vm_page_queue_init(void) { @@ -142,13 +142,13 @@ vm_page_queue_init(void) { } } -vm_page_t vm_page_array; -int vm_page_array_size; -long first_page; +vm_page_t vm_page_array = 0; +int vm_page_array_size = 0; +long first_page = 0; static long last_page; static vm_size_t page_mask; static int page_shift; -int vm_page_zero_count; +int vm_page_zero_count = 0; /* * map of contiguous valid DEV_BSIZE chunks in a page @@ -734,7 +734,7 @@ vm_page_alloc(object, pindex, page_req) { register vm_page_t m; struct vpgqueues *pq; - int queue; + int queue, qtype; int s; #ifdef DIAGNOSTIC @@ -835,15 +835,16 @@ vm_page_alloc(object, pindex, page_req) } queue = m->queue; - if (queue == PQ_ZERO) + qtype = queue - m->pc; + if (qtype == PQ_ZERO) --vm_page_zero_count; pq = &vm_page_queues[queue]; TAILQ_REMOVE(pq->pl, m, pageq); --(*pq->cnt); --(*pq->lcnt); - if ((m->queue - m->pc) == PQ_ZERO) { + if (qtype == PQ_ZERO) { m->flags = PG_ZERO|PG_BUSY; - } else if ((m->queue - m->pc) == PQ_CACHE) { + } else if (qtype == PQ_CACHE) { vm_page_remove(m); m->flags = PG_BUSY; } else { @@ -874,6 +875,26 @@ vm_page_alloc(object, pindex, page_req) return (m); } +void +vm_wait() +{ + int s; + + s = splvm(); + if (curproc == pageproc) { + vm_pageout_pages_needed = 1; + tsleep(&vm_pageout_pages_needed, PSWP, "vmwait", 0); + } else { + if (!vm_pages_needed) { + vm_pages_needed++; + wakeup(&vm_pages_needed); + } + tsleep(&cnt.v_free_count, PVM, "vmwait", 0); + } + splx(s); +} + + /* * vm_page_activate: * diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c index c6888bf1c50b9..9a0b87f9680c5 100644 --- a/sys/vm/vm_pageout.c +++ b/sys/vm/vm_pageout.c @@ -65,7 +65,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_pageout.c,v 1.86 1996/09/28 03:33:40 dyson Exp $ + * $Id: vm_pageout.c,v 1.86.2.1 1997/02/13 08:17:32 bde Exp $ */ /* @@ -221,6 +221,7 @@ vm_pageout_clean(m, sync) if (!sync && object->backing_object) { vm_object_collapse(object); } + mc[vm_pageout_page_count] = m; pageout_count = 1; page_base = vm_pageout_page_count; @@ -517,7 +518,7 @@ vm_pageout_map_deactivate_pages(map, desired) */ tmpe = map->header.next; while (tmpe != &map->header) { - if ((tmpe->is_sub_map == 0) && (tmpe->is_a_map == 0)) { + if ((tmpe->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP)) == 0) { obj = tmpe->object.vm_object; if ((obj != NULL) && (obj->shadow_count <= 1) && ((bigobj == NULL) || @@ -539,7 +540,7 @@ vm_pageout_map_deactivate_pages(map, desired) while (tmpe != &map->header) { if (vm_map_pmap(map)->pm_stats.resident_count <= desired) break; - if ((tmpe->is_sub_map == 0) && (tmpe->is_a_map == 0)) { + if ((tmpe->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP)) == 0) { obj = tmpe->object.vm_object; if (obj) vm_pageout_object_deactivate_pages(map, obj, desired, 0); @@ -810,10 +811,12 @@ rescan0: if (vm_pageout_algorithm_lru || (m->object->ref_count == 0) || (m->act_count == 0)) { --page_shortage; - vm_page_protect(m, VM_PROT_NONE); - if ((m->dirty == 0) && - (m->object->ref_count == 0)) { - vm_page_cache(m); + if (m->object->ref_count == 0) { + vm_page_protect(m, VM_PROT_NONE); + if (m->dirty == 0) + vm_page_cache(m); + else + vm_page_deactivate(m); } else { vm_page_deactivate(m); } @@ -1013,6 +1016,15 @@ vm_pageout() } } +void +pagedaemon_wakeup() +{ + if (!vm_pages_needed && curproc != pageproc) { + vm_pages_needed++; + wakeup(&vm_pages_needed); + } +} + #if !defined(NO_SWAPPING) static void vm_req_vmdaemon() diff --git a/sys/vm/vm_pageout.h b/sys/vm/vm_pageout.h index f17720b778d11..469482910baa7 100644 --- a/sys/vm/vm_pageout.h +++ b/sys/vm/vm_pageout.h @@ -61,7 +61,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_pageout.h,v 1.16 1995/11/20 12:19:22 phk Exp $ + * $Id: vm_pageout.h,v 1.17 1995/11/21 12:55:26 bde Exp $ */ #ifndef _VM_VM_PAGEOUT_H_ @@ -91,38 +91,9 @@ extern int vm_pageout_pages_needed; * Signal pageout-daemon and wait for it. */ -static void pagedaemon_wakeup __P((void)); -static inline void -pagedaemon_wakeup() -{ - if (!vm_pages_needed && curproc != pageproc) { - vm_pages_needed++; - wakeup(&vm_pages_needed); - } -} - +extern void pagedaemon_wakeup __P((void)); #define VM_WAIT vm_wait() - -static void vm_wait __P((void)); -static inline void -vm_wait() -{ - int s; - - s = splhigh(); - if (curproc == pageproc) { - vm_pageout_pages_needed = 1; - tsleep(&vm_pageout_pages_needed, PSWP, "vmwait", 0); - } else { - if (!vm_pages_needed) { - vm_pages_needed++; - wakeup(&vm_pages_needed); - } - tsleep(&cnt.v_free_count, PVM, "vmwait", 0); - } - splx(s); -} - +extern void vm_wait __P((void)); #ifdef KERNEL void vm_pageout_page __P((vm_page_t, vm_object_t)); diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c index 7581086d71830..3badd6ee8e3b4 100644 --- a/sys/vm/vnode_pager.c +++ b/sys/vm/vnode_pager.c @@ -38,7 +38,7 @@ * SUCH DAMAGE. * * from: @(#)vnode_pager.c 7.5 (Berkeley) 4/20/91 - * $Id: vnode_pager.c,v 1.64 1996/09/10 05:28:23 dyson Exp $ + * $Id: vnode_pager.c,v 1.65 1996/10/17 02:49:35 dyson Exp $ */ /* @@ -148,6 +148,8 @@ vnode_pager_alloc(handle, size, prot, offset) else object->flags = 0; + if (vp->v_usecount == 0) + panic("vnode_pager_alloc: no vnode reference"); /* * Hold a reference to the vnode and initialize object data. */ |