1/* 2 * Copyright 2018, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the GNU General Public License version 2. Note that NO WARRANTY is provided. 8 * See "LICENSE_GPLv2.txt" for details. 9 * 10 * @TAG(DATA61_GPL) 11 */ 12 13#ifndef __ARCH_ARMV_VCPU_H_ 14#define __ARCH_ARMV_VCPU_H_ 15 16#include <config.h> 17 18#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT 19 20#include <arch/object/vcpu.h> 21 22/* Trap WFI/WFE/SMC and override CPSR.AIF */ 23#define HCR_COMMON ( HCR_TSC | HCR_TWE | HCR_TWI | HCR_AMO | HCR_IMO \ 24 | HCR_FMO | HCR_DC | HCR_VM) 25/* Allow native tasks to run at PL1, but restrict access */ 26#define HCR_NATIVE ( HCR_COMMON | HCR_TGE | HCR_TVM | HCR_TTLB | HCR_TCACHE \ 27 | HCR_TAC | HCR_SWIO) 28#define HCR_VCPU (HCR_COMMON) 29 30/* Amongst other things we set the caches to enabled by default. This 31 * may cause problems when booting guests that expect caches to be 32 * disabled */ 33#define SCTLR_DEFAULT 0xc5187c 34#define ACTLR_DEFAULT 0x40 35 36static inline word_t 37get_lr_svc(void) 38{ 39 word_t ret; 40 asm ("mrs %[ret], lr_svc" : [ret]"=r"(ret)); 41 return ret; 42} 43 44static inline void 45set_lr_svc(word_t val) 46{ 47 asm ("msr lr_svc, %[val]" :: [val]"r"(val)); 48} 49 50static inline word_t 51get_sp_svc(void) 52{ 53 word_t ret; 54 asm ("mrs %[ret], sp_svc" : [ret]"=r"(ret)); 55 return ret; 56} 57 58static inline void 59set_sp_svc(word_t val) 60{ 61 asm ("msr sp_svc, %[val]" :: [val]"r"(val)); 62} 63 64static inline word_t 65get_spsr_svc(void) 66{ 67 word_t ret; 68 asm ("mrs %[ret], spsr_svc" : [ret]"=r"(ret)); 69 return ret; 70} 71 72static inline void 73set_spsr_svc(word_t val) 74{ 75 asm ("msr spsr_svc, %[val]" :: [val]"r"(val)); 76} 77 78static inline word_t 79get_lr_abt(void) 80{ 81 word_t ret; 82 asm ("mrs %[ret], lr_abt" : [ret]"=r"(ret)); 83 return ret; 84} 85 86static inline void 87set_lr_abt(word_t val) 88{ 89 asm ("msr lr_abt, %[val]" :: [val]"r"(val)); 90} 91 92static inline word_t 93get_sp_abt(void) 94{ 95 word_t ret; 96 asm ("mrs %[ret], sp_abt" : [ret]"=r"(ret)); 97 return ret; 98} 99 100static inline void 101set_sp_abt(word_t val) 102{ 103 asm ("msr sp_abt, %[val]" :: [val]"r"(val)); 104} 105 106static inline word_t 107get_spsr_abt(void) 108{ 109 word_t ret; 110 asm ("mrs %[ret], spsr_abt" : [ret]"=r"(ret)); 111 return ret; 112} 113 114static inline void 115set_spsr_abt(word_t val) 116{ 117 asm ("msr spsr_abt, %[val]" :: [val]"r"(val)); 118} 119 120static inline word_t 121get_lr_und(void) 122{ 123 word_t ret; 124 asm ("mrs %[ret], lr_und" : [ret]"=r"(ret)); 125 return ret; 126} 127 128static inline void 129set_lr_und(word_t val) 130{ 131 asm ("msr lr_und, %[val]" :: [val]"r"(val)); 132} 133 134static inline word_t 135get_sp_und(void) 136{ 137 word_t ret; 138 asm ("mrs %[ret], sp_und" : [ret]"=r"(ret)); 139 return ret; 140} 141 142static inline void 143set_sp_und(word_t val) 144{ 145 asm ("msr sp_und, %[val]" :: [val]"r"(val)); 146} 147 148static inline word_t 149get_spsr_und(void) 150{ 151 word_t ret; 152 asm ("mrs %[ret], spsr_und" : [ret]"=r"(ret)); 153 return ret; 154} 155 156static inline void 157set_spsr_und(word_t val) 158{ 159 asm ("msr spsr_und, %[val]" :: [val]"r"(val)); 160} 161 162static inline word_t 163get_lr_irq(void) 164{ 165 word_t ret; 166 asm ("mrs %[ret], lr_irq" : [ret]"=r"(ret)); 167 return ret; 168} 169 170static inline void 171set_lr_irq(word_t val) 172{ 173 asm ("msr lr_irq, %[val]" :: [val]"r"(val)); 174} 175 176static inline word_t 177get_sp_irq(void) 178{ 179 word_t ret; 180 asm ("mrs %[ret], sp_irq" : [ret]"=r"(ret)); 181 return ret; 182} 183 184static inline void 185set_sp_irq(word_t val) 186{ 187 asm ("msr sp_irq, %[val]" :: [val]"r"(val)); 188} 189 190static inline word_t 191get_spsr_irq(void) 192{ 193 word_t ret; 194 asm ("mrs %[ret], spsr_irq" : [ret]"=r"(ret)); 195 return ret; 196} 197 198static inline void 199set_spsr_irq(word_t val) 200{ 201 asm ("msr spsr_irq, %[val]" :: [val]"r"(val)); 202} 203 204static inline word_t 205get_lr_fiq(void) 206{ 207 word_t ret; 208 asm ("mrs %[ret], lr_fiq" : [ret]"=r"(ret)); 209 return ret; 210} 211 212static inline void 213set_lr_fiq(word_t val) 214{ 215 asm ("msr lr_fiq, %[val]" :: [val]"r"(val)); 216} 217 218static inline word_t 219get_sp_fiq(void) 220{ 221 word_t ret; 222 asm ("mrs %[ret], sp_fiq" : [ret]"=r"(ret)); 223 return ret; 224} 225 226static inline void 227set_sp_fiq(word_t val) 228{ 229 asm ("msr sp_fiq, %[val]" :: [val]"r"(val)); 230} 231 232static inline word_t 233get_spsr_fiq(void) 234{ 235 word_t ret; 236 asm ("mrs %[ret], spsr_fiq" : [ret]"=r"(ret)); 237 return ret; 238} 239 240static inline void 241set_spsr_fiq(word_t val) 242{ 243 asm ("msr spsr_fiq, %[val]" :: [val]"r"(val)); 244} 245 246static inline word_t 247get_r8_fiq(void) 248{ 249 word_t ret; 250 asm ("mrs %[ret], r8_fiq" : [ret]"=r"(ret)); 251 return ret; 252} 253 254static inline void 255set_r8_fiq(word_t val) 256{ 257 asm ("msr r8_fiq, %[val]" :: [val]"r"(val)); 258} 259 260static inline word_t 261get_r9_fiq(void) 262{ 263 word_t ret; 264 asm ("mrs %[ret], r9_fiq" : [ret]"=r"(ret)); 265 return ret; 266} 267 268static inline void 269set_r9_fiq(word_t val) 270{ 271 asm ("msr r9_fiq, %[val]" :: [val]"r"(val)); 272} 273 274static inline word_t 275get_r10_fiq(void) 276{ 277 word_t ret; 278 asm ("mrs %[ret], r10_fiq" : [ret]"=r"(ret)); 279 return ret; 280} 281 282static inline void 283set_r10_fiq(word_t val) 284{ 285 asm ("msr r10_fiq, %[val]" :: [val]"r"(val)); 286} 287 288static inline word_t 289get_r11_fiq(void) 290{ 291 word_t ret; 292 asm ("mrs %[ret], r11_fiq" : [ret]"=r"(ret)); 293 return ret; 294} 295 296static inline void 297set_r11_fiq(word_t val) 298{ 299 asm ("msr r11_fiq, %[val]" :: [val]"r"(val)); 300} 301 302static inline word_t 303get_r12_fiq(void) 304{ 305 word_t ret; 306 asm ("mrs %[ret], r12_fiq" : [ret]"=r"(ret)); 307 return ret; 308} 309 310static inline void 311set_r12_fiq(word_t val) 312{ 313 asm ("msr r12_fiq, %[val]" :: [val]"r"(val)); 314} 315static inline word_t 316get_cntv_tval(void) 317{ 318 word_t ret = 0; 319 MRC(CNTV_TVAL, ret); 320 return ret; 321} 322 323static inline void 324set_cntv_tval(word_t val) 325{ 326 MCR(CNTV_TVAL, val); 327} 328 329static inline word_t 330get_cntv_ctl(void) 331{ 332 word_t ret = 0; 333 MRC(CNTV_CTL, ret); 334 return ret; 335} 336 337static inline void 338set_cntv_ctl(word_t val) 339{ 340 MCR(CNTV_CTL, val); 341} 342 343 344static word_t 345vcpu_hw_read_reg(word_t reg_index) 346{ 347 word_t reg = 0; 348 switch (reg_index) { 349 case seL4_VCPUReg_SCTLR: 350 return getSCTLR(); 351 case seL4_VCPUReg_ACTLR: 352 return getACTLR(); 353 case seL4_VCPUReg_TTBCR: 354 return readTTBCR(); 355 case seL4_VCPUReg_TTBR0: 356 return readTTBR0(); 357 case seL4_VCPUReg_TTBR1: 358 return readTTBR1(); 359 case seL4_VCPUReg_DACR: 360 return readDACR(); 361 case seL4_VCPUReg_DFSR: 362 return getDFSR(); 363 case seL4_VCPUReg_IFSR: 364 return getIFSR(); 365 case seL4_VCPUReg_ADFSR: 366 return getADFSR(); 367 case seL4_VCPUReg_AIFSR: 368 return getAIFSR(); 369 case seL4_VCPUReg_DFAR: 370 return getDFAR(); 371 case seL4_VCPUReg_IFAR: 372 return getIFAR(); 373 case seL4_VCPUReg_PRRR: 374 return getPRRR(); 375 case seL4_VCPUReg_NMRR: 376 return getNMRR(); 377 case seL4_VCPUReg_CIDR: 378 return getCIDR(); 379 case seL4_VCPUReg_TPIDRPRW: 380 return readTPIDRPRW(); 381 case seL4_VCPUReg_FPEXC: 382 return reg; 383 case seL4_VCPUReg_CNTV_TVAL: 384 return get_cntv_tval(); 385 case seL4_VCPUReg_CNTV_CTL: 386 return get_cntv_ctl(); 387 case seL4_VCPUReg_LRsvc: 388 return get_lr_svc(); 389 case seL4_VCPUReg_SPsvc: 390 return get_sp_svc(); 391 case seL4_VCPUReg_LRabt: 392 return get_lr_abt(); 393 case seL4_VCPUReg_SPabt: 394 return get_sp_abt(); 395 case seL4_VCPUReg_LRund: 396 return get_lr_und(); 397 case seL4_VCPUReg_SPund: 398 return get_sp_und(); 399 case seL4_VCPUReg_LRirq: 400 return get_lr_irq(); 401 case seL4_VCPUReg_SPirq: 402 return get_sp_irq(); 403 case seL4_VCPUReg_LRfiq: 404 return get_lr_fiq(); 405 case seL4_VCPUReg_SPfiq: 406 return get_sp_fiq(); 407 case seL4_VCPUReg_R8fiq: 408 return get_r8_fiq(); 409 case seL4_VCPUReg_R9fiq: 410 return get_r9_fiq(); 411 case seL4_VCPUReg_R10fiq: 412 return get_r10_fiq(); 413 case seL4_VCPUReg_R11fiq: 414 return get_r11_fiq(); 415 case seL4_VCPUReg_R12fiq: 416 return get_r12_fiq(); 417 case seL4_VCPUReg_SPSRsvc: 418 return get_spsr_svc(); 419 case seL4_VCPUReg_SPSRabt: 420 return get_spsr_abt(); 421 case seL4_VCPUReg_SPSRund: 422 return get_spsr_und(); 423 case seL4_VCPUReg_SPSRirq: 424 return get_spsr_irq(); 425 case seL4_VCPUReg_SPSRfiq: 426 return get_spsr_fiq(); 427 default: 428 fail("ARM/HYP: Invalid register index"); 429 } 430} 431 432static void 433vcpu_hw_write_reg(word_t reg_index, word_t reg) 434{ 435 switch (reg_index) { 436 case seL4_VCPUReg_SCTLR: 437 setSCTLR(reg); 438 break; 439 case seL4_VCPUReg_ACTLR: 440 setACTLR(reg); 441 break; 442 case seL4_VCPUReg_TTBCR: 443 writeTTBCR(reg); 444 break; 445 case seL4_VCPUReg_TTBR0: 446 writeTTBR0(reg); 447 break; 448 case seL4_VCPUReg_TTBR1: 449 writeTTBR1(reg); 450 break; 451 case seL4_VCPUReg_DACR: 452 writeDACR(reg); 453 break; 454 case seL4_VCPUReg_DFSR: 455 setDFSR(reg); 456 break; 457 case seL4_VCPUReg_IFSR: 458 setIFSR(reg); 459 break; 460 case seL4_VCPUReg_ADFSR: 461 setADFSR(reg); 462 break; 463 case seL4_VCPUReg_AIFSR: 464 setAIFSR(reg); 465 break; 466 case seL4_VCPUReg_DFAR: 467 setDFAR(reg); 468 break; 469 case seL4_VCPUReg_IFAR: 470 setIFAR(reg); 471 break; 472 case seL4_VCPUReg_PRRR: 473 setPRRR(reg); 474 break; 475 case seL4_VCPUReg_NMRR: 476 setNMRR(reg); 477 break; 478 case seL4_VCPUReg_CIDR: 479 setCIDR(reg); 480 break; 481 case seL4_VCPUReg_TPIDRPRW: 482 writeTPIDRPRW(reg); 483 break; 484 case seL4_VCPUReg_FPEXC: 485 break; 486 case seL4_VCPUReg_CNTV_TVAL: 487 set_cntv_tval(reg); 488 break; 489 case seL4_VCPUReg_CNTV_CTL: 490 set_cntv_ctl(reg); 491 break; 492 case seL4_VCPUReg_LRsvc: 493 set_lr_svc(reg); 494 break; 495 case seL4_VCPUReg_SPsvc: 496 set_sp_svc(reg); 497 break; 498 case seL4_VCPUReg_LRabt: 499 set_lr_abt(reg); 500 break; 501 case seL4_VCPUReg_SPabt: 502 set_sp_abt(reg); 503 break; 504 case seL4_VCPUReg_LRund: 505 set_lr_und(reg); 506 break; 507 case seL4_VCPUReg_SPund: 508 set_sp_und(reg); 509 break; 510 case seL4_VCPUReg_LRirq: 511 set_lr_irq(reg); 512 break; 513 case seL4_VCPUReg_SPirq: 514 set_sp_irq(reg); 515 break; 516 case seL4_VCPUReg_LRfiq: 517 set_lr_fiq(reg); 518 break; 519 case seL4_VCPUReg_SPfiq: 520 set_sp_fiq(reg); 521 break; 522 case seL4_VCPUReg_R8fiq: 523 set_r8_fiq(reg); 524 break; 525 case seL4_VCPUReg_R9fiq: 526 set_r9_fiq(reg); 527 break; 528 case seL4_VCPUReg_R10fiq: 529 set_r10_fiq(reg); 530 break; 531 case seL4_VCPUReg_R11fiq: 532 set_r11_fiq(reg); 533 break; 534 case seL4_VCPUReg_R12fiq: 535 set_r12_fiq(reg); 536 break; 537 case seL4_VCPUReg_SPSRsvc: 538 set_spsr_svc(reg); 539 break; 540 case seL4_VCPUReg_SPSRabt: 541 set_spsr_abt(reg); 542 break; 543 case seL4_VCPUReg_SPSRund: 544 set_spsr_und(reg); 545 break; 546 case seL4_VCPUReg_SPSRirq: 547 set_spsr_irq(reg); 548 break; 549 case seL4_VCPUReg_SPSRfiq: 550 set_spsr_fiq(reg); 551 break; 552 default: 553 fail("ARM/HYP: Invalid register index"); 554 } 555} 556 557#endif /* End of CONFIG_ARM_HYPERVISOR_SUPPORT */ 558 559 560#endif 561 562