Subversion Repositories HelenOS

Rev

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