]> pd.if.org Git - zos/blob - smp.c
add a readme with a public domain note
[zos] / smp.c
1 #include <kernel.h>
2 #include <mem.h>
3 #include <smp.h>
4
5 static uint8_t checksum(void *start, size_t n) {
6         uint8_t sum = 0;
7         uint8_t *bytes;
8         int i;
9
10         bytes = start;
11         for (i=0; i<n; i++) {
12                 sum += bytes[i];
13         }
14         return sum;
15 }
16
17 #if 0
18 static void *scanfordword(paddr_t start, paddr_t max, size_t by, uint32_t val) {
19         while (start <= max - by) {
20                 if (*(uint32_t *)(PHY2VIRTP(start)) == val) {
21                         return PHY2VIRTP(start);
22                 }
23                 start += by;
24         }
25         return 0;
26 }
27 #endif
28
29 /* TODO this could probably be a kernel thread, and just power up
30  * processors as though they were hot-plugged.  Except that the
31  * local apic on the BSP needs to be configured
32  */
33 void init_smp(void) {
34         uint16_t *bda;
35         uint32_t mpsig = 0x5f504d5f;
36         uint32_t tabsig = 0x504d4350;
37         uintptr_t mem;
38         struct mpfp *mp = 0;
39         struct mpconfig *config = 0;
40         int i;
41
42         /* search for base table */
43         
44         /* search first KB of the extended bios data area */
45         bda = PHY2VIRTP(0x40E);
46         mem = (uintptr_t)((*bda) << 4);
47
48         for (i=0;i <= 1024 - 16 ;i+=16) {
49                 mp = PHY2VIRTP(mem+i);
50                 if ( mp->signature == mpsig && checksum(mp, 16) == 0) {
51                         goto found;
52                 }
53         }
54
55         /* search last kb of base mem, 639-640k */
56         mem = KB(639);
57         for (i=0;i<1024-16;i+=16) {
58                 mp = PHY2VIRTP(mem+i);
59                 if ( mp->signature == mpsig && checksum(mp, 16) == 0) {
60                         goto found;
61                 }
62         }
63
64         /* search bios rom address space, f0000 - fffff */
65         mem = 0xf0000;
66         for (i=0;i<KB(64)-16;i+=16) {
67                 mp = PHY2VIRTP(mem+i);
68                 if ( mp->signature == mpsig && checksum(mp, 16) == 0) {
69                         goto found;
70                 }
71         }
72
73         printk("mpft not found\n");
74         return;
75 found:
76         printk("found mpft at %llx: features1 %x, features2 %x\n", (uintptr_t)mp,
77                         (uint32_t)mp->features1, (uint32_t)mp->features2);
78         config = PHY2VIRTP(mp->mpconfigptr);
79         if (config->signature != tabsig) {
80                 printk("tabsig bad\n");
81                 return;
82         }
83 #if 0
84         if (checksum(config, (size_t)config->tablelength) != 0) {
85                 printk("config table checksum bad\n");
86                 return;
87         }
88 #endif
89
90         vaddr_t entry = (vaddr_t)config + sizeof *config;
91         printk("mpct local apic: %x, entries: %x, len = %x\n", config->localapicaddr, config->entrycount, config->tablelength);
92         int procnum = 0;
93         for (i=0;i<config->entrycount;i++) {
94                 uint8_t etype;
95                 struct processorentry *proc;
96                 struct ioapic *io;
97
98                 etype = *(uint8_t *)entry;
99                 switch (etype) {
100                         case 0: /* processor */
101                                 proc = (struct processorentry *)entry;
102                                 printk("processor %x, apic = %x:%s%s\n", procnum,
103                                                 (uint32_t)proc->apicid,
104                                                 proc->enabled ? " enabled" : "",
105                                                 proc->bootstrap ? " bsp" : ""
106                                         );
107                                 procnum++;
108                                 entry += 20;
109                                 break;
110                         case 1: /* bus */
111                                 //printk("mp bus\n");
112                                 entry += 8;
113                                 break;
114                         case 2: /* io apic */
115                                 io = (struct ioapic *)entry;
116                                 if (io->enabled) {
117                                         printk("ioapic %x %llx\n", io->id, io->address);
118                                 } else {
119                                         printk("ioapic %x disabledx\n", io->id);
120                                 }
121                                 entry += 8;
122                                 break;
123                         default:
124                                 //printk(" type: %x\n", etype);
125                                 entry += 8;
126                                 break;
127                 }
128         }
129 }