Qmsr,
Qbase,
- Qmax = 16,
+ Qmax = 32,
};
enum {
Procsig,
Proctlbcache,
Procserial,
+
+ Highextfunc = 0x80000000,
+ Procextfeat,
};
typedef long Rdwrfn(Chan*, void*, long, vlong);
}
static void
-checkport(int start, int end)
+checkport(uint start, uint end)
{
+ if(end < start || end > 0x10000)
+ error(Ebadarg);
+
/* standard vga regs are OK */
if(start >= 0x2b0 && end <= 0x2df+1)
return;
archread(Chan *c, void *a, long n, vlong offset)
{
char buf[32], *p;
- int port, i;
+ uint port, end;
ushort *sp;
ulong *lp;
vlong *vp;
IOMap *m;
Rdwrfn *fn;
+ int i;
+ port = offset;
+ end = port+n;
switch((ulong)c->qid.path){
case Qdir:
return devdirread(c, a, n, archdir, narchdir, devgen);
case Qiob:
- port = offset;
- checkport(offset, offset+n);
- for(p = a; port < offset+n; port++)
+ checkport(port, end);
+ for(p = a; port < end; port++)
*p++ = inb(port);
return n;
case Qiow:
if(n & 1)
error(Ebadarg);
- checkport(offset, offset+n);
- sp = a;
- for(port = offset; port < offset+n; port += 2)
+ checkport(port, end);
+ for(sp = a; port < end; port += 2)
*sp++ = ins(port);
return n;
case Qiol:
if(n & 3)
error(Ebadarg);
- checkport(offset, offset+n);
- lp = a;
- for(port = offset; port < offset+n; port += 4)
+ checkport(port, end);
+ for(lp = a; port < end; port += 4)
*lp++ = inl(port);
return n;
case Qmsr:
if(n & 7)
error(Ebadarg);
- vp = a;
- for(port = offset; port < offset+n; port += 8)
+ if((uint)n/8 > -port)
+ error(Ebadarg);
+ end = port+(n/8);
+ for(vp = a; port != end; port++)
if(rdmsr(port, vp++) < 0)
error(Ebadarg);
return n;
lock(&iomap);
i = 0;
for(m = iomap.m; m != nil; m = m->next){
- i = snprint(buf, sizeof(buf), "%8lux %8lux %-12.12s\n", m->start, m->end-1, m->tag);
+ i = snprint(buf, sizeof(buf), "%8lux %8lux %-12.12s\n",
+ m->start, m->end-1, m->tag);
offset -= i;
if(offset < 0)
break;
static long
archwrite(Chan *c, void *a, long n, vlong offset)
{
+ uint port, end;
char *p;
- int port;
ushort *sp;
ulong *lp;
vlong *vp;
Rdwrfn *fn;
+ port = offset;
+ end = port+n;
switch((ulong)c->qid.path){
case Qiob:
- p = a;
- checkport(offset, offset+n);
- for(port = offset; port < offset+n; port++)
+ checkport(port, end);
+ for(p = a; port < end; port++)
outb(port, *p++);
return n;
case Qiow:
if(n & 1)
error(Ebadarg);
- checkport(offset, offset+n);
- sp = a;
- for(port = offset; port < offset+n; port += 2)
+ checkport(port, end);
+ for(sp = a; port < end; port += 2)
outs(port, *sp++);
return n;
case Qiol:
if(n & 3)
error(Ebadarg);
- checkport(offset, offset+n);
- lp = a;
- for(port = offset; port < offset+n; port += 4)
+ checkport(port, end);
+ for(lp = a; port < end; port += 4)
outl(port, *lp++);
return n;
case Qmsr:
if(n & 7)
error(Ebadarg);
- vp = a;
- for(port = offset; port < offset+n; port += 8)
+ if((uint)n/8 > -port)
+ error(Ebadarg);
+ end = port+(n/8);
+ for(vp = a; port != end; port++)
if(wrmsr(port, *vp++) < 0)
error(Ebadarg);
return n;
{ 6, -1, 11, "AMD-Athlon", },/* guesswork */
{ 0xF, -1, 11, "AMD-K8", }, /* guesswork */
{ 0x1F, -1, 11, "AMD-K10", }, /* guesswork */
+ { 23, 1, 13, "AMD Ryzen" },
{ -1, -1, 11, "unknown", }, /* total default */
};
m->cpuidax = regs[0];
m->cpuidcx = regs[2];
m->cpuiddx = regs[3];
+
+ m->cpuidfamily = m->cpuidax >> 8 & 0xf;
+ m->cpuidmodel = m->cpuidax >> 4 & 0xf;
+ m->cpuidstepping = m->cpuidax & 0xf;
+ switch(m->cpuidfamily){
+ case 15:
+ m->cpuidfamily += m->cpuidax >> 20 & 0xff;
+ m->cpuidmodel += m->cpuidax >> 16 & 0xf;
+ break;
+ case 6:
+ m->cpuidmodel += m->cpuidax >> 16 & 0xf;
+ break;
+ }
if(strncmp(m->cpuidid, "AuthenticAMD", 12) == 0 ||
strncmp(m->cpuidid, "Geode by NSC", 12) == 0)
else
tab = x86intel;
- family = X86FAMILY(m->cpuidax);
- model = X86MODEL(m->cpuidax);
+ family = m->cpuidfamily;
+ model = m->cpuidmodel;
for(t=tab; t->name; t++)
if((t->family == family && t->model == model)
|| (t->family == family && t->model == -1)
hwrandbuf = rdrandbuf;
else
hwrandbuf = nil;
+
+ if(sizeof(uintptr) == 8) {
+ /* 8-byte watchpoints are supported in Long Mode */
+ m->havewatchpt8 = 1;
+
+ /* check and enable NX bit */
+ cpuid(Highextfunc, regs);
+ if(regs[0] >= Procextfeat){
+ cpuid(Procextfeat, regs);
+ if((regs[3] & (1<<20)) != 0){
+ vlong efer;
+
+ /* enable no-execute feature */
+ if(rdmsr(Efer, &efer) != -1){
+ efer |= 1ull<<11;
+ if(wrmsr(Efer, efer) != -1)
+ m->havenx = 1;
+ }
+ }
+ }
+ } else if(strcmp(m->cpuidid, "GenuineIntel") == 0){
+ /* some random CPUs that support 8-byte watchpoints */
+ if(family == 15 && (model == 3 || model == 4 || model == 6)
+ || family == 6 && (model == 15 || model == 23 || model == 28))
+ m->havewatchpt8 = 1;
+ /* Intel SDM claims amd64 support implies 8-byte watchpoint support */
+ cpuid(Highextfunc, regs);
+ if(regs[0] >= Procextfeat){
+ cpuid(Procextfeat, regs);
+ if((regs[3] & 1<<29) != 0)
+ m->havewatchpt8 = 1;
+ }
+ }
cputype = t;
return t->family;
if(strcmp(cb->f[1], "mb386") == 0)
coherence = mb386;
else if(strcmp(cb->f[1], "mb586") == 0){
- if(X86FAMILY(m->cpuidax) < 5)
+ if(m->cpuidfamily < 5)
error("invalid coherence ctl on this cpu family");
coherence = mb586;
}else if(strcmp(cb->f[1], "mfence") == 0){
* We get another chance to set it in mpinit() for a
* multiprocessor.
*/
- if(X86FAMILY(m->cpuidax) == 3)
+ if(m->cpuidfamily == 3)
conf.copymode = 1;
- if(X86FAMILY(m->cpuidax) >= 4)
+ if(m->cpuidfamily >= 4)
cmpswap = cmpswap486;
- if(X86FAMILY(m->cpuidax) >= 5)
+ if(m->cpuidfamily >= 5)
coherence = mb586;
if(m->cpuiddx & Sse2)
int
isaconfig(char *class, int ctlrno, ISAConf *isa)
{
- char cc[32], *p;
+ char cc[32], *p, *x;
int i;
snprint(cc, sizeof cc, "%s%d", class, ctlrno);
if(p == nil)
return 0;
+ x = nil;
+ kstrdup(&x, p);
+ p = x;
+
isa->type = "";
isa->nopt = tokenize(p, isa->opt, NISAOPT);
for(i = 0; i < isa->nopt; i++){
iprint("\n");
}
}
+
+void
+setupwatchpts(Proc *pr, Watchpt *wp, int nwp)
+{
+ int i;
+ u8int cfg;
+ Watchpt *p;
+
+ if(nwp > 4)
+ error("there are four watchpoints.");
+ if(nwp == 0){
+ memset(pr->dr, 0, sizeof(pr->dr));
+ return;
+ }
+ for(p = wp; p < wp + nwp; p++){
+ switch(p->type){
+ case WATCHRD|WATCHWR: case WATCHWR:
+ break;
+ case WATCHEX:
+ if(p->len != 1)
+ error("length must be 1 on breakpoints");
+ break;
+ default:
+ error("type must be rw-, -w- or --x");
+ }
+ switch(p->len){
+ case 1: case 2: case 4:
+ break;
+ case 8:
+ if(m->havewatchpt8) break;
+ default:
+ error(m->havewatchpt8 ? "length must be 1,2,4,8" : "length must be 1,2,4");
+ }
+ if((p->addr & p->len - 1) != 0)
+ error("address must be aligned according to length");
+ }
+
+ memset(pr->dr, 0, sizeof(pr->dr));
+ pr->dr[6] = 0xffff8ff0;
+ for(i = 0; i < nwp; i++){
+ pr->dr[i] = wp[i].addr;
+ switch(wp[i].type){
+ case WATCHRD|WATCHWR: cfg = 3; break;
+ case WATCHWR: cfg = 1; break;
+ case WATCHEX: cfg = 0; break;
+ default: continue;
+ }
+ switch(wp[i].len){
+ case 1: break;
+ case 2: cfg |= 4; break;
+ case 4: cfg |= 12; break;
+ case 8: cfg |= 8; break;
+ default: continue;
+ }
+ pr->dr[7] |= cfg << 16 + 4 * i;
+ pr->dr[7] |= 1 << 2 * i + 1;
+ }
+}