Пример #1
0
sval
xh_kern_prog_ex(struct cpu_thread* thread, uval addr)
{
	uval32 ins;
	struct thread_control_area *tca = get_tca();

	sval ret = 0;
	uval srr1 = tca->srr1;

	if (! (srr1 & (1ULL << (63-45)))) goto abort;

	struct vm_class *vmc = find_kernel_vmc(thread, addr);
	if (!vmc) goto abort;

	union ptel pte;
	uval laddr = vmc_xlate(vmc, addr, &pte);
	if (laddr == INVALID_LOGICAL_ADDRESS) goto abort;

	uval pa = logical_to_physical_address(thread->cpu->os, laddr,
					      sizeof(uval32));
	if (pa == INVALID_PHYSICAL_ADDRESS) goto abort;

	ins = *(uval32*)pa;

	ret = decode_spr_ins(thread, addr, ins);
	if (ret == 0) return -1;
abort:
	return insert_exception(thread, EXC_V_DEBUG);
}
Пример #2
0
sval
xh_ext(struct cpu_thread *thread)
{
	struct thread_control_area *tca = get_tca();
	hprintf("Inserting external exception\n");

	thread->vstate.thread_mode &= ~VSTATE_PENDING_EXT;
	tca->vstate &= ~VSTATE_PENDING_EXT;
	return insert_exception(thread, EXC_V_EXT);

}
Пример #3
0
sval
insert_debug_exception(struct cpu_thread *thread, uval dbgflag)
{
	struct thread_control_area *tca = get_tca();
	if (thread->vregs->debug & V_DEBUG_FLAG) {

		thread->vregs->debug |= dbgflag;

		/* Increment to the next instruction */
		tca->srr0 += sizeof(uval32);

		return thread->vregs->active_vsave;
	}
	return insert_exception(thread, EXC_V_DEBUG);

}
Пример #4
0
sval
xh_kern_pgflt(struct cpu_thread* thr, uval type, struct vexc_save_regs *vr)
{
	struct vm_class *vmc = NULL;
	uval orig_addr;
	struct thread_control_area *tca = get_tca();

	if (type == 1) {
		orig_addr = mfdar();
	} else {
		orig_addr = tca->srr0;
	}


	if (thr->vstate.thread_mode & VSTATE_KERN_MODE) {
		vmc = find_kernel_vmc(thr, orig_addr);
	}

	if (!vmc) {
		vmc = find_app_vmc(thr, orig_addr);
	}

	if (!vmc) {
		hprintf("No vm_class for 0x%lx\n", orig_addr);
		breakpoint();

		return insert_debug_exception(thr, V_DEBUG_MEM_FAULT);
	}

	uval addr = ALIGN_DOWN(orig_addr, PGSIZE);
	union ptel pte = { .word = 0 };
	uval la = vmc_xlate(vmc, addr, &pte);
	uval ra;
	uval vsid;

	if (la == INVALID_LOGICAL_ADDRESS) {
		/* If logical address is invalid, and pte is non-zero, then
		 * pte contains physical address
		 */
		if (pte.word == 0) {
			goto reflect;
		}

		ra = pte.bits.rpn << LOG_PGSIZE;
	} else {
		ra = logical_to_physical_address(thr->cpu->os, la, PGSIZE);
	}

	vsid = vmc_class_vsid(thr, vmc, addr);

	pte.bits.rpn = ra >> LOG_PGSIZE;


	sval ret = insert_ea_map(thr, vsid, addr, pte);
	if (ret == H_Success) {

		return vr->reg_gprs[3];
	}

reflect:
	thr->vregs->v_dar = orig_addr;
	thr->vregs->v_dsisr = mfdsisr();


	assert(thr->vregs->exception_vectors[EXC_V_PGFLT],
	       "no pgflt vector defined\n");

	return insert_exception(thr, EXC_V_PGFLT);
}


sval
xh_kern_slb(struct cpu_thread* thread, uval type, struct vexc_save_regs *vr)
{
	struct vm_class *vmc = NULL;
	struct thread_control_area *tca = get_tca();
	uval addr;

	if (type == 1) {
		addr = mfdar();
	} else {
		addr = tca->srr0;
	}

	uval seg_base = ALIGN_DOWN(addr, SEGMENT_SIZE);
	uval lp = LOG_PGSIZE;  /* FIXME: get large page size */
	uval l = 1;
	uval spot;

	if (thread->vstate.thread_mode & VSTATE_KERN_MODE) {
		vmc = find_kernel_vmc(thread, addr);
	}

	if (!vmc) {
		vmc = find_app_vmc(thread, addr);
	}

	if (!vmc) {
		hprintf("No vm_class for 0x%lx\n", addr);
		return insert_debug_exception(thread, V_DEBUG_MEM_FAULT);
	}


	uval vsid = vmc_class_vsid(thread, vmc, addr);

#ifdef FORCE_4K_PAGES
	lp = 12;
	l = 0;
	spot = slb_insert(seg_base, 0, 0, 1, vsid, thread->slb_entries);
#else
	spot = slb_insert(ea, 1, SELECT_LG, 1, vsid, thread->slb_entries);
#endif

	return vr->reg_gprs[3];
}

uval
xh_syscall(uval a1, uval a2, uval a3, uval a4, uval a5, uval a6,
	   uval a7, uval a8, uval a9, uval a10)
{
	struct thread_control_area* tca = (struct thread_control_area*)mfr13();
	struct cpu_thread* thread = tca->active_thread;
	hcall_fn_t hcall_fn;
	const hcall_vec_t* vec = (const hcall_vec_t*)hca.hcall_vector;
	thread->return_args = tca->save_area;

	a1 >>= 2;

	if (a1 >= hca.hcall_vector_len &&
	    a1 - 0x1800 < hca.hcall_6000_vector_len) {
		vec = (const hcall_vec_t*)hca.hcall_6000_vector;
		a1 -= 0x1800;
	}

	hcall_fn = *(const hcall_fn_t*)&vec[a1];
	return hcall_fn(thread, a2, a3, a4, a5, a6, a7, a8, a9, a10);
}

extern void insert_dec_exception(void);
extern void insert_ext_exception(void);

inline void
set_v_msr(struct cpu_thread* thr, uval val)
{
	struct thread_control_area *tca = get_tca();

	if ((val ^ thr->vregs->v_msr) & MSR_PR) {
		if (val & MSR_PR) {
			vmc_exit_kernel(thr);
			thr->vstate.thread_mode &= ~VSTATE_KERN_MODE;
		} else {
			vmc_enter_kernel(thr);
			thr->vstate.thread_mode |= VSTATE_KERN_MODE;
		}
		tca->vstate = thr->vstate.thread_mode;
	}

	thr->vregs->v_msr = (val & ~(MSR_HV|(MSR_SF>>2))) | MSR_AM;

	if (! (val & MSR_EE)) {
		return;
	}
	assert(get_tca()->restore_fn == NULL,
	       "Exception delivery already pending.\n");

	if (thr->vstate.thread_mode & VSTATE_PENDING_EXT) {
		get_tca()->restore_fn = insert_ext_exception;

	} else if (thr->vstate.thread_mode & VSTATE_PENDING_DEC) {
		get_tca()->restore_fn = insert_dec_exception;
	}
}

static inline void
mtgpr(struct cpu_thread* thr, uval gpr, uval val)
{
	switch (gpr) {
	case 14 ... 31:
		thr->reg_gprs[gpr] = val;
		break;
	case 0 ... 13:
		get_tca()->save_area->reg_gprs[gpr] = val;
		break;
	}
}

static inline uval
mfgpr(struct cpu_thread* thr, uval gpr)
{
	uval val;
	switch (gpr) {
	case 14 ... 31:
		val = thr->reg_gprs[gpr];
		break;
	case 0 ... 13:
		val = get_tca()->save_area->reg_gprs[gpr];
		break;
	}
	return val;

}
Пример #5
0
void read_patterns(char *hyph_patterns)
{   FILE *patfile;
    int i, lineno = 0, h, patlen, exclen, maxpatlen = 0, pairs;
    char *syl;
    unsigned char *exception;
    unsigned char syllable[MAXPAT];
    int hyf[MAXPAT];
    struct pattern *p;

    patfile = fopen(hyph_patterns, "r");
    if (patfile==NULL) {
        fprintf(stderr, "Can not open %s for read\n", hyph_patterns);
        exit(1);
    }

    /* the following structure is assumed for the hyphenation patterns:
       % comment
       ...
       % comment
       \patterns{
       pattern
       pattern
       ...
       pattern
       }
    */

    /* we assume that all pointers *entry[] and *tail[] are NULL */

    while (fgets(linep, LINE_LENGTH, patfile)) {
        lineno++;
        if (*linep == '%' || *linep == '\\') continue;
        if (*linep == '}') break;

        pairs = 0;
        h = 0;
        hyf[0] = 0;
        for (i = 0; line[i] != '\n'; i++) {
            if (line[i]=='^') { /* Richard Verhoeven */
                /* ^^?? -> 0x?? */
#define XTON(X)  ((X)>'9'? ((X)-'a'+10):(X)-'0')
                if (line[i+1]=='^' && isxdigit(line[i+2]) &&
                        isxdigit(line[i+3])) {
                    i+=3;
                    line[i]=XTON(line[i-1])*16+XTON(line[i]);
                }
            }
            if (internal[line[i]] >= 0) {
                syllable[h++] = line[i];
                hyf[h] = 0;
            }
            else if (isdigit(line[i])) {
                pairs++;
                if (pairs > MAXHYFS) {
                    fprintf(stderr, "more than %d hyphens in %s", MAXHYFS, linep);
                    continue;
                }
                hyf[h] = (line[i] - '0');
            }
        }
        syllable[h] = '\0';
        if (logging & INPUT) {
            showhyfs(syllable, hyf);
            putchar('\n');
        }
        patlen = strlen((char *) syllable);

        if (patterns_left == 0) {
            pattern_space = (struct pattern *)
                            calloc(PATTERN_CHUNK, sizeof(struct pattern));
            if (pattern_space == NULL) {
                fprintf(stderr, "Out of pattern space\n");
                exit(1);
            }
            patterns_left = PATTERN_CHUNK;
            pattern_bytes+= PATTERN_CHUNK;
            pattern_space_left = pattern_space;
        }
        /* pattern plus \0 minus two first letters */
        if (max(patlen+1-2, 1) > text_left) {
            text_space = (unsigned char *) calloc(TEXT_CHUNK, sizeof(unsigned char));
            if (text_space == NULL) {
                fprintf(stderr, "Out of space\n");
                exit(1);
            }
            text_left = TEXT_CHUNK;
            text_bytes+= TEXT_CHUNK;
            text_space_left = text_space;
        }

        i = key(syllable);
        if (i < 0) {
            fprintf(stderr, "Invalid pattern: %s in line %d\n", linep, lineno);
            exit(1);
        }

        p = pattern_space_left++;
        patterns_left--;
        pattern_cnt++;

        if (entry[i] == NULL) entry[i] = p;
        else tail[i]->next = p;
        tail[i] = p;
        p->next = NULL;
        p->name = text_space_left;
        if (patlen > 2) {
            strcpy((char *) text_space_left, (char *) syllable+2);
            text_space_left+=(patlen+1-2);
            text_left-=(patlen+1-2);
            if (patlen+1 > MAXHYFS) {
                fprintf(stderr, "Can not store more than %d hyf's\n", MAXHYFS);
                exit(1);
            }
        }
        else {
            *text_space_left++ = '\0';
            text_left-=1;
        }
        packhyfs(patlen, hyf, &p->hyfens);
        maxpatlen = max(maxpatlen, patlen);
    }

    /* now read exceptions */
    for (i=0; i<EXCEPTIONS; i++) exc[i] = (unsigned char *) NULL;
    linep = line;

    while (fgets(linep, LINE_LENGTH, patfile)) {
        lineno++;
        if (*linep == '%' || *linep == '\\') continue;
        if (*linep == '}') break;
        exclen = strlen(linep); /* including newline */

        /* get enough text space */
        if (exclen > text_left) {
            text_space = (unsigned char *)
                         calloc((size_t) TEXT_CHUNK, sizeof(unsigned char));
            if (text_space == NULL) {
                fprintf(stderr, "Out of space\n");
                exit(1);
            }
            text_left = TEXT_CHUNK;
            text_bytes+= TEXT_CHUNK;
            text_space_left = text_space;
        }

        exception = text_space_left;
        strncpy((unsigned char *) text_space_left,
                (unsigned char *) linep, exclen - 1);
        text_space_left+=exclen-1;
        *text_space_left++='\0';
        text_left-=exclen;

        insert_exception(exception);
    }

    fclose(patfile);

    if (logging & STATS) {
        int maximum, N, count, average, M;
        unsigned char a, b;
        float sum;
        void syllabe(int, unsigned char *, unsigned char *);

        printf("Loaded %d patterns. Maximum pattern length %d\n",
               pattern_cnt, maxpatlen);
        patterns_left*=sizeof(struct pattern);
        pattern_bytes*=sizeof(struct pattern);
        printf("Memory consumption:\n");
        printf("patterns : %d bytes (%d unused)\n", pattern_bytes, patterns_left);
        printf("syllables: %d bytes (%d unused)\n", text_bytes, text_left);
        sum = maximum = N = 0;
        for (i = 0; i < MAX_KEY; i++) {
            if (entry[i] == NULL) continue;
            for (count = 0, p = entry[i]; p != NULL; p=p->next) count++;
            if (count > maximum) {
                maximum = count;
                M = i;
            }
            sum+=count;
            N++;
        }
        printf("syllables %d   average %5.1f\n", N, ((float) sum/N));
        syllabe(M, &a, &b);
        printf("maximum of patterns %d (%c%c)\n", maximum, a, b);
#     ifdef DEBUGG
        p = entry[M];
        count = 0;
        while (p != NULL) {
            syllable[0] = a;
            syllable[1] = b;
            strcat(syllable, p->name);
            unpackhyfs(strlen(syllable), hyf, p->hyfens);
            printf("<");
            showhyfs(syllable, hyf);
            printf(">, ");
            if (++count % 5 == 0) putchar('\n');
            p = p->next;
        }
        putchar('\n');
#     endif
    }
}