Subversion Repositories HelenOS

Rev

Rev 3835 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3771 rimsky 1
/*
2
 * Copyright (c) 2005 Jakub Jermar
3
 * Copyright (c) 2008 Pavel Rimsky
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 *
10
 * - Redistributions of source code must retain the above copyright
11
 *   notice, this list of conditions and the following disclaimer.
12
 * - Redistributions in binary form must reproduce the above copyright
13
 *   notice, this list of conditions and the following disclaimer in the
14
 *   documentation and/or other materials provided with the distribution.
15
 * - The name of the author may not be used to endorse or promote products
16
 *   derived from this software without specific prior written permission.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 */
29
 
30
/** @addtogroup sparc64mm  
31
 * @{
32
 */
33
/** @file
34
 */
35
 
36
#ifndef KERN_sparc64_sun4v_TLB_H_
37
#define KERN_sparc64_sun4v_TLB_H_
38
 
39
#ifndef __ASM__
40
 
41
#include <arch/mm/sun4v/tte.h>
42
#include <arch/mm/sun4v/mmu.h>
43
#include <arch/mm/page.h>
44
#include <arch/asm.h>
45
#include <arch/barrier.h>
46
#include <arch/types.h>
47
#include <arch/register.h>
48
#include <arch/cpu.h>
49
 
50
/**
51
 * Structure filled by hypervisor (or directly CPU, if implemented so) when
52
 * a MMU fault occurs. The structure describes the exact condition which
53
 * has caused the fault;
54
 */
55
typedef struct mmu_fault_status_area {
56
    uint64_t ift;       /**< Instruction fault type (IFT) */
57
    uint64_t ifa;       /**< Instruction fault address (IFA) */
58
    uint64_t ifc;       /**< Instruction fault context (IFC) */
59
    uint8_t reserved1[0x28];
60
 
61
    uint64_t dft;       /**< Data fault type (DFT) */
62
    uint64_t dfa;       /**< Data fault address (DFA) */
63
    uint64_t dfc;       /**< Data fault context (DFC) */
64
    uint8_t reserved2[0x28];
65
} __attribute__ ((packed)) mmu_fault_status_area_t;
66
 
67
#if 0
68
union tlb_context_reg {
69
    uint64_t v;
70
    struct {
71
        unsigned long : 51;
72
        unsigned context : 13;      /**< Context/ASID. */
73
    } __attribute__ ((packed));
74
};
75
typedef union tlb_context_reg tlb_context_reg_t;
76
 
77
 
78
/** I-/D-TLB Data In/Access Register type. */
79
typedef tte_data_t tlb_data_t;
80
 
81
/** I-/D-TLB Data Access Address in Alternate Space. */
82
 
83
#if defined (US)
84
 
85
union tlb_data_access_addr {
86
    uint64_t value;
87
    struct {
88
        uint64_t : 55;
89
        unsigned tlb_entry : 6;
90
        unsigned : 3;
91
    } __attribute__ ((packed));
92
};
93
typedef union tlb_data_access_addr dtlb_data_access_addr_t;
94
typedef union tlb_data_access_addr dtlb_tag_read_addr_t;
95
typedef union tlb_data_access_addr itlb_data_access_addr_t;
96
typedef union tlb_data_access_addr itlb_tag_read_addr_t;
97
 
98
#elif defined (US3)
99
 
100
/*
101
 * In US3, I-MMU and D-MMU have different formats of the data
102
 * access register virtual address. In the corresponding
103
 * structures the member variable for the entry number is
104
 * called "local_tlb_entry" - it contrasts with the "tlb_entry"
105
 * for the US data access register VA structure. The rationale
106
 * behind this is to prevent careless mistakes in the code
107
 * caused by setting only the entry number and not the TLB
108
 * number in the US3 code (when taking the code from US).
109
 */
110
 
111
union dtlb_data_access_addr {
112
    uint64_t value;
113
    struct {
114
        uint64_t : 45;
115
        unsigned : 1;
116
        unsigned tlb_number : 2;
117
        unsigned : 4;
118
        unsigned local_tlb_entry : 9;
119
        unsigned : 3;
120
    } __attribute__ ((packed));
121
};
122
typedef union dtlb_data_access_addr dtlb_data_access_addr_t;
123
typedef union dtlb_data_access_addr dtlb_tag_read_addr_t;
124
 
125
union itlb_data_access_addr {
126
    uint64_t value;
127
    struct {
128
        uint64_t : 45;
129
        unsigned : 1;
130
        unsigned tlb_number : 2;
131
        unsigned : 6;
132
        unsigned local_tlb_entry : 7;
133
        unsigned : 3;
134
    } __attribute__ ((packed));
135
};
136
typedef union itlb_data_access_addr itlb_data_access_addr_t;
137
typedef union itlb_data_access_addr itlb_tag_read_addr_t;
138
 
139
#endif
140
 
141
/** I-/D-TLB Tag Read Register. */
142
union tlb_tag_read_reg {
143
    uint64_t value;
144
    struct {
145
        uint64_t vpn : 51;  /**< Virtual Address bits 63:13. */
146
        unsigned context : 13;  /**< Context identifier. */
147
    } __attribute__ ((packed));
148
};
149
typedef union tlb_tag_read_reg tlb_tag_read_reg_t;
150
typedef union tlb_tag_read_reg tlb_tag_access_reg_t;
151
 
152
 
153
/** TLB Demap Operation Address. */
154
union tlb_demap_addr {
155
    uint64_t value;
156
    struct {
157
        uint64_t vpn: 51;   /**< Virtual Address bits 63:13. */
158
#if defined (US)
159
        unsigned : 6;       /**< Ignored. */
160
        unsigned type : 1;  /**< The type of demap operation. */
161
#elif defined (US3)
162
        unsigned : 5;       /**< Ignored. */
163
        unsigned type: 2;   /**< The type of demap operation. */
164
#endif
165
        unsigned context : 2;   /**< Context register selection. */
166
        unsigned : 4;       /**< Zero. */
167
    } __attribute__ ((packed));
168
};
169
typedef union tlb_demap_addr tlb_demap_addr_t;
170
 
171
/** TLB Synchronous Fault Status Register. */
172
union tlb_sfsr_reg {
173
    uint64_t value;
174
    struct {
175
#if defined (US)
176
        unsigned long : 40; /**< Implementation dependent. */
177
        unsigned asi : 8;   /**< ASI. */
178
        unsigned : 2;
179
        unsigned ft : 7;    /**< Fault type. */
180
#elif defined (US3)
181
        unsigned long : 39; /**< Implementation dependent. */
182
        unsigned nf : 1;    /**< Non-faulting load. */
183
        unsigned asi : 8;   /**< ASI. */
184
        unsigned tm : 1;    /**< I-TLB miss. */
185
        unsigned : 3;       /**< Reserved. */
186
        unsigned ft : 5;    /**< Fault type. */
187
#endif
188
        unsigned e : 1;     /**< Side-effect bit. */
189
        unsigned ct : 2;    /**< Context Register selection. */
190
        unsigned pr : 1;    /**< Privilege bit. */
191
        unsigned w : 1;     /**< Write bit. */
192
        unsigned ow : 1;    /**< Overwrite bit. */
193
        unsigned fv : 1;    /**< Fault Valid bit. */
194
    } __attribute__ ((packed));
195
};
196
typedef union tlb_sfsr_reg tlb_sfsr_reg_t;
197
 
198
#if defined (US3)
199
 
200
/*
201
 * Functions for determining the number of entries in TLBs. They either return
202
 * a constant value or a value based on the CPU autodetection.
203
 */
204
 
205
/**
206
 * Determine the number of entries in the DMMU's small TLB.
207
 */
208
static inline uint16_t tlb_dsmall_size(void)
209
{
210
    return 16;
211
}
212
 
213
/**
214
 * Determine the number of entries in each DMMU's big TLB.
215
 */
216
static inline uint16_t tlb_dbig_size(void)
217
{
218
    return 512;
219
}
220
 
221
/**
222
 * Determine the number of entries in the IMMU's small TLB.
223
 */
224
static inline uint16_t tlb_ismall_size(void)
225
{
226
    return 16;
227
}
228
 
229
/**
230
 * Determine the number of entries in the IMMU's big TLB.
231
 */
232
static inline uint16_t tlb_ibig_size(void)
233
{
234
    if (((ver_reg_t) ver_read()).impl == IMPL_ULTRASPARCIV_PLUS)
235
        return 512;
236
    else
237
        return 128;
238
}
239
 
240
#endif
241
 
242
/** Read MMU Primary Context Register.
243
 *
244
 * @return      Current value of Primary Context Register.
245
 */
246
static inline uint64_t mmu_primary_context_read(void)
247
{
248
    return asi_u64_read(ASI_DMMU, VA_PRIMARY_CONTEXT_REG);
249
}
250
 
251
/** Write MMU Primary Context Register.
252
 *
253
 * @param v     New value of Primary Context Register.
254
 */
255
static inline void mmu_primary_context_write(uint64_t v)
256
{
257
    asi_u64_write(ASI_DMMU, VA_PRIMARY_CONTEXT_REG, v);
258
    flush_pipeline();
259
}
260
 
261
/** Read MMU Secondary Context Register.
262
 *
263
 * @return      Current value of Secondary Context Register.
264
 */
265
static inline uint64_t mmu_secondary_context_read(void)
266
{
267
    return asi_u64_read(ASI_DMMU, VA_SECONDARY_CONTEXT_REG);
268
}
269
 
270
/** Write MMU Primary Context Register.
271
 *
272
 * @param v     New value of Primary Context Register.
273
 */
274
static inline void mmu_secondary_context_write(uint64_t v)
275
{
276
    asi_u64_write(ASI_DMMU, VA_SECONDARY_CONTEXT_REG, v);
277
    flush_pipeline();
278
}
279
 
280
#if defined (US)
281
 
282
/** Read IMMU TLB Data Access Register.
283
 *
284
 * @param entry     TLB Entry index.
285
 *
286
 * @return      Current value of specified IMMU TLB Data Access
287
 *          Register.
288
 */
289
static inline uint64_t itlb_data_access_read(index_t entry)
290
{
291
    itlb_data_access_addr_t reg;
292
 
293
    reg.value = 0;
294
    reg.tlb_entry = entry;
295
    return asi_u64_read(ASI_ITLB_DATA_ACCESS_REG, reg.value);
296
}
297
 
298
/** Write IMMU TLB Data Access Register.
299
 *
300
 * @param entry     TLB Entry index.
301
 * @param value     Value to be written.
302
 */
303
static inline void itlb_data_access_write(index_t entry, uint64_t value)
304
{
305
    itlb_data_access_addr_t reg;
306
 
307
    reg.value = 0;
308
    reg.tlb_entry = entry;
309
    asi_u64_write(ASI_ITLB_DATA_ACCESS_REG, reg.value, value);
310
    flush_pipeline();
311
}
312
 
313
/** Read DMMU TLB Data Access Register.
314
 *
315
 * @param entry     TLB Entry index.
316
 *
317
 * @return      Current value of specified DMMU TLB Data Access
318
 *          Register.
319
 */
320
static inline uint64_t dtlb_data_access_read(index_t entry)
321
{
322
    dtlb_data_access_addr_t reg;
323
 
324
    reg.value = 0;
325
    reg.tlb_entry = entry;
326
    return asi_u64_read(ASI_DTLB_DATA_ACCESS_REG, reg.value);
327
}
328
 
329
/** Write DMMU TLB Data Access Register.
330
 *
331
 * @param entry     TLB Entry index.
332
 * @param value     Value to be written.
333
 */
334
static inline void dtlb_data_access_write(index_t entry, uint64_t value)
335
{
336
    dtlb_data_access_addr_t reg;
337
 
338
    reg.value = 0;
339
    reg.tlb_entry = entry;
340
    asi_u64_write(ASI_DTLB_DATA_ACCESS_REG, reg.value, value);
341
    membar();
342
}
343
 
344
/** Read IMMU TLB Tag Read Register.
345
 *
346
 * @param entry     TLB Entry index.
347
 *
348
 * @return      Current value of specified IMMU TLB Tag Read Register.
349
 */
350
static inline uint64_t itlb_tag_read_read(index_t entry)
351
{
352
    itlb_tag_read_addr_t tag;
353
 
354
    tag.value = 0;
355
    tag.tlb_entry = entry;
356
    return asi_u64_read(ASI_ITLB_TAG_READ_REG, tag.value);
357
}
358
 
359
/** Read DMMU TLB Tag Read Register.
360
 *
361
 * @param entry     TLB Entry index.
362
 *
363
 * @return      Current value of specified DMMU TLB Tag Read Register.
364
 */
365
static inline uint64_t dtlb_tag_read_read(index_t entry)
366
{
367
    dtlb_tag_read_addr_t tag;
368
 
369
    tag.value = 0;
370
    tag.tlb_entry = entry;
371
    return asi_u64_read(ASI_DTLB_TAG_READ_REG, tag.value);
372
}
373
 
374
#elif defined (US3)
375
 
376
 
377
/** Read IMMU TLB Data Access Register.
378
 *
379
 * @param tlb       TLB number (one of TLB_ISMALL or TLB_IBIG)
380
 * @param entry     TLB Entry index.
381
 *
382
 * @return      Current value of specified IMMU TLB Data Access
383
 *          Register.
384
 */
385
static inline uint64_t itlb_data_access_read(int tlb, index_t entry)
386
{
387
    itlb_data_access_addr_t reg;
388
 
389
    reg.value = 0;
390
    reg.tlb_number = tlb;
391
    reg.local_tlb_entry = entry;
392
    return asi_u64_read(ASI_ITLB_DATA_ACCESS_REG, reg.value);
393
}
394
 
395
/** Write IMMU TLB Data Access Register.
396
 * @param tlb       TLB number (one of TLB_ISMALL or TLB_IBIG)
397
 * @param entry     TLB Entry index.
398
 * @param value     Value to be written.
399
 */
400
static inline void itlb_data_access_write(int tlb, index_t entry,
401
    uint64_t value)
402
{
403
    itlb_data_access_addr_t reg;
404
 
405
    reg.value = 0;
406
    reg.tlb_number = tlb;
407
    reg.local_tlb_entry = entry;
408
    asi_u64_write(ASI_ITLB_DATA_ACCESS_REG, reg.value, value);
409
    flush_pipeline();
410
}
411
 
412
/** Read DMMU TLB Data Access Register.
413
 *
414
 * @param tlb       TLB number (one of TLB_DSMALL, TLB_DBIG, TLB_DBIG)
415
 * @param entry     TLB Entry index.
416
 *
417
 * @return      Current value of specified DMMU TLB Data Access
418
 *          Register.
419
 */
420
static inline uint64_t dtlb_data_access_read(int tlb, index_t entry)
421
{
422
    dtlb_data_access_addr_t reg;
423
 
424
    reg.value = 0;
425
    reg.tlb_number = tlb;
426
    reg.local_tlb_entry = entry;
427
    return asi_u64_read(ASI_DTLB_DATA_ACCESS_REG, reg.value);
428
}
429
 
430
/** Write DMMU TLB Data Access Register.
431
 *
432
 * @param tlb       TLB number (one of TLB_DSMALL, TLB_DBIG_0, TLB_DBIG_1)  
433
 * @param entry     TLB Entry index.
434
 * @param value     Value to be written.
435
 */
436
static inline void dtlb_data_access_write(int tlb, index_t entry,
437
    uint64_t value)
438
{
439
    dtlb_data_access_addr_t reg;
440
 
441
    reg.value = 0;
442
    reg.tlb_number = tlb;
443
    reg.local_tlb_entry = entry;
444
    asi_u64_write(ASI_DTLB_DATA_ACCESS_REG, reg.value, value);
445
    membar();
446
}
447
 
448
/** Read IMMU TLB Tag Read Register.
449
 *
450
 * @param tlb       TLB number (one of TLB_ISMALL or TLB_IBIG)
451
 * @param entry     TLB Entry index.
452
 *
453
 * @return      Current value of specified IMMU TLB Tag Read Register.
454
 */
455
static inline uint64_t itlb_tag_read_read(int tlb, index_t entry)
456
{
457
    itlb_tag_read_addr_t tag;
458
 
459
    tag.value = 0;
460
    tag.tlb_number = tlb;
461
    tag.local_tlb_entry = entry;
462
    return asi_u64_read(ASI_ITLB_TAG_READ_REG, tag.value);
463
}
464
 
465
/** Read DMMU TLB Tag Read Register.
466
 *
467
 * @param tlb       TLB number (one of TLB_DSMALL, TLB_DBIG_0, TLB_DBIG_1)
468
 * @param entry     TLB Entry index.
469
 *
470
 * @return      Current value of specified DMMU TLB Tag Read Register.
471
 */
472
static inline uint64_t dtlb_tag_read_read(int tlb, index_t entry)
473
{
474
    dtlb_tag_read_addr_t tag;
475
 
476
    tag.value = 0;
477
    tag.tlb_number = tlb;
478
    tag.local_tlb_entry = entry;
479
    return asi_u64_read(ASI_DTLB_TAG_READ_REG, tag.value);
480
}
481
 
482
#endif
483
 
484
 
485
/** Write IMMU TLB Tag Access Register.
486
 *
487
 * @param v     Value to be written.
488
 */
489
static inline void itlb_tag_access_write(uint64_t v)
490
{
491
    asi_u64_write(ASI_IMMU, VA_IMMU_TAG_ACCESS, v);
492
    flush_pipeline();
493
}
494
 
495
/** Read IMMU TLB Tag Access Register.
496
 *
497
 * @return      Current value of IMMU TLB Tag Access Register.
498
 */
499
static inline uint64_t itlb_tag_access_read(void)
500
{
501
    return asi_u64_read(ASI_IMMU, VA_IMMU_TAG_ACCESS);
502
}
503
 
504
/** Write DMMU TLB Tag Access Register.
505
 *
506
 * @param v     Value to be written.
507
 */
508
static inline void dtlb_tag_access_write(uint64_t v)
509
{
510
    asi_u64_write(ASI_DMMU, VA_DMMU_TAG_ACCESS, v);
511
    membar();
512
}
513
 
514
/** Read DMMU TLB Tag Access Register.
515
 *
516
 * @return      Current value of DMMU TLB Tag Access Register.
517
 */
518
static inline uint64_t dtlb_tag_access_read(void)
519
{
520
    return asi_u64_read(ASI_DMMU, VA_DMMU_TAG_ACCESS);
521
}
522
 
523
 
524
/** Write IMMU TLB Data in Register.
525
 *
526
 * @param v     Value to be written.
527
 */
528
static inline void itlb_data_in_write(uint64_t v)
529
{
530
    asi_u64_write(ASI_ITLB_DATA_IN_REG, 0, v);
531
    flush_pipeline();
532
}
533
 
534
/** Write DMMU TLB Data in Register.
535
 *
536
 * @param v     Value to be written.
537
 */
538
static inline void dtlb_data_in_write(uint64_t v)
539
{
540
    asi_u64_write(ASI_DTLB_DATA_IN_REG, 0, v);
541
    membar();
542
}
543
 
544
/** Read ITLB Synchronous Fault Status Register.
545
 *
546
 * @return      Current content of I-SFSR register.
547
 */
548
static inline uint64_t itlb_sfsr_read(void)
549
{
550
    return asi_u64_read(ASI_IMMU, VA_IMMU_SFSR);
551
}
552
 
553
/** Write ITLB Synchronous Fault Status Register.
554
 *
555
 * @param v     New value of I-SFSR register.
556
 */
557
static inline void itlb_sfsr_write(uint64_t v)
558
{
559
    asi_u64_write(ASI_IMMU, VA_IMMU_SFSR, v);
560
    flush_pipeline();
561
}
562
 
563
/** Read DTLB Synchronous Fault Status Register.
564
 *
565
 * @return      Current content of D-SFSR register.
566
 */
567
static inline uint64_t dtlb_sfsr_read(void)
568
{
569
    return asi_u64_read(ASI_DMMU, VA_DMMU_SFSR);
570
}
571
 
572
/** Write DTLB Synchronous Fault Status Register.
573
 *
574
 * @param v     New value of D-SFSR register.
575
 */
576
static inline void dtlb_sfsr_write(uint64_t v)
577
{
578
    asi_u64_write(ASI_DMMU, VA_DMMU_SFSR, v);
579
    membar();
580
}
581
 
582
/** Read DTLB Synchronous Fault Address Register.
583
 *
584
 * @return      Current content of D-SFAR register.
585
 */
586
static inline uint64_t dtlb_sfar_read(void)
587
{
588
    return asi_u64_read(ASI_DMMU, VA_DMMU_SFAR);
589
}
590
 
591
/** Perform IMMU TLB Demap Operation.
592
 *
593
 * @param type      Selects between context and page demap (and entire MMU
594
 *          demap on US3).
595
 * @param context_encoding Specifies which Context register has Context ID for
596
 *          demap.
597
 * @param page      Address which is on the page to be demapped.
598
 */
599
static inline void itlb_demap(int type, int context_encoding, uintptr_t page)
600
{
601
    tlb_demap_addr_t da;
602
    page_address_t pg;
603
 
604
    da.value = 0;
605
    pg.address = page;
606
 
607
    da.type = type;
608
    da.context = context_encoding;
609
    da.vpn = pg.vpn;
610
 
611
    /* da.value is the address within the ASI */
612
    asi_u64_write(ASI_IMMU_DEMAP, da.value, 0);
613
 
614
    flush_pipeline();
615
}
616
 
617
/** Perform DMMU TLB Demap Operation.
618
 *
619
 * @param type      Selects between context and page demap (and entire MMU
620
 *          demap on US3).
621
 * @param context_encoding Specifies which Context register has Context ID for
622
 *          demap.
623
 * @param page      Address which is on the page to be demapped.
624
 */
625
static inline void dtlb_demap(int type, int context_encoding, uintptr_t page)
626
{
627
    tlb_demap_addr_t da;
628
    page_address_t pg;
629
 
630
    da.value = 0;
631
    pg.address = page;
632
 
633
    da.type = type;
634
    da.context = context_encoding;
635
    da.vpn = pg.vpn;
636
 
637
    /* da.value is the address within the ASI */
638
    asi_u64_write(ASI_DMMU_DEMAP, da.value, 0);
639
 
640
    membar();
641
}
642
 
643
#endif
644
extern void fast_instruction_access_mmu_miss(unative_t, istate_t *);
645
//extern void fast_data_access_mmu_miss(tlb_tag_access_reg_t, istate_t *);
646
//extern void fast_data_access_protection(tlb_tag_access_reg_t , istate_t *);
647
 
648
extern void dtlb_insert_mapping(uintptr_t, uintptr_t, int, bool, bool);
649
 
650
extern void describe_mmu_fault(void);
651
 
652
#endif /* !def __ASM__ */
653
 
654
#endif
655
 
656
/** @}
657
 */