Subversion Repositories HelenOS

Rev

Rev 2725 | Rev 3230 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2725 Rev 3228
Line 30... Line 30...
30
 * @{
30
 * @{
31
 */
31
 */
32
/** @file
32
/** @file
33
 */
33
 */
34
 
34
 
-
 
35
#include <macros.h>
35
#include <arch/mm/frame.h>
36
#include <arch/mm/frame.h>
-
 
37
#include <arch/mm/tlb.h>
36
#include <mm/frame.h>
38
#include <mm/frame.h>
-
 
39
#include <mm/asid.h>
37
#include <config.h>
40
#include <config.h>
38
#include <arch/drivers/arc.h>
41
#include <arch/drivers/msim.h>
-
 
42
#include <arch/drivers/serial.h>
-
 
43
#include <print.h>
-
 
44
#include <debug.h>
-
 
45
 
-
 
46
#define TLB_PAGE_MASK_1M    (0xff << 13)
-
 
47
 
-
 
48
#define ZERO_FRAMES         4096
-
 
49
#define ZERO_PAGE_WIDTH     20  /* 1M */
-
 
50
#define ZERO_PAGE_SIZE      (1 << ZERO_PAGE_WIDTH)
-
 
51
#define ZERO_PAGE_ASID      ASID_INVALID
-
 
52
#define ZERO_PAGE_TLBI      0
-
 
53
#define ZERO_PAGE_ADDR      0
-
 
54
#define ZERO_PAGE_OFFSET    (ZERO_PAGE_SIZE / sizeof(uint32_t) - 1)
-
 
55
#define ZERO_PAGE_VALUE     (*((volatile uint32_t *) ZERO_PAGE_ADDR + ZERO_PAGE_OFFSET))
-
 
56
 
-
 
57
#define MAX_REGIONS         32
-
 
58
 
-
 
59
typedef struct {
-
 
60
    pfn_t start;
-
 
61
    pfn_t count;
-
 
62
} phys_region_t;
-
 
63
 
-
 
64
static count_t phys_regions_count = 0;
-
 
65
static phys_region_t phys_regions[MAX_REGIONS];
-
 
66
 
-
 
67
 
-
 
68
/** Check whether frame is available
-
 
69
 *
-
 
70
 * Returns true if given frame is generally available for use.
-
 
71
 * Returns false if given frame is used for physical memory
-
 
72
 * mapped devices and cannot be used.
-
 
73
 *
-
 
74
 */
-
 
75
static bool frame_available(pfn_t frame)
-
 
76
{
-
 
77
    /* MSIM device (dprinter) */
-
 
78
    if (frame == (KA2PA(MSIM_VIDEORAM) >> ZERO_PAGE_WIDTH))
-
 
79
        return false;
-
 
80
   
-
 
81
    /* MSIM device (dkeyboard) */
-
 
82
    if (frame == (KA2PA(MSIM_KBD_ADDRESS) >> ZERO_PAGE_WIDTH))
-
 
83
        return false;
-
 
84
   
-
 
85
    /* Simics device (serial line) */
-
 
86
    if (frame == (KA2PA(SERIAL_ADDRESS) >> ZERO_PAGE_WIDTH))
-
 
87
        return false;
-
 
88
   
-
 
89
    return true;
-
 
90
}
-
 
91
 
-
 
92
 
-
 
93
/** Check whether frame is safe to write
-
 
94
 *
-
 
95
 * Returns true if given frame is safe for read/write test.
-
 
96
 * Returns false if given frame should not be touched.
-
 
97
 *
-
 
98
 */
-
 
99
static bool frame_safe(pfn_t frame) __attribute__((unused));
-
 
100
static bool frame_safe(pfn_t frame)
-
 
101
{
-
 
102
    /* Kernel structures */
-
 
103
    if ((frame << ZERO_PAGE_WIDTH) < KA2PA(config.base))
-
 
104
        return false;
-
 
105
   
-
 
106
    /* Kernel */
-
 
107
    if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
-
 
108
        KA2PA(config.base), config.kernel_size))
-
 
109
        return false;
-
 
110
   
-
 
111
    /* Kernel stack */
-
 
112
    if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
-
 
113
        KA2PA(config.stack_base), config.stack_size))
-
 
114
        return false;
-
 
115
   
-
 
116
    /* Init tasks */
-
 
117
    bool safe = true;
-
 
118
    count_t i;
-
 
119
    for (i = 0; i < init.cnt; i++)
-
 
120
        if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
-
 
121
            KA2PA(init.tasks[i].addr), init.tasks[i].size)) {
-
 
122
            safe = false;
-
 
123
            break;
-
 
124
        }
-
 
125
   
-
 
126
    return safe;
-
 
127
}
-
 
128
 
-
 
129
static void frame_add_region(pfn_t start_frame, pfn_t end_frame)
-
 
130
{
-
 
131
    if (end_frame > start_frame) {
-
 
132
        /* Convert 1M frames to 16K frames */
-
 
133
        pfn_t first = ADDR2PFN(start_frame << ZERO_PAGE_WIDTH);
-
 
134
        pfn_t count = ADDR2PFN((end_frame - start_frame - 1) << ZERO_PAGE_WIDTH);
-
 
135
       
-
 
136
        /* Interrupt vector frame is blacklisted */
-
 
137
        pfn_t conf_frame;
-
 
138
        if (start_frame == 0)
-
 
139
            conf_frame = 1;
-
 
140
        else
-
 
141
            conf_frame = first;
-
 
142
       
-
 
143
        zone_create(first, count, conf_frame, 0);
-
 
144
       
-
 
145
        if (phys_regions_count < MAX_REGIONS) {
-
 
146
            phys_regions[phys_regions_count].start = first;
-
 
147
            phys_regions[phys_regions_count].count = count;
-
 
148
            phys_regions_count++;
-
 
149
        }
-
 
150
    }
-
 
151
}
-
 
152
 
39
 
153
 
40
/** Create memory zones
154
/** Create memory zones
41
 *
155
 *
42
 * If ARC is known, read information from ARC, otherwise
156
 * Walk through available 1 MB chunks of physical
43
 * assume some defaults.
157
 * memory and create zones.
44
 * - blacklist first FRAME because there is an exception vector
-
 
-
 
158
 *
45
 */
159
 */
46
void frame_arch_init(void)
160
void frame_arch_init(void)
47
{
161
{
-
 
162
    cp0_index_write(ZERO_PAGE_TLBI);
-
 
163
    tlbr();
-
 
164
   
-
 
165
    uint32_t orig_pagemask = cp0_pagemask_read();
-
 
166
    uint32_t orig_lo0 = cp0_entry_lo0_read();
-
 
167
    uint32_t orig_lo1 = cp0_entry_lo1_read();
-
 
168
    uint32_t orig_hi = cp0_entry_hi_read();
-
 
169
       
-
 
170
    pfn_t start_frame = 0;
-
 
171
    pfn_t frame;
-
 
172
    bool avail = true;
-
 
173
   
-
 
174
    /* Walk through all 1 MB frames */
-
 
175
    for (frame = 0; frame < ZERO_FRAMES; frame++) {
-
 
176
        if (!frame_available(frame))
-
 
177
            avail = false;
-
 
178
        else {
48
    if (!arc_frame_init()) {
179
            if (frame_safe(frame)) {
-
 
180
                entry_lo_t lo0;
-
 
181
                entry_lo_t lo1;
-
 
182
                entry_hi_t hi;
-
 
183
                tlb_prepare_entry_lo(&lo0, false, true, true, false, frame << (ZERO_PAGE_WIDTH - 12));
49
        zone_create(0, ADDR2PFN(CONFIG_MEMORY_SIZE), 1, 0);
184
                tlb_prepare_entry_lo(&lo1, false, false, false, false, 0);
-
 
185
                tlb_prepare_entry_hi(&hi, ZERO_PAGE_ASID, ZERO_PAGE_ADDR);
50
        /*
186
               
-
 
187
                cp0_index_write(ZERO_PAGE_TLBI);
-
 
188
                cp0_pagemask_write(TLB_PAGE_MASK_1M);
-
 
189
                cp0_entry_lo0_write(lo0.value);
-
 
190
                cp0_entry_lo1_write(lo1.value);
51
         * Blacklist interrupt vector
191
                cp0_entry_hi_write(hi.value);
-
 
192
                tlbwi();
-
 
193
               
-
 
194
                ZERO_PAGE_VALUE = 0;
-
 
195
                if (ZERO_PAGE_VALUE != 0)
-
 
196
                    avail = false;
-
 
197
                else {
-
 
198
                    ZERO_PAGE_VALUE = 0xdeadbeef;
-
 
199
                    if (ZERO_PAGE_VALUE != 0xdeadbeef)
-
 
200
                        avail = false;
52
         */
201
                }
-
 
202
            }
-
 
203
        }
-
 
204
       
-
 
205
        if (!avail) {
53
        frame_mark_unavailable(0, 1);
206
            frame_add_region(start_frame, frame);
-
 
207
            start_frame = frame + 1;
-
 
208
            avail = true;
-
 
209
        }
54
    }
210
    }
-
 
211
   
-
 
212
    frame_add_region(start_frame, frame);
-
 
213
   
-
 
214
    /* Cleanup TLB */
-
 
215
    cp0_index_write(ZERO_PAGE_TLBI);
-
 
216
    cp0_pagemask_write(orig_pagemask);
-
 
217
    cp0_entry_lo0_write(orig_lo0);
-
 
218
    cp0_entry_lo1_write(orig_lo1);
-
 
219
    cp0_entry_hi_write(orig_hi);
-
 
220
    tlbwi();
-
 
221
   
-
 
222
    /* Blacklist interrupt vector frame */
-
 
223
    frame_mark_unavailable(0, 1);
-
 
224
}
-
 
225
 
-
 
226
 
-
 
227
void physmem_print(void)
-
 
228
{
-
 
229
    printf("Base       Size\n");
-
 
230
    printf("---------- ----------\n");
-
 
231
   
-
 
232
    count_t i;
-
 
233
    for (i = 0; i < phys_regions_count; i++) {
-
 
234
        printf("%#10x %10u\n",
-
 
235
            PFN2ADDR(phys_regions[i].start), PFN2ADDR(phys_regions[i].count));
-
 
236
    }  
55
}
237
}
56
 
238
 
57
/** @}
239
/** @}
58
 */
240
 */